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 .
23 #include <basic/sberrors.hxx>
24 #include <basic/sbmod.hxx>
25 #include <comphelper/SetFlagContextHelper.hxx>
28 SbiExpression::SbiExpression( SbiParser
* p
, SbiExprType t
,
29 SbiExprMode eMode
, const KeywordSymbolInfo
* pKeywordSymbolInfo
) :
34 pExpr
= (t
!= SbSTDEXPR
) ? Term( pKeywordSymbolInfo
) : Boolean();
37 pExpr
->Optimize(pParser
);
39 if( t
== SbLVALUE
&& !pExpr
->IsLvalue() )
41 p
->Error( ERRCODE_BASIC_LVALUE_EXPECTED
);
43 if( t
== SbOPERAND
&& !IsVariable() )
45 p
->Error( ERRCODE_BASIC_VAR_EXPECTED
);
49 SbiExpression::SbiExpression( SbiParser
* p
, double n
, SbxDataType t
) :
52 m_eMode(EXPRMODE_STANDARD
)
54 pExpr
= std::make_unique
<SbiExprNode
>( n
, t
);
55 pExpr
->Optimize(pParser
);
58 SbiExpression::SbiExpression( SbiParser
* p
, const SbiSymDef
& r
, SbiExprListPtr pPar
) :
61 m_eMode(EXPRMODE_STANDARD
)
63 pExpr
= std::make_unique
<SbiExprNode
>( r
, SbxVARIANT
, std::move(pPar
) );
66 SbiExpression::~SbiExpression() { }
68 // reading in a complete identifier
69 // an identifier has the following form:
70 // name[(Parameter)][.Name[(parameter)]]...
71 // structure elements are coupled via the element pNext,
72 // so that they're not in the tree.
74 // Are there parameters without brackets following? This may be a number,
75 // a string, a symbol or also a comma (if the 1st parameter is missing)
77 static bool DoParametersFollow( const SbiParser
* p
, SbiExprType eCurExpr
, SbiToken eTok
)
83 // but only if similar to CALL!
84 if( !p
->WhiteSpace() || eCurExpr
!= SbSYMBOL
)
88 if ( eTok
== NUMBER
|| eTok
== MINUS
|| eTok
== FIXSTRING
||
89 eTok
== SYMBOL
|| eTok
== COMMA
|| eTok
== DOT
|| eTok
== NOT
|| eTok
== BYVAL
)
93 else // check for default params with reserved names ( e.g. names of tokens )
95 SbiTokenizer
tokens( *static_cast<const SbiTokenizer
*>(p
) );
96 // Urk the Next() / Peek() semantics are... weird
98 if ( tokens
.Peek() == ASSIGN
)
106 // definition of a new symbol
108 static SbiSymDef
* AddSym ( SbiToken eTok
, SbiSymPool
& rPool
, SbiExprType eCurExpr
,
109 const OUString
& rName
, SbxDataType eType
, const SbiExprList
* pPar
)
112 // A= is not a procedure
113 bool bHasType
= ( eTok
== EQ
|| eTok
== DOT
);
114 if( ( !bHasType
&& eCurExpr
== SbSYMBOL
) || pPar
)
116 // so this is a procedure
117 // the correct pool should be found out, as
118 // procs must always get into a public pool
119 SbiSymPool
* pPool
= &rPool
;
120 if( pPool
->GetScope() != SbPUBLIC
)
122 pPool
= &rPool
.GetParser()->aPublics
;
124 SbiProcDef
* pProc
= pPool
->AddProc( rName
);
126 // special treatment for Colls like Documents(1)
127 if( eCurExpr
== SbSTDEXPR
)
132 pDef
->SetType( bHasType
? eType
: SbxEMPTY
);
135 // generate dummy parameters
136 for( sal_Int32 n
= 1; n
<= pPar
->GetSize(); n
++ )
138 OUString aPar
= "PAR" + OUString::number( n
);
139 pProc
->GetParams().AddSym( aPar
);
145 // or a normal symbol
146 pDef
= rPool
.AddSym( rName
);
147 pDef
->SetType( eType
);
152 // currently even keywords are allowed (because of Dflt properties of the same name)
154 std::unique_ptr
<SbiExprNode
> SbiExpression::Term( const KeywordSymbolInfo
* pKeywordSymbolInfo
)
156 if( pParser
->Peek() == DOT
)
158 SbiExprNode
* pWithVar
= pParser
->GetWithVar();
159 // #26608: get to the node-chain's end to pass the correct object
160 SbiSymDef
* pDef
= pWithVar
? pWithVar
->GetRealVar() : nullptr;
161 std::unique_ptr
<SbiExprNode
> pNd
;
168 pNd
= ObjTerm( *pDef
);
171 pNd
->SetWithParent( pWithVar
);
176 pParser
->Error( ERRCODE_BASIC_UNEXPECTED
, DOT
);
177 pNd
= std::make_unique
<SbiExprNode
>( 1.0, SbxDOUBLE
);
182 SbiToken eTok
= (pKeywordSymbolInfo
== nullptr) ? pParser
->Next() : SYMBOL
;
183 // memorize the parsing's begin
184 pParser
->LockColumn();
185 OUString
aSym( (pKeywordSymbolInfo
== nullptr) ? pParser
->GetSym() : pKeywordSymbolInfo
->m_aKeywordSymbol
);
186 SbxDataType eType
= (pKeywordSymbolInfo
== nullptr) ? pParser
->GetType() : pKeywordSymbolInfo
->m_eSbxDataType
;
188 std::unique_ptr
<SbiExprListVector
> pvMoreParLcl
;
189 // are there parameters following?
190 SbiToken eNextTok
= pParser
->Peek();
191 // is it a known parameter?
192 // create a string constant then, which will be recognized
193 // in the SbiParameters-ctor and is continued to be handled
194 if( eNextTok
== ASSIGN
)
196 pParser
->UnlockColumn();
197 return std::make_unique
<SbiExprNode
>( aSym
);
199 // no keywords allowed from here on!
200 if( SbiTokenizer::IsKwd( eTok
)
201 && (!pParser
->IsCompatible() || eTok
!= INPUT
) )
203 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
208 if( DoParametersFollow( pParser
, eCurExpr
, eTok
) )
210 bool bStandaloneExpression
= (m_eMode
== EXPRMODE_STANDALONE
);
211 pPar
= SbiExprList::ParseParameters( pParser
, bStandaloneExpression
);
212 bError
= bError
|| !pPar
->IsValid();
214 bBracket
= pPar
->IsBracket();
215 eTok
= pParser
->Peek();
217 // i75443 check for additional sets of parameters
218 while( eTok
== LPAREN
)
220 if( pvMoreParLcl
== nullptr )
222 pvMoreParLcl
.reset(new SbiExprListVector
);
224 SbiExprListPtr pAddPar
= SbiExprList::ParseParameters( pParser
);
225 bError
= bError
|| !pAddPar
->IsValid();
226 pvMoreParLcl
->push_back( std::move(pAddPar
) );
227 eTok
= pParser
->Peek();
230 // It might be an object part, if . or ! is following.
231 // In case of . the variable must already be defined;
232 // it's an object, if pDef is NULL after the search.
233 bool bObj
= ( ( eTok
== DOT
|| eTok
== EXCLAM
)
234 && !pParser
->WhiteSpace() );
237 bBracket
= false; // Now the bracket for the first term is obsolete
238 if( eType
== SbxVARIANT
)
244 // Name%. really does not work!
245 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
250 SbiSymDef
* pDef
= pParser
->pPool
->Find( aSym
);
253 // Part of the Runtime-Library?
254 // from 31.3.1996: swapped out to parser-method
255 // (is also needed in SbiParser::DefVar() in DIM.CXX)
256 pDef
= pParser
->CheckRTLForSym( aSym
, eType
);
258 // #i109184: Check if symbol is or later will be defined inside module
259 SbModule
& rMod
= pParser
->aGen
.GetModule();
260 if( rMod
.FindMethod( aSym
, SbxClassType::DontCare
) )
271 pDef
= AddSym( eTok
, *pParser
->pPool
, eCurExpr
, aSym
, eType
, pPar
.get() );
272 // Looks like this is a local ( but undefined variable )
273 // if it is in a static procedure then make this Symbol
275 if ( !bObj
&& pParser
->pProc
&& pParser
->pProc
->IsStatic() )
283 SbiConstDef
* pConst
= pDef
->GetConstDef();
287 pvMoreParLcl
.reset();
288 if( pConst
->GetType() == SbxSTRING
)
290 return std::make_unique
<SbiExprNode
>( pConst
->GetString() );
294 return std::make_unique
<SbiExprNode
>( pConst
->GetValue(), pConst
->GetType() );
298 // 0 parameters come up to ()
299 if( pDef
->GetDims() )
301 if( pPar
&& pPar
->GetSize() && pPar
->GetSize() != pDef
->GetDims() )
303 pParser
->Error( ERRCODE_BASIC_WRONG_DIMS
);
306 if( pDef
->IsDefinedAs() )
308 SbxDataType eDefType
= pDef
->GetType();
309 // #119187 Only error if types conflict
310 if( eType
>= SbxINTEGER
&& eType
<= SbxSTRING
&& eType
!= eDefType
)
312 // How? Define with AS first and take a Suffix then?
313 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
316 else if ( eType
== SbxVARIANT
)
318 // if there's nothing named, take the type of the entry,
319 // but only if the var hasn't been defined with AS XXX
320 // so that we catch n% = 5 : print n
324 // checking type of variables:
325 // is there named anything different in the scanner?
326 // That's OK for methods!
327 if( eType
!= SbxVARIANT
&& // Variant takes everything
328 eType
!= pDef
->GetType() &&
329 !pDef
->GetProcDef() )
331 // maybe pDef describes an object that so far has only been
332 // recognized as SbxVARIANT - then change type of pDef
333 // from 16.12.95 (similar cases possible perhaps?!?)
334 if( eType
== SbxOBJECT
&& pDef
->GetType() == SbxVARIANT
)
336 pDef
->SetType( SbxOBJECT
);
340 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
345 auto pNd
= std::make_unique
<SbiExprNode
>( *pDef
, eType
);
348 pPar
= SbiExprList::ParseParameters( pParser
,false,false );
350 pNd
->aVar
.pPar
= pPar
.release();
351 pNd
->aVar
.pvMorePar
= pvMoreParLcl
.release();
354 // from 8.1.95: Object may also be of the type SbxVARIANT
355 if( pDef
->GetType() == SbxVARIANT
)
356 pDef
->SetType( SbxOBJECT
);
357 // if we scan something with point,
358 // the type must be SbxOBJECT
359 if( pDef
->GetType() != SbxOBJECT
&& pDef
->GetType() != SbxVARIANT
)
361 // defer error until runtime if in vba mode
362 if ( !pParser
->IsVBASupportOn() )
364 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
370 pNd
->aVar
.pNext
= ObjTerm( *pDef
).release();
374 pParser
->UnlockColumn();
378 // construction of an object term. A term of this kind is part
379 // of an expression that begins with an object variable.
381 std::unique_ptr
<SbiExprNode
> SbiExpression::ObjTerm( SbiSymDef
& rObj
)
384 SbiToken eTok
= pParser
->Next();
385 if( eTok
!= SYMBOL
&& !SbiTokenizer::IsKwd( eTok
) && !SbiTokenizer::IsExtra( eTok
) )
387 // #66745 Some operators can also be allowed
388 // as identifiers, important for StarOne
389 if( eTok
!= MOD
&& eTok
!= NOT
&& eTok
!= AND
&& eTok
!= OR
&&
390 eTok
!= XOR
&& eTok
!= EQV
&& eTok
!= IMP
&& eTok
!= IS
)
392 pParser
->Error( ERRCODE_BASIC_VAR_EXPECTED
);
401 OUString
aSym( pParser
->GetSym() );
402 SbxDataType eType
= pParser
->GetType();
404 SbiExprListVector
* pvMoreParLcl
= nullptr;
405 eTok
= pParser
->Peek();
407 if( DoParametersFollow( pParser
, eCurExpr
, eTok
) )
409 pPar
= SbiExprList::ParseParameters( pParser
, false/*bStandaloneExpression*/ );
410 bError
= bError
|| !pPar
->IsValid();
411 eTok
= pParser
->Peek();
413 // i109624 check for additional sets of parameters
414 while( eTok
== LPAREN
)
416 if( pvMoreParLcl
== nullptr )
418 pvMoreParLcl
= new SbiExprListVector
;
420 SbiExprListPtr pAddPar
= SbiExprList::ParseParameters( pParser
);
421 bError
= bError
|| !pPar
->IsValid();
422 pvMoreParLcl
->push_back( std::move(pAddPar
) );
423 eTok
= pParser
->Peek();
426 bool bObj
= ( ( eTok
== DOT
|| eTok
== EXCLAM
) && !pParser
->WhiteSpace() );
429 if( eType
== SbxVARIANT
)
435 // Name%. does really not work!
436 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
441 // an object's symbol pool is always PUBLIC
442 SbiSymPool
& rPool
= rObj
.GetPool();
443 rPool
.SetScope( SbPUBLIC
);
444 SbiSymDef
* pDef
= rPool
.Find( aSym
);
447 pDef
= AddSym( eTok
, rPool
, eCurExpr
, aSym
, eType
, pPar
.get() );
448 pDef
->SetType( eType
);
451 auto pNd
= std::make_unique
<SbiExprNode
>( *pDef
, eType
);
452 pNd
->aVar
.pPar
= pPar
.release();
453 pNd
->aVar
.pvMorePar
= pvMoreParLcl
;
456 if( pDef
->GetType() == SbxVARIANT
)
458 pDef
->SetType( SbxOBJECT
);
460 if( pDef
->GetType() != SbxOBJECT
)
462 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
467 pNd
->aVar
.pNext
= ObjTerm( *pDef
).release();
474 // an operand can be:
477 // structure elements
480 // bracketed expressions
482 std::unique_ptr
<SbiExprNode
> SbiExpression::Operand( bool bUsedForTypeOf
)
484 std::unique_ptr
<SbiExprNode
> pRes
;
487 switch( SbiToken eTok
= pParser
->Peek() )
491 // process something like "IF Not r Is Nothing Then .."
492 if( !bUsedForTypeOf
&& pParser
->IsVBASupportOn() && pParser
->Peek() == IS
)
494 eTok
= pParser
->Next();
495 pRes
= std::make_unique
<SbiExprNode
>( std::move(pRes
), eTok
, Like() );
499 pRes
= Term(); break;
505 pRes
= std::make_unique
<SbiExprNode
>( pParser
->GetDbl(), pParser
->GetType() );
509 pRes
= std::make_unique
<SbiExprNode
>( pParser
->GetSym() ); break;
512 if( nParenLevel
== 0 && m_eMode
== EXPRMODE_LPAREN_PENDING
&& pParser
->Peek() == RPAREN
)
514 m_eMode
= EXPRMODE_EMPTY_PAREN
;
515 pRes
= std::make_unique
<SbiExprNode
>(); // Dummy node
521 if( pParser
->Peek() != RPAREN
)
523 // If there was a LPARAM, it does not belong to the expression
524 if( nParenLevel
== 1 && m_eMode
== EXPRMODE_LPAREN_PENDING
)
526 m_eMode
= EXPRMODE_LPAREN_NOT_NEEDED
;
530 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
536 if( nParenLevel
== 1 && m_eMode
== EXPRMODE_LPAREN_PENDING
)
538 SbiToken eTokAfterRParen
= pParser
->Peek();
539 if( eTokAfterRParen
== EQ
|| eTokAfterRParen
== LPAREN
|| eTokAfterRParen
== DOT
)
541 m_eMode
= EXPRMODE_ARRAY_OR_OBJECT
;
545 m_eMode
= EXPRMODE_STANDARD
;
552 // keywords here are OK at the moment!
553 if( SbiTokenizer::IsKwd( eTok
) )
560 pRes
= std::make_unique
<SbiExprNode
>( 1.0, SbxDOUBLE
);
561 pParser
->Error( ERRCODE_BASIC_UNEXPECTED
, eTok
);
568 std::unique_ptr
<SbiExprNode
> SbiExpression::Unary()
570 std::unique_ptr
<SbiExprNode
> pNd
;
571 SbiToken eTok
= pParser
->Peek();
577 pNd
= std::make_unique
<SbiExprNode
>( Unary(), eTok
, nullptr );
580 if( pParser
->IsVBASupportOn() )
587 pNd
= std::make_unique
<SbiExprNode
>( Unary(), eTok
, nullptr );
597 std::unique_ptr
<SbiExprNode
> pObjNode
= Operand( true/*bUsedForTypeOf*/ );
598 pParser
->TestToken( IS
);
599 SbiSymDef
* pTypeDef
= new SbiSymDef( OUString() );
600 pParser
->TypeDecl( *pTypeDef
, true );
601 pNd
= std::make_unique
<SbiExprNode
>( std::move(pObjNode
), pTypeDef
->GetTypeId() );
607 SbiSymDef
* pTypeDef
= new SbiSymDef( OUString() );
608 pParser
->TypeDecl( *pTypeDef
, true );
609 pNd
= std::make_unique
<SbiExprNode
>( pTypeDef
->GetTypeId() );
618 std::unique_ptr
<SbiExprNode
> SbiExpression::Exp()
620 std::unique_ptr
<SbiExprNode
> pNd
= Unary();
621 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
623 while( pParser
->Peek() == EXPON
)
625 SbiToken eTok
= pParser
->Next();
626 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Unary() );
632 std::unique_ptr
<SbiExprNode
> SbiExpression::MulDiv()
634 std::unique_ptr
<SbiExprNode
> pNd
= Exp();
635 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
639 SbiToken eTok
= pParser
->Peek();
640 if( eTok
!= MUL
&& eTok
!= DIV
)
644 eTok
= pParser
->Next();
645 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Exp() );
651 std::unique_ptr
<SbiExprNode
> SbiExpression::IntDiv()
653 std::unique_ptr
<SbiExprNode
> pNd
= MulDiv();
654 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
656 while( pParser
->Peek() == IDIV
)
658 SbiToken eTok
= pParser
->Next();
659 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, MulDiv() );
665 std::unique_ptr
<SbiExprNode
> SbiExpression::Mod()
667 std::unique_ptr
<SbiExprNode
> pNd
= IntDiv();
668 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
670 while( pParser
->Peek() == MOD
)
672 SbiToken eTok
= pParser
->Next();
673 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, IntDiv() );
679 std::unique_ptr
<SbiExprNode
> SbiExpression::AddSub()
681 std::unique_ptr
<SbiExprNode
> pNd
= Mod();
682 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
686 SbiToken eTok
= pParser
->Peek();
687 if( eTok
!= PLUS
&& eTok
!= MINUS
)
691 eTok
= pParser
->Next();
692 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Mod() );
698 std::unique_ptr
<SbiExprNode
> SbiExpression::Cat()
700 std::unique_ptr
<SbiExprNode
> pNd
= AddSub();
701 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
705 SbiToken eTok
= pParser
->Peek();
710 eTok
= pParser
->Next();
711 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, AddSub() );
717 std::unique_ptr
<SbiExprNode
> SbiExpression::Comp()
719 std::unique_ptr
<SbiExprNode
> pNd
= Cat();
720 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
724 SbiToken eTok
= pParser
->Peek();
725 if( m_eMode
== EXPRMODE_ARRAY_OR_OBJECT
)
729 if( eTok
!= EQ
&& eTok
!= NE
&& eTok
!= LT
&&
730 eTok
!= GT
&& eTok
!= LE
&& eTok
!= GE
)
734 eTok
= pParser
->Next();
735 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Cat() );
742 std::unique_ptr
<SbiExprNode
> SbiExpression::VBA_Not()
744 std::unique_ptr
<SbiExprNode
> pNd
;
746 SbiToken eTok
= pParser
->Peek();
750 pNd
= std::make_unique
<SbiExprNode
>( VBA_Not(), eTok
, nullptr );
759 std::unique_ptr
<SbiExprNode
> SbiExpression::Like()
761 std::unique_ptr
<SbiExprNode
> pNd
= pParser
->IsVBASupportOn() ? VBA_Not() : Comp();
762 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
765 while( pParser
->Peek() == LIKE
)
767 SbiToken eTok
= pParser
->Next();
768 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Comp() );
771 // multiple operands in a row does not work
772 if( nCount
> 1 && !pParser
->IsVBASupportOn() )
774 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
781 std::unique_ptr
<SbiExprNode
> SbiExpression::Boolean()
783 std::unique_ptr
<SbiExprNode
> pNd
= Like();
784 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
788 SbiToken eTok
= pParser
->Peek();
789 if( (eTok
!= AND
) && (eTok
!= OR
) &&
790 (eTok
!= XOR
) && (eTok
!= EQV
) &&
791 (eTok
!= IMP
) && (eTok
!= IS
) )
795 eTok
= pParser
->Next();
796 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Like() );
802 SbiConstExpression::SbiConstExpression( SbiParser
* p
) : SbiExpression( p
)
804 if( pExpr
->IsConstant() )
806 eType
= pExpr
->GetType();
807 if( pExpr
->IsNumber() )
814 aVal
= pExpr
->aStrVal
;
819 // #40204 special treatment for sal_Bool-constants
820 bool bIsBool
= false;
821 if( pExpr
->eNodeType
== SbxVARVAL
)
823 SbiSymDef
* pVarDef
= pExpr
->GetVar();
825 bool bBoolVal
= false;
826 if( pVarDef
->GetName().equalsIgnoreAsciiCase( "true" ) )
831 else if( pVarDef
->GetName().equalsIgnoreAsciiCase( "false" ) )
832 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
840 pExpr
= std::make_unique
<SbiExprNode
>( (bBoolVal
? SbxTRUE
: SbxFALSE
), SbxINTEGER
);
841 eType
= pExpr
->GetType();
848 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
855 short SbiConstExpression::GetShortValue()
857 if( eType
== SbxSTRING
)
859 SbxVariableRef refConv
= new SbxVariable
;
860 refConv
->PutString( aVal
);
861 return refConv
->GetInteger();
877 pParser
->Error( ERRCODE_BASIC_OUT_OF_RANGE
);
879 else if( n
< SbxMININT
)
882 pParser
->Error( ERRCODE_BASIC_OUT_OF_RANGE
);
885 return static_cast<short>(n
);
890 SbiExprList::SbiExprList( )
897 SbiExprList::~SbiExprList() {}
899 SbiExpression
* SbiExprList::Get( size_t n
)
901 return aData
[n
].get();
904 void SbiExprList::addExpression( std::unique_ptr
<SbiExpression
>&& pExpr
)
906 aData
.push_back(std::move(pExpr
));
909 // the parameter list is completely parsed
910 // "procedurename()" is OK
911 // it's a function without parameters then
912 // i. e. you give an array as procedure parameter
914 // #i79918/#i80532: bConst has never been set to true
915 // -> reused as bStandaloneExpression
916 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
917 SbiExprListPtr
SbiExprList::ParseParameters( SbiParser
* pParser
, bool bStandaloneExpression
, bool bPar
)
919 auto pExprList
= std::make_unique
<SbiExprList
>();
925 SbiToken eTok
= pParser
->Peek();
927 bool bAssumeExprLParenMode
= false;
928 bool bAssumeArrayMode
= false;
931 if( bStandaloneExpression
)
933 bAssumeExprLParenMode
= true;
937 pExprList
->bBracket
= true;
939 eTok
= pParser
->Peek();
944 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
952 // read in parameter table and lay down in correct order!
953 while( !pExprList
->bError
)
955 std::unique_ptr
<SbiExpression
> pExpr
;
959 pExpr
= std::make_unique
<SbiExpression
>( pParser
, 0, SbxEMPTY
);
961 // named arguments: either .name= or name:=
969 eTok
= pParser
->Peek();
972 if( bAssumeExprLParenMode
)
974 pExpr
= std::make_unique
<SbiExpression
>( pParser
, SbSTDEXPR
, EXPRMODE_LPAREN_PENDING
);
975 bAssumeExprLParenMode
= false;
977 SbiExprMode eModeAfter
= pExpr
->m_eMode
;
978 if( eModeAfter
== EXPRMODE_LPAREN_NOT_NEEDED
)
980 pExprList
->bBracket
= true;
982 else if( eModeAfter
== EXPRMODE_ARRAY_OR_OBJECT
)
984 // Expression "looks" like an array assignment
985 // a(...)[(...)] = ? or a(...).b(...)
986 // RPAREN is already parsed
987 pExprList
->bBracket
= true;
988 bAssumeArrayMode
= true;
991 else if( eModeAfter
== EXPRMODE_EMPTY_PAREN
)
993 pExprList
->bBracket
= true;
999 pExpr
= std::make_unique
<SbiExpression
>( pParser
);
1001 if( bByVal
&& pExpr
->IsLvalue() )
1005 if( !bAssumeArrayMode
)
1008 if( pParser
->Peek() == ASSIGN
)
1011 // SbiExpression::Term() has made as string out of it
1012 aName
= pExpr
->GetString();
1014 pExpr
= std::make_unique
<SbiExpression
>( pParser
);
1016 pExpr
->GetName() = aName
;
1019 pExprList
->bError
= pExprList
->bError
|| !pExpr
->IsValid();
1020 pExprList
->aData
.push_back(std::move(pExpr
));
1021 if( bAssumeArrayMode
)
1026 eTok
= pParser
->Peek();
1029 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
1032 if (SbiTokenizer::IsEoln(eTok
) && pExprList
->bBracket
)
1034 // tdf#106529: only fail here in strict mode (i.e. when compiled from IDE), and
1035 // allow legacy code with missing closing parenthesis when started e.g. from
1036 // extensions and event handlers
1037 if (comphelper::IsContextFlagActive(u
"BasicStrict"_ustr
))
1039 pParser
->Error(ERRCODE_BASIC_EXPECTED
, RPAREN
);
1040 pExprList
->bError
= true;
1045 pParser
->Error( pExprList
->bBracket
? ERRCODE_BASIC_BAD_BRACKETS
: ERRCODE_BASIC_EXPECTED
, COMMA
);
1046 pExprList
->bError
= true;
1051 eTok
= pParser
->Peek();
1052 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
1059 if( eTok
== RPAREN
)
1063 if( !pExprList
->bBracket
)
1065 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
1066 pExprList
->bError
= true;
1069 pExprList
->nDim
= pExprList
->GetSize();
1073 // A list of array dimensions is parsed.
1075 SbiExprListPtr
SbiExprList::ParseDimList( SbiParser
* pParser
)
1077 auto pExprList
= std::make_unique
<SbiExprList
>();
1079 if( pParser
->Next() != LPAREN
)
1081 pParser
->Error( ERRCODE_BASIC_EXPECTED
, LPAREN
);
1082 pExprList
->bError
= true; return pExprList
;
1085 if( pParser
->Peek() != RPAREN
)
1090 auto pExpr1
= std::make_unique
<SbiExpression
>( pParser
);
1091 eTok
= pParser
->Next();
1094 auto pExpr2
= std::make_unique
<SbiExpression
>( pParser
);
1095 pExpr1
->ConvertToIntConstIfPossible();
1096 pExpr2
->ConvertToIntConstIfPossible();
1097 eTok
= pParser
->Next();
1098 pExprList
->bError
= pExprList
->bError
|| !pExpr1
->IsValid() || !pExpr2
->IsValid();
1099 pExprList
->aData
.push_back(std::move(pExpr1
));
1100 pExprList
->aData
.push_back(std::move(pExpr2
));
1105 pExpr1
->ConvertToIntConstIfPossible();
1106 pExprList
->bError
= pExprList
->bError
|| !pExpr1
->IsValid();
1107 pExprList
->aData
.push_back(std::move(pExpr1
));
1110 if( eTok
== RPAREN
) break;
1113 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
1119 else pParser
->Next();
1123 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */