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