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