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