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