xref: /AOO41X/main/basic/source/comp/parser.cxx (revision 3d7628264b67541a59f8a1d4df8ea02ab31c33a6)
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 
SbiParser(StarBASIC * pb,SbModule * pm)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?
CheckRTLForSym(const String & rSym,SbxDataType eType)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 
HasGlobalCode()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 
OpenBlock(SbiToken eTok,SbiExprNode * pVar)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 
CloseBlock()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 
Exit()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 
TestSymbol(sal_Bool bKwdOk)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 
TestToken(SbiToken t)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 
TestComma()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 
TestEoln()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 
StmntBlock(SbiToken eEnd)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 
Parse()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
GetWithVar()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 
Symbol(const KeywordSymbolInfo * pKeywordSymbolInfo)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 
Assign()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 
Set()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
LSet()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
RSet()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 
DefXXX()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 
Stop()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 
Implements()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 
EnableCompatibility()742 void SbiParser::EnableCompatibility()
743 {
744     if( !bCompatible )
745         AddConstants();
746     bCompatible = sal_True;
747 }
748 
749 // OPTION
750 
Option()751 void SbiParser::Option()
752 {
753     switch( Next() )
754     {
755         case BASIC_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 
addStringConst(SbiSymPool & rPool,const char * pSym,const String & rStr)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 
addStringConst(SbiSymPool & rPool,const char * pSym,const char * pStr)824 inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
825 {
826     addStringConst( rPool, pSym, String::CreateFromAscii( pStr ) );
827 }
828 
AddConstants(void)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 
ErrorStmnt()853 void SbiParser::ErrorStmnt()
854 {
855     SbiExpression aPar( this );
856     aPar.Gen();
857     aGen.Gen( _ERROR );
858 }
859 
860