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