1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_basic.hxx" 26 27 #include "sbcomp.hxx" 28 #include <basic/sbx.hxx> // w.g. ...IMPL_REF(...sbxvariable) 29 #include "expr.hxx" 30 31 /*************************************************************************** 32 |* 33 |* SbiExpression 34 |* 35 ***************************************************************************/ 36 37 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t, 38 SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo ) 39 { 40 pParser = p; 41 bError = bByVal = bBased = bBracket = sal_False; 42 nParenLevel = 0; 43 eCurExpr = t; 44 m_eMode = eMode; 45 pNext = NULL; 46 pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean(); 47 if( t != SbSYMBOL ) 48 pExpr->Optimize(); 49 if( t == SbLVALUE && !pExpr->IsLvalue() ) 50 p->Error( SbERR_LVALUE_EXPECTED ); 51 if( t == SbOPERAND && !IsVariable() ) 52 p->Error( SbERR_VAR_EXPECTED ); 53 } 54 55 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t ) 56 { 57 pParser = p; 58 eCurExpr = SbOPERAND; 59 pNext = NULL; 60 bError = bByVal = bBased = bBracket = sal_False; 61 pExpr = new SbiExprNode( pParser, n, t ); 62 pExpr->Optimize(); 63 } 64 65 SbiExpression::SbiExpression( SbiParser* p, const String& r ) 66 { 67 pParser = p; 68 pNext = NULL; 69 bError = bByVal = bBased = bBracket = sal_False; 70 eCurExpr = SbOPERAND; 71 pExpr = new SbiExprNode( pParser, r ); 72 } 73 74 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar ) 75 { 76 pParser = p; 77 pNext = NULL; 78 bError = bByVal = bBased = bBracket = sal_False; 79 eCurExpr = SbOPERAND; 80 pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar ); 81 } 82 83 SbiExpression::SbiExpression( SbiParser* p, SbiToken t ) 84 { 85 pParser = p; 86 pNext = NULL; 87 bError = bByVal = bBased = bBracket = sal_False; 88 eCurExpr = SbOPERAND; 89 pExpr = new SbiExprNode( pParser, NULL, t, NULL ); 90 } 91 92 SbiExpression::~SbiExpression() 93 { 94 delete pExpr; 95 } 96 97 // Einlesen eines kompletten Bezeichners 98 // Ein Bezeichner hat folgende Form: 99 // name[(Parameter)][.Name[(parameter)]]... 100 // Strukturelemente werden ueber das Element pNext verkoppelt, 101 // damit sie nicht im Baum stehen. 102 103 // Folgen Parameter ohne Klammer? Dies kann eine Zahl, ein String, 104 // ein Symbol oder auch ein Komma sein (wenn der 1. Parameter fehlt) 105 106 static sal_Bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok ) 107 { 108 if( eTok == LPAREN ) 109 return sal_True; 110 // Aber nur, wenn CALL-aehnlich! 111 if( !p->WhiteSpace() || eCurExpr != SbSYMBOL ) 112 return sal_False; 113 if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING 114 || eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL ) 115 { 116 return sal_True; 117 } 118 else // check for default params with reserved names ( e.g. names of tokens ) 119 { 120 SbiTokenizer tokens( *(SbiTokenizer*)p ); 121 // Urk the Next() / Peek() symantics are... weird 122 tokens.Next(); 123 if ( tokens.Peek() == ASSIGN ) 124 return sal_True; 125 } 126 return sal_False; 127 } 128 129 // Definition eines neuen Symbols 130 131 static SbiSymDef* AddSym 132 ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr, 133 const String& rName, SbxDataType eType, SbiParameters* pPar ) 134 { 135 SbiSymDef* pDef; 136 // A= ist keine Prozedur 137 sal_Bool bHasType = sal_Bool( eTok == EQ || eTok == DOT ); 138 if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar ) 139 { 140 // Dies ist also eine Prozedur 141 // da suche man doch den richtigen Pool raus, da Procs 142 // immer in einem Public-Pool landen muessen 143 SbiSymPool* pPool = &rPool; 144 if( pPool->GetScope() != SbPUBLIC ) 145 pPool = &rPool.GetParser()->aPublics; 146 SbiProcDef* pProc = pPool->AddProc( rName ); 147 148 // Sonderbehandlung fuer Colls wie Documents(1) 149 if( eCurExpr == SbSTDEXPR ) 150 bHasType = sal_True; 151 152 pDef = pProc; 153 pDef->SetType( bHasType ? eType : SbxEMPTY ); 154 if( pPar ) 155 { 156 // Dummy-Parameter generieren 157 sal_uInt16 n = 1; 158 for( short i = 0; i < pPar->GetSize(); i++ ) 159 { 160 String aPar = String::CreateFromAscii( "PAR" ); 161 aPar += ++n; 162 pProc->GetParams().AddSym( aPar ); 163 } 164 } 165 } 166 else 167 { 168 // oder ein normales Symbol 169 pDef = rPool.AddSym( rName ); 170 pDef->SetType( eType ); 171 } 172 return pDef; 173 } 174 175 // Zur Zeit sind sogar Keywords zugelassen (wg. gleichnamiger Dflt-Properties) 176 177 SbiExprNode* SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo ) 178 { 179 if( pParser->Peek() == DOT ) 180 { 181 // eine WITH-Variable 182 SbiExprNode* pWithVar = pParser->GetWithVar(); 183 // #26608: Ans Ende der Node-Kette gehen, um richtiges Objekt zu uebergeben 184 SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL; 185 SbiExprNode* pNd = NULL; 186 if( !pDef ) 187 { 188 pParser->Next(); 189 } 190 else 191 { 192 pNd = ObjTerm( *pDef ); 193 if( pNd ) 194 pNd->SetWithParent( pWithVar ); 195 } 196 if( !pNd ) 197 { 198 pParser->Error( SbERR_UNEXPECTED, DOT ); 199 pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE ); 200 } 201 return pNd; 202 } 203 204 SbiToken eTok = (pKeywordSymbolInfo == NULL) ? pParser->Next() : pKeywordSymbolInfo->m_eTok; 205 // Anfang des Parsings merken 206 pParser->LockColumn(); 207 String aSym( (pKeywordSymbolInfo == NULL) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol ); 208 SbxDataType eType = (pKeywordSymbolInfo == NULL) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType; 209 SbiParameters* pPar = NULL; 210 SbiExprListVector* pvMoreParLcl = NULL; 211 // Folgen Parameter? 212 SbiToken eNextTok = pParser->Peek(); 213 // Ist es ein benannter Parameter? 214 // Dann einfach eine Stringkonstante erzeugen. Diese wird 215 // im SbiParameters-ctor erkannt und weiterverarbeitet 216 if( eNextTok == ASSIGN ) 217 { 218 pParser->UnlockColumn(); 219 return new SbiExprNode( pParser, aSym ); 220 } 221 // ab hier sind keine Keywords zugelassen! 222 if( pParser->IsKwd( eTok ) ) 223 { 224 if( pParser->IsCompatible() && eTok == INPUT ) 225 { 226 eTok = SYMBOL; 227 } 228 else 229 { 230 pParser->Error( SbERR_SYNTAX ); 231 bError = sal_True; 232 } 233 } 234 235 if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) ) 236 { 237 bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE); 238 pPar = new SbiParameters( pParser, bStandaloneExpression ); 239 bError |= !pPar->IsValid(); 240 if( !bError ) 241 bBracket = pPar->IsBracket(); 242 eTok = pParser->Peek(); 243 244 // i75443 check for additional sets of parameters 245 while( eTok == LPAREN ) 246 { 247 if( pvMoreParLcl == NULL ) 248 pvMoreParLcl = new SbiExprListVector(); 249 SbiParameters* pAddPar = new SbiParameters( pParser ); 250 pvMoreParLcl->push_back( pAddPar ); 251 bError |= !pPar->IsValid(); 252 eTok = pParser->Peek(); 253 } 254 } 255 // Es koennte ein Objektteil sein, wenn . oder ! folgt 256 // Bei . muss aber die Variable bereits definiert sein; wenn pDef 257 // nach der Suche NULL ist, isses ein Objekt! 258 sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM ) 259 && !pParser->WhiteSpace() ); 260 if( bObj ) 261 { 262 bBracket = sal_False; // Now the bracket for the first term is obsolete 263 if( eType == SbxVARIANT ) 264 eType = SbxOBJECT; 265 else 266 { 267 // Name%. geht wirklich nicht! 268 pParser->Error( SbERR_BAD_DECLARATION, aSym ); 269 bError = sal_True; 270 } 271 } 272 // Suche: 273 SbiSymDef* pDef = pParser->pPool->Find( aSym ); 274 if( !pDef ) 275 { 276 // Teil der Runtime-Library? 277 // AB 31.3.1996: In Parser-Methode ausgelagert 278 // (wird auch in SbiParser::DefVar() in DIM.CXX benoetigt) 279 pDef = pParser->CheckRTLForSym( aSym, eType ); 280 281 // #i109184: Check if symbol is or later will be defined inside module 282 SbModule& rMod = pParser->aGen.GetModule(); 283 SbxArray* pModMethods = rMod.GetMethods(); 284 if( pModMethods->Find( aSym, SbxCLASS_DONTCARE ) ) 285 pDef = NULL; 286 } 287 if( !pDef ) 288 { 289 // Falls ein Punkt angegeben war, isses Teil eines Objekts, 290 // also muss der Returnwert ein Objekt sein 291 if( bObj ) 292 eType = SbxOBJECT; 293 pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar ); 294 // Looks like this is a local ( but undefined variable ) 295 // if it is in a static procedure then make this Symbol 296 // static 297 if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() ) 298 pDef->SetStatic(); 299 } 300 else 301 { 302 303 // Symbol ist bereits definiert. 304 // Ist es eine Konstante? 305 SbiConstDef* pConst = pDef->GetConstDef(); 306 if( pConst ) 307 { 308 if( pConst->GetType() == SbxSTRING ) 309 return new SbiExprNode( pParser, pConst->GetString() ); 310 else 311 return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() ); 312 } 313 // Hat es Dimensionen, 314 // und sind auch Parameter angegeben? 315 // (Wobei 0 Parameter () entsprechen) 316 if( pDef->GetDims() ) 317 { 318 if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() ) 319 pParser->Error( SbERR_WRONG_DIMS ); 320 } 321 if( pDef->IsDefinedAs() ) 322 { 323 SbxDataType eDefType = pDef->GetType(); 324 // #119187 Only error if types conflict 325 if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType ) 326 { 327 // Wie? Erst mit AS definieren und dann einen Suffix nehmen? 328 pParser->Error( SbERR_BAD_DECLARATION, aSym ); 329 bError = sal_True; 330 } 331 else if ( eType == SbxVARIANT ) 332 // Falls nix angegeben, den Typ des Eintrags nehmen 333 // aber nur, wenn die Var nicht mit AS XXX definiert ist 334 // damit erwischen wir n% = 5 : print n 335 eType = eDefType; 336 } 337 // Typcheck bei Variablen: 338 // ist explizit im Scanner etwas anderes angegeben? 339 // Bei Methoden ist dies OK! 340 if( eType != SbxVARIANT && // Variant nimmt alles 341 eType != pDef->GetType() && 342 !pDef->GetProcDef() ) 343 { 344 // Es kann sein, dass pDef ein Objekt beschreibt, das bisher 345 // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern 346 // AB, 16.12.95 (Vielleicht noch aehnliche Faelle moeglich ?!?) 347 if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT ) 348 { 349 pDef->SetType( SbxOBJECT ); 350 } 351 else 352 { 353 pParser->Error( SbERR_BAD_DECLARATION, aSym ); 354 bError = sal_True; 355 } 356 } 357 } 358 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType ); 359 if( !pPar ) 360 pPar = new SbiParameters( pParser,sal_False,sal_False ); 361 pNd->aVar.pPar = pPar; 362 pNd->aVar.pvMorePar = pvMoreParLcl; 363 if( bObj ) 364 { 365 // AB, 8.1.95: Objekt kann auch vom Typ SbxVARIANT sein 366 if( pDef->GetType() == SbxVARIANT ) 367 pDef->SetType( SbxOBJECT ); 368 // Falls wir etwas mit Punkt einscannen, muss der 369 // Typ SbxOBJECT sein 370 if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT ) 371 { 372 pParser->Error( SbERR_BAD_DECLARATION, aSym ); 373 bError = sal_True; 374 } 375 if( !bError ) 376 pNd->aVar.pNext = ObjTerm( *pDef ); 377 } 378 // Merken der Spalte 1 wieder freigeben 379 pParser->UnlockColumn(); 380 return pNd; 381 } 382 383 // Aufbau eines Objekt-Terms. Ein derartiger Term ist Teil 384 // eines Ausdrucks, der mit einer Objektvariablen beginnt. 385 386 SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj ) 387 { 388 pParser->Next(); 389 SbiToken eTok = pParser->Next(); 390 if( eTok != SYMBOL && !pParser->IsKwd( eTok ) && !pParser->IsExtra( eTok ) ) 391 { 392 // #66745 Einige Operatoren koennen in diesem Kontext auch 393 // als Identifier zugelassen werden, wichtig fuer StarOne 394 if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR && 395 eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS ) 396 { 397 pParser->Error( SbERR_VAR_EXPECTED ); 398 bError = sal_True; 399 } 400 } 401 /* #118410 Allow type for Class methods and RTL object, e.g. RTL.Chr$(97) 402 else 403 { 404 if( pParser->GetType() != SbxVARIANT ) 405 pParser->Error( SbERR_SYNTAX ), bError = sal_True; 406 } 407 */ 408 if( bError ) 409 return NULL; 410 411 String aSym( pParser->GetSym() ); 412 SbxDataType eType = pParser->GetType(); 413 SbiParameters* pPar = NULL; 414 SbiExprListVector* pvMoreParLcl = NULL; 415 eTok = pParser->Peek(); 416 // Parameter? 417 if( DoParametersFollow( pParser, eCurExpr, eTok ) ) 418 { 419 bool bStandaloneExpression = false; 420 pPar = new SbiParameters( pParser, bStandaloneExpression ); 421 bError |= !pPar->IsValid(); 422 eTok = pParser->Peek(); 423 424 // i109624 check for additional sets of parameters 425 while( eTok == LPAREN ) 426 { 427 if( pvMoreParLcl == NULL ) 428 pvMoreParLcl = new SbiExprListVector(); 429 SbiParameters* pAddPar = new SbiParameters( pParser ); 430 pvMoreParLcl->push_back( pAddPar ); 431 bError |= !pPar->IsValid(); 432 eTok = pParser->Peek(); 433 } 434 435 } 436 sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() ); 437 if( bObj ) 438 { 439 if( eType == SbxVARIANT ) 440 eType = SbxOBJECT; 441 else 442 { 443 // Name%. geht wirklich nicht! 444 pParser->Error( SbERR_BAD_DECLARATION, aSym ); 445 bError = sal_True; 446 } 447 } 448 449 // Der Symbol-Pool eines Objekts ist immer PUBLIC 450 SbiSymPool& rPool = rObj.GetPool(); 451 rPool.SetScope( SbPUBLIC ); 452 SbiSymDef* pDef = rPool.Find( aSym ); 453 if( !pDef ) 454 { 455 pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar ); 456 pDef->SetType( eType ); 457 } 458 459 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType ); 460 pNd->aVar.pPar = pPar; 461 pNd->aVar.pvMorePar = pvMoreParLcl; 462 if( bObj ) 463 { 464 // Falls wir etwas mit Punkt einscannen, muss der 465 // Typ SbxOBJECT sein 466 467 // AB, 3.1.96 468 // Es kann sein, dass pDef ein Objekt beschreibt, das bisher 469 // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern 470 if( pDef->GetType() == SbxVARIANT ) 471 pDef->SetType( SbxOBJECT ); 472 473 if( pDef->GetType() != SbxOBJECT ) 474 { 475 pParser->Error( SbERR_BAD_DECLARATION, aSym ); 476 bError = sal_True; 477 } 478 if( !bError ) 479 { 480 pNd->aVar.pNext = ObjTerm( *pDef ); 481 pNd->eType = eType; 482 } 483 } 484 return pNd; 485 } 486 487 // Als Operanden kommen in Betracht: 488 // Konstante 489 // skalare Variable 490 // Strukturelemente 491 // Array-Elemente 492 // Funktionen 493 // geklammerte Ausdruecke 494 495 SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf ) 496 { 497 SbiExprNode *pRes; 498 SbiToken eTok; 499 500 // Operand testen: 501 switch( eTok = pParser->Peek() ) 502 { 503 case SYMBOL: 504 pRes = Term(); 505 // process something like "IF Not r Is Nothing Then .." 506 if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS ) 507 { 508 eTok = pParser->Next(); 509 pRes = new SbiExprNode( pParser, pRes, eTok, Like() ); 510 } 511 break; 512 case DOT: // .with 513 pRes = Term(); break; 514 case NUMBER: 515 pParser->Next(); 516 pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() ); 517 break; 518 case FIXSTRING: 519 pParser->Next(); 520 pRes = new SbiExprNode( pParser, pParser->GetSym() ); break; 521 case LPAREN: 522 pParser->Next(); 523 if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN ) 524 { 525 m_eMode = EXPRMODE_EMPTY_PAREN; 526 pRes = new SbiExprNode(); // Dummy node 527 pParser->Next(); 528 break; 529 } 530 nParenLevel++; 531 pRes = Boolean(); 532 if( pParser->Peek() != RPAREN ) 533 { 534 // If there was a LPARAM, it does not belong to the expression 535 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING ) 536 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED; 537 else 538 pParser->Error( SbERR_BAD_BRACKETS ); 539 } 540 else 541 { 542 pParser->Next(); 543 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING ) 544 { 545 SbiToken eTokAfterRParen = pParser->Peek(); 546 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT ) 547 m_eMode = EXPRMODE_ARRAY_OR_OBJECT; 548 else 549 m_eMode = EXPRMODE_STANDARD; 550 } 551 } 552 nParenLevel--; 553 pRes->bComposite = sal_True; 554 break; 555 default: 556 // Zur Zeit sind Keywords hier OK! 557 if( pParser->IsKwd( eTok ) ) 558 pRes = Term(); 559 else 560 { 561 pParser->Next(); 562 pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE ); // bei Fehlern 563 pParser->Error( SbERR_UNEXPECTED, eTok ); 564 } 565 } 566 return pRes; 567 } 568 569 SbiExprNode* SbiExpression::Unary() 570 { 571 SbiExprNode* pNd; 572 SbiToken eTok = pParser->Peek(); 573 switch( eTok ) 574 { 575 case MINUS: 576 eTok = NEG; 577 pParser->Next(); 578 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL ); 579 break; 580 case NOT: 581 if( pParser->IsVBASupportOn() ) 582 { 583 pNd = Operand(); 584 } 585 else 586 { 587 pParser->Next(); 588 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL ); 589 } 590 break; 591 case PLUS: 592 pParser->Next(); 593 pNd = Unary(); 594 break; 595 case TYPEOF: 596 { 597 pParser->Next(); 598 bool bUsedForTypeOf = true; 599 SbiExprNode* pObjNode = Operand( bUsedForTypeOf ); 600 pParser->TestToken( IS ); 601 String aDummy; 602 SbiSymDef* pTypeDef = new SbiSymDef( aDummy ); 603 pParser->TypeDecl( *pTypeDef, sal_True ); 604 pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() ); 605 break; 606 } 607 case NEW: 608 { 609 pParser->Next(); 610 String aStr; 611 SbiSymDef* pTypeDef = new SbiSymDef( aStr ); 612 pParser->TypeDecl( *pTypeDef, sal_True ); 613 pNd = new SbiExprNode( pParser, pTypeDef->GetTypeId() ); 614 break; 615 } 616 default: 617 pNd = Operand(); 618 } 619 return pNd; 620 } 621 622 SbiExprNode* SbiExpression::Exp() 623 { 624 SbiExprNode* pNd = Unary(); 625 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 626 { 627 while( pParser->Peek() == EXPON ) { 628 SbiToken eTok = pParser->Next(); 629 pNd = new SbiExprNode( pParser, pNd, eTok, Unary() ); 630 } 631 } 632 return pNd; 633 } 634 635 SbiExprNode* SbiExpression::MulDiv() 636 { 637 SbiExprNode* pNd = Exp(); 638 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 639 { 640 for( ;; ) 641 { 642 SbiToken eTok = pParser->Peek(); 643 if( eTok != MUL && eTok != DIV ) 644 break; 645 eTok = pParser->Next(); 646 pNd = new SbiExprNode( pParser, pNd, eTok, Exp() ); 647 } 648 } 649 return pNd; 650 } 651 652 SbiExprNode* SbiExpression::IntDiv() 653 { 654 SbiExprNode* pNd = MulDiv(); 655 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 656 { 657 while( pParser->Peek() == IDIV ) { 658 SbiToken eTok = pParser->Next(); 659 pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() ); 660 } 661 } 662 return pNd; 663 } 664 665 SbiExprNode* SbiExpression::Mod() 666 { 667 SbiExprNode* pNd = IntDiv(); 668 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 669 { 670 while( pParser->Peek() == MOD ) { 671 SbiToken eTok = pParser->Next(); 672 pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() ); 673 } 674 } 675 return pNd; 676 } 677 678 SbiExprNode* SbiExpression::AddSub() 679 { 680 SbiExprNode* pNd = Mod(); 681 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 682 { 683 for( ;; ) 684 { 685 SbiToken eTok = pParser->Peek(); 686 if( eTok != PLUS && eTok != MINUS ) 687 break; 688 eTok = pParser->Next(); 689 pNd = new SbiExprNode( pParser, pNd, eTok, Mod() ); 690 } 691 } 692 return pNd; 693 } 694 695 SbiExprNode* SbiExpression::Cat() 696 { 697 SbiExprNode* pNd = AddSub(); 698 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 699 { 700 for( ;; ) 701 { 702 SbiToken eTok = pParser->Peek(); 703 if( eTok != CAT ) 704 break; 705 eTok = pParser->Next(); 706 pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() ); 707 } 708 } 709 return pNd; 710 } 711 712 SbiExprNode* SbiExpression::Comp() 713 { 714 SbiExprNode* pNd = Cat(); 715 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 716 { 717 short nCount = 0; 718 for( ;; ) 719 { 720 SbiToken eTok = pParser->Peek(); 721 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT ) 722 break; 723 if( eTok != EQ && eTok != NE && eTok != LT 724 && eTok != GT && eTok != LE && eTok != GE ) 725 break; 726 eTok = pParser->Next(); 727 pNd = new SbiExprNode( pParser, pNd, eTok, Cat() ); 728 nCount++; 729 } 730 } 731 return pNd; 732 } 733 734 SbiExprNode* SbiExpression::VBA_Not() 735 { 736 SbiExprNode* pNd = NULL; 737 738 SbiToken eTok = pParser->Peek(); 739 if( eTok == NOT ) 740 { 741 pParser->Next(); 742 pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL ); 743 } 744 else 745 { 746 pNd = Comp(); 747 } 748 return pNd; 749 } 750 751 SbiExprNode* SbiExpression::Like() 752 { 753 SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp(); 754 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 755 { 756 short nCount = 0; 757 while( pParser->Peek() == LIKE ) { 758 SbiToken eTok = pParser->Next(); 759 pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++; 760 } 761 // Mehrere Operatoren hintereinander gehen nicht 762 if( nCount > 1 ) 763 { 764 pParser->Error( SbERR_SYNTAX ); 765 bError = sal_True; 766 } 767 } 768 return pNd; 769 } 770 771 SbiExprNode* SbiExpression::Boolean() 772 { 773 SbiExprNode* pNd = Like(); 774 if( m_eMode != EXPRMODE_EMPTY_PAREN ) 775 { 776 for( ;; ) 777 { 778 SbiToken eTok = pParser->Peek(); 779 if( eTok != AND && eTok != OR && eTok != XOR 780 && eTok != EQV && eTok != IMP && eTok != IS ) 781 break; 782 eTok = pParser->Next(); 783 pNd = new SbiExprNode( pParser, pNd, eTok, Like() ); 784 } 785 } 786 return pNd; 787 } 788 789 /*************************************************************************** 790 |* 791 |* SbiConstExpression 792 |* 793 ***************************************************************************/ 794 795 // Parsing einer Expression, die sich zu einer numerischen 796 // Konstanten verarbeiten laesst. 797 798 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p ) 799 { 800 if( pExpr->IsConstant() ) 801 { 802 eType = pExpr->GetType(); 803 if( pExpr->IsNumber() ) 804 { 805 nVal = pExpr->nVal; 806 } 807 else 808 { 809 nVal = 0; 810 aVal = pExpr->aStrVal; 811 } 812 } 813 else 814 { 815 // #40204 Spezialbehandlung fuer sal_Bool-Konstanten 816 sal_Bool bIsBool = sal_False; 817 if( pExpr->eNodeType == SbxVARVAL ) 818 { 819 SbiSymDef* pVarDef = pExpr->GetVar(); 820 821 // Ist es eine sal_Bool-Konstante? 822 sal_Bool bBoolVal = sal_False; 823 if( pVarDef->GetName().EqualsIgnoreCaseAscii( "true" ) ) 824 //if( pVarDef->GetName().ICompare( "true" ) == COMPARE_EQUAL ) 825 { 826 bIsBool = sal_True; 827 bBoolVal = sal_True; 828 } 829 else if( pVarDef->GetName().EqualsIgnoreCaseAscii( "false" ) ) 830 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL ) 831 { 832 bIsBool = sal_True; 833 bBoolVal = sal_False; 834 } 835 836 // Wenn es ein sal_Bool ist, Node austauschen 837 if( bIsBool ) 838 { 839 delete pExpr; 840 pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER ); 841 eType = pExpr->GetType(); 842 nVal = pExpr->nVal; 843 } 844 } 845 846 if( !bIsBool ) 847 { 848 pParser->Error( SbERR_SYNTAX ); 849 eType = SbxDOUBLE; 850 nVal = 0; 851 } 852 } 853 } 854 855 short SbiConstExpression::GetShortValue() 856 { 857 if( eType == SbxSTRING ) 858 { 859 SbxVariableRef refConv = new SbxVariable; 860 refConv->PutString( aVal ); 861 return refConv->GetInteger(); 862 } 863 else 864 { 865 double n = nVal; 866 if( n > 0 ) n += .5; else n -= .5; 867 if( n > SbxMAXINT ) n = SbxMAXINT, pParser->Error( SbERR_OUT_OF_RANGE ); 868 else 869 if( n < SbxMININT ) n = SbxMININT, pParser->Error( SbERR_OUT_OF_RANGE ); 870 return (short) n; 871 } 872 } 873 874 875 /*************************************************************************** 876 |* 877 |* SbiExprList 878 |* 879 ***************************************************************************/ 880 881 SbiExprList::SbiExprList( SbiParser* p ) 882 { 883 pParser = p; 884 pFirst = NULL; 885 nExpr = 886 nDim = 0; 887 bError = 888 bBracket = sal_False; 889 } 890 891 SbiExprList::~SbiExprList() 892 { 893 SbiExpression* p = pFirst; 894 while( p ) 895 { 896 SbiExpression* q = p->pNext; 897 delete p; 898 p = q; 899 } 900 } 901 902 // Parameter anfordern (ab 0) 903 904 SbiExpression* SbiExprList::Get( short n ) 905 { 906 SbiExpression* p = pFirst; 907 while( n-- && p ) 908 p = p->pNext; 909 return p; 910 } 911 912 void SbiExprList::addExpression( SbiExpression* pExpr ) 913 { 914 SbiExpression* p = pFirst; 915 while( p && p->pNext ) 916 p = p->pNext; 917 918 p->pNext = pExpr; 919 } 920 921 922 /*************************************************************************** 923 |* 924 |* SbiParameters 925 |* 926 ***************************************************************************/ 927 928 // Parsender Konstruktor: 929 // Die Parameterliste wird komplett geparst. 930 // "Prozedurname()" ist OK. 931 // Dann handelt es sich um eine Funktion ohne Parameter 932 // respektive um die Angabe eines Arrays als Prozedurparameter. 933 934 // #i79918/#i80532: bConst has never been set to true 935 // -> reused as bStandaloneExpression 936 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) : 937 SbiParameters::SbiParameters( SbiParser* p, sal_Bool bStandaloneExpression, sal_Bool bPar) : 938 SbiExprList( p ) 939 { 940 if( !bPar ) 941 return; 942 943 SbiExpression *pExpr; 944 SbiToken eTok = pParser->Peek(); 945 946 // evtl. Klammer auf weg: 947 bool bAssumeExprLParenMode = false; 948 bool bAssumeArrayMode = false; 949 if( eTok == LPAREN ) 950 { 951 if( bStandaloneExpression ) 952 { 953 bAssumeExprLParenMode = true; 954 } 955 else 956 { 957 bBracket = sal_True; 958 pParser->Next(); 959 eTok = pParser->Peek(); 960 } 961 } 962 963 // Ende-Test 964 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) ) 965 { 966 if( eTok == RPAREN ) 967 pParser->Next(); 968 return; 969 } 970 // Parametertabelle einlesen und in richtiger Folge ablegen! 971 SbiExpression* pLast = NULL; 972 String aName; 973 while( !bError ) 974 { 975 aName.Erase(); 976 // Fehlendes Argument 977 if( eTok == COMMA ) 978 { 979 pExpr = new SbiExpression( pParser, 0, SbxEMPTY ); 980 //if( bConst ) 981 // pParser->Error( SbERR_SYNTAX ), bError = sal_True; 982 } 983 // Benannte Argumente: entweder .name= oder name:= 984 else 985 { 986 bool bByVal = false; 987 if( eTok == BYVAL ) 988 { 989 bByVal = true; 990 pParser->Next(); 991 eTok = pParser->Peek(); 992 } 993 994 if( bAssumeExprLParenMode ) 995 { 996 pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING ); 997 bAssumeExprLParenMode = sal_False; 998 999 SbiExprMode eModeAfter = pExpr->m_eMode; 1000 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED ) 1001 { 1002 bBracket = sal_True; 1003 } 1004 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT ) 1005 { 1006 // Expression "looks" like an array assignment 1007 // a(...)[(...)] = ? or a(...).b(...) 1008 // RPAREN is already parsed 1009 bBracket = sal_True; 1010 bAssumeArrayMode = true; 1011 eTok = NIL; 1012 } 1013 else if( eModeAfter == EXPRMODE_EMPTY_PAREN ) 1014 { 1015 bBracket = sal_True; 1016 delete pExpr; 1017 if( bByVal ) 1018 pParser->Error( SbERR_LVALUE_EXPECTED ); 1019 return; 1020 } 1021 } 1022 else 1023 pExpr = new SbiExpression( pParser ); 1024 1025 if( bByVal && pExpr->IsLvalue() ) 1026 pExpr->SetByVal(); 1027 1028 //pExpr = bConst ? new SbiConstExpression( pParser ) 1029 // : new SbiExpression( pParser ); 1030 if( !bAssumeArrayMode ) 1031 { 1032 if( pParser->Peek() == ASSIGN ) 1033 { 1034 // VBA mode: name:= 1035 // SbiExpression::Term() hat einen String daraus gemacht 1036 aName = pExpr->GetString(); 1037 delete pExpr; 1038 pParser->Next(); 1039 pExpr = new SbiExpression( pParser ); 1040 //if( bConst ) 1041 // pParser->Error( SbERR_SYNTAX ), bError = sal_True; 1042 } 1043 pExpr->GetName() = aName; 1044 } 1045 } 1046 pExpr->pNext = NULL; 1047 if( !pLast ) 1048 pFirst = pLast = pExpr; 1049 else 1050 pLast->pNext = pExpr, pLast = pExpr; 1051 nExpr++; 1052 bError |= !pExpr->IsValid(); 1053 1054 if( bAssumeArrayMode ) 1055 break; 1056 1057 // Naechstes Element? 1058 eTok = pParser->Peek(); 1059 if( eTok != COMMA ) 1060 { 1061 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) ) 1062 break; 1063 pParser->Error( bBracket 1064 ? SbERR_BAD_BRACKETS 1065 : SbERR_EXPECTED, COMMA ); 1066 bError = sal_True; 1067 } 1068 else 1069 { 1070 pParser->Next(); 1071 eTok = pParser->Peek(); 1072 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) ) 1073 break; 1074 } 1075 } 1076 // Schliessende Klammer 1077 if( eTok == RPAREN ) 1078 { 1079 pParser->Next(); 1080 pParser->Peek(); 1081 if( !bBracket ) 1082 { 1083 pParser->Error( SbERR_BAD_BRACKETS ); 1084 bError = sal_True; 1085 } 1086 } 1087 nDim = nExpr; 1088 } 1089 1090 /*************************************************************************** 1091 |* 1092 |* SbiDimList 1093 |* 1094 ***************************************************************************/ 1095 1096 // Parsender Konstruktor: 1097 // Eine Liste von Array-Dimensionen wird geparst. Die Ausdruecke werden 1098 // auf numerisch getestet. Das bCONST-Bit wird gesetzt, wenn alle Ausdruecke 1099 // Integer-Konstanten sind. 1100 1101 SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p ) 1102 { 1103 bConst = sal_True; 1104 1105 if( pParser->Next() != LPAREN ) 1106 { 1107 pParser->Error( SbERR_EXPECTED, LPAREN ); 1108 bError = sal_True; return; 1109 } 1110 1111 if( pParser->Peek() != RPAREN ) 1112 { 1113 SbiExpression *pExpr1, *pExpr2, *pLast = NULL; 1114 SbiToken eTok; 1115 for( ;; ) 1116 { 1117 pExpr1 = new SbiExpression( pParser ); 1118 eTok = pParser->Next(); 1119 if( eTok == TO ) 1120 { 1121 pExpr2 = new SbiExpression( pParser ); 1122 eTok = pParser->Next(); 1123 bConst &= pExpr1->IsIntConstant() & pExpr2->IsIntConstant(); 1124 bError |= !pExpr1->IsValid(); 1125 bError |= !pExpr2->IsValid(); 1126 pExpr1->pNext = pExpr2; 1127 if( !pLast ) 1128 pFirst = pExpr1; 1129 else 1130 pLast->pNext = pExpr1; 1131 pLast = pExpr2; 1132 nExpr += 2; 1133 } 1134 else 1135 { 1136 // Nur eine Dim-Angabe 1137 pExpr1->SetBased(); 1138 pExpr1->pNext = NULL; 1139 bConst &= pExpr1->IsIntConstant(); 1140 bError |= !pExpr1->IsValid(); 1141 if( !pLast ) 1142 pFirst = pLast = pExpr1; 1143 else 1144 pLast->pNext = pExpr1, pLast = pExpr1; 1145 nExpr++; 1146 } 1147 nDim++; 1148 if( eTok == RPAREN ) break; 1149 if( eTok != COMMA ) 1150 { 1151 pParser->Error( SbERR_BAD_BRACKETS ); 1152 pParser->Next(); 1153 break; 1154 } 1155 } 1156 } 1157 else pParser->Next(); 1158 } 1159 1160