1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 21 #include <memory> 22 #include <parser.hxx> 23 #include <basic/sberrors.hxx> 24 #include <basic/sbmod.hxx> 25 #include <expr.hxx> 26 #include <uno/current_context.hxx> 27 28 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t, 29 SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo ) 30 { 31 pParser = p; 32 bBased = bError = bByVal = bBracket = false; 33 nParenLevel = 0; 34 eCurExpr = t; 35 m_eMode = eMode; 36 pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean(); 37 if( t != SbSYMBOL ) 38 { 39 pExpr->Optimize(pParser); 40 } 41 if( t == SbLVALUE && !pExpr->IsLvalue() ) 42 { 43 p->Error( ERRCODE_BASIC_LVALUE_EXPECTED ); 44 } 45 if( t == SbOPERAND && !IsVariable() ) 46 { 47 p->Error( ERRCODE_BASIC_VAR_EXPECTED ); 48 } 49 } 50 51 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t ) 52 { 53 pParser = p; 54 bBased = bError = bByVal = bBracket = false; 55 nParenLevel = 0; 56 eCurExpr = SbOPERAND; 57 m_eMode = EXPRMODE_STANDARD; 58 pExpr = std::make_unique<SbiExprNode>( n, t ); 59 pExpr->Optimize(pParser); 60 } 61 62 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprListPtr pPar ) 63 { 64 pParser = p; 65 bBased = bError = bByVal = bBracket = false; 66 nParenLevel = 0; 67 eCurExpr = SbOPERAND; 68 m_eMode = EXPRMODE_STANDARD; 69 pExpr = std::make_unique<SbiExprNode>( r, SbxVARIANT, std::move(pPar) ); 70 } 71 72 SbiExpression::~SbiExpression() { } 73 74 // reading in a complete identifier 75 // an identifier has the following form: 76 // name[(Parameter)][.Name[(parameter)]]... 77 // structure elements are coupled via the element pNext, 78 // so that they're not in the tree. 79 80 // Are there parameters without brackets following? This may be a number, 81 // a string, a symbol or also a comma (if the 1st parameter is missing) 82 83 static bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok ) 84 { 85 if( eTok == LPAREN ) 86 { 87 return true; 88 } 89 // but only if similar to CALL! 90 if( !p->WhiteSpace() || eCurExpr != SbSYMBOL ) 91 { 92 return false; 93 } 94 if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING || 95 eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL ) 96 { 97 return true; 98 } 99 else // check for default params with reserved names ( e.g. names of tokens ) 100 { 101 SbiTokenizer tokens( *static_cast<SbiTokenizer*>(p) ); 102 // Urk the Next() / Peek() semantics are... weird 103 tokens.Next(); 104 if ( tokens.Peek() == ASSIGN ) 105 { 106 return true; 107 } 108 } 109 return false; 110 } 111 112 // definition of a new symbol 113 114 static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr, 115 const OUString& rName, SbxDataType eType, const SbiExprList* pPar ) 116 { 117 SbiSymDef* pDef; 118 // A= is not a procedure 119 bool bHasType = ( eTok == EQ || eTok == DOT ); 120 if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar ) 121 { 122 // so this is a procedure 123 // the correct pool should be found out, as 124 // procs must always get into a public pool 125 SbiSymPool* pPool = &rPool; 126 if( pPool->GetScope() != SbPUBLIC ) 127 { 128 pPool = &rPool.GetParser()->aPublics; 129 } 130 SbiProcDef* pProc = pPool->AddProc( rName ); 131 132 // special treatment for Colls like Documents(1) 133 if( eCurExpr == SbSTDEXPR ) 134 { 135 bHasType = true; 136 } 137 pDef = pProc; 138 pDef->SetType( bHasType ? eType : SbxEMPTY ); 139 if( pPar ) 140 { 141 // generate dummy parameters 142 for( sal_Int32 n = 1; n <= pPar->GetSize(); n++ ) 143 { 144 OUString aPar = "PAR" + OUString::number( n ); 145 pProc->GetParams().AddSym( aPar ); 146 } 147 } 148 } 149 else 150 { 151 // or a normal symbol 152 pDef = rPool.AddSym( rName ); 153 pDef->SetType( eType ); 154 } 155 return pDef; 156 } 157 158 // currently even keywords are allowed (because of Dflt properties of the same name) 159 160 std::unique_ptr<SbiExprNode> SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo ) 161 { 162 if( pParser->Peek() == DOT ) 163 { 164 SbiExprNode* pWithVar = pParser->GetWithVar(); 165 // #26608: get to the node-chain's end to pass the correct object 166 SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : nullptr; 167 std::unique_ptr<SbiExprNode> pNd; 168 if( !pDef ) 169 { 170 pParser->Next(); 171 } 172 else 173 { 174 pNd = ObjTerm( *pDef ); 175 if( pNd ) 176 { 177 pNd->SetWithParent( pWithVar ); 178 } 179 } 180 if( !pNd ) 181 { 182 pParser->Error( ERRCODE_BASIC_UNEXPECTED, DOT ); 183 pNd = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE ); 184 } 185 return pNd; 186 } 187 188 SbiToken eTok = (pKeywordSymbolInfo == nullptr) ? pParser->Next() : SYMBOL; 189 // memorize the parsing's begin 190 pParser->LockColumn(); 191 OUString aSym( (pKeywordSymbolInfo == nullptr) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol ); 192 SbxDataType eType = (pKeywordSymbolInfo == nullptr) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType; 193 SbiExprListPtr pPar; 194 std::unique_ptr<SbiExprListVector> pvMoreParLcl; 195 // are there parameters following? 196 SbiToken eNextTok = pParser->Peek(); 197 // is it a known parameter? 198 // create a string constant then, which will be recognized 199 // in the SbiParameters-ctor and is continued to be handled 200 if( eNextTok == ASSIGN ) 201 { 202 pParser->UnlockColumn(); 203 return std::make_unique<SbiExprNode>( aSym ); 204 } 205 // no keywords allowed from here on! 206 if( SbiTokenizer::IsKwd( eTok ) 207 && (!pParser->IsCompatible() || eTok != INPUT) ) 208 { 209 pParser->Error( ERRCODE_BASIC_SYNTAX ); 210 bError = true; 211 } 212 213 if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) ) 214 { 215 bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE); 216 pPar = SbiExprList::ParseParameters( pParser, bStandaloneExpression ); 217 bError = bError || !pPar->IsValid(); 218 if( !bError ) 219 bBracket = pPar->IsBracket(); 220 eTok = pParser->Peek(); 221 222 // i75443 check for additional sets of parameters 223 while( eTok == LPAREN ) 224 { 225 if( pvMoreParLcl == nullptr ) 226 { 227 pvMoreParLcl.reset(new SbiExprListVector); 228 } 229 SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser ); 230 bError = bError || !pAddPar->IsValid(); 231 pvMoreParLcl->push_back( std::move(pAddPar) ); 232 eTok = pParser->Peek(); 233 } 234 } 235 // It might be an object part, if . or ! is following. 236 // In case of . the variable must already be defined; 237 // it's an object, if pDef is NULL after the search. 238 bool bObj = ( ( eTok == DOT || eTok == EXCLAM ) 239 && !pParser->WhiteSpace() ); 240 if( bObj ) 241 { 242 bBracket = false; // Now the bracket for the first term is obsolete 243 if( eType == SbxVARIANT ) 244 { 245 eType = SbxOBJECT; 246 } 247 else 248 { 249 // Name%. really does not work! 250 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym ); 251 bError = true; 252 } 253 } 254 // Search: 255 SbiSymDef* pDef = pParser->pPool->Find( aSym ); 256 if( !pDef ) 257 { 258 // Part of the Runtime-Library? 259 // from 31.3.1996: swapped out to parser-method 260 // (is also needed in SbiParser::DefVar() in DIM.CXX) 261 pDef = pParser->CheckRTLForSym( aSym, eType ); 262 263 // #i109184: Check if symbol is or later will be defined inside module 264 SbModule& rMod = pParser->aGen.GetModule(); 265 if( rMod.FindMethod( aSym, SbxClassType::DontCare ) ) 266 { 267 pDef = nullptr; 268 } 269 } 270 if( !pDef ) 271 { 272 if( bObj ) 273 { 274 eType = SbxOBJECT; 275 } 276 pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar.get() ); 277 // Looks like this is a local ( but undefined variable ) 278 // if it is in a static procedure then make this Symbol 279 // static 280 if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() ) 281 { 282 pDef->SetStatic(); 283 } 284 } 285 else 286 { 287 288 SbiConstDef* pConst = pDef->GetConstDef(); 289 if( pConst ) 290 { 291 pPar = nullptr; 292 pvMoreParLcl.reset(); 293 if( pConst->GetType() == SbxSTRING ) 294 { 295 return std::make_unique<SbiExprNode>( pConst->GetString() ); 296 } 297 else 298 { 299 return std::make_unique<SbiExprNode>( pConst->GetValue(), pConst->GetType() ); 300 } 301 } 302 303 // 0 parameters come up to () 304 if( pDef->GetDims() ) 305 { 306 if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() ) 307 { 308 pParser->Error( ERRCODE_BASIC_WRONG_DIMS ); 309 } 310 } 311 if( pDef->IsDefinedAs() ) 312 { 313 SbxDataType eDefType = pDef->GetType(); 314 // #119187 Only error if types conflict 315 if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType ) 316 { 317 // How? Define with AS first and take a Suffix then? 318 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym ); 319 bError = true; 320 } 321 else if ( eType == SbxVARIANT ) 322 { 323 // if there's nothing named, take the type of the entry, 324 // but only if the var hasn't been defined with AS XXX 325 // so that we catch n% = 5 : print n 326 eType = eDefType; 327 } 328 } 329 // checking type of variables: 330 // is there named anything different in the scanner? 331 // That's OK for methods! 332 if( eType != SbxVARIANT && // Variant takes everything 333 eType != pDef->GetType() && 334 !pDef->GetProcDef() ) 335 { 336 // maybe pDef describes an object that so far has only been 337 // recognized as SbxVARIANT - then change type of pDef 338 // from 16.12.95 (similar cases possible perhaps?!?) 339 if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT ) 340 { 341 pDef->SetType( SbxOBJECT ); 342 } 343 else 344 { 345 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym ); 346 bError = true; 347 } 348 } 349 } 350 std::unique_ptr<SbiExprNode> pNd(new SbiExprNode( *pDef, eType )); 351 if( !pPar ) 352 { 353 pPar = SbiExprList::ParseParameters( pParser,false,false ); 354 } 355 pNd->aVar.pPar = pPar.release(); 356 pNd->aVar.pvMorePar = pvMoreParLcl.release(); 357 if( bObj ) 358 { 359 // from 8.1.95: Object may also be of the type SbxVARIANT 360 if( pDef->GetType() == SbxVARIANT ) 361 pDef->SetType( SbxOBJECT ); 362 // if we scan something with point, 363 // the type must be SbxOBJECT 364 if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT ) 365 { 366 // defer error until runtime if in vba mode 367 if ( !pParser->IsVBASupportOn() ) 368 { 369 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym ); 370 bError = true; 371 } 372 } 373 if( !bError ) 374 { 375 pNd->aVar.pNext = ObjTerm( *pDef ).release(); 376 } 377 } 378 379 pParser->UnlockColumn(); 380 return pNd; 381 } 382 383 // construction of an object term. A term of this kind is part 384 // of an expression that begins with an object variable. 385 386 std::unique_ptr<SbiExprNode> SbiExpression::ObjTerm( SbiSymDef& rObj ) 387 { 388 pParser->Next(); 389 SbiToken eTok = pParser->Next(); 390 if( eTok != SYMBOL && !SbiTokenizer::IsKwd( eTok ) && !SbiTokenizer::IsExtra( eTok ) ) 391 { 392 // #66745 Some operators can also be allowed 393 // as identifiers, important for StarOne 394 if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR && 395 eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS ) 396 { 397 pParser->Error( ERRCODE_BASIC_VAR_EXPECTED ); 398 bError = true; 399 } 400 } 401 402 if( bError ) 403 { 404 return nullptr; 405 } 406 OUString aSym( pParser->GetSym() ); 407 SbxDataType eType = pParser->GetType(); 408 SbiExprListPtr pPar; 409 SbiExprListVector* pvMoreParLcl = nullptr; 410 eTok = pParser->Peek(); 411 412 if( DoParametersFollow( pParser, eCurExpr, eTok ) ) 413 { 414 pPar = SbiExprList::ParseParameters( pParser, false/*bStandaloneExpression*/ ); 415 bError = bError || !pPar->IsValid(); 416 eTok = pParser->Peek(); 417 418 // i109624 check for additional sets of parameters 419 while( eTok == LPAREN ) 420 { 421 if( pvMoreParLcl == nullptr ) 422 { 423 pvMoreParLcl = new SbiExprListVector; 424 } 425 SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser ); 426 bError = bError || !pPar->IsValid(); 427 pvMoreParLcl->push_back( std::move(pAddPar) ); 428 eTok = pParser->Peek(); 429 } 430 } 431 bool bObj = ( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() ); 432 if( bObj ) 433 { 434 if( eType == SbxVARIANT ) 435 { 436 eType = SbxOBJECT; 437 } 438 else 439 { 440 // Name%. does really not work! 441 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym ); 442 bError = true; 443 } 444 } 445 446 // an object's symbol pool is always PUBLIC 447 SbiSymPool& rPool = rObj.GetPool(); 448 rPool.SetScope( SbPUBLIC ); 449 SbiSymDef* pDef = rPool.Find( aSym ); 450 if( !pDef ) 451 { 452 pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar.get() ); 453 pDef->SetType( eType ); 454 } 455 456 std::unique_ptr<SbiExprNode> pNd(new SbiExprNode( *pDef, eType )); 457 pNd->aVar.pPar = pPar.release(); 458 pNd->aVar.pvMorePar = pvMoreParLcl; 459 if( bObj ) 460 { 461 if( pDef->GetType() == SbxVARIANT ) 462 { 463 pDef->SetType( SbxOBJECT ); 464 } 465 if( pDef->GetType() != SbxOBJECT ) 466 { 467 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym ); 468 bError = true; 469 } 470 if( !bError ) 471 { 472 pNd->aVar.pNext = ObjTerm( *pDef ).release(); 473 pNd->eType = eType; 474 } 475 } 476 return pNd; 477 } 478 479 // an operand can be: 480 // constant 481 // scalar variable 482 // structure elements 483 // array elements 484 // functions 485 // bracketed expressions 486 487 std::unique_ptr<SbiExprNode> SbiExpression::Operand( bool bUsedForTypeOf ) 488 { 489 std::unique_ptr<SbiExprNode> pRes; 490 491 // test operand: 492 switch( SbiToken eTok = pParser->Peek() ) 493 { 494 case SYMBOL: 495 pRes = Term(); 496 // process something like "IF Not r Is Nothing Then .." 497 if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS ) 498 { 499 eTok = pParser->Next(); 500 pRes = std::make_unique<SbiExprNode>( std::move(pRes), eTok, Like() ); 501 } 502 break; 503 case DOT: // .with 504 pRes = Term(); break; 505 case NOT: 506 pRes = VBA_Not(); 507 break; 508 case NUMBER: 509 pParser->Next(); 510 pRes = std::make_unique<SbiExprNode>( pParser->GetDbl(), pParser->GetType() ); 511 break; 512 case FIXSTRING: 513 pParser->Next(); 514 pRes = std::make_unique<SbiExprNode>( pParser->GetSym() ); break; 515 case LPAREN: 516 pParser->Next(); 517 if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN ) 518 { 519 m_eMode = EXPRMODE_EMPTY_PAREN; 520 pRes = std::make_unique<SbiExprNode>(); // Dummy node 521 pParser->Next(); 522 break; 523 } 524 nParenLevel++; 525 pRes = Boolean(); 526 if( pParser->Peek() != RPAREN ) 527 { 528 // If there was a LPARAM, it does not belong to the expression 529 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING ) 530 { 531 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED; 532 } 533 else 534 { 535 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS ); 536 } 537 } 538 else 539 { 540 pParser->Next(); 541 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING ) 542 { 543 SbiToken eTokAfterRParen = pParser->Peek(); 544 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT ) 545 { 546 m_eMode = EXPRMODE_ARRAY_OR_OBJECT; 547 } 548 else 549 { 550 m_eMode = EXPRMODE_STANDARD; 551 } 552 } 553 } 554 nParenLevel--; 555 break; 556 default: 557 // keywords here are OK at the moment! 558 if( SbiTokenizer::IsKwd( eTok ) ) 559 { 560 pRes = Term(); 561 } 562 else 563 { 564 pParser->Next(); 565 pRes = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE ); 566 pParser->Error( ERRCODE_BASIC_UNEXPECTED, eTok ); 567 } 568 break; 569 } 570 return pRes; 571 } 572 573 std::unique_ptr<SbiExprNode> SbiExpression::Unary() 574 { 575 std::unique_ptr<SbiExprNode> pNd; 576 SbiToken eTok = pParser->Peek(); 577 switch( eTok ) 578 { 579 case MINUS: 580 eTok = NEG; 581 pParser->Next(); 582 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr ); 583 break; 584 case NOT: 585 if( pParser->IsVBASupportOn() ) 586 { 587 pNd = Operand(); 588 } 589 else 590 { 591 pParser->Next(); 592 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr ); 593 } 594 break; 595 case PLUS: 596 pParser->Next(); 597 pNd = Unary(); 598 break; 599 case TYPEOF: 600 { 601 pParser->Next(); 602 std::unique_ptr<SbiExprNode> pObjNode = Operand( true/*bUsedForTypeOf*/ ); 603 pParser->TestToken( IS ); 604 SbiSymDef* pTypeDef = new SbiSymDef( OUString() ); 605 pParser->TypeDecl( *pTypeDef, true ); 606 pNd = std::make_unique<SbiExprNode>( std::move(pObjNode), pTypeDef->GetTypeId() ); 607 break; 608 } 609 case NEW: 610 { 611 pParser->Next(); 612 SbiSymDef* pTypeDef = new SbiSymDef( OUString() ); 613 pParser->TypeDecl( *pTypeDef, true ); 614 pNd = std::make_unique<SbiExprNode>( pTypeDef->GetTypeId() ); 615 break; 616 } 617 default: 618 pNd = Operand(); 619 } 620 return pNd; 621 } 622 623 std::unique_ptr<SbiExprNode> SbiExpression::Exp() 624 { 625 std::unique_ptr<SbiExprNode> pNd = Unary(); 626 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 627 { 628 while( pParser->Peek() == EXPON ) 629 { 630 SbiToken eTok = pParser->Next(); 631 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Unary() ); 632 } 633 } 634 return pNd; 635 } 636 637 std::unique_ptr<SbiExprNode> SbiExpression::MulDiv() 638 { 639 std::unique_ptr<SbiExprNode> pNd = Exp(); 640 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 641 { 642 for( ;; ) 643 { 644 SbiToken eTok = pParser->Peek(); 645 if( eTok != MUL && eTok != DIV ) 646 { 647 break; 648 } 649 eTok = pParser->Next(); 650 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Exp() ); 651 } 652 } 653 return pNd; 654 } 655 656 std::unique_ptr<SbiExprNode> SbiExpression::IntDiv() 657 { 658 std::unique_ptr<SbiExprNode> pNd = MulDiv(); 659 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 660 { 661 while( pParser->Peek() == IDIV ) 662 { 663 SbiToken eTok = pParser->Next(); 664 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, MulDiv() ); 665 } 666 } 667 return pNd; 668 } 669 670 std::unique_ptr<SbiExprNode> SbiExpression::Mod() 671 { 672 std::unique_ptr<SbiExprNode> pNd = IntDiv(); 673 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 674 { 675 while( pParser->Peek() == MOD ) 676 { 677 SbiToken eTok = pParser->Next(); 678 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, IntDiv() ); 679 } 680 } 681 return pNd; 682 } 683 684 std::unique_ptr<SbiExprNode> SbiExpression::AddSub() 685 { 686 std::unique_ptr<SbiExprNode> pNd = Mod(); 687 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 688 { 689 for( ;; ) 690 { 691 SbiToken eTok = pParser->Peek(); 692 if( eTok != PLUS && eTok != MINUS ) 693 { 694 break; 695 } 696 eTok = pParser->Next(); 697 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Mod() ); 698 } 699 } 700 return pNd; 701 } 702 703 std::unique_ptr<SbiExprNode> SbiExpression::Cat() 704 { 705 std::unique_ptr<SbiExprNode> pNd = AddSub(); 706 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 707 { 708 for( ;; ) 709 { 710 SbiToken eTok = pParser->Peek(); 711 if( eTok != CAT ) 712 { 713 break; 714 } 715 eTok = pParser->Next(); 716 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, AddSub() ); 717 } 718 } 719 return pNd; 720 } 721 722 std::unique_ptr<SbiExprNode> SbiExpression::Comp() 723 { 724 std::unique_ptr<SbiExprNode> pNd = Cat(); 725 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 726 { 727 short nCount = 0; 728 for( ;; ) 729 { 730 SbiToken eTok = pParser->Peek(); 731 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT ) 732 { 733 break; 734 } 735 if( eTok != EQ && eTok != NE && eTok != LT && 736 eTok != GT && eTok != LE && eTok != GE ) 737 { 738 break; 739 } 740 eTok = pParser->Next(); 741 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Cat() ); 742 nCount++; 743 } 744 } 745 return pNd; 746 } 747 748 749 std::unique_ptr<SbiExprNode> SbiExpression::VBA_Not() 750 { 751 std::unique_ptr<SbiExprNode> pNd; 752 753 SbiToken eTok = pParser->Peek(); 754 if( eTok == NOT ) 755 { 756 pParser->Next(); 757 pNd = std::make_unique<SbiExprNode>( VBA_Not(), eTok, nullptr ); 758 } 759 else 760 { 761 pNd = Comp(); 762 } 763 return pNd; 764 } 765 766 std::unique_ptr<SbiExprNode> SbiExpression::Like() 767 { 768 std::unique_ptr<SbiExprNode> pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp(); 769 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 770 { 771 short nCount = 0; 772 while( pParser->Peek() == LIKE ) 773 { 774 SbiToken eTok = pParser->Next(); 775 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Comp() ); 776 nCount++; 777 } 778 // multiple operands in a row does not work 779 if( nCount > 1 && !pParser->IsVBASupportOn() ) 780 { 781 pParser->Error( ERRCODE_BASIC_SYNTAX ); 782 bError = true; 783 } 784 } 785 return pNd; 786 } 787 788 std::unique_ptr<SbiExprNode> SbiExpression::Boolean() 789 { 790 std::unique_ptr<SbiExprNode> pNd = Like(); 791 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 792 { 793 for( ;; ) 794 { 795 SbiToken eTok = pParser->Peek(); 796 if( (eTok != AND) && (eTok != OR) && 797 (eTok != XOR) && (eTok != EQV) && 798 (eTok != IMP) && (eTok != IS) ) 799 { 800 break; 801 } 802 eTok = pParser->Next(); 803 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Like() ); 804 } 805 } 806 return pNd; 807 } 808 809 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p ) 810 { 811 if( pExpr->IsConstant() ) 812 { 813 eType = pExpr->GetType(); 814 if( pExpr->IsNumber() ) 815 { 816 nVal = pExpr->nVal; 817 } 818 else 819 { 820 nVal = 0; 821 aVal = pExpr->aStrVal; 822 } 823 } 824 else 825 { 826 // #40204 special treatment for sal_Bool-constants 827 bool bIsBool = false; 828 if( pExpr->eNodeType == SbxVARVAL ) 829 { 830 SbiSymDef* pVarDef = pExpr->GetVar(); 831 832 bool bBoolVal = false; 833 if( pVarDef->GetName().equalsIgnoreAsciiCase( "true" ) ) 834 { 835 bIsBool = true; 836 bBoolVal = true; 837 } 838 else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) ) 839 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL ) 840 { 841 bIsBool = true; 842 bBoolVal = false; 843 } 844 845 if( bIsBool ) 846 { 847 pExpr = std::make_unique<SbiExprNode>( (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER ); 848 eType = pExpr->GetType(); 849 nVal = pExpr->nVal; 850 } 851 } 852 853 if( !bIsBool ) 854 { 855 pParser->Error( ERRCODE_BASIC_SYNTAX ); 856 eType = SbxDOUBLE; 857 nVal = 0; 858 } 859 } 860 } 861 862 short SbiConstExpression::GetShortValue() 863 { 864 if( eType == SbxSTRING ) 865 { 866 SbxVariableRef refConv = new SbxVariable; 867 refConv->PutString( aVal ); 868 return refConv->GetInteger(); 869 } 870 else 871 { 872 double n = nVal; 873 if( n > 0 ) 874 { 875 n += .5; 876 } 877 else 878 { 879 n -= .5; 880 } 881 if( n > SbxMAXINT ) 882 { 883 n = SbxMAXINT; 884 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE ); 885 } 886 else if( n < SbxMININT ) 887 { 888 n = SbxMININT; 889 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE ); 890 } 891 892 return static_cast<short>(n); 893 } 894 } 895 896 897 SbiExprList::SbiExprList( ) 898 { 899 nDim = 0; 900 bError = false; 901 bBracket = false; 902 } 903 904 SbiExprList::~SbiExprList() {} 905 906 SbiExpression* SbiExprList::Get( size_t n ) 907 { 908 return aData[n].get(); 909 } 910 911 void SbiExprList::addExpression( std::unique_ptr<SbiExpression>&& pExpr ) 912 { 913 aData.push_back(std::move(pExpr)); 914 } 915 916 // the parameter list is completely parsed 917 // "procedurename()" is OK 918 // it's a function without parameters then 919 // i. e. you give an array as procedure parameter 920 921 // #i79918/#i80532: bConst has never been set to true 922 // -> reused as bStandaloneExpression 923 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) : 924 SbiExprListPtr SbiExprList::ParseParameters( SbiParser* pParser, bool bStandaloneExpression, bool bPar) 925 { 926 auto pExprList = std::make_unique<SbiExprList>(); 927 if( !bPar ) 928 { 929 return pExprList; 930 } 931 932 SbiToken eTok = pParser->Peek(); 933 934 bool bAssumeExprLParenMode = false; 935 bool bAssumeArrayMode = false; 936 if( eTok == LPAREN ) 937 { 938 if( bStandaloneExpression ) 939 { 940 bAssumeExprLParenMode = true; 941 } 942 else 943 { 944 pExprList->bBracket = true; 945 pParser->Next(); 946 eTok = pParser->Peek(); 947 } 948 } 949 950 951 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) ) 952 { 953 if( eTok == RPAREN ) 954 { 955 pParser->Next(); 956 } 957 return pExprList; 958 } 959 // read in parameter table and lay down in correct order! 960 while( !pExprList->bError ) 961 { 962 std::unique_ptr<SbiExpression> pExpr; 963 // missing argument 964 if( eTok == COMMA ) 965 { 966 pExpr = std::make_unique<SbiExpression>( pParser, 0, SbxEMPTY ); 967 } 968 // named arguments: either .name= or name:= 969 else 970 { 971 bool bByVal = false; 972 if( eTok == BYVAL ) 973 { 974 bByVal = true; 975 pParser->Next(); 976 eTok = pParser->Peek(); 977 } 978 979 if( bAssumeExprLParenMode ) 980 { 981 pExpr = std::make_unique<SbiExpression>( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING ); 982 bAssumeExprLParenMode = false; 983 984 SbiExprMode eModeAfter = pExpr->m_eMode; 985 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED ) 986 { 987 pExprList->bBracket = true; 988 } 989 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT ) 990 { 991 // Expression "looks" like an array assignment 992 // a(...)[(...)] = ? or a(...).b(...) 993 // RPAREN is already parsed 994 pExprList->bBracket = true; 995 bAssumeArrayMode = true; 996 eTok = NIL; 997 } 998 else if( eModeAfter == EXPRMODE_EMPTY_PAREN ) 999 { 1000 pExprList->bBracket = true; 1001 return pExprList; 1002 } 1003 } 1004 else 1005 { 1006 pExpr = std::make_unique<SbiExpression>( pParser ); 1007 } 1008 if( bByVal && pExpr->IsLvalue() ) 1009 { 1010 pExpr->SetByVal(); 1011 } 1012 if( !bAssumeArrayMode ) 1013 { 1014 OUString aName; 1015 if( pParser->Peek() == ASSIGN ) 1016 { 1017 // VBA mode: name:= 1018 // SbiExpression::Term() has made as string out of it 1019 aName = pExpr->GetString(); 1020 pParser->Next(); 1021 pExpr = std::make_unique<SbiExpression>( pParser ); 1022 } 1023 pExpr->GetName() = aName; 1024 } 1025 } 1026 pExprList->bError = pExprList->bError || !pExpr->IsValid(); 1027 pExprList->aData.push_back(std::move(pExpr)); 1028 if( bAssumeArrayMode ) 1029 { 1030 break; 1031 } 1032 // next element? 1033 eTok = pParser->Peek(); 1034 if( eTok != COMMA ) 1035 { 1036 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) ) 1037 { 1038 // tdf#80731 1039 if (SbiTokenizer::IsEoln(eTok) && pExprList->bBracket) 1040 { 1041 // tdf#106529: only fail here in strict mode (i.e. when compiled from IDE), and 1042 // allow legacy code with missing closing parenthesis when started e.g. from 1043 // extensions and event handlers 1044 bool bCheckStrict = false; 1045 if (auto xContext = css::uno::getCurrentContext()) 1046 xContext->getValueByName("BasicStrict") >>= bCheckStrict; 1047 if (bCheckStrict) 1048 { 1049 pParser->Error(ERRCODE_BASIC_EXPECTED, RPAREN); 1050 pExprList->bError = true; 1051 } 1052 } 1053 break; 1054 } 1055 pParser->Error( pExprList->bBracket ? ERRCODE_BASIC_BAD_BRACKETS : ERRCODE_BASIC_EXPECTED, COMMA ); 1056 pExprList->bError = true; 1057 } 1058 else 1059 { 1060 pParser->Next(); 1061 eTok = pParser->Peek(); 1062 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) ) 1063 { 1064 break; 1065 } 1066 } 1067 } 1068 // closing bracket 1069 if( eTok == RPAREN ) 1070 { 1071 pParser->Next(); 1072 pParser->Peek(); 1073 if( !pExprList->bBracket ) 1074 { 1075 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS ); 1076 pExprList->bError = true; 1077 } 1078 } 1079 pExprList->nDim = pExprList->GetSize(); 1080 return pExprList; 1081 } 1082 1083 // A list of array dimensions is parsed. 1084 1085 SbiExprListPtr SbiExprList::ParseDimList( SbiParser* pParser ) 1086 { 1087 auto pExprList = std::make_unique<SbiExprList>(); 1088 1089 if( pParser->Next() != LPAREN ) 1090 { 1091 pParser->Error( ERRCODE_BASIC_EXPECTED, LPAREN ); 1092 pExprList->bError = true; return pExprList; 1093 } 1094 1095 if( pParser->Peek() != RPAREN ) 1096 { 1097 SbiToken eTok; 1098 for( ;; ) 1099 { 1100 auto pExpr1 = std::make_unique<SbiExpression>( pParser ); 1101 eTok = pParser->Next(); 1102 if( eTok == TO ) 1103 { 1104 auto pExpr2 = std::make_unique<SbiExpression>( pParser ); 1105 pExpr1->ConvertToIntConstIfPossible(); 1106 pExpr2->ConvertToIntConstIfPossible(); 1107 eTok = pParser->Next(); 1108 pExprList->bError = pExprList->bError || !pExpr1->IsValid() || !pExpr2->IsValid(); 1109 pExprList->aData.push_back(std::move(pExpr1)); 1110 pExprList->aData.push_back(std::move(pExpr2)); 1111 } 1112 else 1113 { 1114 pExpr1->SetBased(); 1115 pExpr1->ConvertToIntConstIfPossible(); 1116 pExprList->bError = pExprList->bError || !pExpr1->IsValid(); 1117 pExprList->aData.push_back(std::move(pExpr1)); 1118 } 1119 pExprList->nDim++; 1120 if( eTok == RPAREN ) break; 1121 if( eTok != COMMA ) 1122 { 1123 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS ); 1124 pParser->Next(); 1125 break; 1126 } 1127 } 1128 } 1129 else pParser->Next(); 1130 return pExprList; 1131 } 1132 1133 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1134
