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