Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / basic / source / comp / exprtree.cxx
blobd75b32364e307981a9c7960a388821869e36c5aa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <memory>
22 #include "parser.hxx"
23 #include <basic/sbx.hxx>
24 #include "expr.hxx"
25 #include <o3tl/make_unique.hxx>
27 /***************************************************************************
29 |* SbiExpression
31 ***************************************************************************/
33 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
34 SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
36 pParser = p;
37 bBased = bError = bByVal = bBracket = false;
38 nParenLevel = 0;
39 eCurExpr = t;
40 m_eMode = eMode;
41 pExpr.reset((t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean());
42 if( t != SbSYMBOL )
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 )
58 pParser = p;
59 bBased = bError = bByVal = bBracket = false;
60 nParenLevel = 0;
61 eCurExpr = SbOPERAND;
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 )
69 pParser = p;
70 bBased = bError = bByVal = bBracket = false;
71 nParenLevel = 0;
72 eCurExpr = SbOPERAND;
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 )
90 if( eTok == LPAREN )
92 return true;
94 // but only if similar to CALL!
95 if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
97 return false;
99 if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
100 eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL )
102 return true;
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
108 tokens.Next();
109 if ( tokens.Peek() == ASSIGN )
111 return true;
114 return false;
117 // definition of a new symbol
119 static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
120 const OUString& rName, SbxDataType eType, SbiExprList* pPar )
122 SbiSymDef* pDef;
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 )
140 bHasType = true;
142 pDef = pProc;
143 pDef->SetType( bHasType ? eType : SbxEMPTY );
144 if( pPar )
146 // generate dummy parameters
147 sal_Int32 n = 1;
148 for( short i = 0; i < pPar->GetSize(); i++ )
150 n += 1;
151 OUStringBuffer aPar("PAR");
152 aPar.append(n);
153 pProc->GetParams().AddSym( aPar.makeStringAndClear() );
157 else
159 // or a normal symbol
160 pDef = rPool.AddSym( rName );
161 pDef->SetType( eType );
163 return pDef;
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;
176 if( !pDef )
178 pParser->Next();
180 else
182 pNd = ObjTerm( *pDef );
183 if( pNd )
185 pNd->SetWithParent( pWithVar );
188 if( !pNd )
190 pParser->Error( ERRCODE_BASIC_UNEXPECTED, DOT );
191 pNd = new SbiExprNode( 1.0, SbxDOUBLE );
193 return pNd;
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;
201 SbiExprListPtr pPar;
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 );
218 bError = true;
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();
226 if( !bError )
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() );
248 if( bObj )
250 bBracket = false; // Now the bracket for the first term is obsolete
251 if( eType == SbxVARIANT )
253 eType = SbxOBJECT;
255 else
257 // Name%. really does not work!
258 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
259 bError = true;
262 // Search:
263 SbiSymDef* pDef = pParser->pPool->Find( aSym );
264 if( !pDef )
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 ) )
275 pDef = nullptr;
278 if( !pDef )
280 if( bObj )
282 eType = SbxOBJECT;
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
287 // static
288 if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
290 pDef->SetStatic();
293 else
296 SbiConstDef* pConst = pDef->GetConstDef();
297 if( pConst )
299 pPar = nullptr;
300 delete pvMoreParLcl;
301 if( pConst->GetType() == SbxSTRING )
303 return new SbiExprNode( pConst->GetString() );
305 else
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 );
327 bError = true;
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
334 eType = eDefType;
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 );
351 else
353 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
354 bError = true;
358 SbiExprNode* pNd = new SbiExprNode( *pDef, eType );
359 if( !pPar )
361 pPar = SbiExprList::ParseParameters( pParser,false,false );
363 pNd->aVar.pPar = pPar.release();
364 pNd->aVar.pvMorePar = pvMoreParLcl;
365 if( bObj )
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 );
378 bError = true;
381 if( !bError )
383 pNd->aVar.pNext = ObjTerm( *pDef );
387 pParser->UnlockColumn();
388 return pNd;
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 )
396 pParser->Next();
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 );
406 bError = true;
410 if( bError )
412 return nullptr;
414 OUString aSym( pParser->GetSym() );
415 SbxDataType eType = pParser->GetType();
416 SbiExprListPtr pPar;
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() );
441 if( bObj )
443 if( eType == SbxVARIANT )
445 eType = SbxOBJECT;
447 else
449 // Name%. does really not work!
450 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
451 bError = true;
455 // an object's symbol pool is always PUBLIC
456 SbiSymPool& rPool = rObj.GetPool();
457 rPool.SetScope( SbPUBLIC );
458 SbiSymDef* pDef = rPool.Find( aSym );
459 if( !pDef )
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;
468 if( bObj )
470 if( pDef->GetType() == SbxVARIANT )
472 pDef->SetType( SbxOBJECT );
474 if( pDef->GetType() != SbxOBJECT )
476 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
477 bError = true;
479 if( !bError )
481 pNd->aVar.pNext = ObjTerm( *pDef );
482 pNd->eType = eType;
485 return pNd;
488 // an operand can be:
489 // constant
490 // scalar variable
491 // structure elements
492 // array elements
493 // functions
494 // bracketed expressions
496 SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf )
498 SbiExprNode *pRes;
500 // test operand:
501 switch( SbiToken eTok = pParser->Peek() )
503 case SYMBOL:
504 pRes = Term();
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() );
511 break;
512 case DOT: // .with
513 pRes = Term(); break;
514 case NUMBER:
515 pParser->Next();
516 pRes = new SbiExprNode( pParser->GetDbl(), pParser->GetType() );
517 break;
518 case FIXSTRING:
519 pParser->Next();
520 pRes = new SbiExprNode( pParser->GetSym() ); break;
521 case LPAREN:
522 pParser->Next();
523 if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
525 m_eMode = EXPRMODE_EMPTY_PAREN;
526 pRes = new SbiExprNode(); // Dummy node
527 pParser->Next();
528 break;
530 nParenLevel++;
531 pRes = Boolean();
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;
539 else
541 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
544 else
546 pParser->Next();
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;
554 else
556 m_eMode = EXPRMODE_STANDARD;
560 nParenLevel--;
561 break;
562 default:
563 // keywords here are OK at the moment!
564 if( SbiTokenizer::IsKwd( eTok ) )
566 pRes = Term();
568 else
570 pParser->Next();
571 pRes = new SbiExprNode( 1.0, SbxDOUBLE );
572 pParser->Error( ERRCODE_BASIC_UNEXPECTED, eTok );
574 break;
576 return pRes;
579 SbiExprNode* SbiExpression::Unary()
581 SbiExprNode* pNd;
582 SbiToken eTok = pParser->Peek();
583 switch( eTok )
585 case MINUS:
586 eTok = NEG;
587 pParser->Next();
588 pNd = new SbiExprNode( Unary(), eTok, nullptr );
589 break;
590 case NOT:
591 if( pParser->IsVBASupportOn() )
593 pNd = Operand();
595 else
597 pParser->Next();
598 pNd = new SbiExprNode( Unary(), eTok, nullptr );
600 break;
601 case PLUS:
602 pParser->Next();
603 pNd = Unary();
604 break;
605 case TYPEOF:
607 pParser->Next();
608 bool bUsedForTypeOf = true;
609 SbiExprNode* pObjNode = Operand( bUsedForTypeOf );
610 pParser->TestToken( IS );
611 OUString aDummy;
612 SbiSymDef* pTypeDef = new SbiSymDef( aDummy );
613 pParser->TypeDecl( *pTypeDef, true );
614 pNd = new SbiExprNode( pObjNode, pTypeDef->GetTypeId() );
615 break;
617 case NEW:
619 pParser->Next();
620 OUString aStr;
621 SbiSymDef* pTypeDef = new SbiSymDef( aStr );
622 pParser->TypeDecl( *pTypeDef, true );
623 pNd = new SbiExprNode( pTypeDef->GetTypeId() );
624 break;
626 default:
627 pNd = Operand();
629 return pNd;
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() );
643 return pNd;
646 SbiExprNode* SbiExpression::MulDiv()
648 SbiExprNode* pNd = Exp();
649 if( m_eMode != EXPRMODE_EMPTY_PAREN )
651 for( ;; )
653 SbiToken eTok = pParser->Peek();
654 if( eTok != MUL && eTok != DIV )
656 break;
658 eTok = pParser->Next();
659 pNd = new SbiExprNode( pNd, eTok, Exp() );
662 return pNd;
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() );
676 return pNd;
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() );
690 return pNd;
693 SbiExprNode* SbiExpression::AddSub()
695 SbiExprNode* pNd = Mod();
696 if( m_eMode != EXPRMODE_EMPTY_PAREN )
698 for( ;; )
700 SbiToken eTok = pParser->Peek();
701 if( eTok != PLUS && eTok != MINUS )
703 break;
705 eTok = pParser->Next();
706 pNd = new SbiExprNode( pNd, eTok, Mod() );
709 return pNd;
712 SbiExprNode* SbiExpression::Cat()
714 SbiExprNode* pNd = AddSub();
715 if( m_eMode != EXPRMODE_EMPTY_PAREN )
717 for( ;; )
719 SbiToken eTok = pParser->Peek();
720 if( eTok != CAT )
722 break;
724 eTok = pParser->Next();
725 pNd = new SbiExprNode( pNd, eTok, AddSub() );
728 return pNd;
731 SbiExprNode* SbiExpression::Comp()
733 SbiExprNode* pNd = Cat();
734 if( m_eMode != EXPRMODE_EMPTY_PAREN )
736 short nCount = 0;
737 for( ;; )
739 SbiToken eTok = pParser->Peek();
740 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
742 break;
744 if( eTok != EQ && eTok != NE && eTok != LT &&
745 eTok != GT && eTok != LE && eTok != GE )
747 break;
749 eTok = pParser->Next();
750 pNd = new SbiExprNode( pNd, eTok, Cat() );
751 nCount++;
754 return pNd;
758 SbiExprNode* SbiExpression::VBA_Not()
760 SbiExprNode* pNd = nullptr;
762 SbiToken eTok = pParser->Peek();
763 if( eTok == NOT )
765 pParser->Next();
766 pNd = new SbiExprNode( VBA_Not(), eTok, nullptr );
768 else
770 pNd = Comp();
772 return pNd;
775 SbiExprNode* SbiExpression::Like()
777 SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
778 if( m_eMode != EXPRMODE_EMPTY_PAREN )
780 short nCount = 0;
781 while( pParser->Peek() == LIKE )
783 SbiToken eTok = pParser->Next();
784 pNd = new SbiExprNode( pNd, eTok, Comp() );
785 nCount++;
787 // multiple operands in a row does not work
788 if( nCount > 1 && !pParser->IsVBASupportOn() )
790 pParser->Error( ERRCODE_BASIC_SYNTAX );
791 bError = true;
794 return pNd;
797 SbiExprNode* SbiExpression::Boolean()
799 SbiExprNode* pNd = Like();
800 if( m_eMode != EXPRMODE_EMPTY_PAREN )
802 for( ;; )
804 SbiToken eTok = pParser->Peek();
805 if( (eTok != AND) && (eTok != OR) &&
806 (eTok != XOR) && (eTok != EQV) &&
807 (eTok != IMP) && (eTok != IS) )
809 break;
811 eTok = pParser->Next();
812 pNd = new SbiExprNode( pNd, eTok, Like() );
815 return pNd;
818 /***************************************************************************
820 |* SbiConstExpression
822 ***************************************************************************/
824 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
826 if( pExpr->IsConstant() )
828 eType = pExpr->GetType();
829 if( pExpr->IsNumber() )
831 nVal = pExpr->nVal;
833 else
835 nVal = 0;
836 aVal = pExpr->aStrVal;
839 else
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" ) )
850 bIsBool = true;
851 bBoolVal = true;
853 else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
854 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
856 bIsBool = true;
857 bBoolVal = false;
860 if( bIsBool )
862 pExpr = o3tl::make_unique<SbiExprNode>( (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
863 eType = pExpr->GetType();
864 nVal = pExpr->nVal;
868 if( !bIsBool )
870 pParser->Error( ERRCODE_BASIC_SYNTAX );
871 eType = SbxDOUBLE;
872 nVal = 0;
877 short SbiConstExpression::GetShortValue()
879 if( eType == SbxSTRING )
881 SbxVariableRef refConv = new SbxVariable;
882 refConv->PutString( aVal );
883 return refConv->GetInteger();
885 else
887 double n = nVal;
888 if( n > 0 )
890 n += .5;
892 else
894 n -= .5;
896 if( n > SbxMAXINT )
898 n = SbxMAXINT;
899 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
901 else if( n < SbxMININT )
903 n = SbxMININT;
904 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
907 return (short) n;
912 /***************************************************************************
914 |* SbiExprList
916 ***************************************************************************/
918 SbiExprList::SbiExprList( )
920 nDim = 0;
921 bError = false;
922 bBracket = false;
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>();
948 if( !bPar )
950 return pExprList;
953 SbiToken eTok = pParser->Peek();
955 bool bAssumeExprLParenMode = false;
956 bool bAssumeArrayMode = false;
957 if( eTok == LPAREN )
959 if( bStandaloneExpression )
961 bAssumeExprLParenMode = true;
963 else
965 pExprList->bBracket = true;
966 pParser->Next();
967 eTok = pParser->Peek();
972 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
974 if( eTok == RPAREN )
976 pParser->Next();
978 return pExprList;
980 // read in parameter table and lay down in correct order!
981 while( !pExprList->bError )
983 std::unique_ptr<SbiExpression> pExpr;
984 // missing argument
985 if( eTok == COMMA )
987 pExpr = o3tl::make_unique<SbiExpression>( pParser, 0, SbxEMPTY );
989 // named arguments: either .name= or name:=
990 else
992 bool bByVal = false;
993 if( eTok == BYVAL )
995 bByVal = true;
996 pParser->Next();
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;
1017 eTok = NIL;
1019 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1021 pExprList->bBracket = true;
1022 return pExprList;
1025 else
1027 pExpr = o3tl::make_unique<SbiExpression>( pParser );
1029 if( bByVal && pExpr->IsLvalue() )
1031 pExpr->SetByVal();
1033 if( !bAssumeArrayMode )
1035 OUString aName;
1036 if( pParser->Peek() == ASSIGN )
1038 // VBA mode: name:=
1039 // SbiExpression::Term() has made as string out of it
1040 aName = pExpr->GetString();
1041 pParser->Next();
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 )
1051 break;
1053 // next element?
1054 eTok = pParser->Peek();
1055 if( eTok != COMMA )
1057 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1059 break;
1061 pParser->Error( pExprList->bBracket ? ERRCODE_BASIC_BAD_BRACKETS : ERRCODE_BASIC_EXPECTED, COMMA );
1062 pExprList->bError = true;
1064 else
1066 pParser->Next();
1067 eTok = pParser->Peek();
1068 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1070 break;
1074 // closing bracket
1075 if( eTok == RPAREN )
1077 pParser->Next();
1078 pParser->Peek();
1079 if( !pExprList->bBracket )
1081 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1082 pExprList->bError = true;
1085 pExprList->nDim = pExprList->GetSize();
1086 return pExprList;
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 )
1103 SbiToken eTok;
1104 for( ;; )
1106 auto pExpr1 = o3tl::make_unique<SbiExpression>( pParser );
1107 eTok = pParser->Next();
1108 if( eTok == TO )
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));
1118 else
1120 pExpr1->SetBased();
1121 pExpr1->ConvertToIntConstIfPossible();
1122 pExprList->bError = pExprList->bError || !pExpr1->IsValid();
1123 pExprList->aData.push_back(std::move(pExpr1));
1125 pExprList->nDim++;
1126 if( eTok == RPAREN ) break;
1127 if( eTok != COMMA )
1129 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1130 pParser->Next();
1131 break;
1135 else pParser->Next();
1136 return pExprList;
1139 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */