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