/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basic.hxx"
#include <basic/sbx.hxx>
#include "sbcomp.hxx"
#include <com/sun/star/script/ModuleType.hpp>

struct SbiParseStack {				// "Stack" fuer Statement-Blocks
	SbiParseStack* pNext;  			// Chain
	SbiExprNode* pWithVar;			// Variable fuer WITH
	SbiToken eExitTok;				// Exit-Token
	sal_uInt32  nChain;					// JUMP-Chain
};

struct SbiStatement {
	SbiToken eTok;
	void( SbiParser::*Func )();		// Verarbeitungsroutine
	sal_Bool  bMain;					// sal_True: ausserhalb SUBs OK
	sal_Bool  bSubr;					// sal_True: in SUBs OK
};

#define	Y	sal_True
#define	N	sal_False

static SbiStatement StmntTable [] = {
{ CALL,		&SbiParser::Call,   	N, Y, }, // CALL
{ CLOSE,	&SbiParser::Close,		N, Y, }, // CLOSE
{ _CONST_,	&SbiParser::Dim, 		Y, Y, }, // CONST
{ DECLARE,	&SbiParser::Declare,	Y, N, }, // DECLARE
{ DEFBOOL,	&SbiParser::DefXXX,		Y, N, }, // DEFBOOL
{ DEFCUR,	&SbiParser::DefXXX,		Y, N, }, // DEFCUR
{ DEFDATE,	&SbiParser::DefXXX,		Y, N, }, // DEFDATE
{ DEFDBL,	&SbiParser::DefXXX,		Y, N, }, // DEFDBL
{ DEFERR,	&SbiParser::DefXXX,		Y, N, }, // DEFERR
{ DEFINT,	&SbiParser::DefXXX,		Y, N, }, // DEFINT
{ DEFLNG,	&SbiParser::DefXXX,		Y, N, }, // DEFLNG
{ DEFOBJ,	&SbiParser::DefXXX,		Y, N, }, // DEFOBJ
{ DEFSNG,	&SbiParser::DefXXX,		Y, N, }, // DEFSNG
{ DEFSTR,	&SbiParser::DefXXX,		Y, N, }, // DEFSTR
{ DEFVAR,	&SbiParser::DefXXX,		Y, N, }, // DEFVAR
{ DIM,		&SbiParser::Dim,		Y, Y, }, // DIM
{ DO,		&SbiParser::DoLoop,		N, Y, }, // DO
{ ELSE,		&SbiParser::NoIf,		N, Y, }, // ELSE
{ ELSEIF,	&SbiParser::NoIf,		N, Y, }, // ELSEIF
{ ENDIF,	&SbiParser::NoIf,		N, Y, }, // ENDIF
{ END,		&SbiParser::Stop,		N, Y, }, // END
{ ENUM,		&SbiParser::Enum,		Y, N, }, // TYPE
{ ERASE,	&SbiParser::Erase,		N, Y, }, // ERASE
{ _ERROR_,	&SbiParser::ErrorStmnt,	N, Y, }, // ERROR
{ EXIT,		&SbiParser::Exit,		N, Y, }, // EXIT
{ FOR,		&SbiParser::For,		N, Y, }, // FOR
{ FUNCTION,	&SbiParser::SubFunc,	Y, N, }, // FUNCTION
{ GOSUB,	&SbiParser::Goto,		N, Y, }, // GOSUB
{ GLOBAL,	&SbiParser::Dim,		Y, N, }, // GLOBAL
{ GOTO,		&SbiParser::Goto,		N, Y, }, // GOTO
{ IF,		&SbiParser::If,			N, Y, }, // IF
{ IMPLEMENTS, &SbiParser::Implements, Y, N, }, // IMPLEMENTS
{ INPUT,	&SbiParser::Input,		N, Y, }, // INPUT
{ LET,		&SbiParser::Assign,		N, Y, }, // LET
{ LINE,		&SbiParser::Line,		N, Y, }, // LINE, -> LINE INPUT (#i92642)
{ LINEINPUT,&SbiParser::LineInput,	N, Y, }, // LINE INPUT
{ LOOP,		&SbiParser::BadBlock,	N, Y, }, // LOOP
{ LSET,		&SbiParser::LSet,		N, Y, }, // LSET
{ NAME,		&SbiParser::Name,		N, Y, }, // NAME
{ NEXT,		&SbiParser::BadBlock,	N, Y, }, // NEXT
{ ON,		&SbiParser::On,			N, Y, }, // ON
{ OPEN,		&SbiParser::Open,		N, Y, }, // OPEN
{ OPTION,	&SbiParser::Option,    	Y, N, }, // OPTION
{ PRINT,	&SbiParser::Print,		N, Y, }, // PRINT
{ PRIVATE,	&SbiParser::Dim,  		Y, N, }, // PRIVATE
{ PROPERTY,	&SbiParser::SubFunc,	Y, N, }, // FUNCTION
{ PUBLIC,	&SbiParser::Dim,  		Y, N, }, // PUBLIC
{ REDIM,	&SbiParser::ReDim,  	N, Y, }, // DIM
{ RESUME,	&SbiParser::Resume,		N, Y, }, // RESUME
{ RETURN,	&SbiParser::Return,		N, Y, }, // RETURN
{ RSET,		&SbiParser::RSet,		N, Y, }, // RSET
{ SELECT,	&SbiParser::Select,		N, Y, }, // SELECT
{ SET,		&SbiParser::Set,		N, Y, }, // SET
{ STATIC,	&SbiParser::Static,		Y, Y, }, // STATIC
{ STOP,		&SbiParser::Stop,		N, Y, }, // STOP
{ SUB,		&SbiParser::SubFunc,	Y, N, }, // SUB
{ TYPE,		&SbiParser::Type,		Y, N, }, // TYPE
{ UNTIL,	&SbiParser::BadBlock,	N, Y, }, // UNTIL
{ WHILE,	&SbiParser::While,		N, Y, }, // WHILE
{ WEND,		&SbiParser::BadBlock,	N, Y, }, // WEND
{ WITH,		&SbiParser::With,		N, Y, }, // WITH
{ WRITE,	&SbiParser::Write,		N, Y, }, // WRITE

{ NIL, NULL, N, N }
};


#ifdef _MSC_VER
// 'this' : used in base member initializer list
#pragma warning( disable: 4355 )
#endif

SbiParser::SbiParser( StarBASIC* pb, SbModule* pm )
		: SbiTokenizer( pm->GetSource32(), pb ),
		  aGblStrings( this ),
		  aLclStrings( this ),
		  aGlobals( aGblStrings, SbGLOBAL ),
		  aPublics( aGblStrings, SbPUBLIC ),
		  aRtlSyms( aGblStrings, SbRTL ),
		  aGen( *pm, this, 1024 )
{
	pBasic	 = pb;
	eCurExpr = SbSYMBOL;
	eEndTok  = NIL;
	pProc    = NULL;
	pStack   = NULL;
	pWithVar = NULL;
	nBase	 = 0;
	bText	 =
	bGblDefs =
	bNewGblDefs =
	bSingleLineIf =
	bExplicit = sal_False;
	bClassModule = ( pm->GetModuleType() == com::sun::star::script::ModuleType::CLASS );
	OSL_TRACE("Parser - %s, bClassModule %d", rtl::OUStringToOString( pm->GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), bClassModule );
	pPool	 = &aPublics;
	for( short i = 0; i < 26; i++ )
		eDefTypes[ i ] = SbxVARIANT;    // Kein expliziter Defaulttyp

	aPublics.SetParent( &aGlobals );
	aGlobals.SetParent( &aRtlSyms );

	// Die globale Chainkette faengt bei Adresse 0 an:
	nGblChain = aGen.Gen( _JUMP, 0 );

	rTypeArray = new SbxArray; // Array fuer Benutzerdefinierte Typen
	rEnumArray = new SbxArray; // Array for Enum types
	bVBASupportOn = pm->IsVBACompat();
	if ( bVBASupportOn )
		EnableCompatibility();

}


// Ist  Teil der Runtime-Library?
SbiSymDef* SbiParser::CheckRTLForSym( const String& rSym, SbxDataType eType )
{
	SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE );
	SbiSymDef* pDef = NULL;
	if( pVar )
	{
		if( dynamic_cast< SbxMethod* >(pVar) )
		{
			SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym );
			pProc_->SetType( pVar->GetType() );
			pDef = pProc_;
		}
		else
		{
			pDef = aRtlSyms.AddSym( rSym );
			pDef->SetType( eType );
		}
	}
	return pDef;
}

// Globale Chainkette schliessen

sal_Bool SbiParser::HasGlobalCode()
{
	if( bGblDefs && nGblChain )
	{
		aGen.BackChain( nGblChain );
		aGen.Gen( _LEAVE );
		// aGen.Gen( _STOP );
		nGblChain = 0;
	}
	return bGblDefs;
}

void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar )
{
	SbiParseStack* p = new SbiParseStack;
	p->eExitTok = eTok;
	p->nChain   = 0;
	p->pWithVar = pWithVar;
	p->pNext    = pStack;
	pStack      = p;
	pWithVar    = pVar;

	// #29955 for-Schleifen-Ebene pflegen
	if( eTok == FOR )
		aGen.IncForLevel();
}

void SbiParser::CloseBlock()
{
	if( pStack )
	{
		SbiParseStack* p = pStack;

		// #29955 for-Schleifen-Ebene pflegen
		if( p->eExitTok == FOR )
			aGen.DecForLevel();

		aGen.BackChain( p->nChain );
		pStack = p->pNext;
		pWithVar = p->pWithVar;
		delete p;
	}
}

// EXIT ...

void SbiParser::Exit()
{
	SbiToken eTok = Next();
	for( SbiParseStack* p = pStack; p; p = p->pNext )
	{
		SbiToken eExitTok = p->eExitTok;
		if( eTok == eExitTok || 
			(eTok == PROPERTY && (eExitTok == GET || eExitTok == LET) ) )	// #i109051
		{
			p->nChain = aGen.Gen( _JUMP, p->nChain );
			return;
		}
	}
	if( pStack )
		Error( SbERR_EXPECTED, pStack->eExitTok );
	else
		Error( SbERR_BAD_EXIT );
}

sal_Bool SbiParser::TestSymbol( sal_Bool bKwdOk )
{
	Peek();
	if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) )
	{
		Next(); return sal_True;
	}
	Error( SbERR_SYMBOL_EXPECTED );
	return sal_False;
}

// Testen auf ein bestimmtes Token

sal_Bool SbiParser::TestToken( SbiToken t )
{
	if( Peek() == t )
	{
		Next(); return sal_True;
	}
	else
	{
		Error( SbERR_EXPECTED, t );
		return sal_False;
	}
}

// Testen auf Komma oder EOLN

sal_Bool SbiParser::TestComma()
{
	SbiToken eTok = Peek();
	if( IsEoln( eTok ) )
	{
		Next();
		return sal_False;
	}
	else if( eTok != COMMA )
	{
		Error( SbERR_EXPECTED, COMMA );
		return sal_False;
	}
	Next();
	return sal_True;
}

// Testen, ob EOLN vorliegt

void SbiParser::TestEoln()
{
	if( !IsEoln( Next() ) )
	{
		Error( SbERR_EXPECTED, EOLN );
		while( !IsEoln( Next() ) ) {}
	}
}

// Parsing eines Statement-Blocks
// Das Parsing laeuft bis zum Ende-Token.

void SbiParser::StmntBlock( SbiToken eEnd )
{
	SbiToken xe = eEndTok;
	eEndTok = eEnd;
	while( !bAbort && Parse() ) {}
	eEndTok = xe;
	if( IsEof() )
	{
		Error( SbERR_BAD_BLOCK, eEnd );
		bAbort = sal_True;
	}
}

// Die Hauptroutine. Durch wiederholten Aufrufs dieser Routine wird
// die Quelle geparst. Returnwert sal_False bei Ende/Fehlern.

sal_Bool SbiParser::Parse()
{
	if( bAbort ) return sal_False;

	EnableErrors();

	bErrorIsSymbol = false;
	Peek();
	bErrorIsSymbol = true;
	// Dateiende?
	if( IsEof() )
	{
		// AB #33133: Falls keine Sub angelegt wurde, muss hier
		// der globale Chain abgeschlossen werden!
		// AB #40689: Durch die neue static-Behandlung kann noch
		// ein nGblChain vorhanden sein, daher vorher abfragen
		if( bNewGblDefs && nGblChain == 0 )
			nGblChain = aGen.Gen( _JUMP, 0 );
		return sal_False;
	}

	// Leerstatement?
	if( IsEoln( eCurTok ) )
	{
		Next(); return sal_True;
	}

	if( !bSingleLineIf && MayBeLabel( sal_True ) )
	{
		// Ist ein Label
		if( !pProc )
			Error( SbERR_NOT_IN_MAIN, aSym );
		else
			pProc->GetLabels().Define( aSym );
		Next(); Peek();
		// Leerstatement?
		if( IsEoln( eCurTok ) )
		{
			Next(); return sal_True;
		}
	}

	// Ende des Parsings?
	if( eCurTok == eEndTok ||
		( bVBASupportOn	&&		// #i109075
		  (eCurTok == ENDFUNC || eCurTok == ENDPROPERTY || eCurTok == ENDSUB) &&
		  (eEndTok == ENDFUNC || eEndTok == ENDPROPERTY || eEndTok == ENDSUB) ) )
	{
		Next();
		if( eCurTok != NIL )
			aGen.Statement();
		return sal_False;
	}

	// Kommentar?
	if( eCurTok == REM )
	{
		Next(); return sal_True;
	}

	// Kommt ein Symbol, ist es entweder eine Variable( LET )
	// oder eine SUB-Prozedur( CALL ohne Klammern )
	// DOT fuer Zuweisungen im WITH-Block: .A=5
	if( eCurTok == SYMBOL || eCurTok == DOT )
	{
		if( !pProc )
			Error( SbERR_EXPECTED, SUB );
		else
		{
			// Damit Zeile & Spalte stimmen...
			Next();
			Push( eCurTok );
			aGen.Statement();
				Symbol();
		}
	}
	else
	{
		Next();

		// Hier folgen nun die Statement-Parser.

		SbiStatement* p;
		for( p = StmntTable; p->eTok != NIL; p++ )
			if( p->eTok == eCurTok )
				break;
		if( p->eTok != NIL )
		{
			if( !pProc && !p->bMain )
				Error( SbERR_NOT_IN_MAIN, eCurTok );
			else if( pProc && !p->bSubr )
				Error( SbERR_NOT_IN_SUBR, eCurTok );
			else
			{
				// globalen Chain pflegen
				// AB #41606/#40689: Durch die neue static-Behandlung kann noch
				// ein nGblChain vorhanden sein, daher vorher abfragen
				if( bNewGblDefs && nGblChain == 0 && 
					( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) )
				{
					nGblChain = aGen.Gen( _JUMP, 0 );
					bNewGblDefs = sal_False;
				}
				// Statement-Opcode bitte auch am Anfang einer Sub
				if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) ||
						eCurTok == SUB || eCurTok == FUNCTION )
					aGen.Statement();
				(this->*( p->Func ) )();
				SbxError nSbxErr = SbxBase::GetError();
				if( nSbxErr )
					SbxBase::ResetError(), Error( (SbError)nSbxErr );
			}
		}
		else
			Error( SbERR_UNEXPECTED, eCurTok );
	}

	// Test auf Ende des Statements:
	// Kann auch ein ELSE sein, da vor dem ELSE kein : stehen muss!

	if( !IsEos() )
	{
		Peek();
		if( !IsEos() && eCurTok != ELSE )
		{
			// falls das Parsing abgebrochen wurde, bis zum ":" vorgehen:
			Error( SbERR_UNEXPECTED, eCurTok );
			while( !IsEos() ) Next();
		}
	}
	// Der Parser bricht am Ende ab, das naechste Token ist noch nicht
	// geholt!
	return sal_True;
}

// Innerste With-Variable liefern
SbiExprNode* SbiParser::GetWithVar()
{
	if( pWithVar )
		return pWithVar;

	// Sonst im Stack suchen
	SbiParseStack* p = pStack;
	while( p )
	{
		// LoopVar kann zur Zeit nur fuer with sein
		if( p->pWithVar )
			return p->pWithVar;
		p = p->pNext;
	}
	return NULL;
}


// Zuweisung oder Subroutine Call

void SbiParser::Symbol( const KeywordSymbolInfo* pKeywordSymbolInfo )
{
	SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD;
	SbiExpression aVar( this, SbSYMBOL, eMode, pKeywordSymbolInfo );

	bool bEQ = ( Peek() == EQ );
	if( !bEQ && bVBASupportOn && aVar.IsBracket() )
		Error( SbERR_EXPECTED, "=" );

	RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL );
	bool bSpecialMidHandling = false;
	SbiSymDef* pDef = aVar.GetRealVar();
	if( bEQ && pDef && pDef->GetScope() == SbRTL )
	{
		String aRtlName = pDef->GetName();
		if( aRtlName.EqualsIgnoreCaseAscii("Mid") )
		{
			SbiExprNode* pExprNode = aVar.GetExprNode();
			// SbiNodeType eNodeType;
			if( pExprNode && pExprNode->GetNodeType() == SbxVARVAL )
			{
				SbiExprList* pPar = pExprNode->GetParameters();
				short nParCount = pPar ? pPar->GetSize() : 0;
				if( nParCount == 2 || nParCount == 3 )
				{
					if( nParCount == 2 )
						pPar->addExpression( new SbiExpression( this, -1, SbxLONG ) );

					TestToken( EQ );
					pPar->addExpression( new SbiExpression( this ) );

					bSpecialMidHandling = true;
				}
			}
		}
	}
	aVar.Gen( eRecMode );
	if( !bSpecialMidHandling )
	{
		if( !bEQ )
		{
			aGen.Gen( _GET );
		}
		else
		{
			// Dann muss es eine Zuweisung sein. Was anderes gibts nicht!
			if( !aVar.IsLvalue() )
				Error( SbERR_LVALUE_EXPECTED );
			TestToken( EQ );
			SbiExpression aExpr( this );
			aExpr.Gen();
			SbiOpcode eOp = _PUT;
			// SbiSymDef* pDef = aVar.GetRealVar();
			if( pDef )
			{
				if( pDef->GetConstDef() )
					Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
				if( pDef->GetType() == SbxOBJECT )
				{
					eOp = _SET;
					if( pDef->GetTypeId() )
					{
						aGen.Gen( _SETCLASS, pDef->GetTypeId() );
						return;
					}
				}
			}
			aGen.Gen( eOp );
		}
	}
}

// Zuweisungen

void SbiParser::Assign()
{
	SbiExpression aLvalue( this, SbLVALUE );
	TestToken( EQ );
	SbiExpression aExpr( this );
	aLvalue.Gen();
	aExpr.Gen();
	sal_uInt16 nLen = 0;
	SbiSymDef* pDef = aLvalue.GetRealVar();
	{
		if( pDef->GetConstDef() )
			Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
		nLen = aLvalue.GetRealVar()->GetLen();
	}
	if( nLen )
		aGen.Gen( _PAD, nLen );
	aGen.Gen( _PUT );
}

// Zuweisungen einer Objektvariablen

void SbiParser::Set()
{
	SbiExpression aLvalue( this, SbLVALUE );
	SbxDataType eType = aLvalue.GetType();
	if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT )
		Error( SbERR_INVALID_OBJECT );
	TestToken( EQ );
	SbiSymDef* pDef = aLvalue.GetRealVar();
	if( pDef && pDef->GetConstDef() )
		Error( SbERR_DUPLICATE_DEF, pDef->GetName() );

	SbiToken eTok = Peek();
	if( eTok == NEW )
	{
		Next();
		String aStr;
		SbiSymDef* pTypeDef = new SbiSymDef( aStr );
		TypeDecl( *pTypeDef, sal_True );

		aLvalue.Gen();
		// aGen.Gen( _CLASS, pDef->GetTypeId() | 0x8000 );
		aGen.Gen( _CREATE, pDef->GetId(), pTypeDef->GetTypeId() );
		aGen.Gen( _SETCLASS, pDef->GetTypeId() );
	}
	else
	{
		SbiExpression aExpr( this );
		aLvalue.Gen();
		aExpr.Gen();
		// Its a good idea to distinguish between
		// set someting = another & 
		// someting = another  
		// ( its necessary for vba objects where set is object
		// specific and also doesn't involve processing default params )
		if( pDef->GetTypeId() )
		{
			if ( bVBASupportOn )
				aGen.Gen( _VBASETCLASS, pDef->GetTypeId() );
			else
				aGen.Gen( _SETCLASS, pDef->GetTypeId() );
		}
		else
		{
			if ( bVBASupportOn )
				aGen.Gen( _VBASET );
			else
				aGen.Gen( _SET );
		}
	}
	// aGen.Gen( _SET );
}

// JSM 07.10.95
void SbiParser::LSet()
{
	SbiExpression aLvalue( this, SbLVALUE );
	if( aLvalue.GetType() != SbxSTRING )
		Error( SbERR_INVALID_OBJECT );
	TestToken( EQ );
	SbiSymDef* pDef = aLvalue.GetRealVar();
	if( pDef && pDef->GetConstDef() )
		Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
	SbiExpression aExpr( this );
	aLvalue.Gen();
	aExpr.Gen();
	aGen.Gen( _LSET );
}

// JSM 07.10.95
void SbiParser::RSet()
{
	SbiExpression aLvalue( this, SbLVALUE );
	if( aLvalue.GetType() != SbxSTRING )
		Error( SbERR_INVALID_OBJECT );
	TestToken( EQ );
	SbiSymDef* pDef = aLvalue.GetRealVar();
	if( pDef && pDef->GetConstDef() )
		Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
	SbiExpression aExpr( this );
	aLvalue.Gen();
	aExpr.Gen();
	aGen.Gen( _RSET );
}

// DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR und so weiter

void SbiParser::DefXXX()
{
	sal_Unicode ch1, ch2;
	SbxDataType t = SbxDataType( eCurTok - DEFINT + SbxINTEGER );

	while( !bAbort )
	{
		if( Next() != SYMBOL ) break;
		ch1 = aSym.ToUpperAscii().GetBuffer()[0];
		ch2 = 0;
		if( Peek() == MINUS )
		{
			Next();
			if( Next() != SYMBOL ) Error( SbERR_SYMBOL_EXPECTED );
			else
			{
				ch2 = aSym.ToUpperAscii().GetBuffer()[0];
				//ch2 = aSym.Upper();
				if( ch2 < ch1 ) Error( SbERR_SYNTAX ), ch2 = 0;
			}
		}
		if (!ch2) ch2 = ch1;
		ch1 -= 'A'; ch2 -= 'A';
		for (; ch1 <= ch2; ch1++) eDefTypes[ ch1 ] = t;
		if( !TestComma() ) break;
	}
}

// STOP/SYSTEM

void SbiParser::Stop()
{
	aGen.Gen( _STOP );
	Peek();		// #35694: Nur Peek(), damit EOL in Single-Line-If erkannt wird
}

// IMPLEMENTS

void SbiParser::Implements()
{
	if( !bClassModule )
	{
		Error( SbERR_UNEXPECTED, IMPLEMENTS );
		return;
	}

	Peek();
	if( eCurTok != SYMBOL )
	{
		Error( SbERR_SYMBOL_EXPECTED );
		return;
	}

	String aImplementedIface = aSym;
	Next();
	if( Peek() == DOT )
	{
		String aDotStr( '.' );
		while( Peek() == DOT )
		{
			aImplementedIface += aDotStr;
			Next();
            SbiToken ePeekTok = Peek();
			if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) )
			{
				Next();
				aImplementedIface += aSym;
			}
			else
			{
				Next();
				Error( SbERR_SYMBOL_EXPECTED );
				break;
			}
		}
	}
	aIfaceVector.push_back( aImplementedIface );
}

void SbiParser::EnableCompatibility()
{
	if( !bCompatible )
		AddConstants();
	bCompatible = sal_True; 
}

// OPTION

void SbiParser::Option()
{
	switch( Next() )
	{
		case BASIC_EXPLICIT:
			bExplicit = sal_True; break;
		case BASE:
			if( Next() == NUMBER )
			{
				if( nVal == 0 || nVal == 1 )
				{
					nBase = (short) nVal;
					break;
				}
			}
			Error( SbERR_EXPECTED, "0/1" );
			break;
		case PRIVATE:
		{
			String aString = SbiTokenizer::Symbol(Next());
			if( !aString.EqualsIgnoreCaseAscii("Module") )
				Error( SbERR_EXPECTED, "Module" );
			break;
		}
		case COMPARE:
		{
			SbiToken eTok = Next();
			if( eTok == BINARY )
				bText = sal_False;
			else if( eTok == SYMBOL && GetSym().EqualsIgnoreCaseAscii("text") )
				bText = sal_True;
			else
				Error( SbERR_EXPECTED, "Text/Binary" );
			break;
		}
		case COMPATIBLE:
			EnableCompatibility();
			break;

		case CLASSMODULE:
			bClassModule = sal_True; 
			aGen.GetModule().SetModuleType( com::sun::star::script::ModuleType::CLASS );
			break;
		case VBASUPPORT:
			if( Next() == NUMBER )
			{
				if ( nVal == 1 || nVal == 0 )
				{
					bVBASupportOn = ( nVal == 1 );
					if ( bVBASupportOn )
						EnableCompatibility();
					// if the module setting is different
					// reset it to what the Option tells us
					if ( bVBASupportOn != aGen.GetModule().IsVBACompat() )
						aGen.GetModule().SetVBACompat( bVBASupportOn );
					break;
				}
			}
			Error( SbERR_EXPECTED, "0/1" );
			break;
		default:
			Error( SbERR_BAD_OPTION, eCurTok );
	}
}

void addStringConst( SbiSymPool& rPool, const char* pSym, const String& rStr )
{
	SbiConstDef* pConst = new SbiConstDef( String::CreateFromAscii( pSym ) );
	pConst->SetType( SbxSTRING );
	pConst->Set( rStr );
	rPool.Add( pConst );
}

inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
{
	addStringConst( rPool, pSym, String::CreateFromAscii( pStr ) );
}

void SbiParser::AddConstants( void )
{
	// #113063 Create constant RTL symbols
	addStringConst( aPublics, "vbCr", "\x0D" );
	addStringConst( aPublics, "vbCrLf", "\x0D\x0A" );
	addStringConst( aPublics, "vbFormFeed", "\x0C" );
	addStringConst( aPublics, "vbLf", "\x0A" );
#if defined(UNX)
	addStringConst( aPublics, "vbNewLine", "\x0A" );
#else
	addStringConst( aPublics, "vbNewLine", "\x0D\x0A" );
#endif
	addStringConst( aPublics, "vbNullString", "" );
	addStringConst( aPublics, "vbTab", "\x09" );
	addStringConst( aPublics, "vbVerticalTab", "\x0B" );

	// Force length 1 and make char 0 afterwards
	String aNullCharStr( String::CreateFromAscii( " " ) );
	aNullCharStr.SetChar( 0, 0 );
	addStringConst( aPublics, "vbNullChar", aNullCharStr );
}

// ERROR n

void SbiParser::ErrorStmnt()
{
	SbiExpression aPar( this );
	aPar.Gen();
	aGen.Gen( _ERROR );
}

