1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dim.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
33 #include <basic/sbx.hxx>
35 #include "sbunoobj.hxx"
38 // Deklaration einer Variablen
39 // Bei Fehlern wird bis zum Komma oder Newline geparst.
40 // Returnwert: eine neue Instanz, die eingefuegt und dann geloescht wird.
41 // Array-Indexe werden als SbiDimList zurueckgegeben
43 SbiSymDef
* SbiParser::VarDecl( SbiDimList
** ppDim
, BOOL bStatic
, BOOL bConst
)
45 // Some keywords can be dim as varibles like " Sub Test( Name as String )"
47 BOOL bKwdOk
= IsVBASupportOn() ? BOOL( (eCurTok
== NAME
) || (eCurTok
== LINE
) || (eCurTok
== TEXT
) ): FALSE
;
48 if( !TestSymbol( bKwdOk
) ) return NULL
;
49 SbxDataType t
= eScanType
;
50 SbiSymDef
* pDef
= bConst
? new SbiConstDef( aSym
) : new SbiSymDef( aSym
);
51 SbiDimList
* pDim
= NULL
;
53 if( Peek() == LPAREN
)
54 pDim
= new SbiDimList( this );
62 Error( SbERR_EXPECTED
, "()" );
70 // Aufloesen einer AS-Typdeklaration
71 // Der Datentyp wird in die uebergebene Variable eingetragen
73 void SbiParser::TypeDecl( SbiSymDef
& rDef
, BOOL bAsNewAlreadyParsed
)
75 SbxDataType eType
= rDef
.GetType();
77 if( bAsNewAlreadyParsed
|| Peek() == AS
)
79 if( !bAsNewAlreadyParsed
)
83 SbiToken eTok
= Next();
84 if( !bAsNewAlreadyParsed
&& eTok
== NEW
)
93 Error( SbERR_SYNTAX
);
94 eType
= SbxVARIANT
; break;
108 Error( SbERR_SYNTAX
);
109 eType
= (eTok
==TBYTE
) ? SbxBYTE
: SbxDataType( eTok
- TINTEGER
+ SbxINTEGER
);
110 if( eType
== SbxSTRING
)
116 SbiConstExpression
aSize( this );
117 nSize
= aSize
.GetShortValue();
119 Error( SbERR_OUT_OF_RANGE
);
123 case SYMBOL
: // kann nur ein TYPE oder eine Objektklasse sein!
124 if( eScanType
!= SbxVARIANT
)
125 Error( SbERR_SYNTAX
);
128 String aCompleteName
= aSym
;
130 // #52709 DIM AS NEW fuer Uno mit voll-qualifizierten Namen
133 String
aDotStr( '.' );
134 while( Peek() == DOT
)
136 aCompleteName
+= aDotStr
;
138 SbiToken ePeekTok
= Peek();
139 if( ePeekTok
== SYMBOL
|| IsKwd( ePeekTok
) )
142 aCompleteName
+= aSym
;
147 Error( SbERR_UNEXPECTED
, SYMBOL
);
152 else if( rEnumArray
->Find( aCompleteName
, SbxCLASS_OBJECT
) || ( IsVBASupportOn() && VBAConstantHelper::instance().isVBAConstantType( aCompleteName
) ) )
158 // In den String-Pool uebernehmen
159 rDef
.SetTypeId( aGblStrings
.Add( aCompleteName
) );
163 case FIXSTRING
: // new syntax for complex UNO types
164 rDef
.SetTypeId( aGblStrings
.Add( aSym
) );
168 Error( SbERR_UNEXPECTED
, eTok
);
171 // Die Variable koennte mit Suffix deklariert sein
172 if( rDef
.GetType() != SbxVARIANT
)
174 if( rDef
.GetType() != eType
)
175 Error( SbERR_VAR_DEFINED
, rDef
.GetName() );
176 else if( eType
== SbxSTRING
&& rDef
.GetLen() != nSize
)
177 Error( SbERR_VAR_DEFINED
, rDef
.GetName() );
179 rDef
.SetType( eType
);
180 rDef
.SetLen( nSize
);
184 // Hier werden Variable, Arrays und Strukturen definiert.
185 // DIM/PRIVATE/PUBLIC/GLOBAL
187 void SbiParser::Dim()
189 DefVar( _DIM
, ( pProc
&& bVBASupportOn
) ? pProc
->IsStatic() : FALSE
);
192 void SbiParser::DefVar( SbiOpcode eOp
, BOOL bStatic
)
194 SbiSymPool
* pOldPool
= pPool
;
195 BOOL bSwitchPool
= FALSE
;
196 BOOL bPersistantGlobal
= FALSE
;
197 SbiToken eFirstTok
= eCurTok
;
198 if( pProc
&& ( eCurTok
== GLOBAL
|| eCurTok
== PUBLIC
|| eCurTok
== PRIVATE
) )
199 Error( SbERR_NOT_IN_SUBR
, eCurTok
);
200 if( eCurTok
== PUBLIC
|| eCurTok
== GLOBAL
)
202 bSwitchPool
= TRUE
; // im richtigen Moment auf globalen Pool schalten
203 if( eCurTok
== GLOBAL
)
204 bPersistantGlobal
= TRUE
;
206 // behavior in VBA is that a module scope variable's lifetime is
207 // tied to the document. e.g. a module scope variable is global
208 if( GetBasic()->IsDocBasic() && bVBASupportOn
&& !pProc
)
209 bPersistantGlobal
= TRUE
;
210 // PRIVATE ist Synonym fuer DIM
213 if( eCurTok
== _CONST_
)
215 else if( Peek() == _CONST_
)
216 Next(), bConst
= TRUE
;
218 // #110004 It can also be a sub/function
219 if( !bConst
&& (eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
||
220 eCurTok
== STATIC
|| eCurTok
== ENUM
|| eCurTok
== DECLARE
) )
222 // Next token is read here, because !bConst
223 bool bPrivate
= ( eFirstTok
== PRIVATE
);
225 if( eCurTok
== STATIC
)
228 DefStatic( bPrivate
);
230 else if( eCurTok
== DECLARE
)
233 DefDeclare( bPrivate
);
236 else if( eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
)
238 // End global chain if necessary (not done in
239 // SbiParser::Parse() under these conditions
240 if( bNewGblDefs
&& nGblChain
== 0 )
242 nGblChain
= aGen
.Gen( _JUMP
, 0 );
246 DefProc( FALSE
, bPrivate
);
249 else if( eCurTok
== ENUM
)
255 else if( eCurTok
== DECLARE
)
258 DefDeclare( bPrivate
);
267 // SHARED wird ignoriert
268 if( Peek() == SHARED
) Next();
273 // PRESERVE nur bei REDIM
274 if( Peek() == PRESERVE
)
280 Error( SbERR_UNEXPECTED
, eCurTok
);
285 // AB 9.7.97, #40689, Statics -> Modul-Initialisierung, in Sub ueberspringen
286 UINT32 nEndOfStaticLbl
= 0;
287 if( !bVBASupportOn
&& bStatic
)
289 nEndOfStaticLbl
= aGen
.Gen( _JUMP
, 0 );
290 aGen
.Statement(); // bei static hier nachholen
293 BOOL bDefined
= FALSE
;
294 while( ( pDef
= VarDecl( &pDim
, bStatic
, bConst
) ) != NULL
)
300 SbiSymDef
* pOld
= pPool
->Find( pDef
->GetName() );
301 // AB 31.3.1996, #25651#, auch in Runtime-Library suchen
302 BOOL bRtlSym
= FALSE
;
305 pOld
= CheckRTLForSym( pDef
->GetName(), SbxVARIANT
);
309 if( pOld
&& !(eOp
== _REDIM
|| eOp
== _REDIMP
) )
311 if( pDef
->GetScope() == SbLOCAL
&& pOld
->GetScope() != SbLOCAL
)
317 // Bei RTL-Symbol immer Fehler
318 if( !bRtlSym
&& (eOp
== _REDIM
|| eOp
== _REDIMP
) )
320 // Bei REDIM die Attribute vergleichen
321 SbxDataType eDefType
;
322 bool bError_
= false;
323 if( pOld
->IsStatic() )
327 else if( pOld
->GetType() != ( eDefType
= pDef
->GetType() ) )
329 if( !( eDefType
== SbxVARIANT
&& !pDef
->IsDefinedAs() ) )
333 Error( SbERR_VAR_DEFINED
, pDef
->GetName() );
336 Error( SbERR_VAR_DEFINED
, pDef
->GetName() );
337 delete pDef
; pDef
= pOld
;
342 // #36374: Variable vor Unterscheidung IsNew() anlegen
343 // Sonst Error bei Dim Identifier As New Type und option explicit
344 if( !bDefined
&& !(eOp
== _REDIM
|| eOp
== _REDIMP
)
345 && ( !bConst
|| pDef
->GetScope() == SbGLOBAL
) )
347 // Variable oder globale Konstante deklarieren
349 switch ( pDef
->GetScope() )
351 case SbGLOBAL
: eOp2
= bPersistantGlobal
? _GLOBAL_P
: _GLOBAL
;
353 case SbPUBLIC
: eOp2
= bPersistantGlobal
? _PUBLIC_P
: _PUBLIC
;
354 // AB 9.7.97, #40689, kein eigener Opcode mehr
355 if( bVBASupportOn
&& bStatic
)
360 global
: aGen
.BackChain( nGblChain
);
362 bGblDefs
= bNewGblDefs
= TRUE
;
364 default: eOp2
= _LOCAL
;
368 sal::static_int_cast
< UINT16
>( pDef
->GetType() ) );
371 // Initialisierung fuer selbstdefinierte Datentypen
372 // und per NEW angelegte Variable
373 if( pDef
->GetType() == SbxOBJECT
374 && pDef
->GetTypeId() )
376 if( !bCompatible
&& !pDef
->IsNew() )
378 String
aTypeName( aGblStrings
.Find( pDef
->GetTypeId() ) );
379 if( rTypeArray
->Find( aTypeName
, SbxCLASS_OBJECT
) == NULL
)
380 Error( SbERR_UNDEF_TYPE
, aTypeName
);
385 Error( SbERR_SYNTAX
);
392 SbiExpression
aExpr( this, *pDef
, NULL
);
394 aGen
.Gen( _REDIMP_ERASE
);
396 pDef
->SetDims( pDim
->GetDims() );
397 SbiExpression
aExpr2( this, *pDef
, pDim
);
399 aGen
.Gen( _DCREATE_REDIMP
, pDef
->GetId(), pDef
->GetTypeId() );
403 pDef
->SetDims( pDim
->GetDims() );
404 SbiExpression
aExpr( this, *pDef
, pDim
);
406 aGen
.Gen( _DCREATE
, pDef
->GetId(), pDef
->GetTypeId() );
411 SbiExpression
aExpr( this, *pDef
);
413 SbiOpcode eOp_
= pDef
->IsNew() ? _CREATE
: _TCREATE
;
414 aGen
.Gen( eOp_
, pDef
->GetId(), pDef
->GetTypeId() );
425 // Konstanten-Definition
428 Error( SbERR_SYNTAX
);
431 SbiExpression
aVar( this, *pDef
);
432 if( !TestToken( EQ
) )
433 goto MyBreak
; // AB 24.6.1996 (s.u.)
434 SbiConstExpression
aExpr( this );
435 if( !bDefined
&& aExpr
.IsValid() )
437 if( pDef
->GetScope() == SbGLOBAL
)
439 // Nur Code fuer globale Konstante erzeugen!
444 SbiConstDef
* pConst
= pDef
->GetConstDef();
445 if( aExpr
.GetType() == SbxSTRING
)
446 pConst
->Set( aExpr
.GetString() );
448 pConst
->Set( aExpr
.GetValue(), aExpr
.GetType() );
453 // Die Variable dimensionieren
454 // Bei REDIM die Var vorher loeschen
457 SbiExpression
aExpr( this, *pDef
, NULL
);
460 // delete the array but
461 // clear the variable ( this
462 // allows the processing of
463 // the param to happen as normal without errors ( ordinary ERASE just clears the array )
464 aGen
.Gen( _ERASE_CLEAR
);
468 else if( eOp
== _REDIMP
)
470 SbiExpression
aExpr( this, *pDef
, NULL
);
472 aGen
.Gen( _REDIMP_ERASE
);
474 pDef
->SetDims( pDim
->GetDims() );
475 if( bPersistantGlobal
)
476 pDef
->SetGlobal( TRUE
);
477 SbiExpression
aExpr( this, *pDef
, pDim
);
479 pDef
->SetGlobal( FALSE
);
480 aGen
.Gen( (eOp
== _STATIC
) ? _DIM
: eOp
);
484 goto MyBreak
; // AB 24.6.1996 (s.u.)
486 // #27963# AB, 24.6.1996
487 // Einfuehrung bSwitchPool (s.o.): pPool darf beim VarDecl-Aufruf
488 // noch nicht auf &aGlobals gesetzt sein.
489 // Ansonsten soll das Verhalten aber absolut identisch bleiben,
490 // d.h. pPool muss immer am Schleifen-Ende zurueckgesetzt werden.
493 continue; // MyBreak überspingen
499 // AB 9.7.97, #40689, Sprung ueber Statics-Deklaration abschliessen
500 if( !bVBASupportOn
&& bStatic
)
502 // globalen Chain pflegen
503 nGblChain
= aGen
.Gen( _JUMP
, 0 );
504 bGblDefs
= bNewGblDefs
= TRUE
;
506 // fuer Sub Sprung auf Ende der statics eintragen
507 aGen
.BackChain( nEndOfStaticLbl
);
513 // Hier werden Arrays redimensioniert.
515 void SbiParser::ReDim()
517 DefVar( _REDIM
, ( pProc
&& bVBASupportOn
) ? pProc
->IsStatic() : FALSE
);
522 void SbiParser::Erase()
526 if( !TestSymbol() ) return;
527 String
aName( aSym
);
528 SbxDataType eType
= eScanType
;
529 SbiSymDef
* pDef
= pPool
->Find( aName
);
533 Error( SbERR_UNDEF_VAR
, aName
);
534 pDef
= pPool
->AddSym( aName
);
535 pDef
->SetType( eType
);
537 SbiExpression
aExpr( this, *pDef
);
540 if( !TestComma() ) break;
544 // Deklaration eines Datentyps
546 void SbiParser::Type()
551 void SbiParser::DefType( BOOL bPrivate
)
553 // TODO: Use bPrivate
556 // Neues Token lesen, es muss ein Symbol sein
560 if (rTypeArray
->Find(aSym
,SbxCLASS_OBJECT
))
562 Error( SbERR_VAR_DEFINED
, aSym
);
566 SbxObject
*pType
= new SbxObject(aSym
);
569 SbiDimList
* pDim
= NULL
;
572 while( !bDone
&& !IsEof() )
590 pElem
= VarDecl(&pDim
,FALSE
,FALSE
);
592 bDone
= TRUE
; // Error occured
596 SbxArray
*pTypeMembers
= pType
-> GetProperties();
597 if (pTypeMembers
-> Find (pElem
->GetName(),SbxCLASS_DONTCARE
))
598 Error (SbERR_VAR_DEFINED
);
601 SbxProperty
*pTypeElem
= new SbxProperty (pElem
->GetName(),pElem
->GetType());
604 SbxDimArray
* pArray
= new SbxDimArray( pElem
->GetType() );
605 if ( pDim
->GetSize() )
607 // Dimension the target array
609 for ( short i
=0; i
<pDim
->GetSize();++i
)
613 SbiExprNode
* pNode
= pDim
->Get(i
)->GetExprNode();
614 ub
= pNode
->GetNumber();
615 if ( !pDim
->Get( i
)->IsBased() ) // each dim is low/up
617 if ( ++i
>= pDim
->GetSize() ) // trouble
618 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
619 pNode
= pDim
->Get(i
)->GetExprNode();
621 ub
= pNode
->GetNumber();
623 else if ( !bCompatible
)
625 pArray
->AddDim32( lb
, ub
);
627 pArray
->setHasFixedSize( true );
630 pArray
->unoAddDim( 0, -1 ); // variant array
631 USHORT nSavFlags
= pTypeElem
->GetFlags();
632 // need to reset the FIXED flag
633 // when calling PutObject ( because the type will not match Object )
634 pTypeElem
->ResetFlag( SBX_FIXED
);
635 pTypeElem
->PutObject( pArray
);
636 pTypeElem
->SetFlags( nSavFlags
);
639 pTypeMembers
->Insert( pTypeElem
, pTypeMembers
->Count() );
645 pType
->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE
);
646 pType
->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE
);
648 rTypeArray
->Insert (pType
,rTypeArray
->Count());
652 // Declaration of Enum type
654 void SbiParser::Enum()
659 void SbiParser::DefEnum( BOOL bPrivate
)
661 // Neues Token lesen, es muss ein Symbol sein
665 String aEnumName
= aSym
;
666 if( rEnumArray
->Find(aEnumName
,SbxCLASS_OBJECT
) )
668 Error( SbERR_VAR_DEFINED
, aSym
);
672 SbxObject
*pEnum
= new SbxObject( aEnumName
);
674 pEnum
->SetFlag( SBX_PRIVATE
);
680 // Starting with -1 to make first default value 0 after ++
681 sal_Int32 nCurrentEnumValue
= -1;
682 while( !bDone
&& !IsEof() )
700 // TODO: Check existing!
701 BOOL bDefined
= FALSE
;
704 pElem
= VarDecl( &pDim
, FALSE
, TRUE
);
707 bDone
= TRUE
; // Error occured
713 Error( SbERR_SYNTAX
);
714 bDone
= TRUE
; // Error occured
718 SbiExpression
aVar( this, *pElem
);
723 SbiConstExpression
aExpr( this );
724 if( !bDefined
&& aExpr
.IsValid() )
726 SbxVariableRef xConvertVar
= new SbxVariable();
727 if( aExpr
.GetType() == SbxSTRING
)
728 xConvertVar
->PutString( aExpr
.GetString() );
730 xConvertVar
->PutDouble( aExpr
.GetValue() );
732 nCurrentEnumValue
= xConvertVar
->GetLong();
738 SbiSymPool
* pPoolToUse
= bPrivate
? pPool
: &aGlobals
;
740 SbiSymDef
* pOld
= pPoolToUse
->Find( pElem
->GetName() );
743 Error( SbERR_VAR_DEFINED
, pElem
->GetName() );
744 bDone
= TRUE
; // Error occured
752 SbiOpcode eOp
= _GLOBAL
;
753 aGen
.BackChain( nGblChain
);
755 bGblDefs
= bNewGblDefs
= TRUE
;
758 sal::static_int_cast
< UINT16
>( pElem
->GetType() ) );
761 USHORT nStringId
= aGen
.GetParser()->aGblStrings
.Add( nCurrentEnumValue
, SbxLONG
);
762 aGen
.Gen( _NUMBER
, nStringId
);
766 SbiConstDef
* pConst
= pElem
->GetConstDef();
767 pConst
->Set( nCurrentEnumValue
, SbxLONG
);
772 SbxArray
*pEnumMembers
= pEnum
->GetProperties();
773 SbxProperty
*pEnumElem
= new SbxProperty( pElem
->GetName(), SbxLONG
);
774 pEnumElem
->PutLong( nCurrentEnumValue
);
775 pEnumElem
->ResetFlag( SBX_WRITE
);
776 pEnumElem
->SetFlag( SBX_CONST
);
777 pEnumMembers
->Insert( pEnumElem
, pEnumMembers
->Count() );
781 pEnum
->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE
);
782 pEnum
->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE
);
784 rEnumArray
->Insert( pEnum
, rEnumArray
->Count() );
788 // Prozedur-Deklaration
789 // das erste Token ist bereits eingelesen (SUB/FUNCTION)
790 // xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
792 SbiProcDef
* SbiParser::ProcDecl( BOOL bDecl
)
794 BOOL bFunc
= BOOL( eCurTok
== FUNCTION
);
795 BOOL bProp
= BOOL( eCurTok
== GET
|| eCurTok
== SET
|| eCurTok
== LET
);
796 if( !TestSymbol() ) return NULL
;
797 String
aName( aSym
);
798 SbxDataType eType
= eScanType
;
799 SbiProcDef
* pDef
= new SbiProcDef( this, aName
, true );
800 pDef
->SetType( eType
);
801 if( Peek() == _CDECL_
)
803 Next(); pDef
->SetCdecl();
808 if( Next() == FIXSTRING
)
809 pDef
->GetLib() = aSym
;
811 Error( SbERR_SYNTAX
);
813 if( Peek() == ALIAS
)
816 if( Next() == FIXSTRING
)
817 pDef
->GetAlias() = aSym
;
819 Error( SbERR_SYNTAX
);
823 // CDECL, LIB und ALIAS sind unzulaessig
824 if( pDef
->GetLib().Len() )
825 Error( SbERR_UNEXPECTED
, LIB
);
826 if( pDef
->GetAlias().Len() )
827 Error( SbERR_UNEXPECTED
, ALIAS
);
828 if( pDef
->IsCdecl() )
829 Error( SbERR_UNEXPECTED
, _CDECL_
);
830 pDef
->SetCdecl( FALSE
);
831 pDef
->GetLib().Erase();
832 pDef
->GetAlias().Erase();
834 else if( !pDef
->GetLib().Len() )
836 // ALIAS und CDECL nur zusammen mit LIB
837 if( pDef
->GetAlias().Len() )
838 Error( SbERR_UNEXPECTED
, ALIAS
);
839 if( pDef
->IsCdecl() )
840 Error( SbERR_UNEXPECTED
, _CDECL_
);
841 pDef
->SetCdecl( FALSE
);
842 pDef
->GetAlias().Erase();
845 if( Peek() == LPAREN
)
848 if( Peek() == RPAREN
)
853 BOOL bOptional
= FALSE
;
854 BOOL bParamArray
= FALSE
;
855 while( Peek() == BYVAL
|| Peek() == BYREF
|| Peek() == _OPTIONAL_
)
857 if ( Peek() == BYVAL
) Next(), bByVal
= TRUE
;
858 else if ( Peek() == BYREF
) Next(), bByVal
= FALSE
;
859 else if ( Peek() == _OPTIONAL_
) Next(), bOptional
= TRUE
;
861 if( bCompatible
&& Peek() == PARAMARRAY
)
863 if( bByVal
|| bByVal
|| bOptional
)
864 Error( SbERR_UNEXPECTED
, PARAMARRAY
);
868 SbiSymDef
* pPar
= VarDecl( NULL
, FALSE
, FALSE
);
876 pPar
->SetParamArray();
877 pDef
->GetParams().Add( pPar
);
878 SbiToken eTok
= Next();
879 if( eTok
!= COMMA
&& eTok
!= RPAREN
)
882 if( bOptional
&& bCompatible
&& eTok
== EQ
)
884 SbiConstExpression
* pDefaultExpr
= new SbiConstExpression( this );
885 SbxDataType eType2
= pDefaultExpr
->GetType();
888 if( eType2
== SbxSTRING
)
889 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetString() );
891 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetValue(), eType2
);
893 pPar
->SetDefaultId( nStringId
);
897 if( eTok
== COMMA
|| eTok
== RPAREN
)
902 Error( SbERR_EXPECTED
, RPAREN
);
911 if( eType
!= SbxVARIANT
&& pDef
->GetType() != eType
)
912 Error( SbERR_BAD_DECLARATION
, aName
);
913 // if( pDef->GetType() == SbxOBJECT )
914 // pDef->SetType( SbxVARIANT ),
915 // Error( SbERR_SYNTAX );
916 if( pDef
->GetType() == SbxVARIANT
&& !( bFunc
|| bProp
) )
917 pDef
->SetType( SbxEMPTY
);
923 void SbiParser::Declare()
928 void SbiParser::DefDeclare( BOOL bPrivate
)
931 if( eCurTok
!= SUB
&& eCurTok
!= FUNCTION
)
932 Error( SbERR_UNEXPECTED
, eCurTok
);
935 SbiProcDef
* pDef
= ProcDecl( TRUE
);
938 if( !pDef
->GetLib().Len() )
939 Error( SbERR_EXPECTED
, LIB
);
941 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
944 SbiProcDef
* p
= pOld
->GetProcDef();
947 // Als Variable deklariert
948 Error( SbERR_BAD_DECLARATION
, pDef
->GetName() );
956 aPublics
.Add( pDef
);
959 pDef
->SetPublic( !bPrivate
);
964 void SbiParser::Attribute()
966 // TODO: Need to implement the method as an attributed object.
967 while( Next() != EQ
)
969 String
aSym( GetSym() );
975 Error( SbERR_SYNTAX
);
977 SbiExpression
aValue( this );
979 // Don't generate any code - just discard it.
982 // Aufruf einer SUB oder FUNCTION
984 void SbiParser::Call()
986 String
aName( aSym
);
987 SbiExpression
aVar( this, SbSYMBOL
);
988 aVar
.Gen( FORCE_CALL
);
994 void SbiParser::SubFunc()
996 DefProc( FALSE
, FALSE
);
999 // Einlesen einer Prozedur
1001 BOOL
runsInSetup( void );
1003 void SbiParser::DefProc( BOOL bStatic
, BOOL bPrivate
)
1005 USHORT l1
= nLine
, l2
= nLine
;
1006 BOOL bSub
= BOOL( eCurTok
== SUB
);
1007 BOOL bProperty
= BOOL( eCurTok
== PROPERTY
);
1008 PropertyMode ePropertyMode
= PROPERTY_MODE_NONE
;
1012 if( eCurTok
== GET
)
1013 ePropertyMode
= PROPERTY_MODE_GET
;
1014 else if( eCurTok
== LET
)
1015 ePropertyMode
= PROPERTY_MODE_LET
;
1016 else if( eCurTok
== SET
)
1017 ePropertyMode
= PROPERTY_MODE_SET
;
1019 Error( SbERR_EXPECTED
, "Get or Let or Set" );
1022 SbiToken eExit
= eCurTok
;
1023 SbiProcDef
* pDef
= ProcDecl( FALSE
);
1026 pDef
->setPropertyMode( ePropertyMode
);
1028 // Ist die Proc bereits deklariert?
1029 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1032 bool bError_
= false;
1034 pProc
= pOld
->GetProcDef();
1037 // Als Variable deklariert
1038 Error( SbERR_BAD_DECLARATION
, pDef
->GetName() );
1043 // #100027: Multiple declaration -> Error
1044 // #112787: Not for setup, REMOVE for 8
1045 else if( !runsInSetup() && pProc
->IsUsedForProcDecl() )
1047 PropertyMode ePropMode
= pDef
->getPropertyMode();
1048 if( ePropMode
== PROPERTY_MODE_NONE
|| ePropMode
== pProc
->getPropertyMode() )
1050 Error( SbERR_PROC_DEFINED
, pDef
->GetName() );
1059 pDef
->Match( pProc
);
1064 aPublics
.Add( pDef
), pProc
= pDef
;
1068 pProc
->SetPublic( !bPrivate
);
1070 // Nun setzen wir die Suchhierarchie fuer Symbole sowie die aktuelle
1072 aPublics
.SetProcId( pProc
->GetId() );
1073 pProc
->GetParams().SetParent( &aPublics
);
1076 if ( bVBASupportOn
)
1077 pProc
->SetStatic( TRUE
);
1079 Error( SbERR_NOT_IMPLEMENTED
); // STATIC SUB ...
1083 pProc
->SetStatic( FALSE
);
1085 // Normalfall: Lokale Variable->Parameter->Globale Variable
1086 pProc
->GetLocals().SetParent( &pProc
->GetParams() );
1087 pPool
= &pProc
->GetLocals();
1091 StmntBlock( bSub
? ENDSUB
: (bProperty
? ENDPROPERTY
: ENDFUNC
) );
1093 pProc
->SetLine1( l1
);
1094 pProc
->SetLine2( l2
);
1096 aPublics
.SetProcId( 0 );
1098 pProc
->GetLabels().CheckRefs();
1104 // STATIC variable|procedure
1106 void SbiParser::Static()
1111 void SbiParser::DefStatic( BOOL bPrivate
)
1118 // End global chain if necessary (not done in
1119 // SbiParser::Parse() under these conditions
1120 if( bNewGblDefs
&& nGblChain
== 0 )
1122 nGblChain
= aGen
.Gen( _JUMP
, 0 );
1123 bNewGblDefs
= FALSE
;
1126 DefProc( TRUE
, bPrivate
);
1130 Error( SbERR_NOT_IN_SUBR
);
1131 // Pool umsetzen, damit STATIC-Deklarationen im globalen
1133 SbiSymPool
* p
= pPool
; pPool
= &aPublics
;
1134 DefVar( _STATIC
, TRUE
);