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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_basic.hxx" 24 #include <basic/sbx.hxx> 25 #include "sbcomp.hxx" 26 #include <com/sun/star/script/ModuleType.hpp> 27 28 struct SbiParseStack { // "Stack" für Statement-Blocks 29 SbiParseStack* pNext; // Chain 30 SbiExprNode* pWithVar; // Variable für WITH 31 SbiToken eExitTok; // Exit-Token 32 sal_uInt32 nChain; // JUMP-Chain 33 }; 34 35 struct SbiStatement { 36 SbiToken eTok; 37 void( SbiParser::*Func )(); // Verarbeitungsroutine 38 sal_Bool bMain; // sal_True: ausserhalb SUBs OK 39 sal_Bool bSubr; // sal_True: in SUBs OK 40 }; 41 42 #define Y sal_True 43 #define N sal_False 44 45 static SbiStatement StmntTable [] = { 46 { CALL, &SbiParser::Call, N, Y, }, // CALL 47 { CLOSE, &SbiParser::Close, N, Y, }, // CLOSE 48 { _CONST_, &SbiParser::Dim, Y, Y, }, // CONST 49 { DECLARE, &SbiParser::Declare, Y, N, }, // DECLARE 50 { DEFBOOL, &SbiParser::DefXXX, Y, N, }, // DEFBOOL 51 { DEFCUR, &SbiParser::DefXXX, Y, N, }, // DEFCUR 52 { DEFDATE, &SbiParser::DefXXX, Y, N, }, // DEFDATE 53 { DEFDBL, &SbiParser::DefXXX, Y, N, }, // DEFDBL 54 { DEFERR, &SbiParser::DefXXX, Y, N, }, // DEFERR 55 { DEFINT, &SbiParser::DefXXX, Y, N, }, // DEFINT 56 { DEFLNG, &SbiParser::DefXXX, Y, N, }, // DEFLNG 57 { DEFOBJ, &SbiParser::DefXXX, Y, N, }, // DEFOBJ 58 { DEFSNG, &SbiParser::DefXXX, Y, N, }, // DEFSNG 59 { DEFSTR, &SbiParser::DefXXX, Y, N, }, // DEFSTR 60 { DEFVAR, &SbiParser::DefXXX, Y, N, }, // DEFVAR 61 { DIM, &SbiParser::Dim, Y, Y, }, // DIM 62 { DO, &SbiParser::DoLoop, N, Y, }, // DO 63 { ELSE, &SbiParser::NoIf, N, Y, }, // ELSE 64 { ELSEIF, &SbiParser::NoIf, N, Y, }, // ELSEIF 65 { ENDIF, &SbiParser::NoIf, N, Y, }, // ENDIF 66 { END, &SbiParser::Stop, N, Y, }, // END 67 { ENUM, &SbiParser::Enum, Y, N, }, // TYPE 68 { ERASE, &SbiParser::Erase, N, Y, }, // ERASE 69 { _ERROR_, &SbiParser::ErrorStmnt, N, Y, }, // ERROR 70 { EXIT, &SbiParser::Exit, N, Y, }, // EXIT 71 { FOR, &SbiParser::For, N, Y, }, // FOR 72 { FUNCTION, &SbiParser::SubFunc, Y, N, }, // FUNCTION 73 { GOSUB, &SbiParser::Goto, N, Y, }, // GOSUB 74 { GLOBAL, &SbiParser::Dim, Y, N, }, // GLOBAL 75 { GOTO, &SbiParser::Goto, N, Y, }, // GOTO 76 { IF, &SbiParser::If, N, Y, }, // IF 77 { IMPLEMENTS, &SbiParser::Implements, Y, N, }, // IMPLEMENTS 78 { INPUT, &SbiParser::Input, N, Y, }, // INPUT 79 { LET, &SbiParser::Assign, N, Y, }, // LET 80 { LINE, &SbiParser::Line, N, Y, }, // LINE, -> LINE INPUT (#i92642) 81 { LINEINPUT,&SbiParser::LineInput, N, Y, }, // LINE INPUT 82 { LOOP, &SbiParser::BadBlock, N, Y, }, // LOOP 83 { LSET, &SbiParser::LSet, N, Y, }, // LSET 84 { NAME, &SbiParser::Name, N, Y, }, // NAME 85 { NEXT, &SbiParser::BadBlock, N, Y, }, // NEXT 86 { ON, &SbiParser::On, N, Y, }, // ON 87 { OPEN, &SbiParser::Open, N, Y, }, // OPEN 88 { OPTION, &SbiParser::Option, Y, N, }, // OPTION 89 { PRINT, &SbiParser::Print, N, Y, }, // PRINT 90 { PRIVATE, &SbiParser::Dim, Y, N, }, // PRIVATE 91 { PROPERTY, &SbiParser::SubFunc, Y, N, }, // FUNCTION 92 { PUBLIC, &SbiParser::Dim, Y, N, }, // PUBLIC 93 { REDIM, &SbiParser::ReDim, N, Y, }, // DIM 94 { RESUME, &SbiParser::Resume, N, Y, }, // RESUME 95 { RETURN, &SbiParser::Return, N, Y, }, // RETURN 96 { RSET, &SbiParser::RSet, N, Y, }, // RSET 97 { SELECT, &SbiParser::Select, N, Y, }, // SELECT 98 { SET, &SbiParser::Set, N, Y, }, // SET 99 { STATIC, &SbiParser::Static, Y, Y, }, // STATIC 100 { STOP, &SbiParser::Stop, N, Y, }, // STOP 101 { SUB, &SbiParser::SubFunc, Y, N, }, // SUB 102 { TYPE, &SbiParser::Type, Y, N, }, // TYPE 103 { UNTIL, &SbiParser::BadBlock, N, Y, }, // UNTIL 104 { WHILE, &SbiParser::While, N, Y, }, // WHILE 105 { WEND, &SbiParser::BadBlock, N, Y, }, // WEND 106 { WITH, &SbiParser::With, N, Y, }, // WITH 107 { WRITE, &SbiParser::Write, N, Y, }, // WRITE 108 109 { NIL, NULL, N, N } 110 }; 111 112 113 #ifdef _MSC_VER 114 // 'this' : used in base member initializer list 115 #pragma warning( disable: 4355 ) 116 #endif 117 118 SbiParser::SbiParser( StarBASIC* pb, SbModule* pm ) 119 : SbiTokenizer( pm->GetSource32(), pb ), 120 aGblStrings( this ), 121 aLclStrings( this ), 122 aGlobals( aGblStrings, SbGLOBAL ), 123 aPublics( aGblStrings, SbPUBLIC ), 124 aRtlSyms( aGblStrings, SbRTL ), 125 aGen( *pm, this, 1024 ) 126 { 127 pBasic = pb; 128 eCurExpr = SbSYMBOL; 129 eEndTok = NIL; 130 pProc = NULL; 131 pStack = NULL; 132 pWithVar = NULL; 133 nBase = 0; 134 bText = 135 bGblDefs = 136 bNewGblDefs = 137 bSingleLineIf = 138 bExplicit = sal_False; 139 bClassModule = ( pm->GetModuleType() == com::sun::star::script::ModuleType::CLASS ); 140 OSL_TRACE("Parser - %s, bClassModule %d", rtl::OUStringToOString( pm->GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), bClassModule ); 141 pPool = &aPublics; 142 for( short i = 0; i < 26; i++ ) 143 eDefTypes[ i ] = SbxVARIANT; // Kein expliziter Defaulttyp 144 145 aPublics.SetParent( &aGlobals ); 146 aGlobals.SetParent( &aRtlSyms ); 147 148 // Die globale Chainkette faengt bei Adresse 0 an: 149 nGblChain = aGen.Gen( _JUMP, 0 ); 150 151 rTypeArray = new SbxArray; // Array fuer Benutzerdefinierte Typen 152 rEnumArray = new SbxArray; // Array for Enum types 153 bVBASupportOn = pm->IsVBACompat(); 154 if ( bVBASupportOn ) 155 EnableCompatibility(); 156 157 } 158 159 160 // Ist Teil der Runtime-Library? 161 SbiSymDef* SbiParser::CheckRTLForSym( const String& rSym, SbxDataType eType ) 162 { 163 SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE ); 164 SbiSymDef* pDef = NULL; 165 if( pVar ) 166 { 167 if( pVar->IsA( TYPE(SbxMethod) ) ) 168 { 169 SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym ); 170 SbxMethod* pMethod = (SbxMethod*) pVar; 171 if ( pMethod && pMethod->IsRuntimeFunction() ) 172 { 173 pProc_->SetType( pMethod->GetRuntimeFunctionReturnType() ); 174 } 175 else 176 { 177 pProc_->SetType( pVar->GetType() ); 178 } 179 pDef = pProc_; 180 } 181 else 182 { 183 pDef = aRtlSyms.AddSym( rSym ); 184 pDef->SetType( eType ); 185 } 186 } 187 return pDef; 188 } 189 190 // Globale Chainkette schliessen 191 192 sal_Bool SbiParser::HasGlobalCode() 193 { 194 if( bGblDefs && nGblChain ) 195 { 196 aGen.BackChain( nGblChain ); 197 aGen.Gen( _LEAVE ); 198 // aGen.Gen( _STOP ); 199 nGblChain = 0; 200 } 201 return bGblDefs; 202 } 203 204 void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar ) 205 { 206 SbiParseStack* p = new SbiParseStack; 207 p->eExitTok = eTok; 208 p->nChain = 0; 209 p->pWithVar = pWithVar; 210 p->pNext = pStack; 211 pStack = p; 212 pWithVar = pVar; 213 214 // #29955 for-Schleifen-Ebene pflegen 215 if( eTok == FOR ) 216 aGen.IncForLevel(); 217 } 218 219 void SbiParser::CloseBlock() 220 { 221 if( pStack ) 222 { 223 SbiParseStack* p = pStack; 224 225 // #29955 for-Schleifen-Ebene pflegen 226 if( p->eExitTok == FOR ) 227 aGen.DecForLevel(); 228 229 aGen.BackChain( p->nChain ); 230 pStack = p->pNext; 231 pWithVar = p->pWithVar; 232 delete p; 233 } 234 } 235 236 // EXIT ... 237 238 void SbiParser::Exit() 239 { 240 SbiToken eTok = Next(); 241 for( SbiParseStack* p = pStack; p; p = p->pNext ) 242 { 243 SbiToken eExitTok = p->eExitTok; 244 if( eTok == eExitTok || 245 (eTok == PROPERTY && (eExitTok == GET || eExitTok == LET) ) ) // #i109051 246 { 247 p->nChain = aGen.Gen( _JUMP, p->nChain ); 248 return; 249 } 250 } 251 if( pStack ) 252 Error( SbERR_EXPECTED, pStack->eExitTok ); 253 else 254 Error( SbERR_BAD_EXIT ); 255 } 256 257 sal_Bool SbiParser::TestSymbol( sal_Bool bKwdOk ) 258 { 259 Peek(); 260 if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) ) 261 { 262 Next(); return sal_True; 263 } 264 Error( SbERR_SYMBOL_EXPECTED ); 265 return sal_False; 266 } 267 268 // Testen auf ein bestimmtes Token 269 270 sal_Bool SbiParser::TestToken( SbiToken t ) 271 { 272 if( Peek() == t ) 273 { 274 Next(); return sal_True; 275 } 276 else 277 { 278 Error( SbERR_EXPECTED, t ); 279 return sal_False; 280 } 281 } 282 283 // Testen auf Komma oder EOLN 284 285 sal_Bool SbiParser::TestComma() 286 { 287 SbiToken eTok = Peek(); 288 if( IsEoln( eTok ) ) 289 { 290 Next(); 291 return sal_False; 292 } 293 else if( eTok != COMMA ) 294 { 295 Error( SbERR_EXPECTED, COMMA ); 296 return sal_False; 297 } 298 Next(); 299 return sal_True; 300 } 301 302 // Testen, ob EOLN vorliegt 303 304 void SbiParser::TestEoln() 305 { 306 if( !IsEoln( Next() ) ) 307 { 308 Error( SbERR_EXPECTED, EOLN ); 309 while( !IsEoln( Next() ) ) {} 310 } 311 } 312 313 // Parsing eines Statement-Blocks 314 // Das Parsing läuft bis zum Ende-Token. 315 316 void SbiParser::StmntBlock( SbiToken eEnd ) 317 { 318 SbiToken xe = eEndTok; 319 eEndTok = eEnd; 320 while( !bAbort && Parse() ) {} 321 eEndTok = xe; 322 if( IsEof() ) 323 { 324 Error( SbERR_BAD_BLOCK, eEnd ); 325 bAbort = sal_True; 326 } 327 } 328 329 // Die Hauptroutine. Durch wiederholten Aufrufs dieser Routine wird 330 // die Quelle geparst. Returnwert sal_False bei Ende/Fehlern. 331 332 sal_Bool SbiParser::Parse() 333 { 334 if( bAbort ) return sal_False; 335 336 EnableErrors(); 337 338 bErrorIsSymbol = false; 339 Peek(); 340 bErrorIsSymbol = true; 341 // Dateiende? 342 if( IsEof() ) 343 { 344 // AB #33133: Falls keine Sub angelegt wurde, muss hier 345 // der globale Chain abgeschlossen werden! 346 // AB #40689: Durch die neue static-Behandlung kann noch 347 // ein nGblChain vorhanden sein, daher vorher abfragen 348 if( bNewGblDefs && nGblChain == 0 ) 349 nGblChain = aGen.Gen( _JUMP, 0 ); 350 return sal_False; 351 } 352 353 // Leerstatement? 354 if( IsEoln( eCurTok ) ) 355 { 356 Next(); return sal_True; 357 } 358 359 if( !bSingleLineIf && MayBeLabel( sal_True ) ) 360 { 361 // Ist ein Label 362 if( !pProc ) 363 Error( SbERR_NOT_IN_MAIN, aSym ); 364 else 365 pProc->GetLabels().Define( aSym ); 366 Next(); Peek(); 367 // Leerstatement? 368 if( IsEoln( eCurTok ) ) 369 { 370 Next(); return sal_True; 371 } 372 } 373 374 // Ende des Parsings? 375 if( eCurTok == eEndTok || 376 ( bVBASupportOn && // #i109075 377 (eCurTok == ENDFUNC || eCurTok == ENDPROPERTY || eCurTok == ENDSUB) && 378 (eEndTok == ENDFUNC || eEndTok == ENDPROPERTY || eEndTok == ENDSUB) ) ) 379 { 380 Next(); 381 if( eCurTok != NIL ) 382 aGen.Statement(); 383 return sal_False; 384 } 385 386 // Kommentar? 387 if( eCurTok == REM ) 388 { 389 Next(); return sal_True; 390 } 391 392 // Kommt ein Symbol, ist es entweder eine Variable( LET ) 393 // oder eine SUB-Prozedur( CALL ohne Klammern ) 394 // DOT für Zuweisungen im WITH-Block: .A=5 395 if( eCurTok == SYMBOL || eCurTok == DOT ) 396 { 397 if( !pProc ) 398 Error( SbERR_EXPECTED, SUB ); 399 else 400 { 401 // Damit Zeile & Spalte stimmen... 402 Next(); 403 Push( eCurTok ); 404 aGen.Statement(); 405 Symbol(); 406 } 407 } 408 else 409 { 410 Next(); 411 412 // Hier folgen nun die Statement-Parser. 413 414 SbiStatement* p; 415 for( p = StmntTable; p->eTok != NIL; p++ ) 416 if( p->eTok == eCurTok ) 417 break; 418 if( p->eTok != NIL ) 419 { 420 if( !pProc && !p->bMain ) 421 Error( SbERR_NOT_IN_MAIN, eCurTok ); 422 else if( pProc && !p->bSubr ) 423 Error( SbERR_NOT_IN_SUBR, eCurTok ); 424 else 425 { 426 // globalen Chain pflegen 427 // AB #41606/#40689: Durch die neue static-Behandlung kann noch 428 // ein nGblChain vorhanden sein, daher vorher abfragen 429 if( bNewGblDefs && nGblChain == 0 && 430 ( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) ) 431 { 432 nGblChain = aGen.Gen( _JUMP, 0 ); 433 bNewGblDefs = sal_False; 434 } 435 // Statement-Opcode bitte auch am Anfang einer Sub 436 if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) || 437 eCurTok == SUB || eCurTok == FUNCTION ) 438 aGen.Statement(); 439 (this->*( p->Func ) )(); 440 SbxError nSbxErr = SbxBase::GetError(); 441 if( nSbxErr ) 442 SbxBase::ResetError(), Error( (SbError)nSbxErr ); 443 } 444 } 445 else 446 Error( SbERR_UNEXPECTED, eCurTok ); 447 } 448 449 // Test auf Ende des Statements: 450 // Kann auch ein ELSE sein, da vor dem ELSE kein : stehen muss! 451 452 if( !IsEos() ) 453 { 454 Peek(); 455 if( !IsEos() && eCurTok != ELSE ) 456 { 457 // falls das Parsing abgebrochen wurde, bis zum ":" vorgehen: 458 Error( SbERR_UNEXPECTED, eCurTok ); 459 while( !IsEos() ) Next(); 460 } 461 } 462 // Der Parser bricht am Ende ab, das nächste Token ist noch nicht 463 // geholt! 464 return sal_True; 465 } 466 467 // Innerste With-Variable liefern 468 SbiExprNode* SbiParser::GetWithVar() 469 { 470 if( pWithVar ) 471 return pWithVar; 472 473 // Sonst im Stack suchen 474 SbiParseStack* p = pStack; 475 while( p ) 476 { 477 // LoopVar kann zur Zeit nur für with sein 478 if( p->pWithVar ) 479 return p->pWithVar; 480 p = p->pNext; 481 } 482 return NULL; 483 } 484 485 486 // Zuweisung oder Subroutine Call 487 488 void SbiParser::Symbol( const KeywordSymbolInfo* pKeywordSymbolInfo ) 489 { 490 SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD; 491 SbiExpression aVar( this, SbSYMBOL, eMode, pKeywordSymbolInfo ); 492 493 bool bEQ = ( Peek() == EQ ); 494 if( !bEQ && bVBASupportOn && aVar.IsBracket() ) 495 Error( SbERR_EXPECTED, "=" ); 496 497 RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL ); 498 bool bSpecialMidHandling = false; 499 SbiSymDef* pDef = aVar.GetRealVar(); 500 if( bEQ && pDef && pDef->GetScope() == SbRTL ) 501 { 502 String aRtlName = pDef->GetName(); 503 if( aRtlName.EqualsIgnoreCaseAscii("Mid") ) 504 { 505 SbiExprNode* pExprNode = aVar.GetExprNode(); 506 // SbiNodeType eNodeType; 507 if( pExprNode && pExprNode->GetNodeType() == SbxVARVAL ) 508 { 509 SbiExprList* pPar = pExprNode->GetParameters(); 510 short nParCount = pPar ? pPar->GetSize() : 0; 511 if( nParCount == 2 || nParCount == 3 ) 512 { 513 if( nParCount == 2 ) 514 pPar->addExpression( new SbiExpression( this, -1, SbxLONG ) ); 515 516 TestToken( EQ ); 517 pPar->addExpression( new SbiExpression( this ) ); 518 519 bSpecialMidHandling = true; 520 } 521 } 522 } 523 } 524 aVar.Gen( eRecMode ); 525 if( !bSpecialMidHandling ) 526 { 527 if( !bEQ ) 528 { 529 aGen.Gen( _GET ); 530 } 531 else 532 { 533 // Dann muss es eine Zuweisung sein. Was anderes gibt es nicht! 534 if( !aVar.IsLvalue() ) 535 Error( SbERR_LVALUE_EXPECTED ); 536 TestToken( EQ ); 537 SbiExpression aExpr( this ); 538 aExpr.Gen(); 539 SbiOpcode eOp = _PUT; 540 // SbiSymDef* pDef = aVar.GetRealVar(); 541 if( pDef ) 542 { 543 if( pDef->GetConstDef() ) 544 Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); 545 if( pDef->GetType() == SbxOBJECT ) 546 { 547 eOp = _SET; 548 if( pDef->GetTypeId() ) 549 { 550 aGen.Gen( _SETCLASS, pDef->GetTypeId() ); 551 return; 552 } 553 } 554 } 555 aGen.Gen( eOp ); 556 } 557 } 558 } 559 560 // Zuweisungen 561 562 void SbiParser::Assign() 563 { 564 SbiExpression aLvalue( this, SbLVALUE ); 565 TestToken( EQ ); 566 SbiExpression aExpr( this ); 567 aLvalue.Gen(); 568 aExpr.Gen(); 569 sal_uInt16 nLen = 0; 570 SbiSymDef* pDef = aLvalue.GetRealVar(); 571 { 572 if( pDef->GetConstDef() ) 573 Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); 574 nLen = aLvalue.GetRealVar()->GetLen(); 575 } 576 if( nLen ) 577 aGen.Gen( _PAD, nLen ); 578 aGen.Gen( _PUT ); 579 } 580 581 // Zuweisungen einer Objektvariablen 582 583 void SbiParser::Set() 584 { 585 SbiExpression aLvalue( this, SbLVALUE ); 586 SbxDataType eType = aLvalue.GetType(); 587 if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT ) 588 Error( SbERR_INVALID_OBJECT ); 589 TestToken( EQ ); 590 SbiSymDef* pDef = aLvalue.GetRealVar(); 591 if( pDef && pDef->GetConstDef() ) 592 Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); 593 594 SbiToken eTok = Peek(); 595 if( eTok == NEW ) 596 { 597 Next(); 598 String aStr; 599 SbiSymDef* pTypeDef = new SbiSymDef( aStr ); 600 TypeDecl( *pTypeDef, sal_True ); 601 602 aLvalue.Gen(); 603 // aGen.Gen( _CLASS, pDef->GetTypeId() | 0x8000 ); 604 aGen.Gen( _CREATE, pDef->GetId(), pTypeDef->GetTypeId() ); 605 aGen.Gen( _SETCLASS, pDef->GetTypeId() ); 606 } 607 else 608 { 609 SbiExpression aExpr( this ); 610 aLvalue.Gen(); 611 aExpr.Gen(); 612 // It's a good idea to distinguish between 613 // set something = another & 614 // something = another 615 // ( it's necessary for vba objects where set is object 616 // specific and also doesn't involve processing default params ) 617 if( pDef->GetTypeId() ) 618 { 619 if ( bVBASupportOn ) 620 aGen.Gen( _VBASETCLASS, pDef->GetTypeId() ); 621 else 622 aGen.Gen( _SETCLASS, pDef->GetTypeId() ); 623 } 624 else 625 { 626 if ( bVBASupportOn ) 627 aGen.Gen( _VBASET ); 628 else 629 aGen.Gen( _SET ); 630 } 631 } 632 // aGen.Gen( _SET ); 633 } 634 635 // JSM 07.10.95 636 void SbiParser::LSet() 637 { 638 SbiExpression aLvalue( this, SbLVALUE ); 639 if( aLvalue.GetType() != SbxSTRING ) 640 Error( SbERR_INVALID_OBJECT ); 641 TestToken( EQ ); 642 SbiSymDef* pDef = aLvalue.GetRealVar(); 643 if( pDef && pDef->GetConstDef() ) 644 Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); 645 SbiExpression aExpr( this ); 646 aLvalue.Gen(); 647 aExpr.Gen(); 648 aGen.Gen( _LSET ); 649 } 650 651 // JSM 07.10.95 652 void SbiParser::RSet() 653 { 654 SbiExpression aLvalue( this, SbLVALUE ); 655 if( aLvalue.GetType() != SbxSTRING ) 656 Error( SbERR_INVALID_OBJECT ); 657 TestToken( EQ ); 658 SbiSymDef* pDef = aLvalue.GetRealVar(); 659 if( pDef && pDef->GetConstDef() ) 660 Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); 661 SbiExpression aExpr( this ); 662 aLvalue.Gen(); 663 aExpr.Gen(); 664 aGen.Gen( _RSET ); 665 } 666 667 // DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR und so weiter 668 669 void SbiParser::DefXXX() 670 { 671 sal_Unicode ch1, ch2; 672 SbxDataType t = SbxDataType( eCurTok - DEFINT + SbxINTEGER ); 673 674 while( !bAbort ) 675 { 676 if( Next() != SYMBOL ) break; 677 ch1 = aSym.ToUpperAscii().GetBuffer()[0]; 678 ch2 = 0; 679 if( Peek() == MINUS ) 680 { 681 Next(); 682 if( Next() != SYMBOL ) Error( SbERR_SYMBOL_EXPECTED ); 683 else 684 { 685 ch2 = aSym.ToUpperAscii().GetBuffer()[0]; 686 //ch2 = aSym.Upper(); 687 if( ch2 < ch1 ) Error( SbERR_SYNTAX ), ch2 = 0; 688 } 689 } 690 if (!ch2) ch2 = ch1; 691 ch1 -= 'A'; ch2 -= 'A'; 692 for (; ch1 <= ch2; ch1++) eDefTypes[ ch1 ] = t; 693 if( !TestComma() ) break; 694 } 695 } 696 697 // STOP/SYSTEM 698 699 void SbiParser::Stop() 700 { 701 aGen.Gen( _STOP ); 702 Peek(); // #35694: Nur Peek(), damit EOL in Single-Line-If erkannt wird 703 } 704 705 // IMPLEMENTS 706 707 void SbiParser::Implements() 708 { 709 if( !bClassModule ) 710 { 711 Error( SbERR_UNEXPECTED, IMPLEMENTS ); 712 return; 713 } 714 715 Peek(); 716 if( eCurTok != SYMBOL ) 717 { 718 Error( SbERR_SYMBOL_EXPECTED ); 719 return; 720 } 721 722 String aImplementedIface = aSym; 723 Next(); 724 if( Peek() == DOT ) 725 { 726 String aDotStr( '.' ); 727 while( Peek() == DOT ) 728 { 729 aImplementedIface += aDotStr; 730 Next(); 731 SbiToken ePeekTok = Peek(); 732 if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) ) 733 { 734 Next(); 735 aImplementedIface += aSym; 736 } 737 else 738 { 739 Next(); 740 Error( SbERR_SYMBOL_EXPECTED ); 741 break; 742 } 743 } 744 } 745 aIfaceVector.push_back( aImplementedIface ); 746 } 747 748 void SbiParser::EnableCompatibility() 749 { 750 if( !bCompatible ) 751 AddConstants(); 752 bCompatible = sal_True; 753 } 754 755 // OPTION 756 757 void SbiParser::Option() 758 { 759 switch( Next() ) 760 { 761 case BASIC_EXPLICIT: 762 bExplicit = sal_True; break; 763 case BASE: 764 if( Next() == NUMBER ) 765 { 766 if( nVal == 0 || nVal == 1 ) 767 { 768 nBase = (short) nVal; 769 break; 770 } 771 } 772 Error( SbERR_EXPECTED, "0/1" ); 773 break; 774 case PRIVATE: 775 { 776 String aString = SbiTokenizer::Symbol(Next()); 777 if( !aString.EqualsIgnoreCaseAscii("Module") ) 778 Error( SbERR_EXPECTED, "Module" ); 779 break; 780 } 781 case COMPARE: 782 { 783 SbiToken eTok = Next(); 784 if( eTok == BINARY ) 785 bText = sal_False; 786 else if( eTok == SYMBOL && GetSym().EqualsIgnoreCaseAscii("text") ) 787 bText = sal_True; 788 else 789 Error( SbERR_EXPECTED, "Text/Binary" ); 790 break; 791 } 792 case COMPATIBLE: 793 EnableCompatibility(); 794 break; 795 796 case CLASSMODULE: 797 bClassModule = sal_True; 798 aGen.GetModule().SetModuleType( com::sun::star::script::ModuleType::CLASS ); 799 break; 800 case VBASUPPORT: 801 if( Next() == NUMBER ) 802 { 803 if ( nVal == 1 || nVal == 0 ) 804 { 805 bVBASupportOn = ( nVal == 1 ); 806 if ( bVBASupportOn ) 807 EnableCompatibility(); 808 // if the module setting is different 809 // reset it to what the Option tells us 810 if ( bVBASupportOn != aGen.GetModule().IsVBACompat() ) 811 aGen.GetModule().SetVBACompat( bVBASupportOn ); 812 break; 813 } 814 } 815 Error( SbERR_EXPECTED, "0/1" ); 816 break; 817 default: 818 Error( SbERR_BAD_OPTION, eCurTok ); 819 } 820 } 821 822 void addStringConst( SbiSymPool& rPool, const char* pSym, const String& rStr ) 823 { 824 SbiConstDef* pConst = new SbiConstDef( String::CreateFromAscii( pSym ) ); 825 pConst->SetType( SbxSTRING ); 826 pConst->Set( rStr ); 827 rPool.Add( pConst ); 828 } 829 830 inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr ) 831 { 832 addStringConst( rPool, pSym, String::CreateFromAscii( pStr ) ); 833 } 834 835 void SbiParser::AddConstants( void ) 836 { 837 // #113063 Create constant RTL symbols 838 addStringConst( aPublics, "vbCr", "\x0D" ); 839 addStringConst( aPublics, "vbCrLf", "\x0D\x0A" ); 840 addStringConst( aPublics, "vbFormFeed", "\x0C" ); 841 addStringConst( aPublics, "vbLf", "\x0A" ); 842 #if defined(UNX) 843 addStringConst( aPublics, "vbNewLine", "\x0A" ); 844 #else 845 addStringConst( aPublics, "vbNewLine", "\x0D\x0A" ); 846 #endif 847 addStringConst( aPublics, "vbNullString", "" ); 848 addStringConst( aPublics, "vbTab", "\x09" ); 849 addStringConst( aPublics, "vbVerticalTab", "\x0B" ); 850 851 // Force length 1 and make char 0 afterwards 852 String aNullCharStr( String::CreateFromAscii( " " ) ); 853 aNullCharStr.SetChar( 0, 0 ); 854 addStringConst( aPublics, "vbNullChar", aNullCharStr ); 855 } 856 857 // ERROR n 858 859 void SbiParser::ErrorStmnt() 860 { 861 SbiExpression aPar( this ); 862 aPar.Gen(); 863 aGen.Gen( _ERROR ); 864 } 865 866 /* vim: set noet sw=4 ts=4: */ 867