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