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>
21 #include "sbunoobj.hxx"
23 #include <svtools/miscopt.hxx>
24 #include <osl/diagnose.h>
25 #include <com/sun/star/reflection/theCoreReflection.hpp>
26 #include <comphelper/namedvaluecollection.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp>
29 #include <com/sun/star/reflection/XIdlMethod.hpp>
30 #include <com/sun/star/uno/Exception.hpp>
31 #include <basic/codecompletecache.hxx>
32 #include <boost/scoped_ptr.hpp>
34 using namespace ::com::sun::star
;
35 using namespace ::com::sun::star::uno
;
37 // Declaration of a variable
38 // If there are errors it will be parsed up to the comma or the newline.
39 // Return-value: a new instance, which were inserted and then deleted.
40 // Array-Indexex were returned as SbiDimList
42 SbiSymDef
* SbiParser::VarDecl( SbiDimList
** ppDim
, bool bStatic
, bool bConst
)
44 bool bWithEvents
= false;
45 if( Peek() == WITHEVENTS
)
50 if( !TestSymbol() ) return NULL
;
51 SbxDataType t
= eScanType
;
52 SbiSymDef
* pDef
= bConst
? new SbiConstDef( aSym
) : new SbiSymDef( aSym
);
53 SbiDimList
* pDim
= NULL
;
55 if( Peek() == LPAREN
)
57 pDim
= new SbiDimList( this );
58 if( !pDim
->GetDims() )
59 pDef
->SetWithBrackets();
65 pDef
->SetWithEvents();
70 Error( SbERR_EXPECTED
, "()" );
78 // Resolving of a AS-Type-Declaration
79 // The data type were inserted into the handed over variable
81 void SbiParser::TypeDecl( SbiSymDef
& rDef
, bool bAsNewAlreadyParsed
)
83 SbxDataType eType
= rDef
.GetType();
84 if( bAsNewAlreadyParsed
|| Peek() == AS
)
87 if( !bAsNewAlreadyParsed
)
90 SbiToken eTok
= Next();
91 if( !bAsNewAlreadyParsed
&& eTok
== NEW
)
100 Error( SbERR_SYNTAX
);
101 eType
= SbxVARIANT
; break;
115 Error( SbERR_SYNTAX
);
116 eType
= (eTok
==TBYTE
) ? SbxBYTE
: SbxDataType( eTok
- TINTEGER
+ SbxINTEGER
);
117 if( eType
== SbxSTRING
)
123 SbiConstExpression
aSize( this );
124 nSize
= aSize
.GetShortValue();
125 if( nSize
< 0 || (bVBASupportOn
&& nSize
<= 0) )
126 Error( SbERR_OUT_OF_RANGE
);
128 rDef
.SetFixedStringLength( nSize
);
132 case SYMBOL
: // can only be a TYPE or a object class!
133 if( eScanType
!= SbxVARIANT
)
134 Error( SbERR_SYNTAX
);
137 OUString aCompleteName
= aSym
;
139 // #52709 DIM AS NEW for Uno with full-qualified name
142 OUString
aDotStr( '.' );
143 while( Peek() == DOT
)
145 aCompleteName
+= aDotStr
;
147 SbiToken ePeekTok
= Peek();
148 if( ePeekTok
== SYMBOL
|| IsKwd( ePeekTok
) )
151 aCompleteName
+= aSym
;
156 Error( SbERR_UNEXPECTED
, SYMBOL
);
161 else if( rEnumArray
->Find( aCompleteName
, SbxCLASS_OBJECT
) || ( IsVBASupportOn() && VBAConstantHelper::instance().isVBAConstantType( aCompleteName
) ) )
167 // Take over in the string pool
168 rDef
.SetTypeId( aGblStrings
.Add( aCompleteName
) );
170 if( rDef
.IsNew() && pProc
== NULL
)
171 aRequiredTypes
.push_back( aCompleteName
);
175 case FIXSTRING
: // new syntax for complex UNO types
176 rDef
.SetTypeId( aGblStrings
.Add( aSym
) );
180 Error( SbERR_UNEXPECTED
, eTok
);
183 // The variable could have been declared with a suffix
184 if( rDef
.GetType() != SbxVARIANT
)
186 if( rDef
.GetType() != eType
)
187 Error( SbERR_VAR_DEFINED
, rDef
.GetName() );
188 else if( eType
== SbxSTRING
&& rDef
.GetLen() != nSize
)
189 Error( SbERR_VAR_DEFINED
, rDef
.GetName() );
191 rDef
.SetType( eType
);
192 rDef
.SetLen( nSize
);
196 // Here variables, arrays and structures were definied.
197 // DIM/PRIVATE/PUBLIC/GLOBAL
199 void SbiParser::Dim()
201 DefVar( _DIM
, pProc
&& bVBASupportOn
&& pProc
->IsStatic() );
204 void SbiParser::DefVar( SbiOpcode eOp
, bool bStatic
)
206 SbiSymPool
* pOldPool
= pPool
;
207 bool bSwitchPool
= false;
208 bool bPersistantGlobal
= false;
209 SbiToken eFirstTok
= eCurTok
;
211 if( pProc
&& ( eCurTok
== GLOBAL
|| eCurTok
== PUBLIC
|| eCurTok
== PRIVATE
) )
212 Error( SbERR_NOT_IN_SUBR
, eCurTok
);
213 if( eCurTok
== PUBLIC
|| eCurTok
== GLOBAL
)
215 bSwitchPool
= true; // at the right moment switch to the global pool
216 if( eCurTok
== GLOBAL
)
217 bPersistantGlobal
= true;
219 // behavior in VBA is that a module scope variable's lifetime is
220 // tied to the document. e.g. a module scope variable is global
221 if( GetBasic()->IsDocBasic() && bVBASupportOn
&& !pProc
)
222 bPersistantGlobal
= true;
223 // PRIVATE is a synonymous for DIM
226 if( eCurTok
== _CONST_
)
228 else if( Peek() == _CONST_
)
229 Next(), bConst
= true;
231 // #110004 It can also be a sub/function
232 if( !bConst
&& (eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
||
233 eCurTok
== STATIC
|| eCurTok
== ENUM
|| eCurTok
== DECLARE
|| eCurTok
== TYPE
) )
235 // Next token is read here, because !bConst
236 bool bPrivate
= ( eFirstTok
== PRIVATE
);
238 if( eCurTok
== STATIC
)
241 DefStatic( bPrivate
);
243 else if( eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
)
245 // End global chain if necessary (not done in
246 // SbiParser::Parse() under these conditions
247 if( bNewGblDefs
&& nGblChain
== 0 )
249 nGblChain
= aGen
.Gen( _JUMP
, 0 );
253 DefProc( false, bPrivate
);
256 else if( eCurTok
== ENUM
)
262 else if( eCurTok
== DECLARE
)
265 DefDeclare( bPrivate
);
269 else if( eCurTok
== TYPE
)
281 // SHARED were ignored
282 if( Peek() == SHARED
) Next();
287 // PRESERVE only at REDIM
288 if( Peek() == PRESERVE
)
294 Error( SbERR_UNEXPECTED
, eCurTok
);
299 // #40689, Statics -> Modul-Initialising, skip in Sub
300 sal_uInt32 nEndOfStaticLbl
= 0;
301 if( !bVBASupportOn
&& bStatic
)
303 nEndOfStaticLbl
= aGen
.Gen( _JUMP
, 0 );
304 aGen
.Statement(); // catch up on static here
307 bool bDefined
= false;
308 while( ( pDef
= VarDecl( &pDim
, bStatic
, bConst
) ) != NULL
)
310 /*fprintf(stderr, "Actual sub: \n");
311 fprintf(stderr, "Symbol name: %s\n",OUStringToOString(pDef->GetName(),RTL_TEXTENCODING_UTF8).getStr());*/
316 SbiSymDef
* pOld
= pPool
->Find( pDef
->GetName() );
317 // search also in the Runtime-Library
318 bool bRtlSym
= false;
321 pOld
= CheckRTLForSym( pDef
->GetName(), SbxVARIANT
);
325 if( pOld
&& !(eOp
== _REDIM
|| eOp
== _REDIMP
) )
327 if( pDef
->GetScope() == SbLOCAL
&& pOld
->GetScope() != SbLOCAL
)
333 // always an error at a RTL-S
334 if( !bRtlSym
&& (eOp
== _REDIM
|| eOp
== _REDIMP
) )
336 // compare the attributes at a REDIM
337 SbxDataType eDefType
;
338 bool bError_
= false;
339 if( pOld
->IsStatic() )
343 else if( pOld
->GetType() != ( eDefType
= pDef
->GetType() ) )
345 if( !( eDefType
== SbxVARIANT
&& !pDef
->IsDefinedAs() ) )
349 Error( SbERR_VAR_DEFINED
, pDef
->GetName() );
352 Error( SbERR_VAR_DEFINED
, pDef
->GetName() );
353 delete pDef
; pDef
= pOld
;
358 // #36374: Create the variable in front of the distinction IsNew()
359 // Otherwise error at Dim Identifier As New Type and option explicit
360 if( !bDefined
&& !(eOp
== _REDIM
|| eOp
== _REDIMP
)
361 && ( !bConst
|| pDef
->GetScope() == SbGLOBAL
) )
363 // Declare variable or global constant
365 switch ( pDef
->GetScope() )
367 case SbGLOBAL
: eOp2
= bPersistantGlobal
? _GLOBAL_P
: _GLOBAL
;
369 case SbPUBLIC
: eOp2
= bPersistantGlobal
? _PUBLIC_P
: _PUBLIC
;
370 // #40689, no own Opcode anymore
371 if( bVBASupportOn
&& bStatic
)
376 global
: aGen
.BackChain( nGblChain
);
378 bGblDefs
= bNewGblDefs
= true;
380 default: eOp2
= _LOCAL
;
382 sal_uInt32 nOpnd2
= sal::static_int_cast
< sal_uInt16
>( pDef
->GetType() );
383 if( pDef
->IsWithEvents() )
384 nOpnd2
|= SBX_TYPE_WITH_EVENTS_FLAG
;
386 if( bCompatible
&& pDef
->IsNew() )
387 nOpnd2
|= SBX_TYPE_DIM_AS_NEW_FLAG
;
389 short nFixedStringLength
= pDef
->GetFixedStringLength();
390 if( nFixedStringLength
>= 0 )
391 nOpnd2
|= (SBX_FIXED_LEN_STRING_FLAG
+ (sal_uInt32(nFixedStringLength
) << 17)); // len = all bits above 0x10000
393 if( pDim
!= NULL
&& pDim
->GetDims() > 0 )
394 nOpnd2
|= SBX_TYPE_VAR_TO_DIM_FLAG
;
396 aGen
.Gen( eOp2
, pDef
->GetId(), nOpnd2
);
399 // Initialising for self-defined daty types
400 // and per NEW created variable
401 if( pDef
->GetType() == SbxOBJECT
402 && pDef
->GetTypeId() )
404 if( !bCompatible
&& !pDef
->IsNew() )
406 OUString
aTypeName( aGblStrings
.Find( pDef
->GetTypeId() ) );
407 if( rTypeArray
->Find( aTypeName
, SbxCLASS_OBJECT
) == NULL
)
409 if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
411 if(!IsUnoInterface(aTypeName
))
412 Error( SbERR_UNDEF_TYPE
, aTypeName
);
415 Error( SbERR_UNDEF_TYPE
, aTypeName
);
421 Error( SbERR_SYNTAX
);
428 SbiExpression
aExpr( this, *pDef
, NULL
);
430 aGen
.Gen( _REDIMP_ERASE
);
432 pDef
->SetDims( pDim
->GetDims() );
433 SbiExpression
aExpr2( this, *pDef
, pDim
);
435 aGen
.Gen( _DCREATE_REDIMP
, pDef
->GetId(), pDef
->GetTypeId() );
439 pDef
->SetDims( pDim
->GetDims() );
440 SbiExpression
aExpr( this, *pDef
, pDim
);
442 aGen
.Gen( _DCREATE
, pDef
->GetId(), pDef
->GetTypeId() );
447 SbiExpression
aExpr( this, *pDef
);
449 SbiOpcode eOp_
= pDef
->IsNew() ? _CREATE
: _TCREATE
;
450 aGen
.Gen( eOp_
, pDef
->GetId(), pDef
->GetTypeId() );
461 // Definition of the constants
464 Error( SbERR_SYNTAX
);
467 SbiExpression
aVar( this, *pDef
);
468 if( !TestToken( EQ
) )
469 goto MyBreak
; // (see below)
470 SbiConstExpression
aExpr( this );
471 if( !bDefined
&& aExpr
.IsValid() )
473 if( pDef
->GetScope() == SbGLOBAL
)
475 // Create code only for the global constant!
480 SbiConstDef
* pConst
= pDef
->GetConstDef();
481 if( aExpr
.GetType() == SbxSTRING
)
482 pConst
->Set( aExpr
.GetString() );
484 pConst
->Set( aExpr
.GetValue(), aExpr
.GetType() );
489 // Dimension the variable
490 // Delete the var at REDIM beforehand
493 SbiExpression
aExpr( this, *pDef
, NULL
);
496 // delete the array but
497 // clear the variable ( this
498 // allows the processing of
499 // the param to happen as normal without errors ( ordinary ERASE just clears the array )
500 aGen
.Gen( _ERASE_CLEAR
);
504 else if( eOp
== _REDIMP
)
506 SbiExpression
aExpr( this, *pDef
, NULL
);
508 aGen
.Gen( _REDIMP_ERASE
);
510 pDef
->SetDims( pDim
->GetDims() );
511 if( bPersistantGlobal
)
512 pDef
->SetGlobal( true );
513 SbiExpression
aExpr( this, *pDef
, pDim
);
515 pDef
->SetGlobal( false );
516 aGen
.Gen( (eOp
== _STATIC
) ? _DIM
: eOp
);
522 // Implementation of bSwitchPool (see above): pPool must not be set to &aGlobals
523 // at the VarDecl-Call.
524 // Apart from that the behavior should be absolutely identical,
525 // i.e., pPool had to be reset always at the end of the loop.
528 continue; // Skip MyBreak
534 // #40689, finalize the jump over statics declarations
535 if( !bVBASupportOn
&& bStatic
)
537 // maintain the global chain
538 nGblChain
= aGen
.Gen( _JUMP
, 0 );
539 bGblDefs
= bNewGblDefs
= true;
541 // Register for Sub a jump to the end of statics
542 aGen
.BackChain( nEndOfStaticLbl
);
547 // Here were Arrays redimensioned.
549 void SbiParser::ReDim()
551 DefVar( _REDIM
, pProc
&& bVBASupportOn
&& pProc
->IsStatic() );
556 void SbiParser::Erase()
560 SbiExpression
aExpr( this, SbLVALUE
);
563 if( !TestComma() ) break;
567 // Declaration of a data type
569 void SbiParser::Type()
574 void SbiParser::DefType( bool bPrivate
)
576 // TODO: Use bPrivate
579 // Read the new Token lesen. It had to be a symbol
583 if (rTypeArray
->Find(aSym
,SbxCLASS_OBJECT
))
585 Error( SbERR_VAR_DEFINED
, aSym
);
589 SbxObject
*pType
= new SbxObject(aSym
);
591 boost::scoped_ptr
<SbiSymDef
> pElem
;
592 SbiDimList
* pDim
= NULL
;
595 while( !bDone
&& !IsEof() )
610 pElem
.reset(VarDecl(&pDim
, false, false));
612 bDone
= true; // Error occurred
616 SbxArray
*pTypeMembers
= pType
->GetProperties();
617 OUString aElemName
= pElem
->GetName();
618 if( pTypeMembers
->Find( aElemName
, SbxCLASS_DONTCARE
) )
620 Error (SbERR_VAR_DEFINED
);
624 SbxDataType eElemType
= pElem
->GetType();
625 SbxProperty
*pTypeElem
= new SbxProperty( aElemName
, eElemType
);
628 SbxDimArray
* pArray
= new SbxDimArray( pElem
->GetType() );
629 if ( pDim
->GetSize() )
631 // Dimension the target array
633 for ( short i
=0; i
<pDim
->GetSize();++i
)
635 sal_Int32 lb
= nBase
;
636 SbiExprNode
* pNode
= pDim
->Get(i
)->GetExprNode();
637 sal_Int32 ub
= pNode
->GetNumber();
638 if ( !pDim
->Get( i
)->IsBased() ) // each dim is low/up
640 if ( ++i
>= pDim
->GetSize() ) // trouble
641 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
642 pNode
= pDim
->Get(i
)->GetExprNode();
644 ub
= pNode
->GetNumber();
646 else if ( !bCompatible
)
648 pArray
->AddDim32( lb
, ub
);
650 pArray
->setHasFixedSize( true );
653 pArray
->unoAddDim( 0, -1 ); // variant array
654 SbxFlagBits nSavFlags
= pTypeElem
->GetFlags();
655 // need to reset the FIXED flag
656 // when calling PutObject ( because the type will not match Object )
657 pTypeElem
->ResetFlag( SBX_FIXED
);
658 pTypeElem
->PutObject( pArray
);
659 pTypeElem
->SetFlags( nSavFlags
);
662 if( eElemType
== SbxOBJECT
)
664 sal_uInt16 nElemTypeId
= pElem
->GetTypeId();
665 if( nElemTypeId
!= 0 )
667 OUString
aTypeName( aGblStrings
.Find( nElemTypeId
) );
668 SbxObject
* pTypeObj
= static_cast< SbxObject
* >( rTypeArray
->Find( aTypeName
, SbxCLASS_OBJECT
) );
669 if( pTypeObj
!= NULL
)
671 SbxObject
* pCloneObj
= cloneTypeObjectImpl( *pTypeObj
);
672 pTypeElem
->PutObject( pCloneObj
);
676 pTypeMembers
->Insert( pTypeElem
, pTypeMembers
->Count() );
678 delete pDim
, pDim
= NULL
;
683 pType
->Remove( OUString("Name"), SbxCLASS_DONTCARE
);
684 pType
->Remove( OUString("Parent"), SbxCLASS_DONTCARE
);
686 rTypeArray
->Insert (pType
,rTypeArray
->Count());
690 // Declaration of Enum type
692 void SbiParser::Enum()
697 void SbiParser::DefEnum( bool bPrivate
)
699 // Read a the new Token. It had to be a symbol
703 OUString aEnumName
= aSym
;
704 if( rEnumArray
->Find(aEnumName
,SbxCLASS_OBJECT
) )
706 Error( SbERR_VAR_DEFINED
, aSym
);
710 SbxObject
*pEnum
= new SbxObject( aEnumName
);
713 pEnum
->SetFlag( SBX_PRIVATE
);
719 // Starting with -1 to make first default value 0 after ++
720 sal_Int32 nCurrentEnumValue
= -1;
721 while( !bDone
&& !IsEof() )
739 // TODO: Check existing!
741 pElem
= VarDecl( &pDim
, false, true );
744 bDone
= true; // Error occurred
750 Error( SbERR_SYNTAX
);
751 bDone
= true; // Error occurred
755 SbiExpression
aVar( this, *pElem
);
760 SbiConstExpression
aExpr( this );
761 if( aExpr
.IsValid() )
763 SbxVariableRef xConvertVar
= new SbxVariable();
764 if( aExpr
.GetType() == SbxSTRING
)
765 xConvertVar
->PutString( aExpr
.GetString() );
767 xConvertVar
->PutDouble( aExpr
.GetValue() );
769 nCurrentEnumValue
= xConvertVar
->GetLong();
775 SbiSymPool
* pPoolToUse
= bPrivate
? pPool
: &aGlobals
;
777 SbiSymDef
* pOld
= pPoolToUse
->Find( pElem
->GetName() );
780 Error( SbERR_VAR_DEFINED
, pElem
->GetName() );
781 bDone
= true; // Error occurred
789 SbiOpcode eOp
= _GLOBAL
;
790 aGen
.BackChain( nGblChain
);
792 bGblDefs
= bNewGblDefs
= true;
795 sal::static_int_cast
< sal_uInt16
>( pElem
->GetType() ) );
798 sal_uInt16 nStringId
= aGen
.GetParser()->aGblStrings
.Add( nCurrentEnumValue
, SbxLONG
);
799 aGen
.Gen( _NUMBER
, nStringId
);
803 SbiConstDef
* pConst
= pElem
->GetConstDef();
804 pConst
->Set( nCurrentEnumValue
, SbxLONG
);
809 SbxArray
*pEnumMembers
= pEnum
->GetProperties();
810 SbxProperty
*pEnumElem
= new SbxProperty( pElem
->GetName(), SbxLONG
);
811 pEnumElem
->PutLong( nCurrentEnumValue
);
812 pEnumElem
->ResetFlag( SBX_WRITE
);
813 pEnumElem
->SetFlag( SBX_CONST
);
814 pEnumMembers
->Insert( pEnumElem
, pEnumMembers
->Count() );
818 pEnum
->Remove( OUString("Name"), SbxCLASS_DONTCARE
);
819 pEnum
->Remove( OUString("Parent"), SbxCLASS_DONTCARE
);
821 rEnumArray
->Insert( pEnum
, rEnumArray
->Count() );
825 // Procedure-Declaration
826 // the first Token is already read in (SUB/FUNCTION)
827 // xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
829 SbiProcDef
* SbiParser::ProcDecl( bool bDecl
)
831 bool bFunc
= ( eCurTok
== FUNCTION
);
832 bool bProp
= ( eCurTok
== GET
|| eCurTok
== SET
|| eCurTok
== LET
);
833 if( !TestSymbol() ) return NULL
;
834 OUString
aName( aSym
);
835 SbxDataType eType
= eScanType
;
836 SbiProcDef
* pDef
= new SbiProcDef( this, aName
, true );
837 pDef
->SetType( eType
);
838 if( Peek() == _CDECL_
)
840 Next(); pDef
->SetCdecl();
845 if( Next() == FIXSTRING
)
847 pDef
->GetLib() = aSym
;
851 Error( SbERR_SYNTAX
);
854 if( Peek() == ALIAS
)
857 if( Next() == FIXSTRING
)
859 pDef
->GetAlias() = aSym
;
863 Error( SbERR_SYNTAX
);
868 // CDECL, LIB and ALIAS are invalid
869 if( !pDef
->GetLib().isEmpty() )
871 Error( SbERR_UNEXPECTED
, LIB
);
873 if( !pDef
->GetAlias().isEmpty() )
875 Error( SbERR_UNEXPECTED
, ALIAS
);
877 if( pDef
->IsCdecl() )
879 Error( SbERR_UNEXPECTED
, _CDECL_
);
881 pDef
->SetCdecl( false );
882 pDef
->GetLib().clear();
883 pDef
->GetAlias().clear();
885 else if( pDef
->GetLib().isEmpty() )
887 // ALIAS and CDECL only together with LIB
888 if( !pDef
->GetAlias().isEmpty() )
890 Error( SbERR_UNEXPECTED
, ALIAS
);
892 if( pDef
->IsCdecl() )
894 Error( SbERR_UNEXPECTED
, _CDECL_
);
896 pDef
->SetCdecl( false );
897 pDef
->GetAlias().clear();
900 if( Peek() == LPAREN
)
903 if( Peek() == RPAREN
)
912 bool bOptional
= false;
913 bool bParamArray
= false;
914 while( Peek() == BYVAL
|| Peek() == BYREF
|| Peek() == _OPTIONAL_
)
916 if( Peek() == BYVAL
)
920 else if ( Peek() == BYREF
)
924 else if ( Peek() == _OPTIONAL_
)
930 if( bCompatible
&& Peek() == PARAMARRAY
)
932 if( bByVal
|| bOptional
)
934 Error( SbERR_UNEXPECTED
, PARAMARRAY
);
939 SbiSymDef
* pPar
= VarDecl( NULL
, false, false );
954 pPar
->SetParamArray();
956 pDef
->GetParams().Add( pPar
);
957 SbiToken eTok
= Next();
958 if( eTok
!= COMMA
&& eTok
!= RPAREN
)
961 if( bOptional
&& bCompatible
&& eTok
== EQ
)
963 boost::scoped_ptr
<SbiConstExpression
> pDefaultExpr(new SbiConstExpression( this ));
964 SbxDataType eType2
= pDefaultExpr
->GetType();
966 sal_uInt16 nStringId
;
967 if( eType2
== SbxSTRING
)
969 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetString() );
973 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetValue(), eType2
);
975 pPar
->SetDefaultId( nStringId
);
976 pDefaultExpr
.reset();
979 if( eTok
== COMMA
|| eTok
== RPAREN
)
986 Error( SbERR_EXPECTED
, RPAREN
);
998 if( eType
!= SbxVARIANT
&& pDef
->GetType() != eType
)
1000 Error( SbERR_BAD_DECLARATION
, aName
);
1002 if( pDef
->GetType() == SbxVARIANT
&& !( bFunc
|| bProp
) )
1004 pDef
->SetType( SbxEMPTY
);
1011 void SbiParser::Declare()
1013 DefDeclare( false );
1016 void SbiParser::DefDeclare( bool bPrivate
)
1019 if( eCurTok
!= SUB
&& eCurTok
!= FUNCTION
)
1021 Error( SbERR_UNEXPECTED
, eCurTok
);
1025 bool bFunction
= (eCurTok
== FUNCTION
);
1027 SbiProcDef
* pDef
= ProcDecl( true );
1030 if( pDef
->GetLib().isEmpty() )
1032 Error( SbERR_EXPECTED
, LIB
);
1034 // Is it already there?
1035 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1038 SbiProcDef
* p
= pOld
->GetProcDef();
1041 // Declared as a variable
1042 Error( SbERR_BAD_DECLARATION
, pDef
->GetName() );
1053 aPublics
.Add( pDef
);
1057 pDef
->SetPublic( !bPrivate
);
1059 // New declare handling
1060 if( !pDef
->GetLib().isEmpty())
1062 if( bNewGblDefs
&& nGblChain
== 0 )
1064 nGblChain
= aGen
.Gen( _JUMP
, 0 );
1065 bNewGblDefs
= false;
1068 sal_uInt16 nSavLine
= nLine
;
1071 pDef
->SetLine1( nSavLine
);
1072 pDef
->SetLine2( nSavLine
);
1074 SbiSymPool
& rPool
= pDef
->GetParams();
1075 sal_uInt16 nParCount
= rPool
.GetSize();
1077 SbxDataType eType
= pDef
->GetType();
1080 aGen
.Gen( _PARAM
, 0, sal::static_int_cast
< sal_uInt16
>( eType
) );
1086 for( sal_uInt16 i
= 1 ; i
< nParCount
; ++i
)
1088 SbiSymDef
* pParDef
= rPool
.Get( i
);
1089 SbxDataType eParType
= pParDef
->GetType();
1091 aGen
.Gen( _PARAM
, i
, sal::static_int_cast
< sal_uInt16
>( eParType
) );
1094 sal_uInt16 nTyp
= sal::static_int_cast
< sal_uInt16
>( pParDef
->GetType() );
1095 if( pParDef
->IsByVal() )
1097 // Reset to avoid additional byval in call to wrapper function
1098 pParDef
->SetByVal( false );
1101 aGen
.Gen( _ARGTYP
, nTyp
);
1105 aGen
.Gen( _LIB
, aGblStrings
.Add( pDef
->GetLib() ) );
1107 SbiOpcode eOp
= pDef
->IsCdecl() ? _CALLC
: _CALL
;
1108 sal_uInt16 nId
= pDef
->GetId();
1109 if( !pDef
->GetAlias().isEmpty() )
1111 nId
= ( nId
& 0x8000 ) | aGblStrings
.Add( pDef
->GetAlias() );
1117 aGen
.Gen( eOp
, nId
, sal::static_int_cast
< sal_uInt16
>( eType
) );
1130 void SbiParser::Attribute()
1132 // TODO: Need to implement the method as an attributed object.
1133 while( Next() != EQ
)
1143 Error( SbERR_SYNTAX
);
1147 SbiExpression
aValue( this );
1149 // Don't generate any code - just discard it.
1152 // Call of a SUB or a FUNCTION
1154 void SbiParser::Call()
1156 SbiExpression
aVar( this, SbSYMBOL
);
1157 aVar
.Gen( FORCE_CALL
);
1163 void SbiParser::SubFunc()
1165 DefProc( false, false );
1168 // Read in of a procedure
1170 void SbiParser::DefProc( bool bStatic
, bool bPrivate
)
1172 sal_uInt16 l1
= nLine
;
1173 bool bSub
= ( eCurTok
== SUB
);
1174 bool bProperty
= ( eCurTok
== PROPERTY
);
1175 PropertyMode ePropertyMode
= PROPERTY_MODE_NONE
;
1179 if( eCurTok
== GET
)
1181 ePropertyMode
= PROPERTY_MODE_GET
;
1183 else if( eCurTok
== LET
)
1185 ePropertyMode
= PROPERTY_MODE_LET
;
1187 else if( eCurTok
== SET
)
1189 ePropertyMode
= PROPERTY_MODE_SET
;
1193 Error( SbERR_EXPECTED
, "Get or Let or Set" );
1197 SbiToken eExit
= eCurTok
;
1198 SbiProcDef
* pDef
= ProcDecl( false );
1203 pDef
->setPropertyMode( ePropertyMode
);
1205 // Is the Proc already declared?
1206 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1209 bool bError_
= false;
1211 pProc
= pOld
->GetProcDef();
1214 // Declared as a variable
1215 Error( SbERR_BAD_DECLARATION
, pDef
->GetName() );
1220 // #100027: Multiple declaration -> Error
1221 // #112787: Not for setup, REMOVE for 8
1222 else if( pProc
->IsUsedForProcDecl() )
1224 PropertyMode ePropMode
= pDef
->getPropertyMode();
1225 if( ePropMode
== PROPERTY_MODE_NONE
|| ePropMode
== pProc
->getPropertyMode() )
1227 Error( SbERR_PROC_DEFINED
, pDef
->GetName() );
1236 pDef
->Match( pProc
);
1242 aPublics
.Add( pDef
), pProc
= pDef
;
1248 pProc
->SetPublic( !bPrivate
);
1250 // Now we set the search hierarchy for symbols as well as the
1251 // current procedure.
1252 aPublics
.SetProcId( pProc
->GetId() );
1253 pProc
->GetParams().SetParent( &aPublics
);
1256 if ( bVBASupportOn
)
1258 pProc
->SetStatic( true );
1262 Error( SbERR_NOT_IMPLEMENTED
); // STATIC SUB ...
1267 pProc
->SetStatic( false );
1269 // Normal case: Local variable->parameter->global variable
1270 pProc
->GetLocals().SetParent( &pProc
->GetParams() );
1271 pPool
= &pProc
->GetLocals();
1275 StmntBlock( bSub
? ENDSUB
: (bProperty
? ENDPROPERTY
: ENDFUNC
) );
1276 sal_uInt16 l2
= nLine
;
1277 pProc
->SetLine1( l1
);
1278 pProc
->SetLine2( l2
);
1280 aPublics
.SetProcId( 0 );
1282 pProc
->GetLabels().CheckRefs();
1288 // STATIC variable|procedure
1290 void SbiParser::Static()
1295 void SbiParser::DefStatic( bool bPrivate
)
1304 // End global chain if necessary (not done in
1305 // SbiParser::Parse() under these conditions
1306 if( bNewGblDefs
&& nGblChain
== 0 )
1308 nGblChain
= aGen
.Gen( _JUMP
, 0 );
1309 bNewGblDefs
= false;
1312 DefProc( true, bPrivate
);
1317 Error( SbERR_NOT_IN_SUBR
);
1319 // Reset the Pool, so that STATIC-Declarations go into the
1323 DefVar( _STATIC
, true );
1329 bool SbiParser::IsUnoInterface(const OUString
& sTypeName
)
1333 return css::reflection::theCoreReflection::get(
1334 comphelper::getProcessComponentContext())->forName(sTypeName
).is();
1336 catch(const Exception
&)
1338 OSL_FAIL("Could not create reflection.CoreReflection.");
1343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */