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