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/sberrors.hxx>
21 #include <basic/sbstar.hxx>
22 #include <basic/sbx.hxx>
23 #include <sbunoobj.hxx>
26 #include <osl/diagnose.h>
27 #include <com/sun/star/reflection/theCoreReflection.hpp>
28 #include <comphelper/processfactory.hxx>
29 #include <com/sun/star/uno/Exception.hpp>
30 #include <basic/codecompletecache.hxx>
33 using namespace ::com::sun::star
;
34 using namespace ::com::sun::star::uno
;
36 // Declaration of a variable
37 // If there are errors it will be parsed up to the comma or the newline.
38 // Return-value: a new instance, which were inserted and then deleted.
39 // Array-Index were returned as SbiExprList
41 SbiSymDef
* SbiParser::VarDecl( SbiExprListPtr
* ppDim
, bool bStatic
, bool bConst
)
43 bool bWithEvents
= false;
44 if( Peek() == WITHEVENTS
)
49 if( !TestSymbol() ) return nullptr;
50 SbxDataType t
= eScanType
;
51 SbiSymDef
* pDef
= bConst
? new SbiConstDef( aSym
) : new SbiSymDef( aSym
);
54 if( Peek() == LPAREN
)
56 pDim
= SbiExprList::ParseDimList( this );
57 if( !pDim
->GetDims() )
58 pDef
->SetWithBrackets();
64 pDef
->SetWithEvents();
69 Error( ERRCODE_BASIC_EXPECTED
, "()" );
72 *ppDim
= std::move(pDim
);
76 // Resolving of an AS-Type-Declaration
77 // The data type were inserted into the handed over variable
79 void SbiParser::TypeDecl( SbiSymDef
& rDef
, bool bAsNewAlreadyParsed
)
81 SbxDataType eType
= rDef
.GetType();
82 if( bAsNewAlreadyParsed
|| Peek() == AS
)
85 if( !bAsNewAlreadyParsed
)
88 SbiToken eTok
= Next();
89 if( !bAsNewAlreadyParsed
&& eTok
== NEW
)
98 Error( ERRCODE_BASIC_SYNTAX
);
99 eType
= SbxVARIANT
; break;
113 Error( ERRCODE_BASIC_SYNTAX
);
114 eType
= (eTok
==TBYTE
) ? SbxBYTE
: SbxDataType( eTok
- TINTEGER
+ SbxINTEGER
);
115 if( eType
== SbxSTRING
)
121 SbiConstExpression
aSize( this );
122 nSize
= aSize
.GetShortValue();
123 if( nSize
< 0 || (bVBASupportOn
&& nSize
<= 0) )
124 Error( ERRCODE_BASIC_OUT_OF_RANGE
);
126 rDef
.SetFixedStringLength( nSize
);
130 case SYMBOL
: // can only be a TYPE or an object class!
131 if( eScanType
!= SbxVARIANT
)
132 Error( ERRCODE_BASIC_SYNTAX
);
135 OUString aCompleteName
= aSym
;
137 // #52709 DIM AS NEW for Uno with full-qualified name
140 OUString
aDotStr( '.' );
141 while( Peek() == DOT
)
143 aCompleteName
+= aDotStr
;
145 SbiToken ePeekTok
= Peek();
146 if( ePeekTok
== SYMBOL
|| IsKwd( ePeekTok
) )
149 aCompleteName
+= aSym
;
154 Error( ERRCODE_BASIC_UNEXPECTED
, SYMBOL
);
159 else if( rEnumArray
->Find( aCompleteName
, SbxClassType::Object
) || ( IsVBASupportOn() && VBAConstantHelper::instance().isVBAConstantType( aCompleteName
) ) )
165 // Take over in the string pool
166 rDef
.SetTypeId( aGblStrings
.Add( aCompleteName
) );
168 if( rDef
.IsNew() && pProc
== nullptr )
169 aRequiredTypes
.push_back( aCompleteName
);
173 case FIXSTRING
: // new syntax for complex UNO types
174 rDef
.SetTypeId( aGblStrings
.Add( aSym
) );
178 Error( ERRCODE_BASIC_UNEXPECTED
, eTok
);
181 // The variable could have been declared with a suffix
182 if( rDef
.GetType() != SbxVARIANT
)
184 if( rDef
.GetType() != eType
)
185 Error( ERRCODE_BASIC_VAR_DEFINED
, rDef
.GetName() );
186 else if( eType
== SbxSTRING
&& rDef
.GetLen() != nSize
)
187 Error( ERRCODE_BASIC_VAR_DEFINED
, rDef
.GetName() );
189 rDef
.SetType( eType
);
190 rDef
.SetLen( nSize
);
194 // Here variables, arrays and structures were defined.
195 // DIM/PRIVATE/PUBLIC/GLOBAL
197 void SbiParser::Dim()
199 DefVar( SbiOpcode::DIM_
, pProc
&& bVBASupportOn
&& pProc
->IsStatic() );
202 void SbiParser::DefVar( SbiOpcode eOp
, bool bStatic
)
204 SbiSymPool
* pOldPool
= pPool
;
205 bool bSwitchPool
= false;
206 bool bPersistentGlobal
= false;
207 SbiToken eFirstTok
= eCurTok
;
209 if( pProc
&& ( eCurTok
== GLOBAL
|| eCurTok
== PUBLIC
|| eCurTok
== PRIVATE
) )
210 Error( ERRCODE_BASIC_NOT_IN_SUBR
, eCurTok
);
211 if( eCurTok
== PUBLIC
|| eCurTok
== GLOBAL
)
213 bSwitchPool
= true; // at the right moment switch to the global pool
214 if( eCurTok
== GLOBAL
)
215 bPersistentGlobal
= true;
217 // behavior in VBA is that a module scope variable's lifetime is
218 // tied to the document. e.g. a module scope variable is global
219 if( GetBasic()->IsDocBasic() && bVBASupportOn
&& !pProc
)
220 bPersistentGlobal
= true;
221 // PRIVATE is a synonymous for DIM
224 if( eCurTok
== CONST_
)
226 else if( Peek() == CONST_
)
232 // #110004 It can also be a sub/function
233 if( !bConst
&& (eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
||
234 eCurTok
== STATIC
|| eCurTok
== ENUM
|| eCurTok
== DECLARE
|| eCurTok
== TYPE
) )
236 // Next token is read here, because !bConst
237 bool bPrivate
= ( eFirstTok
== PRIVATE
);
239 if( eCurTok
== STATIC
)
242 DefStatic( bPrivate
);
244 else if( eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
)
246 // End global chain if necessary (not done in
247 // SbiParser::Parse() under these conditions
248 if( bNewGblDefs
&& nGblChain
== 0 )
250 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
254 DefProc( false, bPrivate
);
257 else if( eCurTok
== ENUM
)
263 else if( eCurTok
== DECLARE
)
266 DefDeclare( bPrivate
);
270 else if( eCurTok
== TYPE
)
273 DefType(); // TODO: Use bPrivate in DefType()
278 // SHARED were ignored
279 if( Peek() == SHARED
) Next();
281 // PRESERVE only at REDIM
282 if( Peek() == PRESERVE
)
285 if( eOp
== SbiOpcode::REDIM_
)
286 eOp
= SbiOpcode::REDIMP_
;
288 Error( ERRCODE_BASIC_UNEXPECTED
, eCurTok
);
293 // #40689, Statics -> Module-Initialising, skip in Sub
294 sal_uInt32 nEndOfStaticLbl
= 0;
295 if( !bVBASupportOn
&& bStatic
)
297 nEndOfStaticLbl
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
298 aGen
.Statement(); // catch up on static here
301 bool bDefined
= false;
302 while( ( pDef
= VarDecl( &pDim
, bStatic
, bConst
) ) != nullptr )
304 /*fprintf(stderr, "Actual sub: \n");
305 fprintf(stderr, "Symbol name: %s\n",OUStringToOString(pDef->GetName(),RTL_TEXTENCODING_UTF8).getStr());*/
310 SbiSymDef
* pOld
= pPool
->Find( pDef
->GetName() );
311 // search also in the Runtime-Library
312 bool bRtlSym
= false;
315 pOld
= CheckRTLForSym( pDef
->GetName(), SbxVARIANT
);
319 if( pOld
&& !(eOp
== SbiOpcode::REDIM_
|| eOp
== SbiOpcode::REDIMP_
) )
321 if( pDef
->GetScope() == SbLOCAL
)
322 if (auto eOldScope
= pOld
->GetScope(); eOldScope
!= SbLOCAL
&& eOldScope
!= SbPARAM
)
328 // always an error at a RTL-S
329 if( !bRtlSym
&& (eOp
== SbiOpcode::REDIM_
|| eOp
== SbiOpcode::REDIMP_
) )
331 // compare the attributes at a REDIM
332 SbxDataType eDefType
;
333 bool bError_
= false;
334 if( pOld
->IsStatic() )
338 else if( pOld
->GetType() != ( eDefType
= pDef
->GetType() ) )
340 if( !( eDefType
== SbxVARIANT
&& !pDef
->IsDefinedAs() ) )
344 Error( ERRCODE_BASIC_VAR_DEFINED
, pDef
->GetName() );
347 Error( ERRCODE_BASIC_VAR_DEFINED
, pDef
->GetName() );
348 delete pDef
; pDef
= pOld
;
353 // #36374: Create the variable in front of the distinction IsNew()
354 // Otherwise error at Dim Identifier As New Type and option explicit
355 if( !bDefined
&& !(eOp
== SbiOpcode::REDIM_
|| eOp
== SbiOpcode::REDIMP_
)
356 && ( !bConst
|| pDef
->GetScope() == SbGLOBAL
) )
358 // Declare variable or global constant
360 switch ( pDef
->GetScope() )
362 case SbGLOBAL
: eOp2
= bPersistentGlobal
? SbiOpcode::GLOBAL_P_
: SbiOpcode::GLOBAL_
;
364 case SbPUBLIC
: eOp2
= bPersistentGlobal
? SbiOpcode::PUBLIC_P_
: SbiOpcode::PUBLIC_
;
365 // #40689, no own Opcode anymore
366 if( bVBASupportOn
&& bStatic
)
368 eOp2
= SbiOpcode::STATIC_
;
371 global
: aGen
.BackChain( nGblChain
);
373 bGblDefs
= bNewGblDefs
= true;
375 default: eOp2
= SbiOpcode::LOCAL_
;
377 sal_uInt32 nOpnd2
= sal::static_int_cast
< sal_uInt16
>( pDef
->GetType() );
378 if( pDef
->IsWithEvents() )
379 nOpnd2
|= SBX_TYPE_WITH_EVENTS_FLAG
;
381 if( bCompatible
&& pDef
->IsNew() )
382 nOpnd2
|= SBX_TYPE_DIM_AS_NEW_FLAG
;
384 short nFixedStringLength
= pDef
->GetFixedStringLength();
385 if( nFixedStringLength
>= 0 )
386 nOpnd2
|= (SBX_FIXED_LEN_STRING_FLAG
+ (sal_uInt32(nFixedStringLength
) << 17)); // len = all bits above 0x10000
388 if( pDim
!= nullptr && pDim
->GetDims() > 0 )
389 nOpnd2
|= SBX_TYPE_VAR_TO_DIM_FLAG
;
391 aGen
.Gen( eOp2
, pDef
->GetId(), nOpnd2
);
394 // Initialising for self-defined data types
395 // and per NEW created variable
396 if( pDef
->GetType() == SbxOBJECT
397 && pDef
->GetTypeId() )
399 if( !bCompatible
&& !pDef
->IsNew() )
401 OUString
aTypeName( aGblStrings
.Find( pDef
->GetTypeId() ) );
402 if( rTypeArray
->Find( aTypeName
, SbxClassType::Object
) == nullptr )
404 if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
406 if(!IsUnoInterface(aTypeName
))
407 Error( ERRCODE_BASIC_UNDEF_TYPE
, aTypeName
);
410 Error( ERRCODE_BASIC_UNDEF_TYPE
, aTypeName
);
416 Error( ERRCODE_BASIC_SYNTAX
);
421 if( eOp
== SbiOpcode::REDIMP_
)
423 SbiExpression
aExpr( this, *pDef
, nullptr );
425 aGen
.Gen( SbiOpcode::REDIMP_ERASE_
);
427 pDef
->SetDims( pDim
->GetDims() );
428 SbiExpression
aExpr2( this, *pDef
, std::move(pDim
) );
430 aGen
.Gen( SbiOpcode::DCREATE_REDIMP_
, pDef
->GetId(), pDef
->GetTypeId() );
434 pDef
->SetDims( pDim
->GetDims() );
435 SbiExpression
aExpr( this, *pDef
, std::move(pDim
) );
437 aGen
.Gen( SbiOpcode::DCREATE_
, pDef
->GetId(), pDef
->GetTypeId() );
442 SbiExpression
aExpr( this, *pDef
);
444 SbiOpcode eOp_
= pDef
->IsNew() ? SbiOpcode::CREATE_
: SbiOpcode::TCREATE_
;
445 aGen
.Gen( eOp_
, pDef
->GetId(), pDef
->GetTypeId() );
447 aGen
.Gen( SbiOpcode::VBASET_
);
449 aGen
.Gen( SbiOpcode::SET_
);
456 // Definition of the constants
459 Error( ERRCODE_BASIC_SYNTAX
);
461 SbiExpression
aVar( this, *pDef
);
462 if( !TestToken( EQ
) )
463 goto MyBreak
; // (see below)
464 SbiConstExpression
aExpr( this );
465 if( !bDefined
&& aExpr
.IsValid() )
467 if( pDef
->GetScope() == SbGLOBAL
)
469 // Create code only for the global constant!
472 aGen
.Gen( SbiOpcode::PUTC_
);
474 SbiConstDef
* pConst
= pDef
->GetConstDef();
475 if( aExpr
.GetType() == SbxSTRING
)
476 pConst
->Set( aExpr
.GetString() );
478 pConst
->Set( aExpr
.GetValue(), aExpr
.GetType() );
483 // Dimension the variable
484 // Delete the var at REDIM beforehand
485 if( eOp
== SbiOpcode::REDIM_
)
487 SbiExpression
aExpr( this, *pDef
, nullptr );
490 // delete the array but
491 // clear the variable ( this
492 // allows the processing of
493 // the param to happen as normal without errors ( ordinary ERASE just clears the array )
494 aGen
.Gen( SbiOpcode::ERASE_CLEAR_
);
496 aGen
.Gen( SbiOpcode::ERASE_
);
498 else if( eOp
== SbiOpcode::REDIMP_
)
500 SbiExpression
aExpr( this, *pDef
, nullptr );
502 aGen
.Gen( SbiOpcode::REDIMP_ERASE_
);
504 pDef
->SetDims( pDim
->GetDims() );
505 if( bPersistentGlobal
)
506 pDef
->SetGlobal( true );
507 SbiExpression
aExpr( this, *pDef
, std::move(pDim
) );
509 pDef
->SetGlobal( false );
510 aGen
.Gen( (eOp
== SbiOpcode::STATIC_
) ? SbiOpcode::DIM_
: eOp
);
516 // Implementation of bSwitchPool (see above): pPool must not be set to &aGlobals
517 // at the VarDecl-Call.
518 // Apart from that the behavior should be absolutely identical,
519 // i.e., pPool had to be reset always at the end of the loop.
522 continue; // Skip MyBreak
528 // #40689, finalize the jump over statics declarations
529 if( !bVBASupportOn
&& bStatic
)
531 // maintain the global chain
532 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
533 bGblDefs
= bNewGblDefs
= true;
535 // Register for Sub a jump to the end of statics
536 aGen
.BackChain( nEndOfStaticLbl
);
541 // Here were Arrays redimensioned.
543 void SbiParser::ReDim()
545 DefVar( SbiOpcode::REDIM_
, pProc
&& bVBASupportOn
&& pProc
->IsStatic() );
550 void SbiParser::Erase()
554 SbiExpression
aExpr( this, SbLVALUE
);
556 aGen
.Gen( SbiOpcode::ERASE_
);
557 if( !TestComma() ) break;
561 // Declaration of a data type
563 void SbiParser::Type()
568 void SbiParser::DefType()
570 // Read the new Token lesen. It had to be a symbol
574 if (rTypeArray
->Find(aSym
,SbxClassType::Object
))
576 Error( ERRCODE_BASIC_VAR_DEFINED
, aSym
);
580 SbxObject
*pType
= new SbxObject(aSym
);
584 while( !bDone
&& !IsEof() )
586 std::unique_ptr
<SbiSymDef
> pElem
;
601 pElem
.reset(VarDecl(&pDim
, false, false));
603 bDone
= true; // Error occurred
607 SbxArray
*pTypeMembers
= pType
->GetProperties();
608 OUString aElemName
= pElem
->GetName();
609 if( pTypeMembers
->Find( aElemName
, SbxClassType::DontCare
) )
611 Error (ERRCODE_BASIC_VAR_DEFINED
);
615 SbxDataType eElemType
= pElem
->GetType();
616 SbxProperty
*pTypeElem
= new SbxProperty( aElemName
, eElemType
);
619 SbxDimArray
* pArray
= new SbxDimArray( pElem
->GetType() );
620 if ( pDim
->GetSize() )
622 // Dimension the target array
624 for ( short i
=0; i
<pDim
->GetSize();++i
)
626 sal_Int32 lb
= nBase
;
627 SbiExprNode
* pNode
= pDim
->Get(i
)->GetExprNode();
628 sal_Int32 ub
= pNode
->GetNumber();
629 if ( !pDim
->Get( i
)->IsBased() ) // each dim is low/up
631 if ( ++i
>= pDim
->GetSize() ) // trouble
632 StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR
);
633 pNode
= pDim
->Get(i
)->GetExprNode();
635 ub
= pNode
->GetNumber();
637 else if ( !bCompatible
)
639 pArray
->AddDim32( lb
, ub
);
641 pArray
->setHasFixedSize( true );
644 pArray
->unoAddDim( 0, -1 ); // variant array
645 SbxFlagBits nSavFlags
= pTypeElem
->GetFlags();
646 // need to reset the FIXED flag
647 // when calling PutObject ( because the type will not match Object )
648 pTypeElem
->ResetFlag( SbxFlagBits::Fixed
);
649 pTypeElem
->PutObject( pArray
);
650 pTypeElem
->SetFlags( nSavFlags
);
653 if( eElemType
== SbxOBJECT
)
655 sal_uInt16 nElemTypeId
= pElem
->GetTypeId();
656 if( nElemTypeId
!= 0 )
658 OUString
aTypeName( aGblStrings
.Find( nElemTypeId
) );
659 SbxObject
* pTypeObj
= static_cast< SbxObject
* >( rTypeArray
->Find( aTypeName
, SbxClassType::Object
) );
660 if( pTypeObj
!= nullptr )
662 SbxObject
* pCloneObj
= cloneTypeObjectImpl( *pTypeObj
);
663 pTypeElem
->PutObject( pCloneObj
);
667 pTypeMembers
->Insert( pTypeElem
, pTypeMembers
->Count() );
672 pType
->Remove( "Name", SbxClassType::DontCare
);
673 pType
->Remove( "Parent", SbxClassType::DontCare
);
675 rTypeArray
->Insert (pType
,rTypeArray
->Count());
679 // Declaration of Enum type
681 void SbiParser::Enum()
686 void SbiParser::DefEnum( bool bPrivate
)
688 // Read the new Token. It had to be a symbol
692 OUString aEnumName
= aSym
;
693 if( rEnumArray
->Find(aEnumName
,SbxClassType::Object
) )
695 Error( ERRCODE_BASIC_VAR_DEFINED
, aSym
);
699 SbxObject
*pEnum
= new SbxObject( aEnumName
);
702 pEnum
->SetFlag( SbxFlagBits::Private
);
707 // Starting with -1 to make first default value 0 after ++
708 sal_Int32 nCurrentEnumValue
= -1;
709 while( !bDone
&& !IsEof() )
728 pElem
= VarDecl( &pDim
, false, true );
731 bDone
= true; // Error occurred
736 Error( ERRCODE_BASIC_SYNTAX
);
737 bDone
= true; // Error occurred
741 SbiExpression
aVar( this, *pElem
);
746 SbiConstExpression
aExpr( this );
747 if( 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( ERRCODE_BASIC_VAR_DEFINED
, pElem
->GetName() );
767 bDone
= true; // Error occurred
775 aGen
.BackChain( nGblChain
);
777 bGblDefs
= bNewGblDefs
= true;
779 SbiOpcode::GLOBAL_
, pElem
->GetId(),
780 sal::static_int_cast
< sal_uInt16
>( pElem
->GetType() ) );
783 sal_uInt16 nStringId
= aGen
.GetParser()->aGblStrings
.Add( nCurrentEnumValue
, SbxLONG
);
784 aGen
.Gen( SbiOpcode::NUMBER_
, nStringId
);
785 aGen
.Gen( SbiOpcode::PUTC_
);
788 SbiConstDef
* pConst
= pElem
->GetConstDef();
789 pConst
->Set( nCurrentEnumValue
, SbxLONG
);
794 SbxArray
*pEnumMembers
= pEnum
->GetProperties();
795 SbxProperty
*pEnumElem
= new SbxProperty( pElem
->GetName(), SbxLONG
);
796 pEnumElem
->PutLong( nCurrentEnumValue
);
797 pEnumElem
->ResetFlag( SbxFlagBits::Write
);
798 pEnumElem
->SetFlag( SbxFlagBits::Const
);
799 pEnumMembers
->Insert( pEnumElem
, pEnumMembers
->Count() );
803 pEnum
->Remove( "Name", SbxClassType::DontCare
);
804 pEnum
->Remove( "Parent", SbxClassType::DontCare
);
806 rEnumArray
->Insert( pEnum
, rEnumArray
->Count() );
810 // Procedure-Declaration
811 // the first Token is already read in (SUB/FUNCTION)
812 // xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
814 SbiProcDef
* SbiParser::ProcDecl( bool bDecl
)
816 bool bFunc
= ( eCurTok
== FUNCTION
);
817 bool bProp
= ( eCurTok
== GET
|| eCurTok
== SET
|| eCurTok
== LET
);
818 if( !TestSymbol() ) return nullptr;
819 OUString
aName( aSym
);
820 SbxDataType eType
= eScanType
;
821 SbiProcDef
* pDef
= new SbiProcDef( this, aName
, true );
822 pDef
->SetType( eType
);
823 if( Peek() == CDECL_
)
825 Next(); pDef
->SetCdecl(true);
830 if( Next() == FIXSTRING
)
832 pDef
->GetLib() = aSym
;
836 Error( ERRCODE_BASIC_SYNTAX
);
839 if( Peek() == ALIAS
)
842 if( Next() == FIXSTRING
)
844 pDef
->GetAlias() = aSym
;
848 Error( ERRCODE_BASIC_SYNTAX
);
853 // CDECL, LIB and ALIAS are invalid
854 if( !pDef
->GetLib().isEmpty() )
856 Error( ERRCODE_BASIC_UNEXPECTED
, LIB
);
858 if( !pDef
->GetAlias().isEmpty() )
860 Error( ERRCODE_BASIC_UNEXPECTED
, ALIAS
);
862 if( pDef
->IsCdecl() )
864 Error( ERRCODE_BASIC_UNEXPECTED
, CDECL_
);
866 pDef
->SetCdecl( false );
867 pDef
->GetLib().clear();
868 pDef
->GetAlias().clear();
870 else if( pDef
->GetLib().isEmpty() )
872 // ALIAS and CDECL only together with LIB
873 if( !pDef
->GetAlias().isEmpty() )
875 Error( ERRCODE_BASIC_UNEXPECTED
, ALIAS
);
877 if( pDef
->IsCdecl() )
879 Error( ERRCODE_BASIC_UNEXPECTED
, CDECL_
);
881 pDef
->SetCdecl( false );
882 pDef
->GetAlias().clear();
885 if( Peek() == LPAREN
)
888 if( Peek() == RPAREN
)
897 bool bOptional
= false;
898 bool bParamArray
= false;
899 while( Peek() == BYVAL
|| Peek() == BYREF
|| Peek() == OPTIONAL_
)
901 if( Peek() == BYVAL
)
905 else if ( Peek() == BYREF
)
909 else if ( Peek() == OPTIONAL_
)
915 if( bCompatible
&& Peek() == PARAMARRAY
)
917 if( bByVal
|| bOptional
)
919 Error( ERRCODE_BASIC_UNEXPECTED
, PARAMARRAY
);
924 SbiSymDef
* pPar
= VarDecl( nullptr, false, false );
931 pPar
->SetByVal(true);
939 pPar
->SetParamArray();
941 if (SbiSymDef
* pOldDef
= pDef
->GetParams().Find(pPar
->GetName(), false))
943 Error(ERRCODE_BASIC_VAR_DEFINED
, pPar
->GetName());
948 pDef
->GetParams().Add( pPar
);
949 SbiToken eTok
= Next();
950 if( eTok
!= COMMA
&& eTok
!= RPAREN
)
953 if( bOptional
&& bCompatible
&& eTok
== EQ
)
955 std::unique_ptr
<SbiConstExpression
> pDefaultExpr(new SbiConstExpression( this ));
956 SbxDataType eType2
= pDefaultExpr
->GetType();
958 sal_uInt16 nStringId
;
959 if( eType2
== SbxSTRING
)
961 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetString() );
965 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetValue(), eType2
);
967 pPar
->SetDefaultId( nStringId
);
968 pDefaultExpr
.reset();
971 if( eTok
== COMMA
|| eTok
== RPAREN
)
978 Error( ERRCODE_BASIC_EXPECTED
, RPAREN
);
990 if( eType
!= SbxVARIANT
&& pDef
->GetType() != eType
)
992 Error( ERRCODE_BASIC_BAD_DECLARATION
, aName
);
994 if( pDef
->GetType() == SbxVARIANT
&& !( bFunc
|| bProp
) )
996 pDef
->SetType( SbxEMPTY
);
1003 void SbiParser::Declare()
1005 DefDeclare( false );
1008 void SbiParser::DefDeclare( bool bPrivate
)
1011 if( eCurTok
== PTRSAFE
)
1014 if( eCurTok
!= SUB
&& eCurTok
!= FUNCTION
)
1016 Error( ERRCODE_BASIC_UNEXPECTED
, eCurTok
);
1020 bool bFunction
= (eCurTok
== FUNCTION
);
1022 SbiProcDef
* pDef
= ProcDecl( true );
1025 if( pDef
->GetLib().isEmpty() )
1027 Error( ERRCODE_BASIC_EXPECTED
, LIB
);
1029 // Is it already there?
1030 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1033 SbiProcDef
* p
= pOld
->GetProcDef();
1036 // Declared as a variable
1037 Error( ERRCODE_BASIC_BAD_DECLARATION
, pDef
->GetName() );
1048 aPublics
.Add( pDef
);
1052 pDef
->SetPublic( !bPrivate
);
1054 // New declare handling
1055 if( !pDef
->GetLib().isEmpty())
1057 if( bNewGblDefs
&& nGblChain
== 0 )
1059 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
1060 bNewGblDefs
= false;
1063 sal_uInt16 nSavLine
= nLine
;
1066 pDef
->SetLine1( nSavLine
);
1067 pDef
->SetLine2( nSavLine
);
1069 SbiSymPool
& rPool
= pDef
->GetParams();
1070 sal_uInt16 nParCount
= rPool
.GetSize();
1072 SbxDataType eType
= pDef
->GetType();
1075 aGen
.Gen( SbiOpcode::PARAM_
, 0, sal::static_int_cast
< sal_uInt16
>( eType
) );
1079 aGen
.Gen( SbiOpcode::ARGC_
);
1081 for( sal_uInt16 i
= 1 ; i
< nParCount
; ++i
)
1083 SbiSymDef
* pParDef
= rPool
.Get( i
);
1084 SbxDataType eParType
= pParDef
->GetType();
1086 aGen
.Gen( SbiOpcode::PARAM_
, i
, sal::static_int_cast
< sal_uInt16
>( eParType
) );
1087 aGen
.Gen( SbiOpcode::ARGV_
);
1089 sal_uInt16 nTyp
= sal::static_int_cast
< sal_uInt16
>( pParDef
->GetType() );
1090 if( pParDef
->IsByVal() )
1092 // Reset to avoid additional byval in call to wrapper function
1093 pParDef
->SetByVal( false );
1096 aGen
.Gen( SbiOpcode::ARGTYP_
, nTyp
);
1100 aGen
.Gen( SbiOpcode::LIB_
, aGblStrings
.Add( pDef
->GetLib() ) );
1102 SbiOpcode eOp
= pDef
->IsCdecl() ? SbiOpcode::CALLC_
: SbiOpcode::CALL_
;
1103 sal_uInt16 nId
= pDef
->GetId();
1104 if( !pDef
->GetAlias().isEmpty() )
1106 nId
= ( nId
& 0x8000 ) | aGblStrings
.Add( pDef
->GetAlias() );
1112 aGen
.Gen( eOp
, nId
, sal::static_int_cast
< sal_uInt16
>( eType
) );
1116 aGen
.Gen( SbiOpcode::PUT_
);
1118 aGen
.Gen( SbiOpcode::LEAVE_
);
1125 void SbiParser::Attribute()
1127 // TODO: Need to implement the method as an attributed object.
1128 while( Next() != EQ
)
1138 Error( ERRCODE_BASIC_SYNTAX
);
1142 SbiExpression
aValue( this );
1144 // Don't generate any code - just discard it.
1147 // Call of a SUB or a FUNCTION
1149 void SbiParser::Call()
1151 SbiExpression
aVar( this, SbSYMBOL
);
1152 aVar
.Gen( FORCE_CALL
);
1153 aGen
.Gen( SbiOpcode::GET_
);
1158 void SbiParser::SubFunc()
1160 DefProc( false, false );
1163 // Read in of a procedure
1165 void SbiParser::DefProc( bool bStatic
, bool bPrivate
)
1167 sal_uInt16 l1
= nLine
;
1168 bool bSub
= ( eCurTok
== SUB
);
1169 bool bProperty
= ( eCurTok
== PROPERTY
);
1170 PropertyMode ePropertyMode
= PropertyMode::NONE
;
1174 if( eCurTok
== GET
)
1176 ePropertyMode
= PropertyMode::Get
;
1178 else if( eCurTok
== LET
)
1180 ePropertyMode
= PropertyMode::Let
;
1182 else if( eCurTok
== SET
)
1184 ePropertyMode
= PropertyMode::Set
;
1188 Error( ERRCODE_BASIC_EXPECTED
, "Get or Let or Set" );
1192 SbiToken eExit
= eCurTok
;
1193 SbiProcDef
* pDef
= ProcDecl( false );
1198 pDef
->setPropertyMode( ePropertyMode
);
1200 // Is the Proc already declared?
1201 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1204 pProc
= pOld
->GetProcDef();
1207 // Declared as a variable
1208 Error( ERRCODE_BASIC_BAD_DECLARATION
, pDef
->GetName() );
1212 // #100027: Multiple declaration -> Error
1213 // #112787: Not for setup, REMOVE for 8
1214 else if( pProc
->IsUsedForProcDecl() )
1216 PropertyMode ePropMode
= pDef
->getPropertyMode();
1217 if( ePropMode
== PropertyMode::NONE
|| ePropMode
== pProc
->getPropertyMode() )
1219 Error( ERRCODE_BASIC_PROC_DEFINED
, pDef
->GetName() );
1225 pDef
->Match( pProc
);
1229 aPublics
.Add( pDef
);
1233 pProc
->SetPublic( !bPrivate
);
1235 // Now we set the search hierarchy for symbols as well as the
1236 // current procedure.
1237 aPublics
.SetProcId( pProc
->GetId() );
1238 pProc
->GetParams().SetParent( &aPublics
);
1241 if ( bVBASupportOn
)
1247 Error( ERRCODE_BASIC_NOT_IMPLEMENTED
); // STATIC SUB ...
1252 pProc
->SetStatic( false );
1254 // Normal case: Local variable->parameter->global variable
1255 pProc
->GetLocals().SetParent( &pProc
->GetParams() );
1256 pPool
= &pProc
->GetLocals();
1260 StmntBlock( bSub
? ENDSUB
: (bProperty
? ENDPROPERTY
: ENDFUNC
) );
1261 sal_uInt16 l2
= nLine
;
1262 pProc
->SetLine1( l1
);
1263 pProc
->SetLine2( l2
);
1265 aPublics
.SetProcId( 0 );
1267 pProc
->GetLabels().CheckRefs();
1269 aGen
.Gen( SbiOpcode::LEAVE_
);
1273 // STATIC variable|procedure
1275 void SbiParser::Static()
1280 void SbiParser::DefStatic( bool bPrivate
)
1289 // End global chain if necessary (not done in
1290 // SbiParser::Parse() under these conditions
1291 if( bNewGblDefs
&& nGblChain
== 0 )
1293 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
1294 bNewGblDefs
= false;
1297 DefProc( true, bPrivate
);
1302 Error( ERRCODE_BASIC_NOT_IN_SUBR
);
1304 // Reset the Pool, so that STATIC-Declarations go into the
1308 DefVar( SbiOpcode::STATIC_
, true );
1314 bool SbiParser::IsUnoInterface(const OUString
& sTypeName
)
1318 return css::reflection::theCoreReflection::get(
1319 comphelper::getProcessComponentContext())->forName(sTypeName
).is();
1321 catch(const Exception
&)
1323 OSL_FAIL("Could not create reflection.CoreReflection.");
1328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */