1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <basic/sbx.hxx>
22 #include "sbunoobj.hxx"
25 SbxObject
* cloneTypeObjectImpl( const SbxObject
& rTypeObj
);
27 // Declaration of a variable
28 // If there are errors it will be parsed up to the comma or the newline.
29 // Return-value: a new instance, which were inserted and then deleted.
30 // Array-Indexex were returned as SbiDimList
32 SbiSymDef
* SbiParser::VarDecl( SbiDimList
** ppDim
, bool bStatic
, bool bConst
)
34 bool bWithEvents
= false;
35 if( Peek() == WITHEVENTS
)
40 if( !TestSymbol() ) return NULL
;
41 SbxDataType t
= eScanType
;
42 SbiSymDef
* pDef
= bConst
? new SbiConstDef( aSym
) : new SbiSymDef( aSym
);
43 SbiDimList
* pDim
= NULL
;
45 if( Peek() == LPAREN
)
47 pDim
= new SbiDimList( this );
48 if( !pDim
->GetDims() )
49 pDef
->SetWithBrackets();
55 pDef
->SetWithEvents();
60 Error( SbERR_EXPECTED
, "()" );
68 // Resolving of a AS-Type-Declaration
69 // The data type were inserted into the handed over variable
71 void SbiParser::TypeDecl( SbiSymDef
& rDef
, bool bAsNewAlreadyParsed
)
73 SbxDataType eType
= rDef
.GetType();
74 if( bAsNewAlreadyParsed
|| Peek() == AS
)
77 if( !bAsNewAlreadyParsed
)
80 SbiToken eTok
= Next();
81 if( !bAsNewAlreadyParsed
&& eTok
== NEW
)
90 Error( SbERR_SYNTAX
);
91 eType
= SbxVARIANT
; break;
105 Error( SbERR_SYNTAX
);
106 eType
= (eTok
==TBYTE
) ? SbxBYTE
: SbxDataType( eTok
- TINTEGER
+ SbxINTEGER
);
107 if( eType
== SbxSTRING
)
113 SbiConstExpression
aSize( this );
114 nSize
= aSize
.GetShortValue();
115 if( nSize
< 0 || (bVBASupportOn
&& nSize
<= 0) )
116 Error( SbERR_OUT_OF_RANGE
);
118 rDef
.SetFixedStringLength( nSize
);
122 case SYMBOL
: // can only be a TYPE or a object class!
123 if( eScanType
!= SbxVARIANT
)
124 Error( SbERR_SYNTAX
);
127 OUString aCompleteName
= aSym
;
129 // #52709 DIM AS NEW for Uno with full-qualified name
132 rtl::OUString
aDotStr( '.' );
133 while( Peek() == DOT
)
135 aCompleteName
+= aDotStr
;
137 SbiToken ePeekTok
= Peek();
138 if( ePeekTok
== SYMBOL
|| IsKwd( ePeekTok
) )
141 aCompleteName
+= aSym
;
146 Error( SbERR_UNEXPECTED
, SYMBOL
);
151 else if( rEnumArray
->Find( aCompleteName
, SbxCLASS_OBJECT
) || ( IsVBASupportOn() && VBAConstantHelper::instance().isVBAConstantType( aCompleteName
) ) )
157 // Take over in the string pool
158 rDef
.SetTypeId( aGblStrings
.Add( aCompleteName
) );
160 if( rDef
.IsNew() && pProc
== NULL
)
161 aRequiredTypes
.push_back( aCompleteName
);
165 case FIXSTRING
: // new syntax for complex UNO types
166 rDef
.SetTypeId( aGblStrings
.Add( aSym
) );
170 Error( SbERR_UNEXPECTED
, eTok
);
173 // The variable could have been declared with a suffix
174 if( rDef
.GetType() != SbxVARIANT
)
176 if( rDef
.GetType() != eType
)
177 Error( SbERR_VAR_DEFINED
, rDef
.GetName() );
178 else if( eType
== SbxSTRING
&& rDef
.GetLen() != nSize
)
179 Error( SbERR_VAR_DEFINED
, rDef
.GetName() );
181 rDef
.SetType( eType
);
182 rDef
.SetLen( nSize
);
186 // Here variables, arrays and structures were definied.
187 // DIM/PRIVATE/PUBLIC/GLOBAL
189 void SbiParser::Dim()
191 DefVar( _DIM
, ( pProc
&& bVBASupportOn
) ? pProc
->IsStatic() : false );
194 void SbiParser::DefVar( SbiOpcode eOp
, bool bStatic
)
196 SbiSymPool
* pOldPool
= pPool
;
197 bool bSwitchPool
= false;
198 bool bPersistantGlobal
= false;
199 SbiToken eFirstTok
= eCurTok
;
200 if( pProc
&& ( eCurTok
== GLOBAL
|| eCurTok
== PUBLIC
|| eCurTok
== PRIVATE
) )
201 Error( SbERR_NOT_IN_SUBR
, eCurTok
);
202 if( eCurTok
== PUBLIC
|| eCurTok
== GLOBAL
)
204 bSwitchPool
= true; // at the right moment switch to the global pool
205 if( eCurTok
== GLOBAL
)
206 bPersistantGlobal
= true;
208 // behavior in VBA is that a module scope variable's lifetime is
209 // tied to the document. e.g. a module scope variable is global
210 if( GetBasic()->IsDocBasic() && bVBASupportOn
&& !pProc
)
211 bPersistantGlobal
= true;
212 // PRIVATE is a synonymous for DIM
215 if( eCurTok
== _CONST_
)
217 else if( Peek() == _CONST_
)
218 Next(), bConst
= true;
220 // #110004 It can also be a sub/function
221 if( !bConst
&& (eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
||
222 eCurTok
== STATIC
|| eCurTok
== ENUM
|| eCurTok
== DECLARE
|| eCurTok
== TYPE
) )
224 // Next token is read here, because !bConst
225 bool bPrivate
= ( eFirstTok
== PRIVATE
);
227 if( eCurTok
== STATIC
)
230 DefStatic( bPrivate
);
232 else if( eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
)
234 // End global chain if necessary (not done in
235 // SbiParser::Parse() under these conditions
236 if( bNewGblDefs
&& nGblChain
== 0 )
238 nGblChain
= aGen
.Gen( _JUMP
, 0 );
242 DefProc( false, bPrivate
);
245 else if( eCurTok
== ENUM
)
251 else if( eCurTok
== DECLARE
)
254 DefDeclare( bPrivate
);
258 else if( eCurTok
== TYPE
)
270 // SHARED were ignored
271 if( Peek() == SHARED
) Next();
276 // PRESERVE only at REDIM
277 if( Peek() == PRESERVE
)
283 Error( SbERR_UNEXPECTED
, eCurTok
);
288 // #40689, Statics -> Modul-Initialising, skip in Sub
289 sal_uInt32 nEndOfStaticLbl
= 0;
290 if( !bVBASupportOn
&& bStatic
)
292 nEndOfStaticLbl
= aGen
.Gen( _JUMP
, 0 );
293 aGen
.Statement(); // catch up on static here
296 bool bDefined
= false;
297 while( ( pDef
= VarDecl( &pDim
, bStatic
, bConst
) ) != NULL
)
303 SbiSymDef
* pOld
= pPool
->Find( pDef
->GetName() );
304 // search also in the Runtime-Library
305 bool bRtlSym
= false;
308 pOld
= CheckRTLForSym( pDef
->GetName(), SbxVARIANT
);
312 if( pOld
&& !(eOp
== _REDIM
|| eOp
== _REDIMP
) )
314 if( pDef
->GetScope() == SbLOCAL
&& pOld
->GetScope() != SbLOCAL
)
320 // always an error at a RTL-S
321 if( !bRtlSym
&& (eOp
== _REDIM
|| eOp
== _REDIMP
) )
323 // compare the attributes at a REDIM
324 SbxDataType eDefType
;
325 bool bError_
= false;
326 if( pOld
->IsStatic() )
330 else if( pOld
->GetType() != ( eDefType
= pDef
->GetType() ) )
332 if( !( eDefType
== SbxVARIANT
&& !pDef
->IsDefinedAs() ) )
336 Error( SbERR_VAR_DEFINED
, pDef
->GetName() );
339 Error( SbERR_VAR_DEFINED
, pDef
->GetName() );
340 delete pDef
; pDef
= pOld
;
345 // #36374: Create the variable in front of the distinction IsNew()
346 // Otherwise error at Dim Identifier As New Type and option explicit
347 if( !bDefined
&& !(eOp
== _REDIM
|| eOp
== _REDIMP
)
348 && ( !bConst
|| pDef
->GetScope() == SbGLOBAL
) )
350 // Declare variable or global constant
352 switch ( pDef
->GetScope() )
354 case SbGLOBAL
: eOp2
= bPersistantGlobal
? _GLOBAL_P
: _GLOBAL
;
356 case SbPUBLIC
: eOp2
= bPersistantGlobal
? _PUBLIC_P
: _PUBLIC
;
357 // #40689, no own Opcode anymore
358 if( bVBASupportOn
&& bStatic
)
363 global
: aGen
.BackChain( nGblChain
);
365 bGblDefs
= bNewGblDefs
= true;
367 default: eOp2
= _LOCAL
;
369 sal_uInt32 nOpnd2
= sal::static_int_cast
< sal_uInt16
>( pDef
->GetType() );
370 if( pDef
->IsWithEvents() )
371 nOpnd2
|= SBX_TYPE_WITH_EVENTS_FLAG
;
373 if( bCompatible
&& pDef
->IsNew() )
374 nOpnd2
|= SBX_TYPE_DIM_AS_NEW_FLAG
;
376 short nFixedStringLength
= pDef
->GetFixedStringLength();
377 if( nFixedStringLength
>= 0 )
378 nOpnd2
|= (SBX_FIXED_LEN_STRING_FLAG
+ (sal_uInt32(nFixedStringLength
) << 17)); // len = all bits above 0x10000
380 if( pDim
!= NULL
&& pDim
->GetDims() > 0 )
381 nOpnd2
|= SBX_TYPE_VAR_TO_DIM_FLAG
;
383 aGen
.Gen( eOp2
, pDef
->GetId(), nOpnd2
);
386 // Initialising for self-defined daty types
387 // and per NEW created variable
388 if( pDef
->GetType() == SbxOBJECT
389 && pDef
->GetTypeId() )
391 if( !bCompatible
&& !pDef
->IsNew() )
393 OUString
aTypeName( aGblStrings
.Find( pDef
->GetTypeId() ) );
394 if( rTypeArray
->Find( aTypeName
, SbxCLASS_OBJECT
) == NULL
)
396 Error( SbERR_UNDEF_TYPE
, aTypeName
);
402 Error( SbERR_SYNTAX
);
409 SbiExpression
aExpr( this, *pDef
, NULL
);
411 aGen
.Gen( _REDIMP_ERASE
);
413 pDef
->SetDims( pDim
->GetDims() );
414 SbiExpression
aExpr2( this, *pDef
, pDim
);
416 aGen
.Gen( _DCREATE_REDIMP
, pDef
->GetId(), pDef
->GetTypeId() );
420 pDef
->SetDims( pDim
->GetDims() );
421 SbiExpression
aExpr( this, *pDef
, pDim
);
423 aGen
.Gen( _DCREATE
, pDef
->GetId(), pDef
->GetTypeId() );
428 SbiExpression
aExpr( this, *pDef
);
430 SbiOpcode eOp_
= pDef
->IsNew() ? _CREATE
: _TCREATE
;
431 aGen
.Gen( eOp_
, pDef
->GetId(), pDef
->GetTypeId() );
442 // Definition of the constants
445 Error( SbERR_SYNTAX
);
448 SbiExpression
aVar( this, *pDef
);
449 if( !TestToken( EQ
) )
450 goto MyBreak
; // (see below)
451 SbiConstExpression
aExpr( this );
452 if( !bDefined
&& aExpr
.IsValid() )
454 if( pDef
->GetScope() == SbGLOBAL
)
456 // Create code only for the global constant!
461 SbiConstDef
* pConst
= pDef
->GetConstDef();
462 if( aExpr
.GetType() == SbxSTRING
)
463 pConst
->Set( aExpr
.GetString() );
465 pConst
->Set( aExpr
.GetValue(), aExpr
.GetType() );
470 // Dimension the variable
471 // Delete the var at REDIM beforehand
474 SbiExpression
aExpr( this, *pDef
, NULL
);
477 // delete the array but
478 // clear the variable ( this
479 // allows the processing of
480 // the param to happen as normal without errors ( ordinary ERASE just clears the array )
481 aGen
.Gen( _ERASE_CLEAR
);
485 else if( eOp
== _REDIMP
)
487 SbiExpression
aExpr( this, *pDef
, NULL
);
489 aGen
.Gen( _REDIMP_ERASE
);
491 pDef
->SetDims( pDim
->GetDims() );
492 if( bPersistantGlobal
)
493 pDef
->SetGlobal( sal_True
);
494 SbiExpression
aExpr( this, *pDef
, pDim
);
496 pDef
->SetGlobal( sal_False
);
497 aGen
.Gen( (eOp
== _STATIC
) ? _DIM
: eOp
);
503 // Implementation of bSwitchPool (see above): pPool must not be set to &aGlobals
504 // at the VarDecl-Call.
505 // Apart from that the behavior should be absolutely identical,
506 // i.e., pPool had to be reset always at the end of the loop.
509 continue; // Skip MyBreak
515 // #40689, finalize the jump over statics declarations
516 if( !bVBASupportOn
&& bStatic
)
518 // maintain the global chain
519 nGblChain
= aGen
.Gen( _JUMP
, 0 );
520 bGblDefs
= bNewGblDefs
= true;
522 // Register for Sub a jump to the end of statics
523 aGen
.BackChain( nEndOfStaticLbl
);
528 // Here were Arrays redimensioned.
530 void SbiParser::ReDim()
532 DefVar( _REDIM
, ( pProc
&& bVBASupportOn
) ? pProc
->IsStatic() : false );
537 void SbiParser::Erase()
541 SbiExpression
aExpr( this, SbLVALUE
);
544 if( !TestComma() ) break;
548 // Declaration of a data type
550 void SbiParser::Type()
555 void SbiParser::DefType( bool bPrivate
)
557 // TODO: Use bPrivate
560 // Read the new Token lesen. It had to be a symbol
564 if (rTypeArray
->Find(aSym
,SbxCLASS_OBJECT
))
566 Error( SbERR_VAR_DEFINED
, aSym
);
570 SbxObject
*pType
= new SbxObject(aSym
);
573 SbiDimList
* pDim
= NULL
;
576 while( !bDone
&& !IsEof() )
593 pElem
= VarDecl(&pDim
, false, false);
595 bDone
= true; // Error occurred
599 SbxArray
*pTypeMembers
= pType
->GetProperties();
600 OUString aElemName
= pElem
->GetName();
601 if( pTypeMembers
->Find( aElemName
, SbxCLASS_DONTCARE
) )
603 Error (SbERR_VAR_DEFINED
);
607 SbxDataType eElemType
= pElem
->GetType();
608 SbxProperty
*pTypeElem
= new SbxProperty( aElemName
, eElemType
);
611 SbxDimArray
* pArray
= new SbxDimArray( pElem
->GetType() );
612 if ( pDim
->GetSize() )
614 // Dimension the target array
616 for ( short i
=0; i
<pDim
->GetSize();++i
)
619 sal_Int32 lb
= nBase
;
620 SbiExprNode
* pNode
= pDim
->Get(i
)->GetExprNode();
621 ub
= pNode
->GetNumber();
622 if ( !pDim
->Get( i
)->IsBased() ) // each dim is low/up
624 if ( ++i
>= pDim
->GetSize() ) // trouble
625 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
626 pNode
= pDim
->Get(i
)->GetExprNode();
628 ub
= pNode
->GetNumber();
630 else if ( !bCompatible
)
632 pArray
->AddDim32( lb
, ub
);
634 pArray
->setHasFixedSize( true );
637 pArray
->unoAddDim( 0, -1 ); // variant array
638 sal_uInt16 nSavFlags
= pTypeElem
->GetFlags();
639 // need to reset the FIXED flag
640 // when calling PutObject ( because the type will not match Object )
641 pTypeElem
->ResetFlag( SBX_FIXED
);
642 pTypeElem
->PutObject( pArray
);
643 pTypeElem
->SetFlags( nSavFlags
);
646 if( eElemType
== SbxOBJECT
)
648 sal_uInt16 nElemTypeId
= pElem
->GetTypeId();
649 if( nElemTypeId
!= 0 )
651 OUString
aTypeName( aGblStrings
.Find( nElemTypeId
) );
652 SbxObject
* pTypeObj
= static_cast< SbxObject
* >( rTypeArray
->Find( aTypeName
, SbxCLASS_OBJECT
) );
653 if( pTypeObj
!= NULL
)
655 SbxObject
* pCloneObj
= cloneTypeObjectImpl( *pTypeObj
);
656 pTypeElem
->PutObject( pCloneObj
);
660 pTypeMembers
->Insert( pTypeElem
, pTypeMembers
->Count() );
662 delete pDim
, pDim
= NULL
;
667 pType
->Remove( rtl::OUString("Name"), SbxCLASS_DONTCARE
);
668 pType
->Remove( rtl::OUString("Parent"), SbxCLASS_DONTCARE
);
670 rTypeArray
->Insert (pType
,rTypeArray
->Count());
674 // Declaration of Enum type
676 void SbiParser::Enum()
681 void SbiParser::DefEnum( bool bPrivate
)
683 // Read a the new Token. It had to be a symbol
687 OUString aEnumName
= aSym
;
688 if( rEnumArray
->Find(aEnumName
,SbxCLASS_OBJECT
) )
690 Error( SbERR_VAR_DEFINED
, aSym
);
694 SbxObject
*pEnum
= new SbxObject( aEnumName
);
697 pEnum
->SetFlag( SBX_PRIVATE
);
703 // Starting with -1 to make first default value 0 after ++
704 sal_Int32 nCurrentEnumValue
= -1;
705 while( !bDone
&& !IsEof() )
723 // TODO: Check existing!
724 bool bDefined
= false;
727 pElem
= VarDecl( &pDim
, false, true );
730 bDone
= true; // Error occurred
736 Error( SbERR_SYNTAX
);
737 bDone
= true; // Error occurred
741 SbiExpression
aVar( this, *pElem
);
746 SbiConstExpression
aExpr( this );
747 if( !bDefined
&& aExpr
.IsValid() )
749 SbxVariableRef xConvertVar
= new SbxVariable();
750 if( aExpr
.GetType() == SbxSTRING
)
751 xConvertVar
->PutString( aExpr
.GetString() );
753 xConvertVar
->PutDouble( aExpr
.GetValue() );
755 nCurrentEnumValue
= xConvertVar
->GetLong();
761 SbiSymPool
* pPoolToUse
= bPrivate
? pPool
: &aGlobals
;
763 SbiSymDef
* pOld
= pPoolToUse
->Find( pElem
->GetName() );
766 Error( SbERR_VAR_DEFINED
, pElem
->GetName() );
767 bDone
= true; // Error occurred
775 SbiOpcode eOp
= _GLOBAL
;
776 aGen
.BackChain( nGblChain
);
778 bGblDefs
= bNewGblDefs
= true;
781 sal::static_int_cast
< sal_uInt16
>( pElem
->GetType() ) );
784 sal_uInt16 nStringId
= aGen
.GetParser()->aGblStrings
.Add( nCurrentEnumValue
, SbxLONG
);
785 aGen
.Gen( _NUMBER
, nStringId
);
789 SbiConstDef
* pConst
= pElem
->GetConstDef();
790 pConst
->Set( nCurrentEnumValue
, SbxLONG
);
795 SbxArray
*pEnumMembers
= pEnum
->GetProperties();
796 SbxProperty
*pEnumElem
= new SbxProperty( pElem
->GetName(), SbxLONG
);
797 pEnumElem
->PutLong( nCurrentEnumValue
);
798 pEnumElem
->ResetFlag( SBX_WRITE
);
799 pEnumElem
->SetFlag( SBX_CONST
);
800 pEnumMembers
->Insert( pEnumElem
, pEnumMembers
->Count() );
804 pEnum
->Remove( rtl::OUString("Name"), SbxCLASS_DONTCARE
);
805 pEnum
->Remove( rtl::OUString("Parent"), SbxCLASS_DONTCARE
);
807 rEnumArray
->Insert( pEnum
, rEnumArray
->Count() );
811 // Procedure-Declaration
812 // the first Token is already read in (SUB/FUNCTION)
813 // xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
815 SbiProcDef
* SbiParser::ProcDecl( bool bDecl
)
817 bool bFunc
= ( eCurTok
== FUNCTION
);
818 bool bProp
= ( eCurTok
== GET
|| eCurTok
== SET
|| eCurTok
== LET
);
819 if( !TestSymbol() ) return NULL
;
820 OUString
aName( aSym
);
821 SbxDataType eType
= eScanType
;
822 SbiProcDef
* pDef
= new SbiProcDef( this, aName
, true );
823 pDef
->SetType( eType
);
824 if( Peek() == _CDECL_
)
826 Next(); pDef
->SetCdecl();
831 if( Next() == FIXSTRING
)
833 pDef
->GetLib() = aSym
;
837 Error( SbERR_SYNTAX
);
840 if( Peek() == ALIAS
)
843 if( Next() == FIXSTRING
)
845 pDef
->GetAlias() = aSym
;
849 Error( SbERR_SYNTAX
);
854 // CDECL, LIB and ALIAS are invalid
855 if( !pDef
->GetLib().isEmpty() )
857 Error( SbERR_UNEXPECTED
, LIB
);
859 if( !pDef
->GetAlias().isEmpty() )
861 Error( SbERR_UNEXPECTED
, ALIAS
);
863 if( pDef
->IsCdecl() )
865 Error( SbERR_UNEXPECTED
, _CDECL_
);
867 pDef
->SetCdecl( false );
869 pDef
->GetAlias() = "";
871 else if( pDef
->GetLib().isEmpty() )
873 // ALIAS and CDECL only together with LIB
874 if( !pDef
->GetAlias().isEmpty() )
876 Error( SbERR_UNEXPECTED
, ALIAS
);
878 if( pDef
->IsCdecl() )
880 Error( SbERR_UNEXPECTED
, _CDECL_
);
882 pDef
->SetCdecl( false );
883 pDef
->GetAlias() = "";
886 if( Peek() == LPAREN
)
889 if( Peek() == RPAREN
)
898 bool bOptional
= false;
899 bool bParamArray
= false;
900 while( Peek() == BYVAL
|| Peek() == BYREF
|| Peek() == _OPTIONAL_
)
902 if( Peek() == BYVAL
)
906 else if ( Peek() == BYREF
)
910 else if ( Peek() == _OPTIONAL_
)
916 if( bCompatible
&& Peek() == PARAMARRAY
)
918 if( bByVal
|| bOptional
)
920 Error( SbERR_UNEXPECTED
, PARAMARRAY
);
925 SbiSymDef
* pPar
= VarDecl( NULL
, false, false );
940 pPar
->SetParamArray();
942 pDef
->GetParams().Add( pPar
);
943 SbiToken eTok
= Next();
944 if( eTok
!= COMMA
&& eTok
!= RPAREN
)
947 if( bOptional
&& bCompatible
&& eTok
== EQ
)
949 SbiConstExpression
* pDefaultExpr
= new SbiConstExpression( this );
950 SbxDataType eType2
= pDefaultExpr
->GetType();
952 sal_uInt16 nStringId
;
953 if( eType2
== SbxSTRING
)
955 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetString() );
959 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetValue(), eType2
);
961 pPar
->SetDefaultId( nStringId
);
965 if( eTok
== COMMA
|| eTok
== RPAREN
)
972 Error( SbERR_EXPECTED
, RPAREN
);
984 if( eType
!= SbxVARIANT
&& pDef
->GetType() != eType
)
986 Error( SbERR_BAD_DECLARATION
, aName
);
988 if( pDef
->GetType() == SbxVARIANT
&& !( bFunc
|| bProp
) )
990 pDef
->SetType( SbxEMPTY
);
997 void SbiParser::Declare()
1002 void SbiParser::DefDeclare( bool bPrivate
)
1005 if( eCurTok
!= SUB
&& eCurTok
!= FUNCTION
)
1007 Error( SbERR_UNEXPECTED
, eCurTok
);
1011 bool bFunction
= (eCurTok
== FUNCTION
);
1013 SbiProcDef
* pDef
= ProcDecl( true );
1016 if( pDef
->GetLib().isEmpty() )
1018 Error( SbERR_EXPECTED
, LIB
);
1020 // Is it already there?
1021 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1024 SbiProcDef
* p
= pOld
->GetProcDef();
1027 // Declared as a variable
1028 Error( SbERR_BAD_DECLARATION
, pDef
->GetName() );
1039 aPublics
.Add( pDef
);
1043 pDef
->SetPublic( !bPrivate
);
1045 // New declare handling
1046 if( !pDef
->GetLib().isEmpty())
1048 if( bNewGblDefs
&& nGblChain
== 0 )
1050 nGblChain
= aGen
.Gen( _JUMP
, 0 );
1051 bNewGblDefs
= false;
1054 sal_uInt16 nSavLine
= nLine
;
1057 pDef
->SetLine1( nSavLine
);
1058 pDef
->SetLine2( nSavLine
);
1060 SbiSymPool
& rPool
= pDef
->GetParams();
1061 sal_uInt16 nParCount
= rPool
.GetSize();
1063 SbxDataType eType
= pDef
->GetType();
1066 aGen
.Gen( _PARAM
, 0, sal::static_int_cast
< sal_uInt16
>( eType
) );
1072 for( sal_uInt16 i
= 1 ; i
< nParCount
; ++i
)
1074 SbiSymDef
* pParDef
= rPool
.Get( i
);
1075 SbxDataType eParType
= pParDef
->GetType();
1077 aGen
.Gen( _PARAM
, i
, sal::static_int_cast
< sal_uInt16
>( eParType
) );
1080 sal_uInt16 nTyp
= sal::static_int_cast
< sal_uInt16
>( pParDef
->GetType() );
1081 if( pParDef
->IsByVal() )
1083 // Reset to avoid additional byval in call to wrapper function
1084 pParDef
->SetByVal( sal_False
);
1087 aGen
.Gen( _ARGTYP
, nTyp
);
1091 aGen
.Gen( _LIB
, aGblStrings
.Add( pDef
->GetLib() ) );
1093 SbiOpcode eOp
= pDef
->IsCdecl() ? _CALLC
: _CALL
;
1094 sal_uInt16 nId
= pDef
->GetId();
1095 if( !pDef
->GetAlias().isEmpty() )
1097 nId
= ( nId
& 0x8000 ) | aGblStrings
.Add( pDef
->GetAlias() );
1103 aGen
.Gen( eOp
, nId
, sal::static_int_cast
< sal_uInt16
>( eType
) );
1116 void SbiParser::Attribute()
1118 // TODO: Need to implement the method as an attributed object.
1119 while( Next() != EQ
)
1129 Error( SbERR_SYNTAX
);
1133 SbiExpression
aValue( this );
1135 // Don't generate any code - just discard it.
1138 // Call of a SUB or a FUNCTION
1140 void SbiParser::Call()
1142 SbiExpression
aVar( this, SbSYMBOL
);
1143 aVar
.Gen( FORCE_CALL
);
1149 void SbiParser::SubFunc()
1151 DefProc( false, false );
1154 // Read in of a procedure
1156 void SbiParser::DefProc( bool bStatic
, bool bPrivate
)
1158 sal_uInt16 l1
= nLine
, l2
= nLine
;
1159 bool bSub
= ( eCurTok
== SUB
);
1160 bool bProperty
= ( eCurTok
== PROPERTY
);
1161 PropertyMode ePropertyMode
= PROPERTY_MODE_NONE
;
1165 if( eCurTok
== GET
)
1167 ePropertyMode
= PROPERTY_MODE_GET
;
1169 else if( eCurTok
== LET
)
1171 ePropertyMode
= PROPERTY_MODE_LET
;
1173 else if( eCurTok
== SET
)
1175 ePropertyMode
= PROPERTY_MODE_SET
;
1179 Error( SbERR_EXPECTED
, "Get or Let or Set" );
1183 SbiToken eExit
= eCurTok
;
1184 SbiProcDef
* pDef
= ProcDecl( false );
1189 pDef
->setPropertyMode( ePropertyMode
);
1191 // Is the Proc already declared?
1192 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1195 bool bError_
= false;
1197 pProc
= pOld
->GetProcDef();
1200 // Declared as a variable
1201 Error( SbERR_BAD_DECLARATION
, pDef
->GetName() );
1206 // #100027: Multiple declaration -> Error
1207 // #112787: Not for setup, REMOVE for 8
1208 else if( pProc
->IsUsedForProcDecl() )
1210 PropertyMode ePropMode
= pDef
->getPropertyMode();
1211 if( ePropMode
== PROPERTY_MODE_NONE
|| ePropMode
== pProc
->getPropertyMode() )
1213 Error( SbERR_PROC_DEFINED
, pDef
->GetName() );
1222 pDef
->Match( pProc
);
1228 aPublics
.Add( pDef
), pProc
= pDef
;
1234 pProc
->SetPublic( !bPrivate
);
1236 // Now we set the search hierarchy for symbols as well as the
1237 // current procedure.
1238 aPublics
.SetProcId( pProc
->GetId() );
1239 pProc
->GetParams().SetParent( &aPublics
);
1242 if ( bVBASupportOn
)
1244 pProc
->SetStatic( sal_True
);
1248 Error( SbERR_NOT_IMPLEMENTED
); // STATIC SUB ...
1253 pProc
->SetStatic( sal_False
);
1255 // Normal case: Local variable->parameter->global variable
1256 pProc
->GetLocals().SetParent( &pProc
->GetParams() );
1257 pPool
= &pProc
->GetLocals();
1261 StmntBlock( bSub
? ENDSUB
: (bProperty
? ENDPROPERTY
: ENDFUNC
) );
1263 pProc
->SetLine1( l1
);
1264 pProc
->SetLine2( l2
);
1266 aPublics
.SetProcId( 0 );
1268 pProc
->GetLabels().CheckRefs();
1274 // STATIC variable|procedure
1276 void SbiParser::Static()
1281 void SbiParser::DefStatic( bool bPrivate
)
1290 // End global chain if necessary (not done in
1291 // SbiParser::Parse() under these conditions
1292 if( bNewGblDefs
&& nGblChain
== 0 )
1294 nGblChain
= aGen
.Gen( _JUMP
, 0 );
1295 bNewGblDefs
= false;
1298 DefProc( true, bPrivate
);
1303 Error( SbERR_NOT_IN_SUBR
);
1305 // Reset the Pool, so that STATIC-Declarations go into the
1309 DefVar( _STATIC
, true );
1315 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */