nss: upgrade to release 3.73
[LibreOffice.git] / basic / source / comp / exprtree.cxx
blob38b9adeb98004311b7d2abe4480b26928518940f
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/sberrors.hxx>
24 #include <basic/sbmod.hxx>
25 #include <comphelper/SetFlagContextHelper.hxx>
26 #include <expr.hxx>
28 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
29 SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
31 pParser = p;
32 bBased = bError = bByVal = bBracket = false;
33 nParenLevel = 0;
34 eCurExpr = t;
35 m_eMode = eMode;
36 pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean();
37 if( t != SbSYMBOL )
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 )
53 pParser = p;
54 bBased = bError = bByVal = bBracket = false;
55 nParenLevel = 0;
56 eCurExpr = SbOPERAND;
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 )
64 pParser = p;
65 bBased = bError = bByVal = bBracket = false;
66 nParenLevel = 0;
67 eCurExpr = SbOPERAND;
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 )
85 if( eTok == LPAREN )
87 return true;
89 // but only if similar to CALL!
90 if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
92 return false;
94 if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
95 eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL )
97 return true;
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
103 tokens.Next();
104 if ( tokens.Peek() == ASSIGN )
106 return true;
109 return false;
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 )
117 SbiSymDef* pDef;
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 )
135 bHasType = true;
137 pDef = pProc;
138 pDef->SetType( bHasType ? eType : SbxEMPTY );
139 if( pPar )
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 );
149 else
151 // or a normal symbol
152 pDef = rPool.AddSym( rName );
153 pDef->SetType( eType );
155 return pDef;
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;
168 if( !pDef )
170 pParser->Next();
172 else
174 pNd = ObjTerm( *pDef );
175 if( pNd )
177 pNd->SetWithParent( pWithVar );
180 if( !pNd )
182 pParser->Error( ERRCODE_BASIC_UNEXPECTED, DOT );
183 pNd = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE );
185 return pNd;
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;
193 SbiExprListPtr pPar;
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 );
210 bError = true;
213 eTok = eNextTok;
214 if( DoParametersFollow( pParser, eCurExpr, eTok ) )
216 bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
217 pPar = SbiExprList::ParseParameters( pParser, bStandaloneExpression );
218 bError = bError || !pPar->IsValid();
219 if( !bError )
220 bBracket = pPar->IsBracket();
221 eTok = pParser->Peek();
223 // i75443 check for additional sets of parameters
224 while( eTok == LPAREN )
226 if( pvMoreParLcl == nullptr )
228 pvMoreParLcl.reset(new SbiExprListVector);
230 SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser );
231 bError = bError || !pAddPar->IsValid();
232 pvMoreParLcl->push_back( std::move(pAddPar) );
233 eTok = pParser->Peek();
236 // It might be an object part, if . or ! is following.
237 // In case of . the variable must already be defined;
238 // it's an object, if pDef is NULL after the search.
239 bool bObj = ( ( eTok == DOT || eTok == EXCLAM )
240 && !pParser->WhiteSpace() );
241 if( bObj )
243 bBracket = false; // Now the bracket for the first term is obsolete
244 if( eType == SbxVARIANT )
246 eType = SbxOBJECT;
248 else
250 // Name%. really does not work!
251 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
252 bError = true;
255 // Search:
256 SbiSymDef* pDef = pParser->pPool->Find( aSym );
257 if( !pDef )
259 // Part of the Runtime-Library?
260 // from 31.3.1996: swapped out to parser-method
261 // (is also needed in SbiParser::DefVar() in DIM.CXX)
262 pDef = pParser->CheckRTLForSym( aSym, eType );
264 // #i109184: Check if symbol is or later will be defined inside module
265 SbModule& rMod = pParser->aGen.GetModule();
266 if( rMod.FindMethod( aSym, SbxClassType::DontCare ) )
268 pDef = nullptr;
271 if( !pDef )
273 if( bObj )
275 eType = SbxOBJECT;
277 pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar.get() );
278 // Looks like this is a local ( but undefined variable )
279 // if it is in a static procedure then make this Symbol
280 // static
281 if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
283 pDef->SetStatic();
286 else
289 SbiConstDef* pConst = pDef->GetConstDef();
290 if( pConst )
292 pPar = nullptr;
293 pvMoreParLcl.reset();
294 if( pConst->GetType() == SbxSTRING )
296 return std::make_unique<SbiExprNode>( pConst->GetString() );
298 else
300 return std::make_unique<SbiExprNode>( pConst->GetValue(), pConst->GetType() );
304 // 0 parameters come up to ()
305 if( pDef->GetDims() )
307 if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
309 pParser->Error( ERRCODE_BASIC_WRONG_DIMS );
312 if( pDef->IsDefinedAs() )
314 SbxDataType eDefType = pDef->GetType();
315 // #119187 Only error if types conflict
316 if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
318 // How? Define with AS first and take a Suffix then?
319 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
320 bError = true;
322 else if ( eType == SbxVARIANT )
324 // if there's nothing named, take the type of the entry,
325 // but only if the var hasn't been defined with AS XXX
326 // so that we catch n% = 5 : print n
327 eType = eDefType;
330 // checking type of variables:
331 // is there named anything different in the scanner?
332 // That's OK for methods!
333 if( eType != SbxVARIANT && // Variant takes everything
334 eType != pDef->GetType() &&
335 !pDef->GetProcDef() )
337 // maybe pDef describes an object that so far has only been
338 // recognized as SbxVARIANT - then change type of pDef
339 // from 16.12.95 (similar cases possible perhaps?!?)
340 if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
342 pDef->SetType( SbxOBJECT );
344 else
346 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
347 bError = true;
351 auto pNd = std::make_unique<SbiExprNode>( *pDef, eType );
352 if( !pPar )
354 pPar = SbiExprList::ParseParameters( pParser,false,false );
356 pNd->aVar.pPar = pPar.release();
357 pNd->aVar.pvMorePar = pvMoreParLcl.release();
358 if( bObj )
360 // from 8.1.95: Object may also be of the type SbxVARIANT
361 if( pDef->GetType() == SbxVARIANT )
362 pDef->SetType( SbxOBJECT );
363 // if we scan something with point,
364 // the type must be SbxOBJECT
365 if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
367 // defer error until runtime if in vba mode
368 if ( !pParser->IsVBASupportOn() )
370 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
371 bError = true;
374 if( !bError )
376 pNd->aVar.pNext = ObjTerm( *pDef ).release();
380 pParser->UnlockColumn();
381 return pNd;
384 // construction of an object term. A term of this kind is part
385 // of an expression that begins with an object variable.
387 std::unique_ptr<SbiExprNode> SbiExpression::ObjTerm( SbiSymDef& rObj )
389 pParser->Next();
390 SbiToken eTok = pParser->Next();
391 if( eTok != SYMBOL && !SbiTokenizer::IsKwd( eTok ) && !SbiTokenizer::IsExtra( eTok ) )
393 // #66745 Some operators can also be allowed
394 // as identifiers, important for StarOne
395 if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
396 eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
398 pParser->Error( ERRCODE_BASIC_VAR_EXPECTED );
399 bError = true;
403 if( bError )
405 return nullptr;
407 OUString aSym( pParser->GetSym() );
408 SbxDataType eType = pParser->GetType();
409 SbiExprListPtr pPar;
410 SbiExprListVector* pvMoreParLcl = nullptr;
411 eTok = pParser->Peek();
413 if( DoParametersFollow( pParser, eCurExpr, eTok ) )
415 pPar = SbiExprList::ParseParameters( pParser, false/*bStandaloneExpression*/ );
416 bError = bError || !pPar->IsValid();
417 eTok = pParser->Peek();
419 // i109624 check for additional sets of parameters
420 while( eTok == LPAREN )
422 if( pvMoreParLcl == nullptr )
424 pvMoreParLcl = new SbiExprListVector;
426 SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser );
427 bError = bError || !pPar->IsValid();
428 pvMoreParLcl->push_back( std::move(pAddPar) );
429 eTok = pParser->Peek();
432 bool bObj = ( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
433 if( bObj )
435 if( eType == SbxVARIANT )
437 eType = SbxOBJECT;
439 else
441 // Name%. does really not work!
442 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
443 bError = true;
447 // an object's symbol pool is always PUBLIC
448 SbiSymPool& rPool = rObj.GetPool();
449 rPool.SetScope( SbPUBLIC );
450 SbiSymDef* pDef = rPool.Find( aSym );
451 if( !pDef )
453 pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar.get() );
454 pDef->SetType( eType );
457 auto pNd = std::make_unique<SbiExprNode>( *pDef, eType );
458 pNd->aVar.pPar = pPar.release();
459 pNd->aVar.pvMorePar = pvMoreParLcl;
460 if( bObj )
462 if( pDef->GetType() == SbxVARIANT )
464 pDef->SetType( SbxOBJECT );
466 if( pDef->GetType() != SbxOBJECT )
468 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
469 bError = true;
471 if( !bError )
473 pNd->aVar.pNext = ObjTerm( *pDef ).release();
474 pNd->eType = eType;
477 return pNd;
480 // an operand can be:
481 // constant
482 // scalar variable
483 // structure elements
484 // array elements
485 // functions
486 // bracketed expressions
488 std::unique_ptr<SbiExprNode> SbiExpression::Operand( bool bUsedForTypeOf )
490 std::unique_ptr<SbiExprNode> pRes;
492 // test operand:
493 switch( SbiToken eTok = pParser->Peek() )
495 case SYMBOL:
496 pRes = Term();
497 // process something like "IF Not r Is Nothing Then .."
498 if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
500 eTok = pParser->Next();
501 pRes = std::make_unique<SbiExprNode>( std::move(pRes), eTok, Like() );
503 break;
504 case DOT: // .with
505 pRes = Term(); break;
506 case NOT:
507 pRes = VBA_Not();
508 break;
509 case NUMBER:
510 pParser->Next();
511 pRes = std::make_unique<SbiExprNode>( pParser->GetDbl(), pParser->GetType() );
512 break;
513 case FIXSTRING:
514 pParser->Next();
515 pRes = std::make_unique<SbiExprNode>( pParser->GetSym() ); break;
516 case LPAREN:
517 pParser->Next();
518 if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
520 m_eMode = EXPRMODE_EMPTY_PAREN;
521 pRes = std::make_unique<SbiExprNode>(); // Dummy node
522 pParser->Next();
523 break;
525 nParenLevel++;
526 pRes = Boolean();
527 if( pParser->Peek() != RPAREN )
529 // If there was a LPARAM, it does not belong to the expression
530 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
532 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
534 else
536 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
539 else
541 pParser->Next();
542 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
544 SbiToken eTokAfterRParen = pParser->Peek();
545 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
547 m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
549 else
551 m_eMode = EXPRMODE_STANDARD;
555 nParenLevel--;
556 break;
557 default:
558 // keywords here are OK at the moment!
559 if( SbiTokenizer::IsKwd( eTok ) )
561 pRes = Term();
563 else
565 pParser->Next();
566 pRes = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE );
567 pParser->Error( ERRCODE_BASIC_UNEXPECTED, eTok );
569 break;
571 return pRes;
574 std::unique_ptr<SbiExprNode> SbiExpression::Unary()
576 std::unique_ptr<SbiExprNode> pNd;
577 SbiToken eTok = pParser->Peek();
578 switch( eTok )
580 case MINUS:
581 eTok = NEG;
582 pParser->Next();
583 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr );
584 break;
585 case NOT:
586 if( pParser->IsVBASupportOn() )
588 pNd = Operand();
590 else
592 pParser->Next();
593 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr );
595 break;
596 case PLUS:
597 pParser->Next();
598 pNd = Unary();
599 break;
600 case TYPEOF:
602 pParser->Next();
603 std::unique_ptr<SbiExprNode> pObjNode = Operand( true/*bUsedForTypeOf*/ );
604 pParser->TestToken( IS );
605 SbiSymDef* pTypeDef = new SbiSymDef( OUString() );
606 pParser->TypeDecl( *pTypeDef, true );
607 pNd = std::make_unique<SbiExprNode>( std::move(pObjNode), pTypeDef->GetTypeId() );
608 break;
610 case NEW:
612 pParser->Next();
613 SbiSymDef* pTypeDef = new SbiSymDef( OUString() );
614 pParser->TypeDecl( *pTypeDef, true );
615 pNd = std::make_unique<SbiExprNode>( pTypeDef->GetTypeId() );
616 break;
618 default:
619 pNd = Operand();
621 return pNd;
624 std::unique_ptr<SbiExprNode> SbiExpression::Exp()
626 std::unique_ptr<SbiExprNode> pNd = Unary();
627 if( m_eMode != EXPRMODE_EMPTY_PAREN )
629 while( pParser->Peek() == EXPON )
631 SbiToken eTok = pParser->Next();
632 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Unary() );
635 return pNd;
638 std::unique_ptr<SbiExprNode> SbiExpression::MulDiv()
640 std::unique_ptr<SbiExprNode> pNd = Exp();
641 if( m_eMode != EXPRMODE_EMPTY_PAREN )
643 for( ;; )
645 SbiToken eTok = pParser->Peek();
646 if( eTok != MUL && eTok != DIV )
648 break;
650 eTok = pParser->Next();
651 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Exp() );
654 return pNd;
657 std::unique_ptr<SbiExprNode> SbiExpression::IntDiv()
659 std::unique_ptr<SbiExprNode> pNd = MulDiv();
660 if( m_eMode != EXPRMODE_EMPTY_PAREN )
662 while( pParser->Peek() == IDIV )
664 SbiToken eTok = pParser->Next();
665 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, MulDiv() );
668 return pNd;
671 std::unique_ptr<SbiExprNode> SbiExpression::Mod()
673 std::unique_ptr<SbiExprNode> pNd = IntDiv();
674 if( m_eMode != EXPRMODE_EMPTY_PAREN )
676 while( pParser->Peek() == MOD )
678 SbiToken eTok = pParser->Next();
679 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, IntDiv() );
682 return pNd;
685 std::unique_ptr<SbiExprNode> SbiExpression::AddSub()
687 std::unique_ptr<SbiExprNode> pNd = Mod();
688 if( m_eMode != EXPRMODE_EMPTY_PAREN )
690 for( ;; )
692 SbiToken eTok = pParser->Peek();
693 if( eTok != PLUS && eTok != MINUS )
695 break;
697 eTok = pParser->Next();
698 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Mod() );
701 return pNd;
704 std::unique_ptr<SbiExprNode> SbiExpression::Cat()
706 std::unique_ptr<SbiExprNode> pNd = AddSub();
707 if( m_eMode != EXPRMODE_EMPTY_PAREN )
709 for( ;; )
711 SbiToken eTok = pParser->Peek();
712 if( eTok != CAT )
714 break;
716 eTok = pParser->Next();
717 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, AddSub() );
720 return pNd;
723 std::unique_ptr<SbiExprNode> SbiExpression::Comp()
725 std::unique_ptr<SbiExprNode> pNd = Cat();
726 if( m_eMode != EXPRMODE_EMPTY_PAREN )
728 short nCount = 0;
729 for( ;; )
731 SbiToken eTok = pParser->Peek();
732 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
734 break;
736 if( eTok != EQ && eTok != NE && eTok != LT &&
737 eTok != GT && eTok != LE && eTok != GE )
739 break;
741 eTok = pParser->Next();
742 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Cat() );
743 nCount++;
746 return pNd;
750 std::unique_ptr<SbiExprNode> SbiExpression::VBA_Not()
752 std::unique_ptr<SbiExprNode> pNd;
754 SbiToken eTok = pParser->Peek();
755 if( eTok == NOT )
757 pParser->Next();
758 pNd = std::make_unique<SbiExprNode>( VBA_Not(), eTok, nullptr );
760 else
762 pNd = Comp();
764 return pNd;
767 std::unique_ptr<SbiExprNode> SbiExpression::Like()
769 std::unique_ptr<SbiExprNode> pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
770 if( m_eMode != EXPRMODE_EMPTY_PAREN )
772 short nCount = 0;
773 while( pParser->Peek() == LIKE )
775 SbiToken eTok = pParser->Next();
776 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Comp() );
777 nCount++;
779 // multiple operands in a row does not work
780 if( nCount > 1 && !pParser->IsVBASupportOn() )
782 pParser->Error( ERRCODE_BASIC_SYNTAX );
783 bError = true;
786 return pNd;
789 std::unique_ptr<SbiExprNode> SbiExpression::Boolean()
791 std::unique_ptr<SbiExprNode> pNd = Like();
792 if( m_eMode != EXPRMODE_EMPTY_PAREN )
794 for( ;; )
796 SbiToken eTok = pParser->Peek();
797 if( (eTok != AND) && (eTok != OR) &&
798 (eTok != XOR) && (eTok != EQV) &&
799 (eTok != IMP) && (eTok != IS) )
801 break;
803 eTok = pParser->Next();
804 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Like() );
807 return pNd;
810 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
812 if( pExpr->IsConstant() )
814 eType = pExpr->GetType();
815 if( pExpr->IsNumber() )
817 nVal = pExpr->nVal;
819 else
821 nVal = 0;
822 aVal = pExpr->aStrVal;
825 else
827 // #40204 special treatment for sal_Bool-constants
828 bool bIsBool = false;
829 if( pExpr->eNodeType == SbxVARVAL )
831 SbiSymDef* pVarDef = pExpr->GetVar();
833 bool bBoolVal = false;
834 if( pVarDef->GetName().equalsIgnoreAsciiCase( "true" ) )
836 bIsBool = true;
837 bBoolVal = true;
839 else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
840 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
842 bIsBool = true;
843 bBoolVal = false;
846 if( bIsBool )
848 pExpr = std::make_unique<SbiExprNode>( (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
849 eType = pExpr->GetType();
850 nVal = pExpr->nVal;
854 if( !bIsBool )
856 pParser->Error( ERRCODE_BASIC_SYNTAX );
857 eType = SbxDOUBLE;
858 nVal = 0;
863 short SbiConstExpression::GetShortValue()
865 if( eType == SbxSTRING )
867 SbxVariableRef refConv = new SbxVariable;
868 refConv->PutString( aVal );
869 return refConv->GetInteger();
871 else
873 double n = nVal;
874 if( n > 0 )
876 n += .5;
878 else
880 n -= .5;
882 if( n > SbxMAXINT )
884 n = SbxMAXINT;
885 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
887 else if( n < SbxMININT )
889 n = SbxMININT;
890 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
893 return static_cast<short>(n);
898 SbiExprList::SbiExprList( )
900 nDim = 0;
901 bError = false;
902 bBracket = false;
905 SbiExprList::~SbiExprList() {}
907 SbiExpression* SbiExprList::Get( size_t n )
909 return aData[n].get();
912 void SbiExprList::addExpression( std::unique_ptr<SbiExpression>&& pExpr )
914 aData.push_back(std::move(pExpr));
917 // the parameter list is completely parsed
918 // "procedurename()" is OK
919 // it's a function without parameters then
920 // i. e. you give an array as procedure parameter
922 // #i79918/#i80532: bConst has never been set to true
923 // -> reused as bStandaloneExpression
924 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
925 SbiExprListPtr SbiExprList::ParseParameters( SbiParser* pParser, bool bStandaloneExpression, bool bPar)
927 auto pExprList = std::make_unique<SbiExprList>();
928 if( !bPar )
930 return pExprList;
933 SbiToken eTok = pParser->Peek();
935 bool bAssumeExprLParenMode = false;
936 bool bAssumeArrayMode = false;
937 if( eTok == LPAREN )
939 if( bStandaloneExpression )
941 bAssumeExprLParenMode = true;
943 else
945 pExprList->bBracket = true;
946 pParser->Next();
947 eTok = pParser->Peek();
952 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
954 if( eTok == RPAREN )
956 pParser->Next();
958 return pExprList;
960 // read in parameter table and lay down in correct order!
961 while( !pExprList->bError )
963 std::unique_ptr<SbiExpression> pExpr;
964 // missing argument
965 if( eTok == COMMA )
967 pExpr = std::make_unique<SbiExpression>( pParser, 0, SbxEMPTY );
969 // named arguments: either .name= or name:=
970 else
972 bool bByVal = false;
973 if( eTok == BYVAL )
975 bByVal = true;
976 pParser->Next();
977 eTok = pParser->Peek();
980 if( bAssumeExprLParenMode )
982 pExpr = std::make_unique<SbiExpression>( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
983 bAssumeExprLParenMode = false;
985 SbiExprMode eModeAfter = pExpr->m_eMode;
986 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
988 pExprList->bBracket = true;
990 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
992 // Expression "looks" like an array assignment
993 // a(...)[(...)] = ? or a(...).b(...)
994 // RPAREN is already parsed
995 pExprList->bBracket = true;
996 bAssumeArrayMode = true;
997 eTok = NIL;
999 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1001 pExprList->bBracket = true;
1002 return pExprList;
1005 else
1007 pExpr = std::make_unique<SbiExpression>( pParser );
1009 if( bByVal && pExpr->IsLvalue() )
1011 pExpr->SetByVal();
1013 if( !bAssumeArrayMode )
1015 OUString aName;
1016 if( pParser->Peek() == ASSIGN )
1018 // VBA mode: name:=
1019 // SbiExpression::Term() has made as string out of it
1020 aName = pExpr->GetString();
1021 pParser->Next();
1022 pExpr = std::make_unique<SbiExpression>( pParser );
1024 pExpr->GetName() = aName;
1027 pExprList->bError = pExprList->bError || !pExpr->IsValid();
1028 pExprList->aData.push_back(std::move(pExpr));
1029 if( bAssumeArrayMode )
1031 break;
1033 // next element?
1034 eTok = pParser->Peek();
1035 if( eTok != COMMA )
1037 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1039 // tdf#80731
1040 if (SbiTokenizer::IsEoln(eTok) && pExprList->bBracket)
1042 // tdf#106529: only fail here in strict mode (i.e. when compiled from IDE), and
1043 // allow legacy code with missing closing parenthesis when started e.g. from
1044 // extensions and event handlers
1045 if (comphelper::IsContextFlagActive("BasicStrict"))
1047 pParser->Error(ERRCODE_BASIC_EXPECTED, RPAREN);
1048 pExprList->bError = true;
1051 break;
1053 pParser->Error( pExprList->bBracket ? ERRCODE_BASIC_BAD_BRACKETS : ERRCODE_BASIC_EXPECTED, COMMA );
1054 pExprList->bError = true;
1056 else
1058 pParser->Next();
1059 eTok = pParser->Peek();
1060 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1062 break;
1066 // closing bracket
1067 if( eTok == RPAREN )
1069 pParser->Next();
1070 pParser->Peek();
1071 if( !pExprList->bBracket )
1073 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1074 pExprList->bError = true;
1077 pExprList->nDim = pExprList->GetSize();
1078 return pExprList;
1081 // A list of array dimensions is parsed.
1083 SbiExprListPtr SbiExprList::ParseDimList( SbiParser* pParser )
1085 auto pExprList = std::make_unique<SbiExprList>();
1087 if( pParser->Next() != LPAREN )
1089 pParser->Error( ERRCODE_BASIC_EXPECTED, LPAREN );
1090 pExprList->bError = true; return pExprList;
1093 if( pParser->Peek() != RPAREN )
1095 SbiToken eTok;
1096 for( ;; )
1098 auto pExpr1 = std::make_unique<SbiExpression>( pParser );
1099 eTok = pParser->Next();
1100 if( eTok == TO )
1102 auto pExpr2 = std::make_unique<SbiExpression>( pParser );
1103 pExpr1->ConvertToIntConstIfPossible();
1104 pExpr2->ConvertToIntConstIfPossible();
1105 eTok = pParser->Next();
1106 pExprList->bError = pExprList->bError || !pExpr1->IsValid() || !pExpr2->IsValid();
1107 pExprList->aData.push_back(std::move(pExpr1));
1108 pExprList->aData.push_back(std::move(pExpr2));
1110 else
1112 pExpr1->SetBased();
1113 pExpr1->ConvertToIntConstIfPossible();
1114 pExprList->bError = pExprList->bError || !pExpr1->IsValid();
1115 pExprList->aData.push_back(std::move(pExpr1));
1117 pExprList->nDim++;
1118 if( eTok == RPAREN ) break;
1119 if( eTok != COMMA )
1121 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1122 pParser->Next();
1123 break;
1127 else pParser->Next();
1128 return pExprList;
1131 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */