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