Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / basic / source / comp / exprtree.cxx
blob4fe389983d28bf7641c819545f2fe9f1e5225c1b
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 <expr.hxx>
26 #include <uno/current_context.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 if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
215 bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
216 pPar = SbiExprList::ParseParameters( pParser, bStandaloneExpression );
217 bError = bError || !pPar->IsValid();
218 if( !bError )
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() );
240 if( bObj )
242 bBracket = false; // Now the bracket for the first term is obsolete
243 if( eType == SbxVARIANT )
245 eType = SbxOBJECT;
247 else
249 // Name%. really does not work!
250 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
251 bError = true;
254 // Search:
255 SbiSymDef* pDef = pParser->pPool->Find( aSym );
256 if( !pDef )
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 ) )
267 pDef = nullptr;
270 if( !pDef )
272 if( bObj )
274 eType = SbxOBJECT;
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
279 // static
280 if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
282 pDef->SetStatic();
285 else
288 SbiConstDef* pConst = pDef->GetConstDef();
289 if( pConst )
291 pPar = nullptr;
292 pvMoreParLcl.reset();
293 if( pConst->GetType() == SbxSTRING )
295 return std::make_unique<SbiExprNode>( pConst->GetString() );
297 else
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 );
319 bError = true;
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
326 eType = eDefType;
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 );
343 else
345 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
346 bError = true;
350 std::unique_ptr<SbiExprNode> pNd(new SbiExprNode( *pDef, eType ));
351 if( !pPar )
353 pPar = SbiExprList::ParseParameters( pParser,false,false );
355 pNd->aVar.pPar = pPar.release();
356 pNd->aVar.pvMorePar = pvMoreParLcl.release();
357 if( bObj )
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 );
370 bError = true;
373 if( !bError )
375 pNd->aVar.pNext = ObjTerm( *pDef ).release();
379 pParser->UnlockColumn();
380 return pNd;
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 )
388 pParser->Next();
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 );
398 bError = true;
402 if( bError )
404 return nullptr;
406 OUString aSym( pParser->GetSym() );
407 SbxDataType eType = pParser->GetType();
408 SbiExprListPtr pPar;
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() );
432 if( bObj )
434 if( eType == SbxVARIANT )
436 eType = SbxOBJECT;
438 else
440 // Name%. does really not work!
441 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
442 bError = true;
446 // an object's symbol pool is always PUBLIC
447 SbiSymPool& rPool = rObj.GetPool();
448 rPool.SetScope( SbPUBLIC );
449 SbiSymDef* pDef = rPool.Find( aSym );
450 if( !pDef )
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;
459 if( bObj )
461 if( pDef->GetType() == SbxVARIANT )
463 pDef->SetType( SbxOBJECT );
465 if( pDef->GetType() != SbxOBJECT )
467 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
468 bError = true;
470 if( !bError )
472 pNd->aVar.pNext = ObjTerm( *pDef ).release();
473 pNd->eType = eType;
476 return pNd;
479 // an operand can be:
480 // constant
481 // scalar variable
482 // structure elements
483 // array elements
484 // functions
485 // bracketed expressions
487 std::unique_ptr<SbiExprNode> SbiExpression::Operand( bool bUsedForTypeOf )
489 std::unique_ptr<SbiExprNode> pRes;
491 // test operand:
492 switch( SbiToken eTok = pParser->Peek() )
494 case SYMBOL:
495 pRes = Term();
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() );
502 break;
503 case DOT: // .with
504 pRes = Term(); break;
505 case NOT:
506 pRes = VBA_Not();
507 break;
508 case NUMBER:
509 pParser->Next();
510 pRes = std::make_unique<SbiExprNode>( pParser->GetDbl(), pParser->GetType() );
511 break;
512 case FIXSTRING:
513 pParser->Next();
514 pRes = std::make_unique<SbiExprNode>( pParser->GetSym() ); break;
515 case LPAREN:
516 pParser->Next();
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
521 pParser->Next();
522 break;
524 nParenLevel++;
525 pRes = Boolean();
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;
533 else
535 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
538 else
540 pParser->Next();
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;
548 else
550 m_eMode = EXPRMODE_STANDARD;
554 nParenLevel--;
555 break;
556 default:
557 // keywords here are OK at the moment!
558 if( SbiTokenizer::IsKwd( eTok ) )
560 pRes = Term();
562 else
564 pParser->Next();
565 pRes = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE );
566 pParser->Error( ERRCODE_BASIC_UNEXPECTED, eTok );
568 break;
570 return pRes;
573 std::unique_ptr<SbiExprNode> SbiExpression::Unary()
575 std::unique_ptr<SbiExprNode> pNd;
576 SbiToken eTok = pParser->Peek();
577 switch( eTok )
579 case MINUS:
580 eTok = NEG;
581 pParser->Next();
582 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr );
583 break;
584 case NOT:
585 if( pParser->IsVBASupportOn() )
587 pNd = Operand();
589 else
591 pParser->Next();
592 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr );
594 break;
595 case PLUS:
596 pParser->Next();
597 pNd = Unary();
598 break;
599 case TYPEOF:
601 pParser->Next();
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() );
607 break;
609 case NEW:
611 pParser->Next();
612 SbiSymDef* pTypeDef = new SbiSymDef( OUString() );
613 pParser->TypeDecl( *pTypeDef, true );
614 pNd = std::make_unique<SbiExprNode>( pTypeDef->GetTypeId() );
615 break;
617 default:
618 pNd = Operand();
620 return pNd;
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() );
634 return pNd;
637 std::unique_ptr<SbiExprNode> SbiExpression::MulDiv()
639 std::unique_ptr<SbiExprNode> pNd = Exp();
640 if( m_eMode != EXPRMODE_EMPTY_PAREN )
642 for( ;; )
644 SbiToken eTok = pParser->Peek();
645 if( eTok != MUL && eTok != DIV )
647 break;
649 eTok = pParser->Next();
650 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Exp() );
653 return pNd;
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() );
667 return pNd;
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() );
681 return pNd;
684 std::unique_ptr<SbiExprNode> SbiExpression::AddSub()
686 std::unique_ptr<SbiExprNode> pNd = Mod();
687 if( m_eMode != EXPRMODE_EMPTY_PAREN )
689 for( ;; )
691 SbiToken eTok = pParser->Peek();
692 if( eTok != PLUS && eTok != MINUS )
694 break;
696 eTok = pParser->Next();
697 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Mod() );
700 return pNd;
703 std::unique_ptr<SbiExprNode> SbiExpression::Cat()
705 std::unique_ptr<SbiExprNode> pNd = AddSub();
706 if( m_eMode != EXPRMODE_EMPTY_PAREN )
708 for( ;; )
710 SbiToken eTok = pParser->Peek();
711 if( eTok != CAT )
713 break;
715 eTok = pParser->Next();
716 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, AddSub() );
719 return pNd;
722 std::unique_ptr<SbiExprNode> SbiExpression::Comp()
724 std::unique_ptr<SbiExprNode> pNd = Cat();
725 if( m_eMode != EXPRMODE_EMPTY_PAREN )
727 short nCount = 0;
728 for( ;; )
730 SbiToken eTok = pParser->Peek();
731 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
733 break;
735 if( eTok != EQ && eTok != NE && eTok != LT &&
736 eTok != GT && eTok != LE && eTok != GE )
738 break;
740 eTok = pParser->Next();
741 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Cat() );
742 nCount++;
745 return pNd;
749 std::unique_ptr<SbiExprNode> SbiExpression::VBA_Not()
751 std::unique_ptr<SbiExprNode> pNd;
753 SbiToken eTok = pParser->Peek();
754 if( eTok == NOT )
756 pParser->Next();
757 pNd = std::make_unique<SbiExprNode>( VBA_Not(), eTok, nullptr );
759 else
761 pNd = Comp();
763 return pNd;
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 )
771 short nCount = 0;
772 while( pParser->Peek() == LIKE )
774 SbiToken eTok = pParser->Next();
775 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Comp() );
776 nCount++;
778 // multiple operands in a row does not work
779 if( nCount > 1 && !pParser->IsVBASupportOn() )
781 pParser->Error( ERRCODE_BASIC_SYNTAX );
782 bError = true;
785 return pNd;
788 std::unique_ptr<SbiExprNode> SbiExpression::Boolean()
790 std::unique_ptr<SbiExprNode> pNd = Like();
791 if( m_eMode != EXPRMODE_EMPTY_PAREN )
793 for( ;; )
795 SbiToken eTok = pParser->Peek();
796 if( (eTok != AND) && (eTok != OR) &&
797 (eTok != XOR) && (eTok != EQV) &&
798 (eTok != IMP) && (eTok != IS) )
800 break;
802 eTok = pParser->Next();
803 pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Like() );
806 return pNd;
809 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
811 if( pExpr->IsConstant() )
813 eType = pExpr->GetType();
814 if( pExpr->IsNumber() )
816 nVal = pExpr->nVal;
818 else
820 nVal = 0;
821 aVal = pExpr->aStrVal;
824 else
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" ) )
835 bIsBool = true;
836 bBoolVal = true;
838 else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
839 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
841 bIsBool = true;
842 bBoolVal = false;
845 if( bIsBool )
847 pExpr = std::make_unique<SbiExprNode>( (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
848 eType = pExpr->GetType();
849 nVal = pExpr->nVal;
853 if( !bIsBool )
855 pParser->Error( ERRCODE_BASIC_SYNTAX );
856 eType = SbxDOUBLE;
857 nVal = 0;
862 short SbiConstExpression::GetShortValue()
864 if( eType == SbxSTRING )
866 SbxVariableRef refConv = new SbxVariable;
867 refConv->PutString( aVal );
868 return refConv->GetInteger();
870 else
872 double n = nVal;
873 if( n > 0 )
875 n += .5;
877 else
879 n -= .5;
881 if( n > SbxMAXINT )
883 n = SbxMAXINT;
884 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
886 else if( n < SbxMININT )
888 n = SbxMININT;
889 pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
892 return static_cast<short>(n);
897 SbiExprList::SbiExprList( )
899 nDim = 0;
900 bError = false;
901 bBracket = false;
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>();
927 if( !bPar )
929 return pExprList;
932 SbiToken eTok = pParser->Peek();
934 bool bAssumeExprLParenMode = false;
935 bool bAssumeArrayMode = false;
936 if( eTok == LPAREN )
938 if( bStandaloneExpression )
940 bAssumeExprLParenMode = true;
942 else
944 pExprList->bBracket = true;
945 pParser->Next();
946 eTok = pParser->Peek();
951 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
953 if( eTok == RPAREN )
955 pParser->Next();
957 return pExprList;
959 // read in parameter table and lay down in correct order!
960 while( !pExprList->bError )
962 std::unique_ptr<SbiExpression> pExpr;
963 // missing argument
964 if( eTok == COMMA )
966 pExpr = std::make_unique<SbiExpression>( pParser, 0, SbxEMPTY );
968 // named arguments: either .name= or name:=
969 else
971 bool bByVal = false;
972 if( eTok == BYVAL )
974 bByVal = true;
975 pParser->Next();
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;
996 eTok = NIL;
998 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1000 pExprList->bBracket = true;
1001 return pExprList;
1004 else
1006 pExpr = std::make_unique<SbiExpression>( pParser );
1008 if( bByVal && pExpr->IsLvalue() )
1010 pExpr->SetByVal();
1012 if( !bAssumeArrayMode )
1014 OUString aName;
1015 if( pParser->Peek() == ASSIGN )
1017 // VBA mode: name:=
1018 // SbiExpression::Term() has made as string out of it
1019 aName = pExpr->GetString();
1020 pParser->Next();
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 )
1030 break;
1032 // next element?
1033 eTok = pParser->Peek();
1034 if( eTok != COMMA )
1036 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1038 // tdf#80731
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;
1047 if (bCheckStrict)
1049 pParser->Error(ERRCODE_BASIC_EXPECTED, RPAREN);
1050 pExprList->bError = true;
1053 break;
1055 pParser->Error( pExprList->bBracket ? ERRCODE_BASIC_BAD_BRACKETS : ERRCODE_BASIC_EXPECTED, COMMA );
1056 pExprList->bError = true;
1058 else
1060 pParser->Next();
1061 eTok = pParser->Peek();
1062 if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1064 break;
1068 // closing bracket
1069 if( eTok == RPAREN )
1071 pParser->Next();
1072 pParser->Peek();
1073 if( !pExprList->bBracket )
1075 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1076 pExprList->bError = true;
1079 pExprList->nDim = pExprList->GetSize();
1080 return pExprList;
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 )
1097 SbiToken eTok;
1098 for( ;; )
1100 auto pExpr1 = std::make_unique<SbiExpression>( pParser );
1101 eTok = pParser->Next();
1102 if( eTok == TO )
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));
1112 else
1114 pExpr1->SetBased();
1115 pExpr1->ConvertToIntConstIfPossible();
1116 pExprList->bError = pExprList->bError || !pExpr1->IsValid();
1117 pExprList->aData.push_back(std::move(pExpr1));
1119 pExprList->nDim++;
1120 if( eTok == RPAREN ) break;
1121 if( eTok != COMMA )
1123 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1124 pParser->Next();
1125 break;
1129 else pParser->Next();
1130 return pExprList;
1133 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */