summaryrefslogtreecommitdiff
path: root/basic/source/comp/parser.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/comp/parser.cxx')
-rw-r--r--basic/source/comp/parser.cxx872
1 files changed, 872 insertions, 0 deletions
diff --git a/basic/source/comp/parser.cxx b/basic/source/comp/parser.cxx
new file mode 100644
index 000000000000..2ea78357882f
--- /dev/null
+++ b/basic/source/comp/parser.cxx
@@ -0,0 +1,872 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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 [] = {
+{ ATTRIBUTE, &SbiParser::Attribute, Y, Y, }, // ATTRIBUTE
+{ 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( pVar->IsA( TYPE(SbxMethod) ) )
+ {
+ 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 );
+ 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;
+ }
+
+ // In vba it's possible to do Error.foobar ( even if it results in
+ // a runtime error
+ if ( eCurTok == _ERROR_ && IsVBASupportOn() ) // we probably need to define a subset of keywords where this madness applies e.g. if ( IsVBASupportOn() && SymbolCanBeRedined( eCurTok ) )
+ {
+ SbiTokenizer tokens( *(SbiTokenizer*)this );
+ tokens.Next();
+ if ( tokens.Peek() == DOT )
+ {
+ eCurTok = SYMBOL;
+ ePush = eCurTok;
+ }
+ }
+ // 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();
+ 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;
+ 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( _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 );
+ }
+ }
+}
+
+// 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];
+ 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 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: // Option VBASupport used to override the module mode ( in fact this must reset the mode
+ 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 );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */