xref: /AOO41X/main/basic/source/comp/exprtree.cxx (revision e1f63238eb022c8a12b30d46a012444ff20e0951)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 
27 #include "sbcomp.hxx"
28 #include <basic/sbx.hxx>        // w.g. ...IMPL_REF(...sbxvariable)
29 #include "expr.hxx"
30 
31 /***************************************************************************
32 |*
33 |*      SbiExpression
34 |*
35 ***************************************************************************/
36 
SbiExpression(SbiParser * p,SbiExprType t,SbiExprMode eMode,const KeywordSymbolInfo * pKeywordSymbolInfo)37 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
38     SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
39 {
40     pParser = p;
41     bError = bByVal = bBased = bBracket = sal_False;
42     nParenLevel = 0;
43     eCurExpr = t;
44     m_eMode = eMode;
45     pNext = NULL;
46     pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean();
47     if( t != SbSYMBOL )
48         pExpr->Optimize();
49     if( t == SbLVALUE && !pExpr->IsLvalue() )
50         p->Error( SbERR_LVALUE_EXPECTED );
51     if( t == SbOPERAND && !IsVariable() )
52         p->Error( SbERR_VAR_EXPECTED );
53 }
54 
SbiExpression(SbiParser * p,double n,SbxDataType t)55 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t )
56 {
57     pParser = p;
58     eCurExpr = SbOPERAND;
59     pNext = NULL;
60     bError = bByVal = bBased = bBracket = sal_False;
61     pExpr = new SbiExprNode( pParser, n, t );
62     pExpr->Optimize();
63 }
64 
SbiExpression(SbiParser * p,const String & r)65 SbiExpression::SbiExpression( SbiParser* p, const String& r )
66 {
67     pParser = p;
68     pNext = NULL;
69     bError = bByVal = bBased = bBracket = sal_False;
70     eCurExpr = SbOPERAND;
71     pExpr = new SbiExprNode( pParser, r );
72 }
73 
SbiExpression(SbiParser * p,const SbiSymDef & r,SbiExprList * pPar)74 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar )
75 {
76     pParser = p;
77     pNext = NULL;
78     bError = bByVal = bBased = bBracket = sal_False;
79     eCurExpr = SbOPERAND;
80     pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar );
81 }
82 
SbiExpression(SbiParser * p,SbiToken t)83 SbiExpression::SbiExpression( SbiParser* p, SbiToken t )
84 {
85     pParser = p;
86     pNext = NULL;
87     bError = bByVal = bBased = bBracket = sal_False;
88     eCurExpr = SbOPERAND;
89     pExpr = new SbiExprNode( pParser, NULL, t, NULL );
90 }
91 
~SbiExpression()92 SbiExpression::~SbiExpression()
93 {
94     delete pExpr;
95 }
96 
97 // Einlesen eines kompletten Bezeichners
98 // Ein Bezeichner hat folgende Form:
99 // name[(Parameter)][.Name[(parameter)]]...
100 // Strukturelemente werden ueber das Element pNext verkoppelt,
101 // damit sie nicht im Baum stehen.
102 
103 // Folgen Parameter ohne Klammer? Dies kann eine Zahl, ein String,
104 // ein Symbol oder auch ein Komma sein (wenn der 1. Parameter fehlt)
105 
DoParametersFollow(SbiParser * p,SbiExprType eCurExpr,SbiToken eTok)106 static sal_Bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
107 {
108     if( eTok == LPAREN )
109         return sal_True;
110     // Aber nur, wenn CALL-aehnlich!
111     if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
112         return sal_False;
113     if (   eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING
114         || eTok == SYMBOL || eTok == COMMA  || eTok == DOT || eTok == NOT || eTok == BYVAL )
115     {
116         return sal_True;
117     }
118     else // check for default params with reserved names ( e.g. names of tokens )
119     {
120         SbiTokenizer tokens( *(SbiTokenizer*)p );
121         // Urk the Next() / Peek() symantics are... weird
122         tokens.Next();
123         if ( tokens.Peek() == ASSIGN )
124             return sal_True;
125     }
126     return sal_False;
127 }
128 
129 // Definition eines neuen Symbols
130 
AddSym(SbiToken eTok,SbiSymPool & rPool,SbiExprType eCurExpr,const String & rName,SbxDataType eType,SbiParameters * pPar)131 static SbiSymDef* AddSym
132     ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
133       const String& rName, SbxDataType eType, SbiParameters* pPar )
134 {
135     SbiSymDef* pDef;
136     // A= ist keine Prozedur
137     sal_Bool bHasType = sal_Bool( eTok == EQ || eTok == DOT );
138     if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
139     {
140         // Dies ist also eine Prozedur
141         // da suche man doch den richtigen Pool raus, da Procs
142         // immer in einem Public-Pool landen muessen
143         SbiSymPool* pPool = &rPool;
144         if( pPool->GetScope() != SbPUBLIC )
145             pPool = &rPool.GetParser()->aPublics;
146         SbiProcDef* pProc = pPool->AddProc( rName );
147 
148         // Sonderbehandlung fuer Colls wie Documents(1)
149         if( eCurExpr == SbSTDEXPR )
150             bHasType = sal_True;
151 
152         pDef = pProc;
153         pDef->SetType( bHasType ? eType : SbxEMPTY );
154         if( pPar )
155         {
156             // Dummy-Parameter generieren
157             sal_uInt16 n = 1;
158             for( short i = 0; i < pPar->GetSize(); i++ )
159             {
160                 String aPar = String::CreateFromAscii( "PAR" );
161                 aPar += ++n;
162                 pProc->GetParams().AddSym( aPar );
163             }
164         }
165     }
166     else
167     {
168         // oder ein normales Symbol
169         pDef = rPool.AddSym( rName );
170         pDef->SetType( eType );
171     }
172     return pDef;
173 }
174 
175 // Zur Zeit sind sogar Keywords zugelassen (wg. gleichnamiger Dflt-Properties)
176 
Term(const KeywordSymbolInfo * pKeywordSymbolInfo)177 SbiExprNode* SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
178 {
179     if( pParser->Peek() == DOT )
180     {
181         // eine WITH-Variable
182         SbiExprNode* pWithVar = pParser->GetWithVar();
183         // #26608: Ans Ende der Node-Kette gehen, um richtiges Objekt zu uebergeben
184         SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL;
185         SbiExprNode* pNd = NULL;
186         if( !pDef )
187         {
188             pParser->Next();
189         }
190         else
191         {
192             pNd = ObjTerm( *pDef );
193             if( pNd )
194                 pNd->SetWithParent( pWithVar );
195         }
196         if( !pNd )
197         {
198             pParser->Error( SbERR_UNEXPECTED, DOT );
199             pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
200         }
201         return pNd;
202     }
203 
204     SbiToken eTok = (pKeywordSymbolInfo == NULL) ? pParser->Next() : pKeywordSymbolInfo->m_eTok;
205     // Anfang des Parsings merken
206     pParser->LockColumn();
207     String aSym( (pKeywordSymbolInfo == NULL) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol );
208     SbxDataType eType = (pKeywordSymbolInfo == NULL) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType;
209     SbiParameters* pPar = NULL;
210     SbiExprListVector* pvMoreParLcl = NULL;
211     // Folgen Parameter?
212     SbiToken eNextTok = pParser->Peek();
213     // Ist es ein benannter Parameter?
214     // Dann einfach eine Stringkonstante erzeugen. Diese wird
215     // im SbiParameters-ctor erkannt und weiterverarbeitet
216     if( eNextTok == ASSIGN )
217     {
218         pParser->UnlockColumn();
219         return new SbiExprNode( pParser, aSym );
220     }
221     // ab hier sind keine Keywords zugelassen!
222     if( pParser->IsKwd( eTok ) )
223     {
224         if( pParser->IsCompatible() && eTok == INPUT )
225         {
226             eTok = SYMBOL;
227         }
228         else
229         {
230             pParser->Error( SbERR_SYNTAX );
231             bError = sal_True;
232         }
233     }
234 
235     if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
236     {
237         bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
238         pPar = new SbiParameters( pParser, bStandaloneExpression );
239         bError |= !pPar->IsValid();
240         if( !bError )
241             bBracket = pPar->IsBracket();
242         eTok = pParser->Peek();
243 
244         // i75443 check for additional sets of parameters
245         while( eTok == LPAREN )
246         {
247             if( pvMoreParLcl == NULL )
248                 pvMoreParLcl = new SbiExprListVector();
249             SbiParameters* pAddPar = new SbiParameters( pParser );
250             pvMoreParLcl->push_back( pAddPar );
251             bError |= !pPar->IsValid();
252             eTok = pParser->Peek();
253         }
254     }
255     // Es koennte ein Objektteil sein, wenn . oder ! folgt
256     // Bei . muss aber die Variable bereits definiert sein; wenn pDef
257     // nach der Suche NULL ist, isses ein Objekt!
258     sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM )
259                     && !pParser->WhiteSpace() );
260     if( bObj )
261     {
262         bBracket = sal_False;   // Now the bracket for the first term is obsolete
263         if( eType == SbxVARIANT )
264             eType = SbxOBJECT;
265         else
266         {
267             // Name%. geht wirklich nicht!
268             pParser->Error( SbERR_BAD_DECLARATION, aSym );
269             bError = sal_True;
270         }
271     }
272     // Suche:
273     SbiSymDef* pDef = pParser->pPool->Find( aSym );
274     if( !pDef )
275     {
276         // Teil der Runtime-Library?
277         // AB 31.3.1996: In Parser-Methode ausgelagert
278         // (wird auch in SbiParser::DefVar() in DIM.CXX benoetigt)
279         pDef = pParser->CheckRTLForSym( aSym, eType );
280 
281         // #i109184: Check if symbol is or later will be defined inside module
282         SbModule& rMod = pParser->aGen.GetModule();
283         SbxArray* pModMethods = rMod.GetMethods();
284         if( pModMethods->Find( aSym, SbxCLASS_DONTCARE ) )
285             pDef = NULL;
286     }
287     if( !pDef )
288     {
289         // Falls ein Punkt angegeben war, isses Teil eines Objekts,
290         // also muss der Returnwert ein Objekt sein
291         if( bObj )
292             eType = SbxOBJECT;
293         pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar );
294         // Looks like this is a local ( but undefined variable )
295         // if it is in a static procedure then make this Symbol
296         // static
297         if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
298             pDef->SetStatic();
299     }
300     else
301     {
302 
303         // Symbol ist bereits definiert.
304         // Ist es eine Konstante?
305         SbiConstDef* pConst = pDef->GetConstDef();
306         if( pConst )
307         {
308             if( pConst->GetType() == SbxSTRING )
309                 return new SbiExprNode( pParser, pConst->GetString() );
310             else
311                 return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() );
312         }
313         // Hat es Dimensionen,
314         // und sind auch Parameter angegeben?
315         // (Wobei 0 Parameter () entsprechen)
316         if( pDef->GetDims() )
317         {
318             if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
319                 pParser->Error( SbERR_WRONG_DIMS );
320         }
321         if( pDef->IsDefinedAs() )
322         {
323             SbxDataType eDefType = pDef->GetType();
324             // #119187 Only error if types conflict
325             if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
326             {
327                 // Wie? Erst mit AS definieren und dann einen Suffix nehmen?
328                 pParser->Error( SbERR_BAD_DECLARATION, aSym );
329                 bError = sal_True;
330             }
331             else if ( eType == SbxVARIANT )
332                 // Falls nix angegeben, den Typ des Eintrags nehmen
333                 // aber nur, wenn die Var nicht mit AS XXX definiert ist
334                 // damit erwischen wir n% = 5 : print n
335                 eType = eDefType;
336         }
337         // Typcheck bei Variablen:
338         // ist explizit im Scanner etwas anderes angegeben?
339         // Bei Methoden ist dies OK!
340         if( eType != SbxVARIANT &&          // Variant nimmt alles
341             eType != pDef->GetType() &&
342             !pDef->GetProcDef() )
343         {
344             // Es kann sein, dass pDef ein Objekt beschreibt, das bisher
345             // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern
346             // AB, 16.12.95 (Vielleicht noch aehnliche Faelle moeglich ?!?)
347             if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
348             {
349                 pDef->SetType( SbxOBJECT );
350             }
351             else
352             {
353                 pParser->Error( SbERR_BAD_DECLARATION, aSym );
354                 bError = sal_True;
355             }
356         }
357     }
358     SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
359     if( !pPar )
360         pPar = new SbiParameters( pParser,sal_False,sal_False );
361     pNd->aVar.pPar = pPar;
362     pNd->aVar.pvMorePar = pvMoreParLcl;
363     if( bObj )
364     {
365         // AB, 8.1.95: Objekt kann auch vom Typ SbxVARIANT sein
366         if( pDef->GetType() == SbxVARIANT )
367             pDef->SetType( SbxOBJECT );
368         // Falls wir etwas mit Punkt einscannen, muss der
369         // Typ SbxOBJECT sein
370         if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
371         {
372             pParser->Error( SbERR_BAD_DECLARATION, aSym );
373             bError = sal_True;
374         }
375         if( !bError )
376             pNd->aVar.pNext = ObjTerm( *pDef );
377     }
378     // Merken der Spalte 1 wieder freigeben
379     pParser->UnlockColumn();
380     return pNd;
381 }
382 
383 // Aufbau eines Objekt-Terms. Ein derartiger Term ist Teil
384 // eines Ausdrucks, der mit einer Objektvariablen beginnt.
385 
ObjTerm(SbiSymDef & rObj)386 SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj )
387 {
388     pParser->Next();
389     SbiToken eTok = pParser->Next();
390     if( eTok != SYMBOL && !pParser->IsKwd( eTok ) && !pParser->IsExtra( eTok ) )
391     {
392         // #66745 Einige Operatoren koennen in diesem Kontext auch
393         // als Identifier zugelassen werden, wichtig fuer StarOne
394         if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
395             eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
396         {
397             pParser->Error( SbERR_VAR_EXPECTED );
398             bError = sal_True;
399         }
400     }
401     /* #118410 Allow type for Class methods and RTL object, e.g. RTL.Chr$(97)
402     else
403     {
404         if( pParser->GetType() != SbxVARIANT )
405             pParser->Error( SbERR_SYNTAX ), bError = sal_True;
406     }
407     */
408     if( bError )
409         return NULL;
410 
411     String aSym( pParser->GetSym() );
412     SbxDataType eType = pParser->GetType();
413     SbiParameters* pPar = NULL;
414     SbiExprListVector* pvMoreParLcl = NULL;
415     eTok = pParser->Peek();
416     // Parameter?
417     if( DoParametersFollow( pParser, eCurExpr, eTok ) )
418     {
419         bool bStandaloneExpression = false;
420         pPar = new SbiParameters( pParser, bStandaloneExpression );
421         bError |= !pPar->IsValid();
422         eTok = pParser->Peek();
423 
424         // i109624 check for additional sets of parameters
425         while( eTok == LPAREN )
426         {
427             if( pvMoreParLcl == NULL )
428                 pvMoreParLcl = new SbiExprListVector();
429             SbiParameters* pAddPar = new SbiParameters( pParser );
430             pvMoreParLcl->push_back( pAddPar );
431             bError |= !pPar->IsValid();
432             eTok = pParser->Peek();
433         }
434 
435     }
436     sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
437     if( bObj )
438     {
439         if( eType == SbxVARIANT )
440             eType = SbxOBJECT;
441         else
442         {
443             // Name%. geht wirklich nicht!
444             pParser->Error( SbERR_BAD_DECLARATION, aSym );
445             bError = sal_True;
446         }
447     }
448 
449     // Der Symbol-Pool eines Objekts ist immer PUBLIC
450     SbiSymPool& rPool = rObj.GetPool();
451     rPool.SetScope( SbPUBLIC );
452     SbiSymDef* pDef = rPool.Find( aSym );
453     if( !pDef )
454     {
455         pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar );
456         pDef->SetType( eType );
457     }
458 
459     SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
460     pNd->aVar.pPar = pPar;
461     pNd->aVar.pvMorePar = pvMoreParLcl;
462     if( bObj )
463     {
464         // Falls wir etwas mit Punkt einscannen, muss der
465         // Typ SbxOBJECT sein
466 
467         // AB, 3.1.96
468         // Es kann sein, dass pDef ein Objekt beschreibt, das bisher
469         // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern
470         if( pDef->GetType() == SbxVARIANT )
471             pDef->SetType( SbxOBJECT );
472 
473         if( pDef->GetType() != SbxOBJECT )
474         {
475             pParser->Error( SbERR_BAD_DECLARATION, aSym );
476             bError = sal_True;
477         }
478         if( !bError )
479         {
480             pNd->aVar.pNext = ObjTerm( *pDef );
481             pNd->eType = eType;
482         }
483     }
484     return pNd;
485 }
486 
487 // Als Operanden kommen in Betracht:
488 //      Konstante
489 //      skalare Variable
490 //      Strukturelemente
491 //      Array-Elemente
492 //      Funktionen
493 //      geklammerte Ausdruecke
494 
Operand(bool bUsedForTypeOf)495 SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf )
496 {
497     SbiExprNode *pRes;
498     SbiToken eTok;
499 
500     // Operand testen:
501     switch( eTok = pParser->Peek() )
502     {
503         case SYMBOL:
504             pRes = Term();
505             // process something like "IF Not r Is Nothing Then .."
506             if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
507             {
508                 eTok = pParser->Next();
509                 pRes = new SbiExprNode( pParser, pRes, eTok, Like() );
510             }
511             break;
512         case DOT:   // .with
513             pRes = Term(); break;
514         case NUMBER:
515             pParser->Next();
516             pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() );
517             break;
518         case FIXSTRING:
519             pParser->Next();
520             pRes = new SbiExprNode( pParser, pParser->GetSym() ); break;
521         case LPAREN:
522             pParser->Next();
523             if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
524             {
525                 m_eMode = EXPRMODE_EMPTY_PAREN;
526                 pRes = new SbiExprNode();   // Dummy node
527                 pParser->Next();
528                 break;
529             }
530             nParenLevel++;
531             pRes = Boolean();
532             if( pParser->Peek() != RPAREN )
533             {
534                 // If there was a LPARAM, it does not belong to the expression
535                 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
536                     m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
537                 else
538                     pParser->Error( SbERR_BAD_BRACKETS );
539             }
540             else
541             {
542                 pParser->Next();
543                 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
544                 {
545                     SbiToken eTokAfterRParen = pParser->Peek();
546                     if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
547                         m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
548                     else
549                         m_eMode = EXPRMODE_STANDARD;
550                 }
551             }
552             nParenLevel--;
553             pRes->bComposite = sal_True;
554             break;
555         default:
556             // Zur Zeit sind Keywords hier OK!
557             if( pParser->IsKwd( eTok ) )
558                 pRes = Term();
559             else
560             {
561                 pParser->Next();
562                 pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE ); // bei Fehlern
563                 pParser->Error( SbERR_UNEXPECTED, eTok );
564             }
565     }
566     return pRes;
567 }
568 
Unary()569 SbiExprNode* SbiExpression::Unary()
570 {
571     SbiExprNode* pNd;
572     SbiToken eTok = pParser->Peek();
573     switch( eTok )
574     {
575         case MINUS:
576             eTok = NEG;
577             pParser->Next();
578             pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
579             break;
580         case NOT:
581             if( pParser->IsVBASupportOn() )
582             {
583                 pNd = Operand();
584             }
585             else
586             {
587                 pParser->Next();
588                 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
589             }
590             break;
591         case PLUS:
592             pParser->Next();
593             pNd = Unary();
594             break;
595         case TYPEOF:
596         {
597             pParser->Next();
598             bool bUsedForTypeOf = true;
599             SbiExprNode* pObjNode = Operand( bUsedForTypeOf );
600             pParser->TestToken( IS );
601             String aDummy;
602             SbiSymDef* pTypeDef = new SbiSymDef( aDummy );
603             pParser->TypeDecl( *pTypeDef, sal_True );
604             pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() );
605             break;
606         }
607         case NEW:
608         {
609             pParser->Next();
610             String aStr;
611             SbiSymDef* pTypeDef = new SbiSymDef( aStr );
612             pParser->TypeDecl( *pTypeDef, sal_True );
613             pNd = new SbiExprNode( pParser, pTypeDef->GetTypeId() );
614             break;
615         }
616         default:
617             pNd = Operand();
618     }
619     return pNd;
620 }
621 
Exp()622 SbiExprNode* SbiExpression::Exp()
623 {
624     SbiExprNode* pNd = Unary();
625     if( m_eMode != EXPRMODE_EMPTY_PAREN )
626     {
627         while( pParser->Peek() == EXPON ) {
628             SbiToken eTok = pParser->Next();
629             pNd = new SbiExprNode( pParser, pNd, eTok, Unary() );
630         }
631     }
632     return pNd;
633 }
634 
MulDiv()635 SbiExprNode* SbiExpression::MulDiv()
636 {
637     SbiExprNode* pNd = Exp();
638     if( m_eMode != EXPRMODE_EMPTY_PAREN )
639     {
640         for( ;; )
641         {
642             SbiToken eTok = pParser->Peek();
643             if( eTok != MUL && eTok != DIV )
644                 break;
645             eTok = pParser->Next();
646             pNd = new SbiExprNode( pParser, pNd, eTok, Exp() );
647         }
648     }
649     return pNd;
650 }
651 
IntDiv()652 SbiExprNode* SbiExpression::IntDiv()
653 {
654     SbiExprNode* pNd = MulDiv();
655     if( m_eMode != EXPRMODE_EMPTY_PAREN )
656     {
657         while( pParser->Peek() == IDIV ) {
658             SbiToken eTok = pParser->Next();
659             pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() );
660         }
661     }
662     return pNd;
663 }
664 
Mod()665 SbiExprNode* SbiExpression::Mod()
666 {
667     SbiExprNode* pNd = IntDiv();
668     if( m_eMode != EXPRMODE_EMPTY_PAREN )
669     {
670         while( pParser->Peek() == MOD ) {
671             SbiToken eTok = pParser->Next();
672             pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() );
673         }
674     }
675     return pNd;
676 }
677 
AddSub()678 SbiExprNode* SbiExpression::AddSub()
679 {
680     SbiExprNode* pNd = Mod();
681     if( m_eMode != EXPRMODE_EMPTY_PAREN )
682     {
683         for( ;; )
684         {
685             SbiToken eTok = pParser->Peek();
686             if( eTok != PLUS && eTok != MINUS )
687                 break;
688             eTok = pParser->Next();
689             pNd = new SbiExprNode( pParser, pNd, eTok, Mod() );
690         }
691     }
692     return pNd;
693 }
694 
Cat()695 SbiExprNode* SbiExpression::Cat()
696 {
697     SbiExprNode* pNd = AddSub();
698     if( m_eMode != EXPRMODE_EMPTY_PAREN )
699     {
700         for( ;; )
701         {
702             SbiToken eTok = pParser->Peek();
703             if( eTok != CAT )
704                 break;
705             eTok = pParser->Next();
706             pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() );
707         }
708     }
709     return pNd;
710 }
711 
Comp()712 SbiExprNode* SbiExpression::Comp()
713 {
714     SbiExprNode* pNd = Cat();
715     if( m_eMode != EXPRMODE_EMPTY_PAREN )
716     {
717         short nCount = 0;
718         for( ;; )
719         {
720             SbiToken eTok = pParser->Peek();
721             if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
722                 break;
723             if( eTok != EQ && eTok != NE && eTok != LT
724              && eTok != GT && eTok != LE && eTok != GE )
725                 break;
726             eTok = pParser->Next();
727             pNd = new SbiExprNode( pParser, pNd, eTok, Cat() );
728             nCount++;
729         }
730     }
731     return pNd;
732 }
733 
VBA_Not()734 SbiExprNode* SbiExpression::VBA_Not()
735 {
736     SbiExprNode* pNd = NULL;
737 
738     SbiToken eTok = pParser->Peek();
739     if( eTok == NOT )
740     {
741         pParser->Next();
742         pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL );
743     }
744     else
745     {
746         pNd = Comp();
747     }
748     return pNd;
749 }
750 
Like()751 SbiExprNode* SbiExpression::Like()
752 {
753     SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
754     if( m_eMode != EXPRMODE_EMPTY_PAREN )
755     {
756         short nCount = 0;
757         while( pParser->Peek() == LIKE ) {
758             SbiToken eTok = pParser->Next();
759             pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++;
760         }
761         // Mehrere Operatoren hintereinander gehen nicht
762         if( nCount > 1 )
763         {
764             pParser->Error( SbERR_SYNTAX );
765             bError = sal_True;
766         }
767     }
768     return pNd;
769 }
770 
Boolean()771 SbiExprNode* SbiExpression::Boolean()
772 {
773     SbiExprNode* pNd = Like();
774     if( m_eMode != EXPRMODE_EMPTY_PAREN )
775     {
776         for( ;; )
777         {
778             SbiToken eTok = pParser->Peek();
779             if( eTok != AND && eTok != OR && eTok != XOR
780              && eTok != EQV && eTok != IMP && eTok != IS )
781                 break;
782             eTok = pParser->Next();
783             pNd = new SbiExprNode( pParser, pNd, eTok, Like() );
784         }
785     }
786     return pNd;
787 }
788 
789 /***************************************************************************
790 |*
791 |*      SbiConstExpression
792 |*
793 ***************************************************************************/
794 
795 // Parsing einer Expression, die sich zu einer numerischen
796 // Konstanten verarbeiten laesst.
797 
SbiConstExpression(SbiParser * p)798 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
799 {
800     if( pExpr->IsConstant() )
801     {
802         eType = pExpr->GetType();
803         if( pExpr->IsNumber() )
804         {
805             nVal = pExpr->nVal;
806         }
807         else
808         {
809             nVal = 0;
810             aVal = pExpr->aStrVal;
811         }
812     }
813     else
814     {
815         // #40204 Spezialbehandlung fuer sal_Bool-Konstanten
816         sal_Bool bIsBool = sal_False;
817         if( pExpr->eNodeType == SbxVARVAL )
818         {
819             SbiSymDef* pVarDef = pExpr->GetVar();
820 
821             // Ist es eine sal_Bool-Konstante?
822             sal_Bool bBoolVal = sal_False;
823             if( pVarDef->GetName().EqualsIgnoreCaseAscii( "true" ) )
824             //if( pVarDef->GetName().ICompare( "true" ) == COMPARE_EQUAL )
825             {
826                 bIsBool = sal_True;
827                 bBoolVal = sal_True;
828             }
829             else if( pVarDef->GetName().EqualsIgnoreCaseAscii( "false" ) )
830             //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
831             {
832                 bIsBool = sal_True;
833                 bBoolVal = sal_False;
834             }
835 
836             // Wenn es ein sal_Bool ist, Node austauschen
837             if( bIsBool )
838             {
839                 delete pExpr;
840                 pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
841                 eType = pExpr->GetType();
842                 nVal = pExpr->nVal;
843             }
844         }
845 
846         if( !bIsBool )
847         {
848             pParser->Error( SbERR_SYNTAX );
849             eType = SbxDOUBLE;
850             nVal = 0;
851         }
852     }
853 }
854 
GetShortValue()855 short SbiConstExpression::GetShortValue()
856 {
857     if( eType == SbxSTRING )
858     {
859         SbxVariableRef refConv = new SbxVariable;
860         refConv->PutString( aVal );
861         return refConv->GetInteger();
862     }
863     else
864     {
865         double n = nVal;
866         if( n > 0 ) n += .5; else n -= .5;
867         if( n > SbxMAXINT ) n = SbxMAXINT, pParser->Error( SbERR_OUT_OF_RANGE );
868         else
869         if( n < SbxMININT ) n = SbxMININT, pParser->Error( SbERR_OUT_OF_RANGE );
870         return (short) n;
871     }
872 }
873 
874 
875 /***************************************************************************
876 |*
877 |*      SbiExprList
878 |*
879 ***************************************************************************/
880 
SbiExprList(SbiParser * p)881 SbiExprList::SbiExprList( SbiParser* p )
882 {
883     pParser = p;
884     pFirst = NULL;
885     nExpr  =
886     nDim   = 0;
887     bError =
888     bBracket = sal_False;
889 }
890 
~SbiExprList()891 SbiExprList::~SbiExprList()
892 {
893     SbiExpression* p = pFirst;
894     while( p )
895     {
896         SbiExpression* q = p->pNext;
897         delete p;
898         p = q;
899     }
900 }
901 
902 // Parameter anfordern (ab 0)
903 
Get(short n)904 SbiExpression* SbiExprList::Get( short n )
905 {
906     SbiExpression* p = pFirst;
907     while( n-- && p )
908         p = p->pNext;
909     return p;
910 }
911 
addExpression(SbiExpression * pExpr)912 void SbiExprList::addExpression( SbiExpression* pExpr )
913 {
914     SbiExpression* p = pFirst;
915     while( p && p->pNext )
916         p = p->pNext;
917 
918     p->pNext = pExpr;
919 }
920 
921 
922 /***************************************************************************
923 |*
924 |*      SbiParameters
925 |*
926 ***************************************************************************/
927 
928 // Parsender Konstruktor:
929 // Die Parameterliste wird komplett geparst.
930 // "Prozedurname()" ist OK.
931 // Dann handelt es sich um eine Funktion ohne Parameter
932 // respektive um die Angabe eines Arrays als Prozedurparameter.
933 
934 // #i79918/#i80532: bConst has never been set to true
935 // -> reused as bStandaloneExpression
936 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
SbiParameters(SbiParser * p,sal_Bool bStandaloneExpression,sal_Bool bPar)937 SbiParameters::SbiParameters( SbiParser* p, sal_Bool bStandaloneExpression, sal_Bool bPar) :
938     SbiExprList( p )
939 {
940     if( !bPar )
941         return;
942 
943     SbiExpression *pExpr;
944     SbiToken eTok = pParser->Peek();
945 
946     // evtl. Klammer auf weg:
947     bool bAssumeExprLParenMode = false;
948     bool bAssumeArrayMode = false;
949     if( eTok == LPAREN )
950     {
951         if( bStandaloneExpression )
952         {
953             bAssumeExprLParenMode = true;
954         }
955         else
956         {
957             bBracket = sal_True;
958             pParser->Next();
959             eTok = pParser->Peek();
960         }
961     }
962 
963     // Ende-Test
964     if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
965     {
966         if( eTok == RPAREN )
967             pParser->Next();
968         return;
969     }
970     // Parametertabelle einlesen und in richtiger Folge ablegen!
971     SbiExpression* pLast = NULL;
972     String aName;
973     while( !bError )
974     {
975         aName.Erase();
976         // Fehlendes Argument
977         if( eTok == COMMA )
978         {
979             pExpr = new SbiExpression( pParser, 0, SbxEMPTY );
980             //if( bConst )
981             //  pParser->Error( SbERR_SYNTAX ), bError = sal_True;
982         }
983         // Benannte Argumente: entweder .name= oder name:=
984         else
985         {
986             bool bByVal = false;
987             if( eTok == BYVAL )
988             {
989                 bByVal = true;
990                 pParser->Next();
991                 eTok = pParser->Peek();
992             }
993 
994             if( bAssumeExprLParenMode )
995             {
996                 pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
997                 bAssumeExprLParenMode = sal_False;
998 
999                 SbiExprMode eModeAfter = pExpr->m_eMode;
1000                 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
1001                 {
1002                     bBracket = sal_True;
1003                 }
1004                 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
1005                 {
1006                     // Expression "looks" like an array assignment
1007                     // a(...)[(...)] = ? or a(...).b(...)
1008                     // RPAREN is already parsed
1009                     bBracket = sal_True;
1010                     bAssumeArrayMode = true;
1011                     eTok = NIL;
1012                 }
1013                 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1014                 {
1015                     bBracket = sal_True;
1016                     delete pExpr;
1017                     if( bByVal )
1018                         pParser->Error( SbERR_LVALUE_EXPECTED );
1019                     return;
1020                 }
1021             }
1022             else
1023                 pExpr = new SbiExpression( pParser );
1024 
1025             if( bByVal && pExpr->IsLvalue() )
1026                 pExpr->SetByVal();
1027 
1028             //pExpr = bConst ? new SbiConstExpression( pParser )
1029             //              : new SbiExpression( pParser );
1030             if( !bAssumeArrayMode )
1031             {
1032                 if( pParser->Peek() == ASSIGN )
1033                 {
1034                     // VBA mode: name:=
1035                     // SbiExpression::Term() hat einen String daraus gemacht
1036                     aName = pExpr->GetString();
1037                     delete pExpr;
1038                     pParser->Next();
1039                     pExpr = new SbiExpression( pParser );
1040                     //if( bConst )
1041                     //  pParser->Error( SbERR_SYNTAX ), bError = sal_True;
1042                 }
1043                 pExpr->GetName() = aName;
1044             }
1045         }
1046         pExpr->pNext = NULL;
1047         if( !pLast )
1048             pFirst = pLast = pExpr;
1049         else
1050             pLast->pNext = pExpr, pLast = pExpr;
1051         nExpr++;
1052         bError |= !pExpr->IsValid();
1053 
1054         if( bAssumeArrayMode )
1055             break;
1056 
1057         // Naechstes Element?
1058         eTok = pParser->Peek();
1059         if( eTok != COMMA )
1060         {
1061             if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1062                 break;
1063             pParser->Error( bBracket
1064                             ? SbERR_BAD_BRACKETS
1065                             : SbERR_EXPECTED, COMMA );
1066             bError = sal_True;
1067         }
1068         else
1069         {
1070             pParser->Next();
1071             eTok = pParser->Peek();
1072             if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1073                 break;
1074         }
1075     }
1076     // Schliessende Klammer
1077     if( eTok == RPAREN )
1078     {
1079         pParser->Next();
1080         pParser->Peek();
1081         if( !bBracket )
1082         {
1083             pParser->Error( SbERR_BAD_BRACKETS );
1084             bError = sal_True;
1085         }
1086     }
1087     nDim = nExpr;
1088 }
1089 
1090 /***************************************************************************
1091 |*
1092 |*      SbiDimList
1093 |*
1094 ***************************************************************************/
1095 
1096 // Parsender Konstruktor:
1097 // Eine Liste von Array-Dimensionen wird geparst. Die Ausdruecke werden
1098 // auf numerisch getestet. Das bCONST-Bit wird gesetzt, wenn alle Ausdruecke
1099 // Integer-Konstanten sind.
1100 
SbiDimList(SbiParser * p)1101 SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p )
1102 {
1103     bConst = sal_True;
1104 
1105     if( pParser->Next() != LPAREN )
1106     {
1107         pParser->Error( SbERR_EXPECTED, LPAREN );
1108         bError = sal_True; return;
1109     }
1110 
1111     if( pParser->Peek() != RPAREN )
1112     {
1113         SbiExpression *pExpr1, *pExpr2, *pLast = NULL;
1114         SbiToken eTok;
1115         for( ;; )
1116         {
1117             pExpr1 = new SbiExpression( pParser );
1118             eTok = pParser->Next();
1119             if( eTok == TO )
1120             {
1121                 pExpr2 = new SbiExpression( pParser );
1122                 eTok = pParser->Next();
1123                 bConst &= pExpr1->IsIntConstant() & pExpr2->IsIntConstant();
1124                 bError |= !pExpr1->IsValid();
1125                 bError |= !pExpr2->IsValid();
1126                 pExpr1->pNext = pExpr2;
1127                 if( !pLast )
1128                     pFirst = pExpr1;
1129                 else
1130                     pLast->pNext = pExpr1;
1131                 pLast = pExpr2;
1132                 nExpr += 2;
1133             }
1134             else
1135             {
1136                 // Nur eine Dim-Angabe
1137                 pExpr1->SetBased();
1138                 pExpr1->pNext = NULL;
1139                 bConst &= pExpr1->IsIntConstant();
1140                 bError |= !pExpr1->IsValid();
1141                 if( !pLast )
1142                     pFirst = pLast = pExpr1;
1143                 else
1144                     pLast->pNext = pExpr1, pLast = pExpr1;
1145                 nExpr++;
1146             }
1147             nDim++;
1148             if( eTok == RPAREN ) break;
1149             if( eTok != COMMA )
1150             {
1151                 pParser->Error( SbERR_BAD_BRACKETS );
1152                 pParser->Next();
1153                 break;
1154             }
1155         }
1156     }
1157     else pParser->Next();
1158 }
1159 
1160