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