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 <comphelper/SetFlagContextHelper.hxx>
26 #include <expr.hxx>
27 
SbiExpression(SbiParser * p,SbiExprType t,SbiExprMode eMode,const KeywordSymbolInfo * pKeywordSymbolInfo)28 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
29     SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo ) :
30     pParser(p),
31     eCurExpr(t),
32     m_eMode(eMode)
33 {
34     pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean();
35     if( t != SbSYMBOL )
36     {
37         pExpr->Optimize(pParser);
38     }
39     if( t == SbLVALUE && !pExpr->IsLvalue() )
40     {
41         p->Error( ERRCODE_BASIC_LVALUE_EXPECTED );
42     }
43     if( t == SbOPERAND && !IsVariable() )
44     {
45         p->Error( ERRCODE_BASIC_VAR_EXPECTED );
46     }
47 }
48 
SbiExpression(SbiParser * p,double n,SbxDataType t)49 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t ) :
50     pParser(p),
51     eCurExpr(SbOPERAND),
52     m_eMode(EXPRMODE_STANDARD)
53 {
54     pExpr = std::make_unique<SbiExprNode>( n, t );
55     pExpr->Optimize(pParser);
56 }
57 
SbiExpression(SbiParser * p,const SbiSymDef & r,SbiExprListPtr pPar)58 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprListPtr pPar ) :
59     pParser(p),
60     eCurExpr(SbOPERAND),
61     m_eMode(EXPRMODE_STANDARD)
62 {
63     pExpr = std::make_unique<SbiExprNode>( r, SbxVARIANT, std::move(pPar) );
64 }
65 
~SbiExpression()66 SbiExpression::~SbiExpression() { }
67 
68 // reading in a complete identifier
69 // an identifier has the following form:
70 // name[(Parameter)][.Name[(parameter)]]...
71 // structure elements are coupled via the element pNext,
72 // so that they're not in the tree.
73 
74 // Are there parameters without brackets following? This may be a number,
75 // a string, a symbol or also a comma (if the 1st parameter is missing)
76 
DoParametersFollow(SbiParser * p,SbiExprType eCurExpr,SbiToken eTok)77 static bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
78 {
79     if( eTok == LPAREN )
80     {
81         return true;
82     }
83     // but only if similar to CALL!
84     if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
85     {
86         return false;
87     }
88     if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
89          eTok == SYMBOL || eTok == COMMA  || eTok == DOT || eTok == NOT || eTok == BYVAL )
90     {
91         return true;
92     }
93     else // check for default params with reserved names ( e.g. names of tokens )
94     {
95         SbiTokenizer tokens( *static_cast<SbiTokenizer*>(p) );
96         // Urk the Next() / Peek() semantics are... weird
97         tokens.Next();
98         if ( tokens.Peek() == ASSIGN )
99         {
100             return true;
101         }
102     }
103     return false;
104 }
105 
106 // definition of a new symbol
107 
AddSym(SbiToken eTok,SbiSymPool & rPool,SbiExprType eCurExpr,const OUString & rName,SbxDataType eType,const SbiExprList * pPar)108 static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
109                            const OUString& rName, SbxDataType eType, const SbiExprList* pPar )
110 {
111     SbiSymDef* pDef;
112     // A= is not a procedure
113     bool bHasType = ( eTok == EQ || eTok == DOT );
114     if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
115     {
116         // so this is a procedure
117         // the correct pool should be found out, as
118         // procs must always get into a public pool
119         SbiSymPool* pPool = &rPool;
120         if( pPool->GetScope() != SbPUBLIC )
121         {
122             pPool = &rPool.GetParser()->aPublics;
123         }
124         SbiProcDef* pProc = pPool->AddProc( rName );
125 
126         // special treatment for Colls like Documents(1)
127         if( eCurExpr == SbSTDEXPR )
128         {
129             bHasType = true;
130         }
131         pDef = pProc;
132         pDef->SetType( bHasType ? eType : SbxEMPTY );
133         if( pPar )
134         {
135             // generate dummy parameters
136             for( sal_Int32 n = 1; n <= pPar->GetSize(); n++ )
137             {
138                 OUString aPar = "PAR" + OUString::number( n );
139                 pProc->GetParams().AddSym( aPar );
140             }
141         }
142     }
143     else
144     {
145         // or a normal symbol
146         pDef = rPool.AddSym( rName );
147         pDef->SetType( eType );
148     }
149     return pDef;
150 }
151 
152 // currently even keywords are allowed (because of Dflt properties of the same name)
153 
Term(const KeywordSymbolInfo * pKeywordSymbolInfo)154 std::unique_ptr<SbiExprNode> SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
155 {
156     if( pParser->Peek() == DOT )
157     {
158         SbiExprNode* pWithVar = pParser->GetWithVar();
159         // #26608: get to the node-chain's end to pass the correct object
160         SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : nullptr;
161         std::unique_ptr<SbiExprNode> pNd;
162         if( !pDef )
163         {
164             pParser->Next();
165         }
166         else
167         {
168             pNd = ObjTerm( *pDef );
169             if( pNd )
170             {
171                 pNd->SetWithParent( pWithVar );
172             }
173         }
174         if( !pNd )
175         {
176             pParser->Error( ERRCODE_BASIC_UNEXPECTED, DOT );
177             pNd = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE );
178         }
179         return pNd;
180     }
181 
182     SbiToken eTok = (pKeywordSymbolInfo == nullptr) ? pParser->Next() : SYMBOL;
183     // memorize the parsing's begin
184     pParser->LockColumn();
185     OUString aSym( (pKeywordSymbolInfo == nullptr) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol );
186     SbxDataType eType = (pKeywordSymbolInfo == nullptr) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType;
187     SbiExprListPtr pPar;
188     std::unique_ptr<SbiExprListVector> pvMoreParLcl;
189     // are there parameters following?
190     SbiToken eNextTok = pParser->Peek();
191     // is it a known parameter?
192     // create a string constant then, which will be recognized
193     // in the SbiParameters-ctor and is continued to be handled
194     if( eNextTok == ASSIGN )
195     {
196         pParser->UnlockColumn();
197         return std::make_unique<SbiExprNode>( aSym );
198     }
199     // no keywords allowed from here on!
200     if( SbiTokenizer::IsKwd( eTok )
201         && (!pParser->IsCompatible() || eTok != INPUT) )
202     {
203         pParser->Error( ERRCODE_BASIC_SYNTAX );
204         bError = true;
205     }
206 
207     eTok = eNextTok;
208     if( DoParametersFollow( pParser, eCurExpr, eTok ) )
209     {
210         bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
211         pPar = SbiExprList::ParseParameters( pParser, bStandaloneExpression );
212         bError = bError || !pPar->IsValid();
213         if( !bError )
214             bBracket = pPar->IsBracket();
215         eTok = pParser->Peek();
216 
217         // i75443 check for additional sets of parameters
218         while( eTok == LPAREN )
219         {
220             if( pvMoreParLcl == nullptr )
221             {
222                 pvMoreParLcl.reset(new SbiExprListVector);
223             }
224             SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser );
225             bError = bError || !pAddPar->IsValid();
226             pvMoreParLcl->push_back( std::move(pAddPar) );
227             eTok = pParser->Peek();
228         }
229     }
230     // It might be an object part, if . or ! is following.
231     // In case of . the variable must already be defined;
232     // it's an object, if pDef is NULL after the search.
233     bool bObj = ( ( eTok == DOT || eTok == EXCLAM )
234                     && !pParser->WhiteSpace() );
235     if( bObj )
236     {
237         bBracket = false;   // Now the bracket for the first term is obsolete
238         if( eType == SbxVARIANT )
239         {
240             eType = SbxOBJECT;
241         }
242         else
243         {
244             // Name%. really does not work!
245             pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
246             bError = true;
247         }
248     }
249     // Search:
250     SbiSymDef* pDef = pParser->pPool->Find( aSym );
251     if( !pDef )
252     {
253         // Part of the Runtime-Library?
254         // from 31.3.1996: swapped out to parser-method
255         // (is also needed in SbiParser::DefVar() in DIM.CXX)
256         pDef = pParser->CheckRTLForSym( aSym, eType );
257 
258         // #i109184: Check if symbol is or later will be defined inside module
259         SbModule& rMod = pParser->aGen.GetModule();
260         if( rMod.FindMethod( aSym, SbxClassType::DontCare ) )
261         {
262             pDef = nullptr;
263         }
264     }
265     if( !pDef )
266     {
267         if( bObj )
268         {
269             eType = SbxOBJECT;
270         }
271         pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar.get() );
272         // Looks like this is a local ( but undefined variable )
273         // if it is in a static procedure then make this Symbol
274         // static
275         if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
276         {
277             pDef->SetStatic();
278         }
279     }
280     else
281     {
282 
283         SbiConstDef* pConst = pDef->GetConstDef();
284         if( pConst )
285         {
286             pPar = nullptr;
287             pvMoreParLcl.reset();
288             if( pConst->GetType() == SbxSTRING )
289             {
290                 return std::make_unique<SbiExprNode>( pConst->GetString() );
291             }
292             else
293             {
294                 return std::make_unique<SbiExprNode>( pConst->GetValue(), pConst->GetType() );
295             }
296         }
297 
298         // 0 parameters come up to ()
299         if( pDef->GetDims() )
300         {
301             if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
302             {
303                 pParser->Error( ERRCODE_BASIC_WRONG_DIMS );
304             }
305         }
306         if( pDef->IsDefinedAs() )
307         {
308             SbxDataType eDefType = pDef->GetType();
309             // #119187 Only error if types conflict
310             if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
311             {
312                 // How? Define with AS first and take a Suffix then?
313                 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
314                 bError = true;
315             }
316             else if ( eType == SbxVARIANT )
317             {
318                 // if there's nothing named, take the type of the entry,
319                 // but only if the var hasn't been defined with AS XXX
320                 // so that we catch n% = 5 : print n
321                 eType = eDefType;
322             }
323         }
324         // checking type of variables:
325         // is there named anything different in the scanner?
326         // That's OK for methods!
327         if( eType != SbxVARIANT &&          // Variant takes everything
328             eType != pDef->GetType() &&
329             !pDef->GetProcDef() )
330         {
331             // maybe pDef describes an object that so far has only been
332             // recognized as SbxVARIANT - then change type of pDef
333             // from 16.12.95 (similar cases possible perhaps?!?)
334             if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
335             {
336                 pDef->SetType( SbxOBJECT );
337             }
338             else
339             {
340                 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
341                 bError = true;
342             }
343         }
344     }
345     auto pNd = std::make_unique<SbiExprNode>( *pDef, eType );
346     if( !pPar )
347     {
348         pPar = SbiExprList::ParseParameters( pParser,false,false );
349     }
350     pNd->aVar.pPar = pPar.release();
351     pNd->aVar.pvMorePar = pvMoreParLcl.release();
352     if( bObj )
353     {
354         // from 8.1.95: Object may also be of the type SbxVARIANT
355         if( pDef->GetType() == SbxVARIANT )
356             pDef->SetType( SbxOBJECT );
357         // if we scan something with point,
358         // the type must be SbxOBJECT
359         if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
360         {
361             // defer error until runtime if in vba mode
362             if ( !pParser->IsVBASupportOn() )
363             {
364                 pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
365                 bError = true;
366             }
367         }
368         if( !bError )
369         {
370             pNd->aVar.pNext = ObjTerm( *pDef ).release();
371         }
372     }
373 
374     pParser->UnlockColumn();
375     return pNd;
376 }
377 
378 // construction of an object term. A term of this kind is part
379 // of an expression that begins with an object variable.
380 
ObjTerm(SbiSymDef & rObj)381 std::unique_ptr<SbiExprNode> SbiExpression::ObjTerm( SbiSymDef& rObj )
382 {
383     pParser->Next();
384     SbiToken eTok = pParser->Next();
385     if( eTok != SYMBOL && !SbiTokenizer::IsKwd( eTok ) && !SbiTokenizer::IsExtra( eTok ) )
386     {
387         // #66745 Some operators can also be allowed
388         // as identifiers, important for StarOne
389         if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
390             eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
391         {
392             pParser->Error( ERRCODE_BASIC_VAR_EXPECTED );
393             bError = true;
394         }
395     }
396 
397     if( bError )
398     {
399         return nullptr;
400     }
401     OUString aSym( pParser->GetSym() );
402     SbxDataType eType = pParser->GetType();
403     SbiExprListPtr pPar;
404     SbiExprListVector* pvMoreParLcl = nullptr;
405     eTok = pParser->Peek();
406 
407     if( DoParametersFollow( pParser, eCurExpr, eTok ) )
408     {
409         pPar = SbiExprList::ParseParameters( pParser, false/*bStandaloneExpression*/ );
410         bError = bError || !pPar->IsValid();
411         eTok = pParser->Peek();
412 
413         // i109624 check for additional sets of parameters
414         while( eTok == LPAREN )
415         {
416             if( pvMoreParLcl == nullptr )
417             {
418                 pvMoreParLcl = new SbiExprListVector;
419             }
420             SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser );
421             bError = bError || !pPar->IsValid();
422             pvMoreParLcl->push_back( std::move(pAddPar) );
423             eTok = pParser->Peek();
424         }
425     }
426     bool bObj = ( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
427     if( bObj )
428     {
429         if( eType == SbxVARIANT )
430         {
431             eType = SbxOBJECT;
432         }
433         else
434         {
435             // Name%. does really not work!
436             pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
437             bError = true;
438         }
439     }
440 
441     // an object's symbol pool is always PUBLIC
442     SbiSymPool& rPool = rObj.GetPool();
443     rPool.SetScope( SbPUBLIC );
444     SbiSymDef* pDef = rPool.Find( aSym );
445     if( !pDef )
446     {
447         pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar.get() );
448         pDef->SetType( eType );
449     }
450 
451     auto pNd = std::make_unique<SbiExprNode>( *pDef, eType );
452     pNd->aVar.pPar = pPar.release();
453     pNd->aVar.pvMorePar = pvMoreParLcl;
454     if( bObj )
455     {
456         if( pDef->GetType() == SbxVARIANT )
457         {
458             pDef->SetType( SbxOBJECT );
459         }
460         if( pDef->GetType() != SbxOBJECT )
461         {
462             pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
463             bError = true;
464         }
465         if( !bError )
466         {
467             pNd->aVar.pNext = ObjTerm( *pDef ).release();
468             pNd->eType = eType;
469         }
470     }
471     return pNd;
472 }
473 
474 // an operand can be:
475 //      constant
476 //      scalar variable
477 //      structure elements
478 //      array elements
479 //      functions
480 //      bracketed expressions
481 
Operand(bool bUsedForTypeOf)482 std::unique_ptr<SbiExprNode> SbiExpression::Operand( bool bUsedForTypeOf )
483 {
484     std::unique_ptr<SbiExprNode> pRes;
485 
486     // test operand:
487     switch( SbiToken eTok = pParser->Peek() )
488     {
489     case SYMBOL:
490         pRes = Term();
491         // process something like "IF Not r Is Nothing Then .."
492         if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
493         {
494             eTok = pParser->Next();
495             pRes = std::make_unique<SbiExprNode>( std::move(pRes), eTok, Like() );
496         }
497         break;
498     case DOT:   // .with
499         pRes = Term(); break;
500     case NOT:
501         pRes = VBA_Not();
502         break;
503     case NUMBER:
504         pParser->Next();
505         pRes = std::make_unique<SbiExprNode>( pParser->GetDbl(), pParser->GetType() );
506         break;
507     case FIXSTRING:
508         pParser->Next();
509         pRes = std::make_unique<SbiExprNode>( pParser->GetSym() ); break;
510     case LPAREN:
511         pParser->Next();
512         if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
513         {
514             m_eMode = EXPRMODE_EMPTY_PAREN;
515             pRes = std::make_unique<SbiExprNode>();   // Dummy node
516             pParser->Next();
517             break;
518         }
519         nParenLevel++;
520         pRes = Boolean();
521         if( pParser->Peek() != RPAREN )
522         {
523             // If there was a LPARAM, it does not belong to the expression
524             if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
525             {
526                 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
527             }
528             else
529             {
530                 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
531             }
532         }
533         else
534         {
535             pParser->Next();
536             if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
537             {
538                 SbiToken eTokAfterRParen = pParser->Peek();
539                 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
540                 {
541                     m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
542                 }
543                 else
544                 {
545                     m_eMode = EXPRMODE_STANDARD;
546                 }
547             }
548         }
549         nParenLevel--;
550         break;
551     default:
552         // keywords here are OK at the moment!
553         if( SbiTokenizer::IsKwd( eTok ) )
554         {
555             pRes = Term();
556         }
557         else
558         {
559             pParser->Next();
560             pRes = std::make_unique<SbiExprNode>( 1.0, SbxDOUBLE );
561             pParser->Error( ERRCODE_BASIC_UNEXPECTED, eTok );
562         }
563         break;
564     }
565     return pRes;
566 }
567 
Unary()568 std::unique_ptr<SbiExprNode> SbiExpression::Unary()
569 {
570     std::unique_ptr<SbiExprNode> pNd;
571     SbiToken eTok = pParser->Peek();
572     switch( eTok )
573     {
574         case MINUS:
575             eTok = NEG;
576             pParser->Next();
577             pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr );
578             break;
579         case NOT:
580             if( pParser->IsVBASupportOn() )
581             {
582                 pNd = Operand();
583             }
584             else
585             {
586                 pParser->Next();
587                 pNd = std::make_unique<SbiExprNode>( Unary(), eTok, nullptr );
588             }
589             break;
590         case PLUS:
591             pParser->Next();
592             pNd = Unary();
593             break;
594         case TYPEOF:
595         {
596             pParser->Next();
597             std::unique_ptr<SbiExprNode> pObjNode = Operand( true/*bUsedForTypeOf*/ );
598             pParser->TestToken( IS );
599             SbiSymDef* pTypeDef = new SbiSymDef( OUString() );
600             pParser->TypeDecl( *pTypeDef, true );
601             pNd = std::make_unique<SbiExprNode>( std::move(pObjNode), pTypeDef->GetTypeId() );
602             break;
603         }
604         case NEW:
605         {
606             pParser->Next();
607             SbiSymDef* pTypeDef = new SbiSymDef( OUString() );
608             pParser->TypeDecl( *pTypeDef, true );
609             pNd = std::make_unique<SbiExprNode>( pTypeDef->GetTypeId() );
610             break;
611         }
612         default:
613             pNd = Operand();
614     }
615     return pNd;
616 }
617 
Exp()618 std::unique_ptr<SbiExprNode> SbiExpression::Exp()
619 {
620     std::unique_ptr<SbiExprNode> pNd = Unary();
621     if( m_eMode != EXPRMODE_EMPTY_PAREN )
622     {
623         while( pParser->Peek() == EXPON )
624         {
625             SbiToken eTok = pParser->Next();
626             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Unary() );
627         }
628     }
629     return pNd;
630 }
631 
MulDiv()632 std::unique_ptr<SbiExprNode> SbiExpression::MulDiv()
633 {
634     std::unique_ptr<SbiExprNode> pNd = Exp();
635     if( m_eMode != EXPRMODE_EMPTY_PAREN )
636     {
637         for( ;; )
638         {
639             SbiToken eTok = pParser->Peek();
640             if( eTok != MUL && eTok != DIV )
641             {
642                 break;
643             }
644             eTok = pParser->Next();
645             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Exp() );
646         }
647     }
648     return pNd;
649 }
650 
IntDiv()651 std::unique_ptr<SbiExprNode> SbiExpression::IntDiv()
652 {
653     std::unique_ptr<SbiExprNode> pNd = MulDiv();
654     if( m_eMode != EXPRMODE_EMPTY_PAREN )
655     {
656         while( pParser->Peek() == IDIV )
657         {
658             SbiToken eTok = pParser->Next();
659             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, MulDiv() );
660         }
661     }
662     return pNd;
663 }
664 
Mod()665 std::unique_ptr<SbiExprNode> SbiExpression::Mod()
666 {
667     std::unique_ptr<SbiExprNode> pNd = IntDiv();
668     if( m_eMode != EXPRMODE_EMPTY_PAREN )
669     {
670         while( pParser->Peek() == MOD )
671         {
672             SbiToken eTok = pParser->Next();
673             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, IntDiv() );
674         }
675     }
676     return pNd;
677 }
678 
AddSub()679 std::unique_ptr<SbiExprNode> SbiExpression::AddSub()
680 {
681     std::unique_ptr<SbiExprNode> pNd = Mod();
682     if( m_eMode != EXPRMODE_EMPTY_PAREN )
683     {
684         for( ;; )
685         {
686             SbiToken eTok = pParser->Peek();
687             if( eTok != PLUS && eTok != MINUS )
688             {
689                 break;
690             }
691             eTok = pParser->Next();
692             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Mod() );
693         }
694     }
695     return pNd;
696 }
697 
Cat()698 std::unique_ptr<SbiExprNode> SbiExpression::Cat()
699 {
700     std::unique_ptr<SbiExprNode> pNd = AddSub();
701     if( m_eMode != EXPRMODE_EMPTY_PAREN )
702     {
703         for( ;; )
704         {
705             SbiToken eTok = pParser->Peek();
706             if( eTok != CAT )
707             {
708                 break;
709             }
710             eTok = pParser->Next();
711             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, AddSub() );
712         }
713     }
714     return pNd;
715 }
716 
Comp()717 std::unique_ptr<SbiExprNode> SbiExpression::Comp()
718 {
719     std::unique_ptr<SbiExprNode> pNd = Cat();
720     if( m_eMode != EXPRMODE_EMPTY_PAREN )
721     {
722         short nCount = 0;
723         for( ;; )
724         {
725             SbiToken eTok = pParser->Peek();
726             if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
727             {
728                 break;
729             }
730             if( eTok != EQ && eTok != NE && eTok != LT &&
731                 eTok != GT && eTok != LE && eTok != GE )
732             {
733                 break;
734             }
735             eTok = pParser->Next();
736             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Cat() );
737             nCount++;
738         }
739     }
740     return pNd;
741 }
742 
743 
VBA_Not()744 std::unique_ptr<SbiExprNode> SbiExpression::VBA_Not()
745 {
746     std::unique_ptr<SbiExprNode> pNd;
747 
748     SbiToken eTok = pParser->Peek();
749     if( eTok == NOT )
750     {
751         pParser->Next();
752         pNd = std::make_unique<SbiExprNode>( VBA_Not(), eTok, nullptr );
753     }
754     else
755     {
756         pNd = Comp();
757     }
758     return pNd;
759 }
760 
Like()761 std::unique_ptr<SbiExprNode> SbiExpression::Like()
762 {
763     std::unique_ptr<SbiExprNode> pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
764     if( m_eMode != EXPRMODE_EMPTY_PAREN )
765     {
766         short nCount = 0;
767         while( pParser->Peek() == LIKE )
768         {
769             SbiToken eTok = pParser->Next();
770             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Comp() );
771             nCount++;
772         }
773         // multiple operands in a row does not work
774         if( nCount > 1 && !pParser->IsVBASupportOn() )
775         {
776             pParser->Error( ERRCODE_BASIC_SYNTAX );
777             bError = true;
778         }
779     }
780     return pNd;
781 }
782 
Boolean()783 std::unique_ptr<SbiExprNode> SbiExpression::Boolean()
784 {
785     std::unique_ptr<SbiExprNode> pNd = Like();
786     if( m_eMode != EXPRMODE_EMPTY_PAREN )
787     {
788         for( ;; )
789         {
790             SbiToken eTok = pParser->Peek();
791             if( (eTok != AND) && (eTok != OR) &&
792                 (eTok != XOR) && (eTok != EQV) &&
793                 (eTok != IMP) && (eTok != IS) )
794             {
795                 break;
796             }
797             eTok = pParser->Next();
798             pNd = std::make_unique<SbiExprNode>( std::move(pNd), eTok, Like() );
799         }
800     }
801     return pNd;
802 }
803 
SbiConstExpression(SbiParser * p)804 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
805 {
806     if( pExpr->IsConstant() )
807     {
808         eType = pExpr->GetType();
809         if( pExpr->IsNumber() )
810         {
811             nVal = pExpr->nVal;
812         }
813         else
814         {
815             nVal = 0;
816             aVal = pExpr->aStrVal;
817         }
818     }
819     else
820     {
821         // #40204 special treatment for sal_Bool-constants
822         bool bIsBool = false;
823         if( pExpr->eNodeType == SbxVARVAL )
824         {
825             SbiSymDef* pVarDef = pExpr->GetVar();
826 
827             bool bBoolVal = false;
828             if( pVarDef->GetName().equalsIgnoreAsciiCase( "true" ) )
829             {
830                 bIsBool = true;
831                 bBoolVal = true;
832             }
833             else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
834             //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
835             {
836                 bIsBool = true;
837                 bBoolVal = false;
838             }
839 
840             if( bIsBool )
841             {
842                 pExpr = std::make_unique<SbiExprNode>( (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
843                 eType = pExpr->GetType();
844                 nVal = pExpr->nVal;
845             }
846         }
847 
848         if( !bIsBool )
849         {
850             pParser->Error( ERRCODE_BASIC_SYNTAX );
851             eType = SbxDOUBLE;
852             nVal = 0;
853         }
854     }
855 }
856 
GetShortValue()857 short SbiConstExpression::GetShortValue()
858 {
859     if( eType == SbxSTRING )
860     {
861         SbxVariableRef refConv = new SbxVariable;
862         refConv->PutString( aVal );
863         return refConv->GetInteger();
864     }
865     else
866     {
867         double n = nVal;
868         if( n > 0 )
869         {
870             n += .5;
871         }
872         else
873         {
874             n -= .5;
875         }
876         if( n > SbxMAXINT )
877         {
878             n = SbxMAXINT;
879             pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
880         }
881         else if( n < SbxMININT )
882         {
883             n = SbxMININT;
884             pParser->Error( ERRCODE_BASIC_OUT_OF_RANGE );
885         }
886 
887         return static_cast<short>(n);
888     }
889 }
890 
891 
SbiExprList()892 SbiExprList::SbiExprList( )
893 {
894     nDim   = 0;
895     bError = false;
896     bBracket = false;
897 }
898 
~SbiExprList()899 SbiExprList::~SbiExprList() {}
900 
Get(size_t n)901 SbiExpression* SbiExprList::Get( size_t n )
902 {
903     return aData[n].get();
904 }
905 
addExpression(std::unique_ptr<SbiExpression> && pExpr)906 void SbiExprList::addExpression( std::unique_ptr<SbiExpression>&& pExpr )
907 {
908     aData.push_back(std::move(pExpr));
909 }
910 
911 // the parameter list is completely parsed
912 // "procedurename()" is OK
913 // it's a function without parameters then
914 // i. e. you give an array as procedure parameter
915 
916 // #i79918/#i80532: bConst has never been set to true
917 // -> reused as bStandaloneExpression
918 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
ParseParameters(SbiParser * pParser,bool bStandaloneExpression,bool bPar)919 SbiExprListPtr SbiExprList::ParseParameters( SbiParser* pParser, bool bStandaloneExpression, bool bPar)
920 {
921     auto pExprList = std::make_unique<SbiExprList>();
922     if( !bPar )
923     {
924         return pExprList;
925     }
926 
927     SbiToken eTok = pParser->Peek();
928 
929     bool bAssumeExprLParenMode = false;
930     bool bAssumeArrayMode = false;
931     if( eTok == LPAREN )
932     {
933         if( bStandaloneExpression )
934         {
935             bAssumeExprLParenMode = true;
936         }
937         else
938         {
939             pExprList->bBracket = true;
940             pParser->Next();
941             eTok = pParser->Peek();
942         }
943     }
944 
945 
946     if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
947     {
948         if( eTok == RPAREN )
949         {
950             pParser->Next();
951         }
952         return pExprList;
953     }
954     // read in parameter table and lay down in correct order!
955     while( !pExprList->bError )
956     {
957         std::unique_ptr<SbiExpression> pExpr;
958         // missing argument
959         if( eTok == COMMA )
960         {
961             pExpr = std::make_unique<SbiExpression>( pParser, 0, SbxEMPTY );
962         }
963         // named arguments: either .name= or name:=
964         else
965         {
966             bool bByVal = false;
967             if( eTok == BYVAL )
968             {
969                 bByVal = true;
970                 pParser->Next();
971                 eTok = pParser->Peek();
972             }
973 
974             if( bAssumeExprLParenMode )
975             {
976                 pExpr = std::make_unique<SbiExpression>( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
977                 bAssumeExprLParenMode = false;
978 
979                 SbiExprMode eModeAfter = pExpr->m_eMode;
980                 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
981                 {
982                     pExprList->bBracket = true;
983                 }
984                 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
985                 {
986                     // Expression "looks" like an array assignment
987                     // a(...)[(...)] = ? or a(...).b(...)
988                     // RPAREN is already parsed
989                     pExprList->bBracket = true;
990                     bAssumeArrayMode = true;
991                     eTok = NIL;
992                 }
993                 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
994                 {
995                     pExprList->bBracket = true;
996                     return pExprList;
997                 }
998             }
999             else
1000             {
1001                 pExpr = std::make_unique<SbiExpression>( pParser );
1002             }
1003             if( bByVal && pExpr->IsLvalue() )
1004             {
1005                 pExpr->SetByVal();
1006             }
1007             if( !bAssumeArrayMode )
1008             {
1009                 OUString aName;
1010                 if( pParser->Peek() == ASSIGN )
1011                 {
1012                     // VBA mode: name:=
1013                     // SbiExpression::Term() has made as string out of it
1014                     aName = pExpr->GetString();
1015                     pParser->Next();
1016                     pExpr = std::make_unique<SbiExpression>( pParser );
1017                 }
1018                 pExpr->GetName() = aName;
1019             }
1020         }
1021         pExprList->bError = pExprList->bError || !pExpr->IsValid();
1022         pExprList->aData.push_back(std::move(pExpr));
1023         if( bAssumeArrayMode )
1024         {
1025             break;
1026         }
1027         // next element?
1028         eTok = pParser->Peek();
1029         if( eTok != COMMA )
1030         {
1031             if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1032             {
1033                 // tdf#80731
1034                 if (SbiTokenizer::IsEoln(eTok) && pExprList->bBracket)
1035                 {
1036                     // tdf#106529: only fail here in strict mode (i.e. when compiled from IDE), and
1037                     // allow legacy code with missing closing parenthesis when started e.g. from
1038                     // extensions and event handlers
1039                     if (comphelper::IsContextFlagActive("BasicStrict"))
1040                     {
1041                         pParser->Error(ERRCODE_BASIC_EXPECTED, RPAREN);
1042                         pExprList->bError = true;
1043                     }
1044                 }
1045                 break;
1046             }
1047             pParser->Error( pExprList->bBracket ? ERRCODE_BASIC_BAD_BRACKETS : ERRCODE_BASIC_EXPECTED, COMMA );
1048             pExprList->bError = true;
1049         }
1050         else
1051         {
1052             pParser->Next();
1053             eTok = pParser->Peek();
1054             if( ( pExprList->bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1055             {
1056                 break;
1057             }
1058         }
1059     }
1060     // closing bracket
1061     if( eTok == RPAREN )
1062     {
1063         pParser->Next();
1064         pParser->Peek();
1065         if( !pExprList->bBracket )
1066         {
1067             pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1068             pExprList->bError = true;
1069         }
1070     }
1071     pExprList->nDim = pExprList->GetSize();
1072     return pExprList;
1073 }
1074 
1075 // A list of array dimensions is parsed.
1076 
ParseDimList(SbiParser * pParser)1077 SbiExprListPtr SbiExprList::ParseDimList( SbiParser* pParser )
1078 {
1079     auto pExprList = std::make_unique<SbiExprList>();
1080 
1081     if( pParser->Next() != LPAREN )
1082     {
1083         pParser->Error( ERRCODE_BASIC_EXPECTED, LPAREN );
1084         pExprList->bError = true; return pExprList;
1085     }
1086 
1087     if( pParser->Peek() != RPAREN )
1088     {
1089         SbiToken eTok;
1090         for( ;; )
1091         {
1092             auto pExpr1 = std::make_unique<SbiExpression>( pParser );
1093             eTok = pParser->Next();
1094             if( eTok == TO )
1095             {
1096                 auto pExpr2 = std::make_unique<SbiExpression>( pParser );
1097                 pExpr1->ConvertToIntConstIfPossible();
1098                 pExpr2->ConvertToIntConstIfPossible();
1099                 eTok = pParser->Next();
1100                 pExprList->bError = pExprList->bError || !pExpr1->IsValid() || !pExpr2->IsValid();
1101                 pExprList->aData.push_back(std::move(pExpr1));
1102                 pExprList->aData.push_back(std::move(pExpr2));
1103             }
1104             else
1105             {
1106                 pExpr1->SetBased();
1107                 pExpr1->ConvertToIntConstIfPossible();
1108                 pExprList->bError = pExprList->bError || !pExpr1->IsValid();
1109                 pExprList->aData.push_back(std::move(pExpr1));
1110             }
1111             pExprList->nDim++;
1112             if( eTok == RPAREN ) break;
1113             if( eTok != COMMA )
1114             {
1115                 pParser->Error( ERRCODE_BASIC_BAD_BRACKETS );
1116                 pParser->Next();
1117                 break;
1118             }
1119         }
1120     }
1121     else pParser->Next();
1122     return pExprList;
1123 }
1124 
1125 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1126