2010-10-12 15:53:47 +02:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2000-09-18 15:18:56 +00:00
/*************************************************************************
*
2008-04-11 10:51:42 +00:00
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
2005-09-29 11:48:38 +00:00
*
2010-02-12 15:01:35 +01:00
* Copyright 2000 , 2010 Oracle and / or its affiliates .
2005-09-29 11:48:38 +00:00
*
2008-04-11 10:51:42 +00:00
* OpenOffice . org - a multi - platform office productivity suite
2000-09-18 15:18:56 +00:00
*
2008-04-11 10:51:42 +00:00
* This file is part of OpenOffice . org .
2000-09-18 15:18:56 +00:00
*
2008-04-11 10:51:42 +00:00
* 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 .
2000-09-18 15:18:56 +00:00
*
2008-04-11 10:51:42 +00:00
* 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 ) .
2000-09-18 15:18:56 +00:00
*
2008-04-11 10:51:42 +00:00
* 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 .
2000-09-18 15:18:56 +00:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-17 09:03:03 +00:00
// MARKER(update_precomp.py): autogen include statement, do not remove
# include "precompiled_basic.hxx"
2007-06-27 13:20:42 +00:00
# include <basic/sbx.hxx>
2000-09-18 15:18:56 +00:00
# include "sbcomp.hxx"
2010-04-16 17:28:52 +02:00
# include <com/sun/star/script/ModuleType.hpp>
2000-09-18 15:18:56 +00:00
struct SbiParseStack { // "Stack" fuer Statement-Blocks
SbiParseStack * pNext ; // Chain
SbiExprNode * pWithVar ; // Variable fuer WITH
SbiToken eExitTok ; // Exit-Token
2011-01-10 14:40:57 +01:00
sal_uInt32 nChain ; // JUMP-Chain
2000-09-18 15:18:56 +00:00
} ;
struct SbiStatement {
SbiToken eTok ;
void ( SbiParser : : * Func ) ( ) ; // Verarbeitungsroutine
2011-01-10 14:40:57 +01:00
sal_Bool bMain ; // sal_True: ausserhalb SUBs OK
sal_Bool bSubr ; // sal_True: in SUBs OK
2000-09-18 15:18:56 +00:00
} ;
2011-01-10 14:40:57 +01:00
# define Y sal_True
# define N sal_False
2000-09-18 15:18:56 +00:00
static SbiStatement StmntTable [ ] = {
2010-10-06 10:16:27 +01:00
{ ATTRIBUTE , & SbiParser : : Attribute , Y , Y , } , // ATTRIBUTE
2001-05-17 08:43:07 +00:00
{ 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
2004-11-15 15:34:56 +00:00
{ ENUM , & SbiParser : : Enum , Y , N , } , // TYPE
2001-05-17 08:43:07 +00:00
{ 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
2005-03-29 10:49:55 +00:00
{ IMPLEMENTS , & SbiParser : : Implements , Y , N , } , // IMPLEMENTS
2001-05-17 08:43:07 +00:00
{ INPUT , & SbiParser : : Input , N , Y , } , // INPUT
{ LET , & SbiParser : : Assign , N , Y , } , // LET
2010-06-15 20:02:53 +02:00
{ LINE , & SbiParser : : Line , N , Y , } , // LINE, -> LINE INPUT (#i92642)
2001-05-17 08:43:07 +00:00
{ 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
2004-11-02 10:54:14 +00:00
{ PROPERTY , & SbiParser : : SubFunc , Y , N , } , // FUNCTION
2001-05-17 08:43:07 +00:00
{ 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
2000-09-18 15:18:56 +00:00
2006-06-19 16:42:42 +00:00
{ NIL , NULL , N , N }
2000-09-18 15:18:56 +00:00
} ;
2007-09-06 12:54:06 +00:00
# ifdef _MSC_VER
2000-09-18 15:18:56 +00:00
// 'this' : used in base member initializer list
# pragma warning( disable: 4355 )
# endif
SbiParser : : SbiParser ( StarBASIC * pb , SbModule * pm )
2003-04-23 15:56:49 +00:00
: SbiTokenizer ( pm - > GetSource32 ( ) , pb ) ,
2000-09-18 15:18:56 +00:00
aGblStrings ( this ) ,
aLclStrings ( this ) ,
aGlobals ( aGblStrings , SbGLOBAL ) ,
2006-06-19 16:42:42 +00:00
aPublics ( aGblStrings , SbPUBLIC ) ,
2000-09-18 15:18:56 +00:00
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 =
2011-01-10 14:40:57 +01:00
bExplicit = sal_False ;
2010-04-16 17:28:52 +02:00
bClassModule = ( pm - > GetModuleType ( ) = = com : : sun : : star : : script : : ModuleType : : CLASS ) ;
2010-03-02 12:39:31 +00:00
OSL_TRACE ( " Parser - %s, bClassModule %d " , rtl : : OUStringToOString ( pm - > GetName ( ) , RTL_TEXTENCODING_UTF8 ) . getStr ( ) , bClassModule ) ;
2000-09-18 15:18:56 +00:00
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
2004-11-15 15:34:56 +00:00
rEnumArray = new SbxArray ; // Array for Enum types
2010-03-02 12:39:31 +00:00
bVBASupportOn = pm - > IsVBACompat ( ) ;
if ( bVBASupportOn )
EnableCompatibility ( ) ;
2000-09-18 15:18:56 +00:00
}
// 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 ) ) )
{
2006-06-19 16:42:42 +00:00
SbiProcDef * pProc_ = aRtlSyms . AddProc ( rSym ) ;
pProc_ - > SetType ( pVar - > GetType ( ) ) ;
pDef = pProc_ ;
2000-09-18 15:18:56 +00:00
}
else
{
pDef = aRtlSyms . AddSym ( rSym ) ;
pDef - > SetType ( eType ) ;
}
}
return pDef ;
}
// Globale Chainkette schliessen
2011-01-10 14:40:57 +01:00
sal_Bool SbiParser : : HasGlobalCode ( )
2000-09-18 15:18:56 +00:00
{
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 )
{
2010-06-15 20:02:53 +02:00
SbiToken eExitTok = p - > eExitTok ;
if ( eTok = = eExitTok | |
( eTok = = PROPERTY & & ( eExitTok = = GET | | eExitTok = = LET ) ) ) // #i109051
2000-09-18 15:18:56 +00:00
{
p - > nChain = aGen . Gen ( _JUMP , p - > nChain ) ;
return ;
}
}
if ( pStack )
Error ( SbERR_EXPECTED , pStack - > eExitTok ) ;
else
Error ( SbERR_BAD_EXIT ) ;
}
2011-01-10 14:40:57 +01:00
sal_Bool SbiParser : : TestSymbol ( sal_Bool bKwdOk )
2000-09-18 15:18:56 +00:00
{
Peek ( ) ;
if ( eCurTok = = SYMBOL | | ( bKwdOk & & IsKwd ( eCurTok ) ) )
{
2011-01-10 14:40:57 +01:00
Next ( ) ; return sal_True ;
2000-09-18 15:18:56 +00:00
}
Error ( SbERR_SYMBOL_EXPECTED ) ;
2011-01-10 14:40:57 +01:00
return sal_False ;
2000-09-18 15:18:56 +00:00
}
// Testen auf ein bestimmtes Token
2011-01-10 14:40:57 +01:00
sal_Bool SbiParser : : TestToken ( SbiToken t )
2000-09-18 15:18:56 +00:00
{
if ( Peek ( ) = = t )
{
2011-01-10 14:40:57 +01:00
Next ( ) ; return sal_True ;
2000-09-18 15:18:56 +00:00
}
else
{
Error ( SbERR_EXPECTED , t ) ;
2011-01-10 14:40:57 +01:00
return sal_False ;
2000-09-18 15:18:56 +00:00
}
}
// Testen auf Komma oder EOLN
2011-01-10 14:40:57 +01:00
sal_Bool SbiParser : : TestComma ( )
2000-09-18 15:18:56 +00:00
{
SbiToken eTok = Peek ( ) ;
if ( IsEoln ( eTok ) )
{
Next ( ) ;
2011-01-10 14:40:57 +01:00
return sal_False ;
2000-09-18 15:18:56 +00:00
}
else if ( eTok ! = COMMA )
{
Error ( SbERR_EXPECTED , COMMA ) ;
2011-01-10 14:40:57 +01:00
return sal_False ;
2000-09-18 15:18:56 +00:00
}
Next ( ) ;
2011-01-10 14:40:57 +01:00
return sal_True ;
2000-09-18 15:18:56 +00:00
}
// 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 ) ;
2011-01-10 14:40:57 +01:00
bAbort = sal_True ;
2000-09-18 15:18:56 +00:00
}
}
// Die Hauptroutine. Durch wiederholten Aufrufs dieser Routine wird
2011-01-10 14:40:57 +01:00
// die Quelle geparst. Returnwert sal_False bei Ende/Fehlern.
2000-09-18 15:18:56 +00:00
2011-01-10 14:40:57 +01:00
sal_Bool SbiParser : : Parse ( )
2000-09-18 15:18:56 +00:00
{
2011-01-10 14:40:57 +01:00
if ( bAbort ) return sal_False ;
2000-09-18 15:18:56 +00:00
EnableErrors ( ) ;
2006-05-05 07:48:18 +00:00
bErrorIsSymbol = false ;
2000-09-18 15:18:56 +00:00
Peek ( ) ;
2006-05-05 07:48:18 +00:00
bErrorIsSymbol = true ;
2000-09-18 15:18:56 +00:00
// 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 ) ;
2011-01-10 14:40:57 +01:00
return sal_False ;
2000-09-18 15:18:56 +00:00
}
// Leerstatement?
if ( IsEoln ( eCurTok ) )
{
2011-01-10 14:40:57 +01:00
Next ( ) ; return sal_True ;
2000-09-18 15:18:56 +00:00
}
2011-01-10 14:40:57 +01:00
if ( ! bSingleLineIf & & MayBeLabel ( sal_True ) )
2000-09-18 15:18:56 +00:00
{
// Ist ein Label
if ( ! pProc )
Error ( SbERR_NOT_IN_MAIN , aSym ) ;
else
pProc - > GetLabels ( ) . Define ( aSym ) ;
Next ( ) ; Peek ( ) ;
// Leerstatement?
if ( IsEoln ( eCurTok ) )
{
2011-01-10 14:40:57 +01:00
Next ( ) ; return sal_True ;
2000-09-18 15:18:56 +00:00
}
}
// Ende des Parsings?
2010-06-15 20:02:53 +02:00
if ( eCurTok = = eEndTok | |
( bVBASupportOn & & // #i109075
( eCurTok = = ENDFUNC | | eCurTok = = ENDPROPERTY | | eCurTok = = ENDSUB ) & &
( eEndTok = = ENDFUNC | | eEndTok = = ENDPROPERTY | | eEndTok = = ENDSUB ) ) )
2000-09-18 15:18:56 +00:00
{
Next ( ) ;
if ( eCurTok ! = NIL )
aGen . Statement ( ) ;
2011-01-10 14:40:57 +01:00
return sal_False ;
2000-09-18 15:18:56 +00:00
}
// Kommentar?
if ( eCurTok = = REM )
{
2011-01-10 14:40:57 +01:00
Next ( ) ; return sal_True ;
2000-09-18 15:18:56 +00:00
}
2010-10-06 10:16:27 +01:00
// 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 ;
}
}
2000-09-18 15:18:56 +00:00
// 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 ( ) ;
2008-06-24 15:02:11 +00:00
Symbol ( ) ;
2000-09-18 15:18:56 +00:00
}
}
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 ) ;
2001-05-17 08:43:07 +00:00
else if ( pProc & & ! p - > bSubr )
2000-09-18 15:18:56 +00:00
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
2004-11-02 10:54:14 +00:00
if ( bNewGblDefs & & nGblChain = = 0 & &
( eCurTok = = SUB | | eCurTok = = FUNCTION | | eCurTok = = PROPERTY ) )
2000-09-18 15:18:56 +00:00
{
nGblChain = aGen . Gen ( _JUMP , 0 ) ;
2011-01-10 14:40:57 +01:00
bNewGblDefs = sal_False ;
2000-09-18 15:18:56 +00:00
}
// 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!
2011-01-10 14:40:57 +01:00
return sal_True ;
2000-09-18 15:18:56 +00:00
}
// 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
2010-06-15 20:02:53 +02:00
void SbiParser : : Symbol ( const KeywordSymbolInfo * pKeywordSymbolInfo )
2000-09-18 15:18:56 +00:00
{
2008-06-24 15:02:11 +00:00
SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD ;
2010-06-15 20:02:53 +02:00
SbiExpression aVar ( this , SbSYMBOL , eMode , pKeywordSymbolInfo ) ;
2003-05-22 07:53:47 +00:00
2003-04-23 15:56:49 +00:00
bool bEQ = ( Peek ( ) = = EQ ) ;
2008-06-24 15:02:11 +00:00
if ( ! bEQ & & bVBASupportOn & & aVar . IsBracket ( ) )
Error ( SbERR_EXPECTED , " = " ) ;
2003-05-22 07:53:47 +00:00
RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL ) ;
2006-05-05 07:48:18 +00:00
bool bSpecialMidHandling = false ;
SbiSymDef * pDef = aVar . GetRealVar ( ) ;
if ( bEQ & & pDef & & pDef - > GetScope ( ) = = SbRTL )
2000-09-18 15:18:56 +00:00
{
2006-05-05 07:48:18 +00:00
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 ;
}
}
}
2000-09-18 15:18:56 +00:00
}
2006-05-05 07:48:18 +00:00
aVar . Gen ( eRecMode ) ;
if ( ! bSpecialMidHandling )
2000-09-18 15:18:56 +00:00
{
2006-05-05 07:48:18 +00:00
if ( ! bEQ )
{
aGen . Gen ( _GET ) ;
}
else
2000-09-18 15:18:56 +00:00
{
2006-05-05 07:48:18 +00:00
// 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 )
2000-09-18 15:18:56 +00:00
{
2006-05-05 07:48:18 +00:00
if ( pDef - > GetConstDef ( ) )
Error ( SbERR_DUPLICATE_DEF , pDef - > GetName ( ) ) ;
if ( pDef - > GetType ( ) = = SbxOBJECT )
2005-03-29 10:49:55 +00:00
{
2006-05-05 07:48:18 +00:00
eOp = _SET ;
if ( pDef - > GetTypeId ( ) )
{
aGen . Gen ( _SETCLASS , pDef - > GetTypeId ( ) ) ;
return ;
}
2005-03-29 10:49:55 +00:00
}
2000-09-18 15:18:56 +00:00
}
2006-05-05 07:48:18 +00:00
aGen . Gen ( eOp ) ;
2000-09-18 15:18:56 +00:00
}
}
}
// Zuweisungen
void SbiParser : : Assign ( )
{
SbiExpression aLvalue ( this , SbLVALUE ) ;
TestToken ( EQ ) ;
SbiExpression aExpr ( this ) ;
aLvalue . Gen ( ) ;
aExpr . Gen ( ) ;
2011-01-10 14:40:57 +01:00
sal_uInt16 nLen = 0 ;
2000-09-18 15:18:56 +00:00
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 ) ;
2004-03-17 12:33:25 +00:00
SbxDataType eType = aLvalue . GetType ( ) ;
if ( eType ! = SbxOBJECT & & eType ! = SbxEMPTY & & eType ! = SbxVARIANT )
2000-09-18 15:18:56 +00:00
Error ( SbERR_INVALID_OBJECT ) ;
TestToken ( EQ ) ;
SbiSymDef * pDef = aLvalue . GetRealVar ( ) ;
if ( pDef & & pDef - > GetConstDef ( ) )
Error ( SbERR_DUPLICATE_DEF , pDef - > GetName ( ) ) ;
2004-03-17 12:33:25 +00:00
SbiToken eTok = Peek ( ) ;
if ( eTok = = NEW )
{
Next ( ) ;
String aStr ;
2005-03-29 10:49:55 +00:00
SbiSymDef * pTypeDef = new SbiSymDef ( aStr ) ;
2011-01-10 14:40:57 +01:00
TypeDecl ( * pTypeDef , sal_True ) ;
2004-03-17 12:33:25 +00:00
aLvalue . Gen ( ) ;
2005-03-29 10:49:55 +00:00
aGen . Gen ( _CREATE , pDef - > GetId ( ) , pTypeDef - > GetTypeId ( ) ) ;
aGen . Gen ( _SETCLASS , pDef - > GetTypeId ( ) ) ;
2004-03-17 12:33:25 +00:00
}
else
{
SbiExpression aExpr ( this ) ;
aLvalue . Gen ( ) ;
aExpr . Gen ( ) ;
2006-11-02 15:32:13 +00:00
// 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 )
2004-03-17 12:33:25 +00:00
if ( pDef - > GetTypeId ( ) )
2007-08-30 09:00:07 +00:00
{
if ( bVBASupportOn )
aGen . Gen ( _VBASETCLASS , pDef - > GetTypeId ( ) ) ;
else
aGen . Gen ( _SETCLASS , pDef - > GetTypeId ( ) ) ;
}
2005-03-29 10:49:55 +00:00
else
2006-11-02 15:32:13 +00:00
{
if ( bVBASupportOn )
aGen . Gen ( _VBASET ) ;
else
aGen . Gen ( _SET ) ;
}
2004-03-17 12:33:25 +00:00
}
2000-09-18 15:18:56 +00:00
}
// 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
}
2005-03-29 10:49:55 +00:00
// IMPLEMENTS
void SbiParser : : Implements ( )
{
if ( ! bClassModule )
{
Error ( SbERR_UNEXPECTED , IMPLEMENTS ) ;
return ;
}
2010-06-15 20:02:53 +02:00
Peek ( ) ;
if ( eCurTok ! = SYMBOL )
{
Error ( SbERR_SYMBOL_EXPECTED ) ;
return ;
}
String aImplementedIface = aSym ;
Next ( ) ;
if ( Peek ( ) = = DOT )
2005-03-29 10:49:55 +00:00
{
2010-06-15 20:02:53 +02:00
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 ;
}
}
2005-03-29 10:49:55 +00:00
}
2010-06-15 20:02:53 +02:00
aIfaceVector . push_back ( aImplementedIface ) ;
2005-03-29 10:49:55 +00:00
}
2006-05-05 09:11:46 +00:00
void SbiParser : : EnableCompatibility ( )
{
if ( ! bCompatible )
AddConstants ( ) ;
2011-01-10 14:40:57 +01:00
bCompatible = sal_True ;
2006-05-05 09:11:46 +00:00
}
2000-09-18 15:18:56 +00:00
// OPTION
void SbiParser : : Option ( )
{
switch ( Next ( ) )
{
case EXPLICIT :
2011-01-10 14:40:57 +01:00
bExplicit = sal_True ; break ;
2000-09-18 15:18:56 +00:00
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 :
2010-06-15 20:02:53 +02:00
{
SbiToken eTok = Next ( ) ;
if ( eTok = = BINARY )
2011-01-10 14:40:57 +01:00
bText = sal_False ;
2010-06-15 20:02:53 +02:00
else if ( eTok = = SYMBOL & & GetSym ( ) . EqualsIgnoreCaseAscii ( " text " ) )
2011-01-10 14:40:57 +01:00
bText = sal_True ;
2010-06-15 20:02:53 +02:00
else
Error ( SbERR_EXPECTED , " Text/Binary " ) ;
break ;
}
2004-03-17 12:33:25 +00:00
case COMPATIBLE :
2006-05-05 09:11:46 +00:00
EnableCompatibility ( ) ;
2004-03-17 12:33:25 +00:00
break ;
2004-11-02 10:54:14 +00:00
case CLASSMODULE :
2011-01-10 14:40:57 +01:00
bClassModule = sal_True ;
2010-04-16 17:28:52 +02:00
aGen . GetModule ( ) . SetModuleType ( com : : sun : : star : : script : : ModuleType : : CLASS ) ;
2004-11-02 10:54:14 +00:00
break ;
2010-10-06 10:16:27 +01:00
case VBASUPPORT : // Option VBASupport used to override the module mode ( in fact this must reset the mode
2006-05-05 09:11:46 +00:00
if ( Next ( ) = = NUMBER )
{
if ( nVal = = 1 | | nVal = = 0 )
{
bVBASupportOn = ( nVal = = 1 ) ;
if ( bVBASupportOn )
EnableCompatibility ( ) ;
2010-03-02 12:39:31 +00:00
// if the module setting is different
// reset it to what the Option tells us
if ( bVBASupportOn ! = aGen . GetModule ( ) . IsVBACompat ( ) )
aGen . GetModule ( ) . SetVBACompat ( bVBASupportOn ) ;
2006-05-05 09:11:46 +00:00
break ;
}
}
Error ( SbERR_EXPECTED , " 0/1 " ) ;
break ;
2000-09-18 15:18:56 +00:00
default :
Error ( SbERR_BAD_OPTION , eCurTok ) ;
}
}
2005-03-29 10:49:55 +00:00
void addStringConst ( SbiSymPool & rPool , const char * pSym , const String & rStr )
2004-03-17 12:33:25 +00:00
{
SbiConstDef * pConst = new SbiConstDef ( String : : CreateFromAscii ( pSym ) ) ;
pConst - > SetType ( SbxSTRING ) ;
2005-03-29 10:49:55 +00:00
pConst - > Set ( rStr ) ;
2004-03-17 12:33:25 +00:00
rPool . Add ( pConst ) ;
}
2005-03-29 10:49:55 +00:00
inline void addStringConst ( SbiSymPool & rPool , const char * pSym , const char * pStr )
{
addStringConst ( rPool , pSym , String : : CreateFromAscii ( pStr ) ) ;
}
2004-03-17 12:33:25 +00:00
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
2005-03-29 10:49:55 +00:00
addStringConst ( aPublics , " vbNullString " , " " ) ;
2004-03-17 12:33:25 +00:00
addStringConst ( aPublics , " vbTab " , " \x09 " ) ;
addStringConst ( aPublics , " vbVerticalTab " , " \x0B " ) ;
2005-03-29 10:49:55 +00:00
// Force length 1 and make char 0 afterwards
String aNullCharStr ( String : : CreateFromAscii ( " " ) ) ;
aNullCharStr . SetChar ( 0 , 0 ) ;
addStringConst ( aPublics , " vbNullChar " , aNullCharStr ) ;
2004-03-17 12:33:25 +00:00
}
2000-09-18 15:18:56 +00:00
// ERROR n
void SbiParser : : ErrorStmnt ( )
{
SbiExpression aPar ( this ) ;
aPar . Gen ( ) ;
aGen . Gen ( _ERROR ) ;
}
2010-10-12 15:53:47 +02:00
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */