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/sbx.hxx>
25 #include <o3tl/make_unique.hxx>
27 /***************************************************************************
31 ***************************************************************************/
33 SbiExpression::SbiExpression( SbiParser
* p
, SbiExprType t
,
34 SbiExprMode eMode
, const KeywordSymbolInfo
* pKeywordSymbolInfo
)
37 bBased
= bError
= bByVal
= bBracket
= false;
41 pExpr
.reset((t
!= SbSTDEXPR
) ? Term( pKeywordSymbolInfo
) : Boolean());
44 pExpr
->Optimize(pParser
);
46 if( t
== SbLVALUE
&& !pExpr
->IsLvalue() )
48 p
->Error( ERRCODE_BASIC_LVALUE_EXPECTED
);
50 if( t
== SbOPERAND
&& !IsVariable() )
52 p
->Error( ERRCODE_BASIC_VAR_EXPECTED
);
56 SbiExpression::SbiExpression( SbiParser
* p
, double n
, SbxDataType t
)
59 bBased
= bError
= bByVal
= bBracket
= false;
62 m_eMode
= EXPRMODE_STANDARD
;
63 pExpr
= o3tl::make_unique
<SbiExprNode
>( n
, t
);
64 pExpr
->Optimize(pParser
);
67 SbiExpression::SbiExpression( SbiParser
* p
, const SbiSymDef
& r
, SbiExprListPtr pPar
)
70 bBased
= bError
= bByVal
= bBracket
= false;
73 m_eMode
= EXPRMODE_STANDARD
;
74 pExpr
= o3tl::make_unique
<SbiExprNode
>( r
, SbxVARIANT
, std::move(pPar
) );
77 SbiExpression::~SbiExpression() { }
79 // reading in a complete identifier
80 // an identifier has the following form:
81 // name[(Parameter)][.Name[(parameter)]]...
82 // structure elements are coupled via the element pNext,
83 // so that they're not in the tree.
85 // Are there parameters without brackets following? This may be a number,
86 // a string, a symbol or also a comma (if the 1st parameter is missing)
88 static bool DoParametersFollow( SbiParser
* p
, SbiExprType eCurExpr
, SbiToken eTok
)
94 // but only if similar to CALL!
95 if( !p
->WhiteSpace() || eCurExpr
!= SbSYMBOL
)
99 if ( eTok
== NUMBER
|| eTok
== MINUS
|| eTok
== FIXSTRING
||
100 eTok
== SYMBOL
|| eTok
== COMMA
|| eTok
== DOT
|| eTok
== NOT
|| eTok
== BYVAL
)
104 else // check for default params with reserved names ( e.g. names of tokens )
106 SbiTokenizer
tokens( *static_cast<SbiTokenizer
*>(p
) );
107 // Urk the Next() / Peek() semantics are... weird
109 if ( tokens
.Peek() == ASSIGN
)
117 // definition of a new symbol
119 static SbiSymDef
* AddSym ( SbiToken eTok
, SbiSymPool
& rPool
, SbiExprType eCurExpr
,
120 const OUString
& rName
, SbxDataType eType
, SbiExprList
* pPar
)
123 // A= is not a procedure
124 bool bHasType
= ( eTok
== EQ
|| eTok
== DOT
);
125 if( ( !bHasType
&& eCurExpr
== SbSYMBOL
) || pPar
)
127 // so this is a procedure
128 // the correct pool should be found out, as
129 // procs must always get into a public pool
130 SbiSymPool
* pPool
= &rPool
;
131 if( pPool
->GetScope() != SbPUBLIC
)
133 pPool
= &rPool
.GetParser()->aPublics
;
135 SbiProcDef
* pProc
= pPool
->AddProc( rName
);
137 // special treatment for Colls like Documents(1)
138 if( eCurExpr
== SbSTDEXPR
)
143 pDef
->SetType( bHasType
? eType
: SbxEMPTY
);
146 // generate dummy parameters
148 for( short i
= 0; i
< pPar
->GetSize(); i
++ )
151 OUStringBuffer
aPar("PAR");
153 pProc
->GetParams().AddSym( aPar
.makeStringAndClear() );
159 // or a normal symbol
160 pDef
= rPool
.AddSym( rName
);
161 pDef
->SetType( eType
);
166 // currently even keywords are allowed (because of Dflt properties of the same name)
168 SbiExprNode
* SbiExpression::Term( const KeywordSymbolInfo
* pKeywordSymbolInfo
)
170 if( pParser
->Peek() == DOT
)
172 SbiExprNode
* pWithVar
= pParser
->GetWithVar();
173 // #26608: get to the node-chain's end to pass the correct object
174 SbiSymDef
* pDef
= pWithVar
? pWithVar
->GetRealVar() : nullptr;
175 SbiExprNode
* pNd
= nullptr;
182 pNd
= ObjTerm( *pDef
);
185 pNd
->SetWithParent( pWithVar
);
190 pParser
->Error( ERRCODE_BASIC_UNEXPECTED
, DOT
);
191 pNd
= new SbiExprNode( 1.0, SbxDOUBLE
);
196 SbiToken eTok
= (pKeywordSymbolInfo
== nullptr) ? pParser
->Next() : SYMBOL
;
197 // memorize the parsing's begin
198 pParser
->LockColumn();
199 OUString
aSym( (pKeywordSymbolInfo
== nullptr) ? pParser
->GetSym() : pKeywordSymbolInfo
->m_aKeywordSymbol
);
200 SbxDataType eType
= (pKeywordSymbolInfo
== nullptr) ? pParser
->GetType() : pKeywordSymbolInfo
->m_eSbxDataType
;
202 SbiExprListVector
* pvMoreParLcl
= nullptr;
203 // are there parameters following?
204 SbiToken eNextTok
= pParser
->Peek();
205 // is it a known parameter?
206 // create a string constant then, which will be recognized
207 // in the SbiParameters-ctor and is continued to be handled
208 if( eNextTok
== ASSIGN
)
210 pParser
->UnlockColumn();
211 return new SbiExprNode( aSym
);
213 // no keywords allowed from here on!
214 if( SbiTokenizer::IsKwd( eTok
)
215 && (!pParser
->IsCompatible() || eTok
!= INPUT
) )
217 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
221 if( DoParametersFollow( pParser
, eCurExpr
, eTok
= eNextTok
) )
223 bool bStandaloneExpression
= (m_eMode
== EXPRMODE_STANDALONE
);
224 pPar
= SbiExprList::ParseParameters( pParser
, bStandaloneExpression
);
225 bError
= bError
|| !pPar
->IsValid();
227 bBracket
= pPar
->IsBracket();
228 eTok
= pParser
->Peek();
230 // i75443 check for additional sets of parameters
231 while( eTok
== LPAREN
)
233 if( pvMoreParLcl
== nullptr )
235 pvMoreParLcl
= new SbiExprListVector
;
237 SbiExprListPtr pAddPar
= SbiExprList::ParseParameters( pParser
);
238 bError
= bError
|| !pAddPar
->IsValid();
239 pvMoreParLcl
->push_back( std::move(pAddPar
) );
240 eTok
= pParser
->Peek();
243 // It might be an object part, if . or ! is following.
244 // In case of . the variable must already be defined;
245 // it's an object, if pDef is NULL after the search.
246 bool bObj
= ( ( eTok
== DOT
|| eTok
== EXCLAM
)
247 && !pParser
->WhiteSpace() );
250 bBracket
= false; // Now the bracket for the first term is obsolete
251 if( eType
== SbxVARIANT
)
257 // Name%. really does not work!
258 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
263 SbiSymDef
* pDef
= pParser
->pPool
->Find( aSym
);
266 // Part of the Runtime-Library?
267 // from 31.3.1996: swapped out to parser-method
268 // (is also needed in SbiParser::DefVar() in DIM.CXX)
269 pDef
= pParser
->CheckRTLForSym( aSym
, eType
);
271 // #i109184: Check if symbol is or later will be defined inside module
272 SbModule
& rMod
= pParser
->aGen
.GetModule();
273 if( rMod
.FindMethod( aSym
, SbxClassType::DontCare
) )
284 pDef
= AddSym( eTok
, *pParser
->pPool
, eCurExpr
, aSym
, eType
, pPar
.get() );
285 // Looks like this is a local ( but undefined variable )
286 // if it is in a static procedure then make this Symbol
288 if ( !bObj
&& pParser
->pProc
&& pParser
->pProc
->IsStatic() )
296 SbiConstDef
* pConst
= pDef
->GetConstDef();
301 if( pConst
->GetType() == SbxSTRING
)
303 return new SbiExprNode( pConst
->GetString() );
307 return new SbiExprNode( pConst
->GetValue(), pConst
->GetType() );
311 // 0 parameters come up to ()
312 if( pDef
->GetDims() )
314 if( pPar
&& pPar
->GetSize() && pPar
->GetSize() != pDef
->GetDims() )
316 pParser
->Error( ERRCODE_BASIC_WRONG_DIMS
);
319 if( pDef
->IsDefinedAs() )
321 SbxDataType eDefType
= pDef
->GetType();
322 // #119187 Only error if types conflict
323 if( eType
>= SbxINTEGER
&& eType
<= SbxSTRING
&& eType
!= eDefType
)
325 // How? Define with AS first and take a Suffix then?
326 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
329 else if ( eType
== SbxVARIANT
)
331 // if there's nothing named, take the type of the entry,
332 // but only if the var hasn't been defined with AS XXX
333 // so that we catch n% = 5 : print n
337 // checking type of variables:
338 // is there named anything different in the scanner?
339 // That's OK for methods!
340 if( eType
!= SbxVARIANT
&& // Variant takes everything
341 eType
!= pDef
->GetType() &&
342 !pDef
->GetProcDef() )
344 // maybe pDef describes an object that so far has only been
345 // recognized as SbxVARIANT - then change type of pDef
346 // from 16.12.95 (similar cases possible perhaps?!?)
347 if( eType
== SbxOBJECT
&& pDef
->GetType() == SbxVARIANT
)
349 pDef
->SetType( SbxOBJECT
);
353 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
358 SbiExprNode
* pNd
= new SbiExprNode( *pDef
, eType
);
361 pPar
= SbiExprList::ParseParameters( pParser
,false,false );
363 pNd
->aVar
.pPar
= pPar
.release();
364 pNd
->aVar
.pvMorePar
= pvMoreParLcl
;
367 // from 8.1.95: Object may also be of the type SbxVARIANT
368 if( pDef
->GetType() == SbxVARIANT
)
369 pDef
->SetType( SbxOBJECT
);
370 // if we scan something with point,
371 // the type must be SbxOBJECT
372 if( pDef
->GetType() != SbxOBJECT
&& pDef
->GetType() != SbxVARIANT
)
374 // defer error until runtime if in vba mode
375 if ( !pParser
->IsVBASupportOn() )
377 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
383 pNd
->aVar
.pNext
= ObjTerm( *pDef
);
387 pParser
->UnlockColumn();
391 // construction of an object term. A term of this kind is part
392 // of an expression that begins with an object variable.
394 SbiExprNode
* SbiExpression::ObjTerm( SbiSymDef
& rObj
)
397 SbiToken eTok
= pParser
->Next();
398 if( eTok
!= SYMBOL
&& !SbiTokenizer::IsKwd( eTok
) && !SbiTokenizer::IsExtra( eTok
) )
400 // #66745 Some operators can also be allowed
401 // as identifiers, important for StarOne
402 if( eTok
!= MOD
&& eTok
!= NOT
&& eTok
!= AND
&& eTok
!= OR
&&
403 eTok
!= XOR
&& eTok
!= EQV
&& eTok
!= IMP
&& eTok
!= IS
)
405 pParser
->Error( ERRCODE_BASIC_VAR_EXPECTED
);
414 OUString
aSym( pParser
->GetSym() );
415 SbxDataType eType
= pParser
->GetType();
417 SbiExprListVector
* pvMoreParLcl
= nullptr;
418 eTok
= pParser
->Peek();
420 if( DoParametersFollow( pParser
, eCurExpr
, eTok
) )
422 bool bStandaloneExpression
= false;
423 pPar
= SbiExprList::ParseParameters( pParser
, bStandaloneExpression
);
424 bError
= bError
|| !pPar
->IsValid();
425 eTok
= pParser
->Peek();
427 // i109624 check for additional sets of parameters
428 while( eTok
== LPAREN
)
430 if( pvMoreParLcl
== nullptr )
432 pvMoreParLcl
= new SbiExprListVector
;
434 SbiExprListPtr pAddPar
= SbiExprList::ParseParameters( pParser
);
435 bError
= bError
|| !pPar
->IsValid();
436 pvMoreParLcl
->push_back( std::move(pAddPar
) );
437 eTok
= pParser
->Peek();
440 bool bObj
= ( ( eTok
== DOT
|| eTok
== EXCLAM
) && !pParser
->WhiteSpace() );
443 if( eType
== SbxVARIANT
)
449 // Name%. does really not work!
450 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
455 // an object's symbol pool is always PUBLIC
456 SbiSymPool
& rPool
= rObj
.GetPool();
457 rPool
.SetScope( SbPUBLIC
);
458 SbiSymDef
* pDef
= rPool
.Find( aSym
);
461 pDef
= AddSym( eTok
, rPool
, eCurExpr
, aSym
, eType
, pPar
.get() );
462 pDef
->SetType( eType
);
465 SbiExprNode
* pNd
= new SbiExprNode( *pDef
, eType
);
466 pNd
->aVar
.pPar
= pPar
.release();
467 pNd
->aVar
.pvMorePar
= pvMoreParLcl
;
470 if( pDef
->GetType() == SbxVARIANT
)
472 pDef
->SetType( SbxOBJECT
);
474 if( pDef
->GetType() != SbxOBJECT
)
476 pParser
->Error( ERRCODE_BASIC_BAD_DECLARATION
, aSym
);
481 pNd
->aVar
.pNext
= ObjTerm( *pDef
);
488 // an operand can be:
491 // structure elements
494 // bracketed expressions
496 SbiExprNode
* SbiExpression::Operand( bool bUsedForTypeOf
)
501 switch( SbiToken eTok
= pParser
->Peek() )
505 // process something like "IF Not r Is Nothing Then .."
506 if( !bUsedForTypeOf
&& pParser
->IsVBASupportOn() && pParser
->Peek() == IS
)
508 eTok
= pParser
->Next();
509 pRes
= new SbiExprNode( pRes
, eTok
, Like() );
513 pRes
= Term(); break;
516 pRes
= new SbiExprNode( pParser
->GetDbl(), pParser
->GetType() );
520 pRes
= new SbiExprNode( pParser
->GetSym() ); break;
523 if( nParenLevel
== 0 && m_eMode
== EXPRMODE_LPAREN_PENDING
&& pParser
->Peek() == RPAREN
)
525 m_eMode
= EXPRMODE_EMPTY_PAREN
;
526 pRes
= new SbiExprNode(); // Dummy node
532 if( pParser
->Peek() != RPAREN
)
534 // If there was a LPARAM, it does not belong to the expression
535 if( nParenLevel
== 1 && m_eMode
== EXPRMODE_LPAREN_PENDING
)
537 m_eMode
= EXPRMODE_LPAREN_NOT_NEEDED
;
541 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
547 if( nParenLevel
== 1 && m_eMode
== EXPRMODE_LPAREN_PENDING
)
549 SbiToken eTokAfterRParen
= pParser
->Peek();
550 if( eTokAfterRParen
== EQ
|| eTokAfterRParen
== LPAREN
|| eTokAfterRParen
== DOT
)
552 m_eMode
= EXPRMODE_ARRAY_OR_OBJECT
;
556 m_eMode
= EXPRMODE_STANDARD
;
563 // keywords here are OK at the moment!
564 if( SbiTokenizer::IsKwd( eTok
) )
571 pRes
= new SbiExprNode( 1.0, SbxDOUBLE
);
572 pParser
->Error( ERRCODE_BASIC_UNEXPECTED
, eTok
);
579 SbiExprNode
* SbiExpression::Unary()
582 SbiToken eTok
= pParser
->Peek();
588 pNd
= new SbiExprNode( Unary(), eTok
, nullptr );
591 if( pParser
->IsVBASupportOn() )
598 pNd
= new SbiExprNode( Unary(), eTok
, nullptr );
608 bool bUsedForTypeOf
= true;
609 SbiExprNode
* pObjNode
= Operand( bUsedForTypeOf
);
610 pParser
->TestToken( IS
);
612 SbiSymDef
* pTypeDef
= new SbiSymDef( aDummy
);
613 pParser
->TypeDecl( *pTypeDef
, true );
614 pNd
= new SbiExprNode( pObjNode
, pTypeDef
->GetTypeId() );
621 SbiSymDef
* pTypeDef
= new SbiSymDef( aStr
);
622 pParser
->TypeDecl( *pTypeDef
, true );
623 pNd
= new SbiExprNode( pTypeDef
->GetTypeId() );
632 SbiExprNode
* SbiExpression::Exp()
634 SbiExprNode
* pNd
= Unary();
635 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
637 while( pParser
->Peek() == EXPON
)
639 SbiToken eTok
= pParser
->Next();
640 pNd
= new SbiExprNode( pNd
, eTok
, Unary() );
646 SbiExprNode
* SbiExpression::MulDiv()
648 SbiExprNode
* pNd
= Exp();
649 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
653 SbiToken eTok
= pParser
->Peek();
654 if( eTok
!= MUL
&& eTok
!= DIV
)
658 eTok
= pParser
->Next();
659 pNd
= new SbiExprNode( pNd
, eTok
, Exp() );
665 SbiExprNode
* SbiExpression::IntDiv()
667 SbiExprNode
* pNd
= MulDiv();
668 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
670 while( pParser
->Peek() == IDIV
)
672 SbiToken eTok
= pParser
->Next();
673 pNd
= new SbiExprNode( pNd
, eTok
, MulDiv() );
679 SbiExprNode
* SbiExpression::Mod()
681 SbiExprNode
* pNd
= IntDiv();
682 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
684 while( pParser
->Peek() == MOD
)
686 SbiToken eTok
= pParser
->Next();
687 pNd
= new SbiExprNode( pNd
, eTok
, IntDiv() );
693 SbiExprNode
* SbiExpression::AddSub()
695 SbiExprNode
* pNd
= Mod();
696 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
700 SbiToken eTok
= pParser
->Peek();
701 if( eTok
!= PLUS
&& eTok
!= MINUS
)
705 eTok
= pParser
->Next();
706 pNd
= new SbiExprNode( pNd
, eTok
, Mod() );
712 SbiExprNode
* SbiExpression::Cat()
714 SbiExprNode
* pNd
= AddSub();
715 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
719 SbiToken eTok
= pParser
->Peek();
724 eTok
= pParser
->Next();
725 pNd
= new SbiExprNode( pNd
, eTok
, AddSub() );
731 SbiExprNode
* SbiExpression::Comp()
733 SbiExprNode
* pNd
= Cat();
734 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
739 SbiToken eTok
= pParser
->Peek();
740 if( m_eMode
== EXPRMODE_ARRAY_OR_OBJECT
)
744 if( eTok
!= EQ
&& eTok
!= NE
&& eTok
!= LT
&&
745 eTok
!= GT
&& eTok
!= LE
&& eTok
!= GE
)
749 eTok
= pParser
->Next();
750 pNd
= new SbiExprNode( pNd
, eTok
, Cat() );
758 SbiExprNode
* SbiExpression::VBA_Not()
760 SbiExprNode
* pNd
= nullptr;
762 SbiToken eTok
= pParser
->Peek();
766 pNd
= new SbiExprNode( VBA_Not(), eTok
, nullptr );
775 SbiExprNode
* SbiExpression::Like()
777 SbiExprNode
* pNd
= pParser
->IsVBASupportOn() ? VBA_Not() : Comp();
778 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
781 while( pParser
->Peek() == LIKE
)
783 SbiToken eTok
= pParser
->Next();
784 pNd
= new SbiExprNode( pNd
, eTok
, Comp() );
787 // multiple operands in a row does not work
788 if( nCount
> 1 && !pParser
->IsVBASupportOn() )
790 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
797 SbiExprNode
* SbiExpression::Boolean()
799 SbiExprNode
* pNd
= Like();
800 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
804 SbiToken eTok
= pParser
->Peek();
805 if( (eTok
!= AND
) && (eTok
!= OR
) &&
806 (eTok
!= XOR
) && (eTok
!= EQV
) &&
807 (eTok
!= IMP
) && (eTok
!= IS
) )
811 eTok
= pParser
->Next();
812 pNd
= new SbiExprNode( pNd
, eTok
, Like() );
818 /***************************************************************************
820 |* SbiConstExpression
822 ***************************************************************************/
824 SbiConstExpression::SbiConstExpression( SbiParser
* p
) : SbiExpression( p
)
826 if( pExpr
->IsConstant() )
828 eType
= pExpr
->GetType();
829 if( pExpr
->IsNumber() )
836 aVal
= pExpr
->aStrVal
;
841 // #40204 special treatment for sal_Bool-constants
842 bool bIsBool
= false;
843 if( pExpr
->eNodeType
== SbxVARVAL
)
845 SbiSymDef
* pVarDef
= pExpr
->GetVar();
847 bool bBoolVal
= false;
848 if( pVarDef
->GetName().equalsIgnoreAsciiCase( "true" ) )
853 else if( pVarDef
->GetName().equalsIgnoreAsciiCase( "false" ) )
854 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
862 pExpr
= o3tl::make_unique
<SbiExprNode
>( (bBoolVal
? SbxTRUE
: SbxFALSE
), SbxINTEGER
);
863 eType
= pExpr
->GetType();
870 pParser
->Error( ERRCODE_BASIC_SYNTAX
);
877 short SbiConstExpression::GetShortValue()
879 if( eType
== SbxSTRING
)
881 SbxVariableRef refConv
= new SbxVariable
;
882 refConv
->PutString( aVal
);
883 return refConv
->GetInteger();
899 pParser
->Error( ERRCODE_BASIC_OUT_OF_RANGE
);
901 else if( n
< SbxMININT
)
904 pParser
->Error( ERRCODE_BASIC_OUT_OF_RANGE
);
912 /***************************************************************************
916 ***************************************************************************/
918 SbiExprList::SbiExprList( )
925 SbiExprList::~SbiExprList() {}
927 SbiExpression
* SbiExprList::Get( size_t n
)
929 return aData
[n
].get();
932 void SbiExprList::addExpression( std::unique_ptr
<SbiExpression
>&& pExpr
)
934 aData
.push_back(std::move(pExpr
));
937 // the parameter list is completely parsed
938 // "procedurename()" is OK
939 // it's a function without parameters then
940 // i. e. you give an array as procedure parameter
942 // #i79918/#i80532: bConst has never been set to true
943 // -> reused as bStandaloneExpression
944 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
945 SbiExprListPtr
SbiExprList::ParseParameters( SbiParser
* pParser
, bool bStandaloneExpression
, bool bPar
)
947 auto pExprList
= o3tl::make_unique
<SbiExprList
>();
953 SbiToken eTok
= pParser
->Peek();
955 bool bAssumeExprLParenMode
= false;
956 bool bAssumeArrayMode
= false;
959 if( bStandaloneExpression
)
961 bAssumeExprLParenMode
= true;
965 pExprList
->bBracket
= true;
967 eTok
= pParser
->Peek();
972 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
980 // read in parameter table and lay down in correct order!
981 while( !pExprList
->bError
)
983 std::unique_ptr
<SbiExpression
> pExpr
;
987 pExpr
= o3tl::make_unique
<SbiExpression
>( pParser
, 0, SbxEMPTY
);
989 // named arguments: either .name= or name:=
997 eTok
= pParser
->Peek();
1000 if( bAssumeExprLParenMode
)
1002 pExpr
= o3tl::make_unique
<SbiExpression
>( pParser
, SbSTDEXPR
, EXPRMODE_LPAREN_PENDING
);
1003 bAssumeExprLParenMode
= false;
1005 SbiExprMode eModeAfter
= pExpr
->m_eMode
;
1006 if( eModeAfter
== EXPRMODE_LPAREN_NOT_NEEDED
)
1008 pExprList
->bBracket
= true;
1010 else if( eModeAfter
== EXPRMODE_ARRAY_OR_OBJECT
)
1012 // Expression "looks" like an array assignment
1013 // a(...)[(...)] = ? or a(...).b(...)
1014 // RPAREN is already parsed
1015 pExprList
->bBracket
= true;
1016 bAssumeArrayMode
= true;
1019 else if( eModeAfter
== EXPRMODE_EMPTY_PAREN
)
1021 pExprList
->bBracket
= true;
1027 pExpr
= o3tl::make_unique
<SbiExpression
>( pParser
);
1029 if( bByVal
&& pExpr
->IsLvalue() )
1033 if( !bAssumeArrayMode
)
1036 if( pParser
->Peek() == ASSIGN
)
1039 // SbiExpression::Term() has made as string out of it
1040 aName
= pExpr
->GetString();
1042 pExpr
= o3tl::make_unique
<SbiExpression
>( pParser
);
1044 pExpr
->GetName() = aName
;
1047 pExprList
->bError
= pExprList
->bError
|| !pExpr
->IsValid();
1048 pExprList
->aData
.push_back(std::move(pExpr
));
1049 if( bAssumeArrayMode
)
1054 eTok
= pParser
->Peek();
1057 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
1061 pParser
->Error( pExprList
->bBracket
? ERRCODE_BASIC_BAD_BRACKETS
: ERRCODE_BASIC_EXPECTED
, COMMA
);
1062 pExprList
->bError
= true;
1067 eTok
= pParser
->Peek();
1068 if( ( pExprList
->bBracket
&& eTok
== RPAREN
) || SbiTokenizer::IsEoln( eTok
) )
1075 if( eTok
== RPAREN
)
1079 if( !pExprList
->bBracket
)
1081 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
1082 pExprList
->bError
= true;
1085 pExprList
->nDim
= pExprList
->GetSize();
1089 // A list of array dimensions is parsed.
1091 SbiExprListPtr
SbiExprList::ParseDimList( SbiParser
* pParser
)
1093 auto pExprList
= o3tl::make_unique
<SbiExprList
>();
1095 if( pParser
->Next() != LPAREN
)
1097 pParser
->Error( ERRCODE_BASIC_EXPECTED
, LPAREN
);
1098 pExprList
->bError
= true; return pExprList
;
1101 if( pParser
->Peek() != RPAREN
)
1106 auto pExpr1
= o3tl::make_unique
<SbiExpression
>( pParser
);
1107 eTok
= pParser
->Next();
1110 auto pExpr2
= o3tl::make_unique
<SbiExpression
>( pParser
);
1111 pExpr1
->ConvertToIntConstIfPossible();
1112 pExpr2
->ConvertToIntConstIfPossible();
1113 eTok
= pParser
->Next();
1114 pExprList
->bError
= pExprList
->bError
|| !pExpr1
->IsValid() || !pExpr2
->IsValid();
1115 pExprList
->aData
.push_back(std::move(pExpr1
));
1116 pExprList
->aData
.push_back(std::move(pExpr2
));
1121 pExpr1
->ConvertToIntConstIfPossible();
1122 pExprList
->bError
= pExprList
->bError
|| !pExpr1
->IsValid();
1123 pExprList
->aData
.push_back(std::move(pExpr1
));
1126 if( eTok
== RPAREN
) break;
1129 pParser
->Error( ERRCODE_BASIC_BAD_BRACKETS
);
1135 else pParser
->Next();
1139 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */