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>
26 #include <uno/current_context.hxx>
28 SbiExpression::SbiExpression( SbiParser
* p
, SbiExprType t
,
29 SbiExprMode eMode
, const KeywordSymbolInfo
* pKeywordSymbolInfo
)
32 bBased
= bError
= bByVal
= bBracket
= false;
36 pExpr
= (t
!= SbSTDEXPR
) ? Term( pKeywordSymbolInfo
) : Boolean();
39 pExpr
->Optimize(pParser
);
41 if( t
== SbLVALUE
&& !pExpr
->IsLvalue() )
43 p
->Error( ERRCODE_BASIC_LVALUE_EXPECTED
);
45 if( t
== SbOPERAND
&& !IsVariable() )
47 p
->Error( ERRCODE_BASIC_VAR_EXPECTED
);
51 SbiExpression::SbiExpression( SbiParser
* p
, double n
, SbxDataType t
)
54 bBased
= bError
= bByVal
= bBracket
= false;
57 m_eMode
= EXPRMODE_STANDARD
;
58 pExpr
= std::make_unique
<SbiExprNode
>( n
, t
);
59 pExpr
->Optimize(pParser
);
62 SbiExpression::SbiExpression( SbiParser
* p
, const SbiSymDef
& r
, SbiExprListPtr pPar
)
65 bBased
= bError
= bByVal
= bBracket
= false;
68 m_eMode
= EXPRMODE_STANDARD
;
69 pExpr
= std::make_unique
<SbiExprNode
>( r
, SbxVARIANT
, std::move(pPar
) );
72 SbiExpression::~SbiExpression() { }
74 // reading in a complete identifier
75 // an identifier has the following form:
76 // name[(Parameter)][.Name[(parameter)]]...
77 // structure elements are coupled via the element pNext,
78 // so that they're not in the tree.
80 // Are there parameters without brackets following? This may be a number,
81 // a string, a symbol or also a comma (if the 1st parameter is missing)
83 static bool DoParametersFollow( SbiParser
* p
, SbiExprType eCurExpr
, SbiToken eTok
)
89 // but only if similar to CALL!
90 if( !p
->WhiteSpace() || eCurExpr
!= SbSYMBOL
)
94 if ( eTok
== NUMBER
|| eTok
== MINUS
|| eTok
== FIXSTRING
||
95 eTok
== SYMBOL
|| eTok
== COMMA
|| eTok
== DOT
|| eTok
== NOT
|| eTok
== BYVAL
)
99 else // check for default params with reserved names ( e.g. names of tokens )
101 SbiTokenizer
tokens( *static_cast<SbiTokenizer
*>(p
) );
102 // Urk the Next() / Peek() semantics are... weird
104 if ( tokens
.Peek() == ASSIGN
)
112 // definition of a new symbol
114 static SbiSymDef
* AddSym ( SbiToken eTok
, SbiSymPool
& rPool
, SbiExprType eCurExpr
,
115 const OUString
& rName
, SbxDataType eType
, const SbiExprList
* pPar
)
118 // A= is not a procedure
119 bool bHasType
= ( eTok
== EQ
|| eTok
== DOT
);
120 if( ( !bHasType
&& eCurExpr
== SbSYMBOL
) || pPar
)
122 // so this is a procedure
123 // the correct pool should be found out, as
124 // procs must always get into a public pool
125 SbiSymPool
* pPool
= &rPool
;
126 if( pPool
->GetScope() != SbPUBLIC
)
128 pPool
= &rPool
.GetParser()->aPublics
;
130 SbiProcDef
* pProc
= pPool
->AddProc( rName
);
132 // special treatment for Colls like Documents(1)
133 if( eCurExpr
== SbSTDEXPR
)
138 pDef
->SetType( bHasType
? eType
: SbxEMPTY
);
141 // generate dummy parameters
142 for( sal_Int32 n
= 1; n
<= pPar
->GetSize(); n
++ )
144 OUString aPar
= "PAR" + OUString::number( n
);
145 pProc
->GetParams().AddSym( aPar
);
151 // or a normal symbol
152 pDef
= rPool
.AddSym( rName
);
153 pDef
->SetType( eType
);
158 // currently even keywords are allowed (because of Dflt properties of the same name)
160 std::unique_ptr
<SbiExprNode
> SbiExpression::Term( const KeywordSymbolInfo
* pKeywordSymbolInfo
)
162 if( pParser
->Peek() == DOT
)
164 SbiExprNode
* pWithVar
= pParser
->GetWithVar();
165 // #26608: get to the node-chain's end to pass the correct object
166 SbiSymDef
* pDef
= pWithVar
? pWithVar
->GetRealVar() : nullptr;
167 std::unique_ptr
<SbiExprNode
> pNd
;
174 pNd
= ObjTerm( *pDef
);
177 pNd
->SetWithParent( pWithVar
);
182 pParser
->Error( ERRCODE_BASIC_UNEXPECTED
, DOT
);
183 pNd
= std::make_unique
<SbiExprNode
>( 1.0, SbxDOUBLE
);
188 SbiToken eTok
= (pKeywordSymbolInfo
== nullptr) ? pParser
->Next() : SYMBOL
;
189 // memorize the parsing's begin
190 pParser
->LockColumn();
191 OUString
aSym( (pKeywordSymbolInfo
== nullptr) ? pParser
->GetSym() : pKeywordSymbolInfo
->m_aKeywordSymbol
);
192 SbxDataType eType
= (pKeywordSymbolInfo
== nullptr) ? pParser
->GetType() : pKeywordSymbolInfo
->m_eSbxDataType
;
194 std::unique_ptr
<SbiExprListVector
> pvMoreParLcl
;
195 // are there parameters following?
196 SbiToken eNextTok
= pParser
->Peek();
197 // is it a known parameter?
198 // create a string constant then, which will be recognized
199 // in the SbiParameters-ctor and is continued to be handled
200 if( eNextTok
== ASSIGN
)
202 pParser
->UnlockColumn();
203 return std::make_unique
<SbiExprNode
>( aSym
);
205 // no keywords allowed from here on!
206 if( SbiTokenizer::IsKwd( eTok
)
207 && (!pParser
->IsCompatible() || eTok
!= INPUT
) )
209 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
213 if( DoParametersFollow( pParser
, eCurExpr
, eTok
= eNextTok
) )
215 bool bStandaloneExpression
= (m_eMode
== EXPRMODE_STANDALONE
);
216 pPar
= SbiExprList::ParseParameters( pParser
, bStandaloneExpression
);
217 bError
= bError
|| !pPar
->IsValid();
219 bBracket
= pPar
->IsBracket();
220 eTok
= pParser
->Peek();
222 // i75443 check for additional sets of parameters
223 while( eTok
== LPAREN
)
225 if( pvMoreParLcl
== nullptr )
227 pvMoreParLcl
.reset(new SbiExprListVector
);
229 SbiExprListPtr pAddPar
= SbiExprList::ParseParameters( pParser
);
230 bError
= bError
|| !pAddPar
->IsValid();
231 pvMoreParLcl
->push_back( std::move(pAddPar
) );
232 eTok
= pParser
->Peek();
235 // It might be an object part, if . or ! is following.
236 // In case of . the variable must already be defined;
237 // it's an object, if pDef is NULL after the search.
238 bool bObj
= ( ( eTok
== DOT
|| eTok
== EXCLAM
)
239 && !pParser
->WhiteSpace() );
242 bBracket
= false; // Now the bracket for the first term is obsolete
243 if( eType
== SbxVARIANT
)
249 // Name%. really does not work!
250 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
255 SbiSymDef
* pDef
= pParser
->pPool
->Find( aSym
);
258 // Part of the Runtime-Library?
259 // from 31.3.1996: swapped out to parser-method
260 // (is also needed in SbiParser::DefVar() in DIM.CXX)
261 pDef
= pParser
->CheckRTLForSym( aSym
, eType
);
263 // #i109184: Check if symbol is or later will be defined inside module
264 SbModule
& rMod
= pParser
->aGen
.GetModule();
265 if( rMod
.FindMethod( aSym
, SbxClassType::DontCare
) )
276 pDef
= AddSym( eTok
, *pParser
->pPool
, eCurExpr
, aSym
, eType
, pPar
.get() );
277 // Looks like this is a local ( but undefined variable )
278 // if it is in a static procedure then make this Symbol
280 if ( !bObj
&& pParser
->pProc
&& pParser
->pProc
->IsStatic() )
288 SbiConstDef
* pConst
= pDef
->GetConstDef();
292 pvMoreParLcl
.reset();
293 if( pConst
->GetType() == SbxSTRING
)
295 return std::make_unique
<SbiExprNode
>( pConst
->GetString() );
299 return std::make_unique
<SbiExprNode
>( pConst
->GetValue(), pConst
->GetType() );
303 // 0 parameters come up to ()
304 if( pDef
->GetDims() )
306 if( pPar
&& pPar
->GetSize() && pPar
->GetSize() != pDef
->GetDims() )
308 pParser
->Error( ERRCODE_BASIC_WRONG_DIMS
);
311 if( pDef
->IsDefinedAs() )
313 SbxDataType eDefType
= pDef
->GetType();
314 // #119187 Only error if types conflict
315 if( eType
>= SbxINTEGER
&& eType
<= SbxSTRING
&& eType
!= eDefType
)
317 // How? Define with AS first and take a Suffix then?
318 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
321 else if ( eType
== SbxVARIANT
)
323 // if there's nothing named, take the type of the entry,
324 // but only if the var hasn't been defined with AS XXX
325 // so that we catch n% = 5 : print n
329 // checking type of variables:
330 // is there named anything different in the scanner?
331 // That's OK for methods!
332 if( eType
!= SbxVARIANT
&& // Variant takes everything
333 eType
!= pDef
->GetType() &&
334 !pDef
->GetProcDef() )
336 // maybe pDef describes an object that so far has only been
337 // recognized as SbxVARIANT - then change type of pDef
338 // from 16.12.95 (similar cases possible perhaps?!?)
339 if( eType
== SbxOBJECT
&& pDef
->GetType() == SbxVARIANT
)
341 pDef
->SetType( SbxOBJECT
);
345 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
350 std::unique_ptr
<SbiExprNode
> pNd(new SbiExprNode( *pDef
, eType
));
353 pPar
= SbiExprList::ParseParameters( pParser
,false,false );
355 pNd
->aVar
.pPar
= pPar
.release();
356 pNd
->aVar
.pvMorePar
= pvMoreParLcl
.release();
359 // from 8.1.95: Object may also be of the type SbxVARIANT
360 if( pDef
->GetType() == SbxVARIANT
)
361 pDef
->SetType( SbxOBJECT
);
362 // if we scan something with point,
363 // the type must be SbxOBJECT
364 if( pDef
->GetType() != SbxOBJECT
&& pDef
->GetType() != SbxVARIANT
)
366 // defer error until runtime if in vba mode
367 if ( !pParser
->IsVBASupportOn() )
369 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
375 pNd
->aVar
.pNext
= ObjTerm( *pDef
).release();
379 pParser
->UnlockColumn();
383 // construction of an object term. A term of this kind is part
384 // of an expression that begins with an object variable.
386 std::unique_ptr
<SbiExprNode
> SbiExpression::ObjTerm( SbiSymDef
& rObj
)
389 SbiToken eTok
= pParser
->Next();
390 if( eTok
!= SYMBOL
&& !SbiTokenizer::IsKwd( eTok
) && !SbiTokenizer::IsExtra( eTok
) )
392 // #66745 Some operators can also be allowed
393 // as identifiers, important for StarOne
394 if( eTok
!= MOD
&& eTok
!= NOT
&& eTok
!= AND
&& eTok
!= OR
&&
395 eTok
!= XOR
&& eTok
!= EQV
&& eTok
!= IMP
&& eTok
!= IS
)
397 pParser
->Error( ERRCODE_BASIC_VAR_EXPECTED
);
406 OUString
aSym( pParser
->GetSym() );
407 SbxDataType eType
= pParser
->GetType();
409 SbiExprListVector
* pvMoreParLcl
= nullptr;
410 eTok
= pParser
->Peek();
412 if( DoParametersFollow( pParser
, eCurExpr
, eTok
) )
414 pPar
= SbiExprList::ParseParameters( pParser
, false/*bStandaloneExpression*/ );
415 bError
= bError
|| !pPar
->IsValid();
416 eTok
= pParser
->Peek();
418 // i109624 check for additional sets of parameters
419 while( eTok
== LPAREN
)
421 if( pvMoreParLcl
== nullptr )
423 pvMoreParLcl
= new SbiExprListVector
;
425 SbiExprListPtr pAddPar
= SbiExprList::ParseParameters( pParser
);
426 bError
= bError
|| !pPar
->IsValid();
427 pvMoreParLcl
->push_back( std::move(pAddPar
) );
428 eTok
= pParser
->Peek();
431 bool bObj
= ( ( eTok
== DOT
|| eTok
== EXCLAM
) && !pParser
->WhiteSpace() );
434 if( eType
== SbxVARIANT
)
440 // Name%. does really not work!
441 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
446 // an object's symbol pool is always PUBLIC
447 SbiSymPool
& rPool
= rObj
.GetPool();
448 rPool
.SetScope( SbPUBLIC
);
449 SbiSymDef
* pDef
= rPool
.Find( aSym
);
452 pDef
= AddSym( eTok
, rPool
, eCurExpr
, aSym
, eType
, pPar
.get() );
453 pDef
->SetType( eType
);
456 std::unique_ptr
<SbiExprNode
> pNd(new SbiExprNode( *pDef
, eType
));
457 pNd
->aVar
.pPar
= pPar
.release();
458 pNd
->aVar
.pvMorePar
= pvMoreParLcl
;
461 if( pDef
->GetType() == SbxVARIANT
)
463 pDef
->SetType( SbxOBJECT
);
465 if( pDef
->GetType() != SbxOBJECT
)
467 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
472 pNd
->aVar
.pNext
= ObjTerm( *pDef
).release();
479 // an operand can be:
482 // structure elements
485 // bracketed expressions
487 std::unique_ptr
<SbiExprNode
> SbiExpression::Operand( bool bUsedForTypeOf
)
489 std::unique_ptr
<SbiExprNode
> pRes
;
492 switch( SbiToken eTok
= pParser
->Peek() )
496 // process something like "IF Not r Is Nothing Then .."
497 if( !bUsedForTypeOf
&& pParser
->IsVBASupportOn() && pParser
->Peek() == IS
)
499 eTok
= pParser
->Next();
500 pRes
= std::make_unique
<SbiExprNode
>( std::move(pRes
), eTok
, Like() );
504 pRes
= Term(); break;
510 pRes
= std::make_unique
<SbiExprNode
>( pParser
->GetDbl(), pParser
->GetType() );
514 pRes
= std::make_unique
<SbiExprNode
>( pParser
->GetSym() ); break;
517 if( nParenLevel
== 0 && m_eMode
== EXPRMODE_LPAREN_PENDING
&& pParser
->Peek() == RPAREN
)
519 m_eMode
= EXPRMODE_EMPTY_PAREN
;
520 pRes
= std::make_unique
<SbiExprNode
>(); // Dummy node
526 if( pParser
->Peek() != RPAREN
)
528 // If there was a LPARAM, it does not belong to the expression
529 if( nParenLevel
== 1 && m_eMode
== EXPRMODE_LPAREN_PENDING
)
531 m_eMode
= EXPRMODE_LPAREN_NOT_NEEDED
;
535 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
541 if( nParenLevel
== 1 && m_eMode
== EXPRMODE_LPAREN_PENDING
)
543 SbiToken eTokAfterRParen
= pParser
->Peek();
544 if( eTokAfterRParen
== EQ
|| eTokAfterRParen
== LPAREN
|| eTokAfterRParen
== DOT
)
546 m_eMode
= EXPRMODE_ARRAY_OR_OBJECT
;
550 m_eMode
= EXPRMODE_STANDARD
;
557 // keywords here are OK at the moment!
558 if( SbiTokenizer::IsKwd( eTok
) )
565 pRes
= std::make_unique
<SbiExprNode
>( 1.0, SbxDOUBLE
);
566 pParser
->Error( ERRCODE_BASIC_UNEXPECTED
, eTok
);
573 std::unique_ptr
<SbiExprNode
> SbiExpression::Unary()
575 std::unique_ptr
<SbiExprNode
> pNd
;
576 SbiToken eTok
= pParser
->Peek();
582 pNd
= std::make_unique
<SbiExprNode
>( Unary(), eTok
, nullptr );
585 if( pParser
->IsVBASupportOn() )
592 pNd
= std::make_unique
<SbiExprNode
>( Unary(), eTok
, nullptr );
602 std::unique_ptr
<SbiExprNode
> pObjNode
= Operand( true/*bUsedForTypeOf*/ );
603 pParser
->TestToken( IS
);
604 SbiSymDef
* pTypeDef
= new SbiSymDef( OUString() );
605 pParser
->TypeDecl( *pTypeDef
, true );
606 pNd
= std::make_unique
<SbiExprNode
>( std::move(pObjNode
), pTypeDef
->GetTypeId() );
612 SbiSymDef
* pTypeDef
= new SbiSymDef( OUString() );
613 pParser
->TypeDecl( *pTypeDef
, true );
614 pNd
= std::make_unique
<SbiExprNode
>( pTypeDef
->GetTypeId() );
623 std::unique_ptr
<SbiExprNode
> SbiExpression::Exp()
625 std::unique_ptr
<SbiExprNode
> pNd
= Unary();
626 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
628 while( pParser
->Peek() == EXPON
)
630 SbiToken eTok
= pParser
->Next();
631 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Unary() );
637 std::unique_ptr
<SbiExprNode
> SbiExpression::MulDiv()
639 std::unique_ptr
<SbiExprNode
> pNd
= Exp();
640 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
644 SbiToken eTok
= pParser
->Peek();
645 if( eTok
!= MUL
&& eTok
!= DIV
)
649 eTok
= pParser
->Next();
650 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Exp() );
656 std::unique_ptr
<SbiExprNode
> SbiExpression::IntDiv()
658 std::unique_ptr
<SbiExprNode
> pNd
= MulDiv();
659 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
661 while( pParser
->Peek() == IDIV
)
663 SbiToken eTok
= pParser
->Next();
664 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, MulDiv() );
670 std::unique_ptr
<SbiExprNode
> SbiExpression::Mod()
672 std::unique_ptr
<SbiExprNode
> pNd
= IntDiv();
673 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
675 while( pParser
->Peek() == MOD
)
677 SbiToken eTok
= pParser
->Next();
678 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, IntDiv() );
684 std::unique_ptr
<SbiExprNode
> SbiExpression::AddSub()
686 std::unique_ptr
<SbiExprNode
> pNd
= Mod();
687 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
691 SbiToken eTok
= pParser
->Peek();
692 if( eTok
!= PLUS
&& eTok
!= MINUS
)
696 eTok
= pParser
->Next();
697 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Mod() );
703 std::unique_ptr
<SbiExprNode
> SbiExpression::Cat()
705 std::unique_ptr
<SbiExprNode
> pNd
= AddSub();
706 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
710 SbiToken eTok
= pParser
->Peek();
715 eTok
= pParser
->Next();
716 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, AddSub() );
722 std::unique_ptr
<SbiExprNode
> SbiExpression::Comp()
724 std::unique_ptr
<SbiExprNode
> pNd
= Cat();
725 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
730 SbiToken eTok
= pParser
->Peek();
731 if( m_eMode
== EXPRMODE_ARRAY_OR_OBJECT
)
735 if( eTok
!= EQ
&& eTok
!= NE
&& eTok
!= LT
&&
736 eTok
!= GT
&& eTok
!= LE
&& eTok
!= GE
)
740 eTok
= pParser
->Next();
741 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Cat() );
749 std::unique_ptr
<SbiExprNode
> SbiExpression::VBA_Not()
751 std::unique_ptr
<SbiExprNode
> pNd
;
753 SbiToken eTok
= pParser
->Peek();
757 pNd
= std::make_unique
<SbiExprNode
>( VBA_Not(), eTok
, nullptr );
766 std::unique_ptr
<SbiExprNode
> SbiExpression::Like()
768 std::unique_ptr
<SbiExprNode
> pNd
= pParser
->IsVBASupportOn() ? VBA_Not() : Comp();
769 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
772 while( pParser
->Peek() == LIKE
)
774 SbiToken eTok
= pParser
->Next();
775 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Comp() );
778 // multiple operands in a row does not work
779 if( nCount
> 1 && !pParser
->IsVBASupportOn() )
781 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
788 std::unique_ptr
<SbiExprNode
> SbiExpression::Boolean()
790 std::unique_ptr
<SbiExprNode
> pNd
= Like();
791 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
795 SbiToken eTok
= pParser
->Peek();
796 if( (eTok
!= AND
) && (eTok
!= OR
) &&
797 (eTok
!= XOR
) && (eTok
!= EQV
) &&
798 (eTok
!= IMP
) && (eTok
!= IS
) )
802 eTok
= pParser
->Next();
803 pNd
= std::make_unique
<SbiExprNode
>( std::move(pNd
), eTok
, Like() );
809 SbiConstExpression::SbiConstExpression( SbiParser
* p
) : SbiExpression( p
)
811 if( pExpr
->IsConstant() )
813 eType
= pExpr
->GetType();
814 if( pExpr
->IsNumber() )
821 aVal
= pExpr
->aStrVal
;
826 // #40204 special treatment for sal_Bool-constants
827 bool bIsBool
= false;
828 if( pExpr
->eNodeType
== SbxVARVAL
)
830 SbiSymDef
* pVarDef
= pExpr
->GetVar();
832 bool bBoolVal
= false;
833 if( pVarDef
->GetName().equalsIgnoreAsciiCase( "true" ) )
838 else if( pVarDef
->GetName().equalsIgnoreAsciiCase( "false" ) )
839 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
847 pExpr
= std::make_unique
<SbiExprNode
>( (bBoolVal
? SbxTRUE
: SbxFALSE
), SbxINTEGER
);
848 eType
= pExpr
->GetType();
855 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
862 short SbiConstExpression::GetShortValue()
864 if( eType
== SbxSTRING
)
866 SbxVariableRef refConv
= new SbxVariable
;
867 refConv
->PutString( aVal
);
868 return refConv
->GetInteger();
884 pParser
->Error( ERRCODE_BASIC_OUT_OF_RANGE
);
886 else if( n
< SbxMININT
)
889 pParser
->Error( ERRCODE_BASIC_OUT_OF_RANGE
);
892 return static_cast<short>(n
);
897 SbiExprList::SbiExprList( )
904 SbiExprList::~SbiExprList() {}
906 SbiExpression
* SbiExprList::Get( size_t n
)
908 return aData
[n
].get();
911 void SbiExprList::addExpression( std::unique_ptr
<SbiExpression
>&& pExpr
)
913 aData
.push_back(std::move(pExpr
));
916 // the parameter list is completely parsed
917 // "procedurename()" is OK
918 // it's a function without parameters then
919 // i. e. you give an array as procedure parameter
921 // #i79918/#i80532: bConst has never been set to true
922 // -> reused as bStandaloneExpression
923 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
924 SbiExprListPtr
SbiExprList::ParseParameters( SbiParser
* pParser
, bool bStandaloneExpression
, bool bPar
)
926 auto pExprList
= std::make_unique
<SbiExprList
>();
932 SbiToken eTok
= pParser
->Peek();
934 bool bAssumeExprLParenMode
= false;
935 bool bAssumeArrayMode
= false;
938 if( bStandaloneExpression
)
940 bAssumeExprLParenMode
= true;
944 pExprList
->bBracket
= true;
946 eTok
= pParser
->Peek();
951 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
959 // read in parameter table and lay down in correct order!
960 while( !pExprList
->bError
)
962 std::unique_ptr
<SbiExpression
> pExpr
;
966 pExpr
= std::make_unique
<SbiExpression
>( pParser
, 0, SbxEMPTY
);
968 // named arguments: either .name= or name:=
976 eTok
= pParser
->Peek();
979 if( bAssumeExprLParenMode
)
981 pExpr
= std::make_unique
<SbiExpression
>( pParser
, SbSTDEXPR
, EXPRMODE_LPAREN_PENDING
);
982 bAssumeExprLParenMode
= false;
984 SbiExprMode eModeAfter
= pExpr
->m_eMode
;
985 if( eModeAfter
== EXPRMODE_LPAREN_NOT_NEEDED
)
987 pExprList
->bBracket
= true;
989 else if( eModeAfter
== EXPRMODE_ARRAY_OR_OBJECT
)
991 // Expression "looks" like an array assignment
992 // a(...)[(...)] = ? or a(...).b(...)
993 // RPAREN is already parsed
994 pExprList
->bBracket
= true;
995 bAssumeArrayMode
= true;
998 else if( eModeAfter
== EXPRMODE_EMPTY_PAREN
)
1000 pExprList
->bBracket
= true;
1006 pExpr
= std::make_unique
<SbiExpression
>( pParser
);
1008 if( bByVal
&& pExpr
->IsLvalue() )
1012 if( !bAssumeArrayMode
)
1015 if( pParser
->Peek() == ASSIGN
)
1018 // SbiExpression::Term() has made as string out of it
1019 aName
= pExpr
->GetString();
1021 pExpr
= std::make_unique
<SbiExpression
>( pParser
);
1023 pExpr
->GetName() = aName
;
1026 pExprList
->bError
= pExprList
->bError
|| !pExpr
->IsValid();
1027 pExprList
->aData
.push_back(std::move(pExpr
));
1028 if( bAssumeArrayMode
)
1033 eTok
= pParser
->Peek();
1036 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
1039 if (SbiTokenizer::IsEoln(eTok
) && pExprList
->bBracket
)
1041 // tdf#106529: only fail here in strict mode (i.e. when compiled from IDE), and
1042 // allow legacy code with missing closing parenthesis when started e.g. from
1043 // extensions and event handlers
1044 bool bCheckStrict
= false;
1045 if (auto xContext
= css::uno::getCurrentContext())
1046 xContext
->getValueByName("BasicStrict") >>= bCheckStrict
;
1049 pParser
->Error(ERRCODE_BASIC_EXPECTED
, RPAREN
);
1050 pExprList
->bError
= true;
1055 pParser
->Error( pExprList
->bBracket
? ERRCODE_BASIC_BAD_BRACKETS
: ERRCODE_BASIC_EXPECTED
, COMMA
);
1056 pExprList
->bError
= true;
1061 eTok
= pParser
->Peek();
1062 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
1069 if( eTok
== RPAREN
)
1073 if( !pExprList
->bBracket
)
1075 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
1076 pExprList
->bError
= true;
1079 pExprList
->nDim
= pExprList
->GetSize();
1083 // A list of array dimensions is parsed.
1085 SbiExprListPtr
SbiExprList::ParseDimList( SbiParser
* pParser
)
1087 auto pExprList
= std::make_unique
<SbiExprList
>();
1089 if( pParser
->Next() != LPAREN
)
1091 pParser
->Error( ERRCODE_BASIC_EXPECTED
, LPAREN
);
1092 pExprList
->bError
= true; return pExprList
;
1095 if( pParser
->Peek() != RPAREN
)
1100 auto pExpr1
= std::make_unique
<SbiExpression
>( pParser
);
1101 eTok
= pParser
->Next();
1104 auto pExpr2
= std::make_unique
<SbiExpression
>( pParser
);
1105 pExpr1
->ConvertToIntConstIfPossible();
1106 pExpr2
->ConvertToIntConstIfPossible();
1107 eTok
= pParser
->Next();
1108 pExprList
->bError
= pExprList
->bError
|| !pExpr1
->IsValid() || !pExpr2
->IsValid();
1109 pExprList
->aData
.push_back(std::move(pExpr1
));
1110 pExprList
->aData
.push_back(std::move(pExpr2
));
1115 pExpr1
->ConvertToIntConstIfPossible();
1116 pExprList
->bError
= pExprList
->bError
|| !pExpr1
->IsValid();
1117 pExprList
->aData
.push_back(std::move(pExpr1
));
1120 if( eTok
== RPAREN
) break;
1123 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
1129 else pParser
->Next();
1133 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */