xref: /core/basic/source/comp/exprtree.cxx (revision 7ddedd25)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
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>
27 
28 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
29     SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
30 {
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 )
38     {
39         pExpr->Optimize(pParser);
40     }
41     if( t == SbLVALUE && !pExpr->IsLvalue() )
42     {
43         p->Error( ERRCODE_BASIC_LVALUE_EXPECTED );
44     }
45     if( t == SbOPERAND && !IsVariable() )
46     {
47         p->Error( ERRCODE_BASIC_VAR_EXPECTED );
48     }
49 }
50 
51 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t )
52 {
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);
60 }
61 
62 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprListPtr pPar )
63 {
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) );
70 }
71 
72 SbiExpression::~SbiExpression() { }
73 
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.
79 
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)
82 
83 static bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
84 {
85     if( eTok == LPAREN )
86     {
87         return true;
88     }
89     // but only if similar to CALL!
90     if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
91     {
92         return false;
93     }
94     if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
95          eTok == SYMBOL || eTok == COMMA  || eTok == DOT || eTok == NOT || eTok == BYVAL )
96     {
97         return true;
98     }
99     else // check for default params with reserved names ( e.g. names of tokens )
100     {
101         SbiTokenizer tokens( *static_cast<SbiTokenizer*>(p) );
102         // Urk the Next() / Peek() semantics are... weird
103         tokens.Next();
104         if ( tokens.Peek() == ASSIGN )
105         {
106             return true;
107         }
108     }
109     return false;
110 }
111 
112 // definition of a new symbol
113 
114 static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
115                            const OUString& rName, SbxDataType eType, const SbiExprList* pPar )
116 {
117     SbiSymDef* pDef;
118     // A= is not a procedure
119     bool bHasType = ( eTok == EQ || eTok == DOT );
120     if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
121     {
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 )
127         {
128             pPool = &rPool.GetParser()->aPublics;
129         }
130         SbiProcDef* pProc = pPool->AddProc( rName );
131 
132         // special treatment for Colls like Documents(1)
133         if( eCurExpr == SbSTDEXPR )
134         {
135             bHasType = true;
136         }
137         pDef = pProc;
138         pDef->SetType( bHasType ? eType : SbxEMPTY );
139         if( pPar )
140         {
141             // generate dummy parameters
142             for( sal_Int32 n = 1; n <= pPar->GetSize(); n++ )
143             {
144                 OUString aPar = "PAR" + OUString::number( n );
145                 pProc->GetParams().AddSym( aPar );
146             }
147         }
148     }
149     else
150     {
151         // or a normal symbol
152         pDef = rPool.AddSym( rName );
153         pDef->SetType( eType );
154     }
155     return pDef;
156 }
157 
158 // currently even keywords are allowed (because of Dflt properties of the same name)
159 
160 std::unique_ptr<SbiExprNode> SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
161 {
162     if( pParser->Peek() == DOT )
163     {
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 )
169         {
170             pParser->Next();
171         }
172         else
173         {
174             pNd = ObjTerm( *pDef );
175             if( pNd )
176             {
177                 pNd->SetWithParent( pWithVar );
178             }
179         }
180         if( !pNd )
181         {
182             pParser->Error( ERRCODE_BASIC_UNEXPECTED, DOT );
183             pNd = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE );
184         }
185         return pNd;
186     }
187 
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 )
201     {
202         pParser->UnlockColumn();
203         return std::make_unique<SbiExprNode>( aSym );
204     }
205     // no keywords allowed from here on!
206     if( SbiTokenizer::IsKwd( eTok )
207         && (!pParser->IsCompatible() || eTok != INPUT) )
208     {
209         pParser->Error( ERRCODE_BASIC_SYNTAX );
210         bError = true;
211     }
212 
213     if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
214     {
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();
221 
222         // i75443 check for additional sets of parameters
223         while( eTok == LPAREN )
224         {
225             if( pvMoreParLcl == nullptr )
226             {
227                 pvMoreParLcl.reset(new SbiExprListVector);
228             }
229             SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser );
230             bError = bError || !pAddPar->IsValid();
231             pvMoreParLcl->push_back( std::move(pAddPar) );
232             eTok = pParser->Peek();
233         }
234     }
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 )
241     {
242         bBracket = false;   // Now the bracket for the first term is obsolete
243         if( eType == SbxVARIANT )
244         {
245             eType = SbxOBJECT;
246         }
247         else
248         {
249             // Name%. really does not work!
250             pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
251             bError = true;
252         }
253     }
254     // Search:
255     SbiSymDef* pDef = pParser->pPool->Find( aSym );
256     if( !pDef )
257     {
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 );
262 
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 ) )
266         {
267             pDef = nullptr;
268         }
269     }
270     if( !pDef )
271     {
272         if( bObj )
273         {
274             eType = SbxOBJECT;
275         }
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() )
281         {
282             pDef->SetStatic();
283         }
284     }
285     else
286     {
287 
288         SbiConstDef* pConst = pDef->GetConstDef();
289         if( pConst )
290         {
291             pPar = nullptr;
292             pvMoreParLcl.reset();
293             if( pConst->GetType() == SbxSTRING )
294             {
295                 return std::make_unique<SbiExprNode>( pConst->GetString() );
296             }
297             else
298             {
299                 return std::make_unique<SbiExprNode>( pConst->GetValue(), pConst->GetType() );
300             }
301         }
302 
303         // 0 parameters come up to ()
304         if( pDef->GetDims() )
305         {
306             if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
307             {
308                 pParser->Error( ERRCODE_BASIC_WRONG_DIMS );
309             }
310         }
311         if( pDef->IsDefinedAs() )
312         {
313             SbxDataType eDefType = pDef->GetType();
314             // #119187 Only error if types conflict
315             if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
316             {
317                 // How? Define with AS first and take a Suffix then?
318                 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
319                 bError = true;
320             }
321             else if ( eType == SbxVARIANT )
322             {
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;
327             }
328         }
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() )
335         {
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 )
340             {
341                 pDef->SetType( SbxOBJECT );
342             }
343             else
344             {
345                 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
346                 bError = true;
347             }
348         }
349     }
350     std::unique_ptr<SbiExprNode> pNd(new SbiExprNode( *pDef, eType ));
351     if( !pPar )
352     {
353         pPar = SbiExprList::ParseParameters( pParser,false,false );
354     }
355     pNd->aVar.pPar = pPar.release();
356     pNd->aVar.pvMorePar = pvMoreParLcl.release();
357     if( bObj )
358     {
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 )
365         {
366             // defer error until runtime if in vba mode
367             if ( !pParser->IsVBASupportOn() )
368             {
369                 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
370                 bError = true;
371             }
372         }
373         if( !bError )
374         {
375             pNd->aVar.pNext = ObjTerm( *pDef ).release();
376         }
377     }
378 
379     pParser->UnlockColumn();
380     return pNd;
381 }
382 
383 // construction of an object term. A term of this kind is part
384 // of an expression that begins with an object variable.
385 
386 std::unique_ptr<SbiExprNode> SbiExpression::ObjTerm( SbiSymDef& rObj )
387 {
388     pParser->Next();
389     SbiToken eTok = pParser->Next();
390     if( eTok != SYMBOL && !SbiTokenizer::IsKwd( eTok ) && !SbiTokenizer::IsExtra( eTok ) )
391     {
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 )
396         {
397             pParser->Error( ERRCODE_BASIC_VAR_EXPECTED );
398             bError = true;
399         }
400     }
401 
402     if( bError )
403     {
404         return nullptr;
405     }
406     OUString aSym( pParser->GetSym() );
407     SbxDataType eType = pParser->GetType();
408     SbiExprListPtr pPar;
409     SbiExprListVector* pvMoreParLcl = nullptr;
410     eTok = pParser->Peek();
411 
412     if( DoParametersFollow( pParser, eCurExpr, eTok ) )
413     {
414         pPar = SbiExprList::ParseParameters( pParser, false/*bStandaloneExpression*/ );
415         bError = bError || !pPar->IsValid();
416         eTok = pParser->Peek();
417 
418         // i109624 check for additional sets of parameters
419         while( eTok == LPAREN )
420         {
421             if( pvMoreParLcl == nullptr )
422             {
423                 pvMoreParLcl = new SbiExprListVector;
424             }
425             SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser );
426             bError = bError || !pPar->IsValid();
427             pvMoreParLcl->push_back( std::move(pAddPar) );
428             eTok = pParser->Peek();
429         }
430     }
431     bool bObj = ( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
432     if( bObj )
433     {
434         if( eType == SbxVARIANT )
435         {
436             eType = SbxOBJECT;
437         }
438         else
439         {
440             // Name%. does really not work!
441             pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
442             bError = true;
443         }
444     }
445 
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 )
451     {
452         pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar.get() );
453         pDef->SetType( eType );
454     }
455 
456     std::unique_ptr<SbiExprNode> pNd(new SbiExprNode( *pDef, eType ));
457     pNd->aVar.pPar = pPar.release();
458     pNd->aVar.pvMorePar = pvMoreParLcl;
459     if( bObj )
460     {
461         if( pDef->GetType() == SbxVARIANT )
462         {
463             pDef->SetType( SbxOBJECT );
464         }
465         if( pDef->GetType() != SbxOBJECT )
466         {
467             pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
468             bError = true;
469         }
470         if( !bError )
471         {
472             pNd->aVar.pNext = ObjTerm( *pDef ).release();
473             pNd->eType = eType;
474         }
475     }
476     return pNd;
477 }
478 
479 // an operand can be:
480 //      constant
481 //      scalar variable
482 //      structure elements
483 //      array elements
484 //      functions
485 //      bracketed expressions
486 
487 std::unique_ptr<SbiExprNode> SbiExpression::Operand( bool bUsedForTypeOf )
488 {
489     std::unique_ptr<SbiExprNode> pRes;
490 
491     // test operand:
492     switch( SbiToken eTok = pParser->Peek() )
493     {
494     case SYMBOL:
495         pRes = Term();
496         // process something like "IF Not r Is Nothing Then .."
497         if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
498         {
499             eTok = pParser->Next();
500             pRes = std::make_unique<SbiExprNode>( std::move(pRes), eTok, Like() );
501         }
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 )
518         {
519             m_eMode = EXPRMODE_EMPTY_PAREN;
520             pRes = std::make_unique<SbiExprNode>();   // Dummy node
521             pParser->Next();
522             break;
523         }
524         nParenLevel++;
525         pRes = Boolean();
526         if( pParser->Peek() != RPAREN )
527         {
528             // If there was a LPARAM, it does not belong to the expression
529             if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
530             {
531                 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
532             }
533             else
534             {
535                 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
536             }
537         }
538         else
539         {
540             pParser->Next();
541             if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
542             {
543                 SbiToken eTokAfterRParen = pParser->Peek();
544                 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
545                 {
546                     m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
547                 }
548                 else
549                 {
550                     m_eMode = EXPRMODE_STANDARD;
551                 }
552             }
553         }
554         nParenLevel--;
555         break;
556     default:
557         // keywords here are OK at the moment!
558         if( SbiTokenizer::IsKwd( eTok ) )
559         {
560             pRes = Term();
561         }
562         else
563         {
564             pParser->Next();
565             pRes = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE );
566             pParser->Error( ERRCODE_BASIC_UNEXPECTED, eTok );
567         }
568         break;
569     }
570     return pRes;
571 }
572 
573 std::unique_ptr<SbiExprNode> SbiExpression::Unary()
574 {
575     std::unique_ptr<SbiExprNode> pNd;
576     SbiToken eTok = pParser->Peek();
577     switch( eTok )
578     {
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() )
586             {
587                 pNd = Operand();
588             }
589             else
590             {
591                 pParser->Next();
592                 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr );
593             }
594             break;
595         case PLUS:
596             pParser->Next();
597             pNd = Unary();
598             break;
599         case TYPEOF:
600         {
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;
608         }
609         case NEW:
610         {
611             pParser->Next();
612             SbiSymDef* pTypeDef = new SbiSymDef( OUString() );
613             pParser->TypeDecl( *pTypeDef, true );
614             pNd = std::make_unique<SbiExprNode>( pTypeDef->GetTypeId() );
615             break;
616         }
617         default:
618             pNd = Operand();
619     }
620     return pNd;
621 }
622 
623 std::unique_ptr<SbiExprNode> SbiExpression::Exp()
624 {
625     std::unique_ptr<SbiExprNode> pNd = Unary();
626     if( m_eMode != EXPRMODE_EMPTY_PAREN )
627     {
628         while( pParser->Peek() == EXPON )
629         {
630             SbiToken eTok = pParser->Next();
631             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Unary() );
632         }
633     }
634     return pNd;
635 }
636 
637 std::unique_ptr<SbiExprNode> SbiExpression::MulDiv()
638 {
639     std::unique_ptr<SbiExprNode> pNd = Exp();
640     if( m_eMode != EXPRMODE_EMPTY_PAREN )
641     {
642         for( ;; )
643         {
644             SbiToken eTok = pParser->Peek();
645             if( eTok != MUL && eTok != DIV )
646             {
647                 break;
648             }
649             eTok = pParser->Next();
650             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Exp() );
651         }
652     }
653     return pNd;
654 }
655 
656 std::unique_ptr<SbiExprNode> SbiExpression::IntDiv()
657 {
658     std::unique_ptr<SbiExprNode> pNd = MulDiv();
659     if( m_eMode != EXPRMODE_EMPTY_PAREN )
660     {
661         while( pParser->Peek() == IDIV )
662         {
663             SbiToken eTok = pParser->Next();
664             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, MulDiv() );
665         }
666     }
667     return pNd;
668 }
669 
670 std::unique_ptr<SbiExprNode> SbiExpression::Mod()
671 {
672     std::unique_ptr<SbiExprNode> pNd = IntDiv();
673     if( m_eMode != EXPRMODE_EMPTY_PAREN )
674     {
675         while( pParser->Peek() == MOD )
676         {
677             SbiToken eTok = pParser->Next();
678             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, IntDiv() );
679         }
680     }
681     return pNd;
682 }
683 
684 std::unique_ptr<SbiExprNode> SbiExpression::AddSub()
685 {
686     std::unique_ptr<SbiExprNode> pNd = Mod();
687     if( m_eMode != EXPRMODE_EMPTY_PAREN )
688     {
689         for( ;; )
690         {
691             SbiToken eTok = pParser->Peek();
692             if( eTok != PLUS && eTok != MINUS )
693             {
694                 break;
695             }
696             eTok = pParser->Next();
697             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Mod() );
698         }
699     }
700     return pNd;
701 }
702 
703 std::unique_ptr<SbiExprNode> SbiExpression::Cat()
704 {
705     std::unique_ptr<SbiExprNode> pNd = AddSub();
706     if( m_eMode != EXPRMODE_EMPTY_PAREN )
707     {
708         for( ;; )
709         {
710             SbiToken eTok = pParser->Peek();
711             if( eTok != CAT )
712             {
713                 break;
714             }
715             eTok = pParser->Next();
716             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, AddSub() );
717         }
718     }
719     return pNd;
720 }
721 
722 std::unique_ptr<SbiExprNode> SbiExpression::Comp()
723 {
724     std::unique_ptr<SbiExprNode> pNd = Cat();
725     if( m_eMode != EXPRMODE_EMPTY_PAREN )
726     {
727         short nCount = 0;
728         for( ;; )
729         {
730             SbiToken eTok = pParser->Peek();
731             if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
732             {
733                 break;
734             }
735             if( eTok != EQ && eTok != NE && eTok != LT &&
736                 eTok != GT && eTok != LE && eTok != GE )
737             {
738                 break;
739             }
740             eTok = pParser->Next();
741             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Cat() );
742             nCount++;
743         }
744     }
745     return pNd;
746 }
747 
748 
749 std::unique_ptr<SbiExprNode> SbiExpression::VBA_Not()
750 {
751     std::unique_ptr<SbiExprNode> pNd;
752 
753     SbiToken eTok = pParser->Peek();
754     if( eTok == NOT )
755     {
756         pParser->Next();
757         pNd = std::make_unique<SbiExprNode>( VBA_Not(), eTok, nullptr );
758     }
759     else
760     {
761         pNd = Comp();
762     }
763     return pNd;
764 }
765 
766 std::unique_ptr<SbiExprNode> SbiExpression::Like()
767 {
768     std::unique_ptr<SbiExprNode> pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
769     if( m_eMode != EXPRMODE_EMPTY_PAREN )
770     {
771         short nCount = 0;
772         while( pParser->Peek() == LIKE )
773         {
774             SbiToken eTok = pParser->Next();
775             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Comp() );
776             nCount++;
777         }
778         // multiple operands in a row does not work
779         if( nCount > 1 && !pParser->IsVBASupportOn() )
780         {
781             pParser->Error( ERRCODE_BASIC_SYNTAX );
782             bError = true;
783         }
784     }
785     return pNd;
786 }
787 
788 std::unique_ptr<SbiExprNode> SbiExpression::Boolean()
789 {
790     std::unique_ptr<SbiExprNode> pNd = Like();
791     if( m_eMode != EXPRMODE_EMPTY_PAREN )
792     {
793         for( ;; )
794         {
795             SbiToken eTok = pParser->Peek();
796             if( (eTok != AND) && (eTok != OR) &&
797                 (eTok != XOR) && (eTok != EQV) &&
798                 (eTok != IMP) && (eTok != IS) )
799             {
800                 break;
801             }
802             eTok = pParser->Next();
803             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Like() );
804         }
805     }
806     return pNd;
807 }
808 
809 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
810 {
811     if( pExpr->IsConstant() )
812     {
813         eType = pExpr->GetType();
814         if( pExpr->IsNumber() )
815         {
816             nVal = pExpr->nVal;
817         }
818         else
819         {
820             nVal = 0;
821             aVal = pExpr->aStrVal;
822         }
823     }
824     else
825     {
826         // #40204 special treatment for sal_Bool-constants
827         bool bIsBool = false;
828         if( pExpr->eNodeType == SbxVARVAL )
829         {
830             SbiSymDef* pVarDef = pExpr->GetVar();
831 
832             bool bBoolVal = false;
833             if( pVarDef->GetName().equalsIgnoreAsciiCase( "true" ) )
834             {
835                 bIsBool = true;
836                 bBoolVal = true;
837             }
838             else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
839             //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
840             {
841                 bIsBool = true;
842                 bBoolVal = false;
843             }
844 
845             if( bIsBool )
846             {
847                 pExpr = std::make_unique<SbiExprNode>( (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
848                 eType = pExpr->GetType();
849                 nVal = pExpr->nVal;
850             }
851         }
852 
853         if( !bIsBool )
854         {
855             pParser->Error( ERRCODE_BASIC_SYNTAX );
856             eType = SbxDOUBLE;
857             nVal = 0;
858         }
859     }
860 }
861 
862 short SbiConstExpression::GetShortValue()
863 {
864     if( eType == SbxSTRING )
865     {
866         SbxVariableRef refConv = new SbxVariable;
867         refConv->PutString( aVal );
868         return refConv->GetInteger();
869     }
870     else
871     {
872         double n = nVal;
873         if( n > 0 )
874         {
875             n += .5;
876         }
877         else
878         {
879             n -= .5;
880         }
881         if( n > SbxMAXINT )
882         {
883             n = SbxMAXINT;
884             pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
885         }
886         else if( n < SbxMININT )
887         {
888             n = SbxMININT;
889             pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
890         }
891 
892         return static_cast<short>(n);
893     }
894 }
895 
896 
897 SbiExprList::SbiExprList( )
898 {
899     nDim   = 0;
900     bError = false;
901     bBracket = false;
902 }
903 
904 SbiExprList::~SbiExprList() {}
905 
906 SbiExpression* SbiExprList::Get( size_t n )
907 {
908     return aData[n].get();
909 }
910 
911 void SbiExprList::addExpression( std::unique_ptr<SbiExpression>&& pExpr )
912 {
913     aData.push_back(std::move(pExpr));
914 }
915 
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
920 
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)
925 {
926     auto pExprList = std::make_unique<SbiExprList>();
927     if( !bPar )
928     {
929         return pExprList;
930     }
931 
932     SbiToken eTok = pParser->Peek();
933 
934     bool bAssumeExprLParenMode = false;
935     bool bAssumeArrayMode = false;
936     if( eTok == LPAREN )
937     {
938         if( bStandaloneExpression )
939         {
940             bAssumeExprLParenMode = true;
941         }
942         else
943         {
944             pExprList->bBracket = true;
945             pParser->Next();
946             eTok = pParser->Peek();
947         }
948     }
949 
950 
951     if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
952     {
953         if( eTok == RPAREN )
954         {
955             pParser->Next();
956         }
957         return pExprList;
958     }
959     // read in parameter table and lay down in correct order!
960     while( !pExprList->bError )
961     {
962         std::unique_ptr<SbiExpression> pExpr;
963         // missing argument
964         if( eTok == COMMA )
965         {
966             pExpr = std::make_unique<SbiExpression>( pParser, 0, SbxEMPTY );
967         }
968         // named arguments: either .name= or name:=
969         else
970         {
971             bool bByVal = false;
972             if( eTok == BYVAL )
973             {
974                 bByVal = true;
975                 pParser->Next();
976                 eTok = pParser->Peek();
977             }
978 
979             if( bAssumeExprLParenMode )
980             {
981                 pExpr = std::make_unique<SbiExpression>( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
982                 bAssumeExprLParenMode = false;
983 
984                 SbiExprMode eModeAfter = pExpr->m_eMode;
985                 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
986                 {
987                     pExprList->bBracket = true;
988                 }
989                 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
990                 {
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;
997                 }
998                 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
999                 {
1000                     pExprList->bBracket = true;
1001                     return pExprList;
1002                 }
1003             }
1004             else
1005             {
1006                 pExpr = std::make_unique<SbiExpression>( pParser );
1007             }
1008             if( bByVal && pExpr->IsLvalue() )
1009             {
1010                 pExpr->SetByVal();
1011             }
1012             if( !bAssumeArrayMode )
1013             {
1014                 OUString aName;
1015                 if( pParser->Peek() == ASSIGN )
1016                 {
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 );
1022                 }
1023                 pExpr->GetName() = aName;
1024             }
1025         }
1026         pExprList->bError = pExprList->bError || !pExpr->IsValid();
1027         pExprList->aData.push_back(std::move(pExpr));
1028         if( bAssumeArrayMode )
1029         {
1030             break;
1031         }
1032         // next element?
1033         eTok = pParser->Peek();
1034         if( eTok != COMMA )
1035         {
1036             if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1037             {
1038                 // tdf#80731
1039                 if (SbiTokenizer::IsEoln(eTok) && pExprList->bBracket)
1040                 {
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)
1048                     {
1049                         pParser->Error(ERRCODE_BASIC_EXPECTED, RPAREN);
1050                         pExprList->bError = true;
1051                     }
1052                 }
1053                 break;
1054             }
1055             pParser->Error( pExprList->bBracket ? ERRCODE_BASIC_BAD_BRACKETS : ERRCODE_BASIC_EXPECTED, COMMA );
1056             pExprList->bError = true;
1057         }
1058         else
1059         {
1060             pParser->Next();
1061             eTok = pParser->Peek();
1062             if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1063             {
1064                 break;
1065             }
1066         }
1067     }
1068     // closing bracket
1069     if( eTok == RPAREN )
1070     {
1071         pParser->Next();
1072         pParser->Peek();
1073         if( !pExprList->bBracket )
1074         {
1075             pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1076             pExprList->bError = true;
1077         }
1078     }
1079     pExprList->nDim = pExprList->GetSize();
1080     return pExprList;
1081 }
1082 
1083 // A list of array dimensions is parsed.
1084 
1085 SbiExprListPtr SbiExprList::ParseDimList( SbiParser* pParser )
1086 {
1087     auto pExprList = std::make_unique<SbiExprList>();
1088 
1089     if( pParser->Next() != LPAREN )
1090     {
1091         pParser->Error( ERRCODE_BASIC_EXPECTED, LPAREN );
1092         pExprList->bError = true; return pExprList;
1093     }
1094 
1095     if( pParser->Peek() != RPAREN )
1096     {
1097         SbiToken eTok;
1098         for( ;; )
1099         {
1100             auto pExpr1 = std::make_unique<SbiExpression>( pParser );
1101             eTok = pParser->Next();
1102             if( eTok == TO )
1103             {
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));
1111             }
1112             else
1113             {
1114                 pExpr1->SetBased();
1115                 pExpr1->ConvertToIntConstIfPossible();
1116                 pExprList->bError = pExprList->bError || !pExpr1->IsValid();
1117                 pExprList->aData.push_back(std::move(pExpr1));
1118             }
1119             pExprList->nDim++;
1120             if( eTok == RPAREN ) break;
1121             if( eTok != COMMA )
1122             {
1123                 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1124                 pParser->Next();
1125                 break;
1126             }
1127         }
1128     }
1129     else pParser->Next();
1130     return pExprList;
1131 }
1132 
1133 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1134