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
SbiParser(StarBASIC * pb,SbModule * pm)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?
CheckRTLForSym(const String & rSym,SbxDataType eType)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
HasGlobalCode()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
OpenBlock(SbiToken eTok,SbiExprNode * pVar)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
CloseBlock()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
Exit()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
TestSymbol(sal_Bool bKwdOk)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
TestToken(SbiToken t)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
TestComma()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
TestEoln()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
StmntBlock(SbiToken eEnd)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
Parse()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
GetWithVar()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
Symbol(const KeywordSymbolInfo * pKeywordSymbolInfo)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
Assign()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
Set()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
LSet()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
RSet()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
DefXXX()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
Stop()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
Implements()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
EnableCompatibility()748 void SbiParser::EnableCompatibility()
749 {
750 if( !bCompatible )
751 AddConstants();
752 bCompatible = sal_True;
753 }
754
755 // OPTION
756
Option()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
addStringConst(SbiSymPool & rPool,const char * pSym,const String & rStr)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
addStringConst(SbiSymPool & rPool,const char * pSym,const char * pStr)830 inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
831 {
832 addStringConst( rPool, pSym, String::CreateFromAscii( pStr ) );
833 }
834
AddConstants(void)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
ErrorStmnt()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