merge the formfield patch from ooo-build
[ooovba.git] / basic / source / comp / exprtree.cxx
blob499f0dd47b3506368dd8a64cbdb9e75301430d11
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: exprtree.cxx,v $
10 * $Revision: 1.24.40.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 #include "sbcomp.hxx"
35 #include <basic/sbx.hxx> // w.g. ...IMPL_REF(...sbxvariable)
36 #include "expr.hxx"
38 /***************************************************************************
40 |* SbiExpression
42 ***************************************************************************/
44 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t, SbiExprMode eMode )
46 pParser = p;
47 bError = bByVal = bBased = bBracket = FALSE;
48 nParenLevel = 0;
49 eCurExpr = t;
50 m_eMode = eMode;
51 pNext = NULL;
52 pExpr = (t != SbSTDEXPR ) ? Term() : Boolean();
53 if( t != SbSYMBOL )
54 pExpr->Optimize();
55 if( t == SbLVALUE && !pExpr->IsLvalue() )
56 p->Error( SbERR_LVALUE_EXPECTED );
57 if( t == SbOPERAND && !IsVariable() )
58 p->Error( SbERR_VAR_EXPECTED );
61 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t )
63 pParser = p;
64 eCurExpr = SbOPERAND;
65 pNext = NULL;
66 bError = bByVal = bBased = bBracket = FALSE;
67 pExpr = new SbiExprNode( pParser, n, t );
68 pExpr->Optimize();
71 SbiExpression::SbiExpression( SbiParser* p, const String& r )
73 pParser = p;
74 pNext = NULL;
75 bError = bByVal = bBased = bBracket = FALSE;
76 eCurExpr = SbOPERAND;
77 pExpr = new SbiExprNode( pParser, r );
80 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar )
82 pParser = p;
83 pNext = NULL;
84 bError = bByVal = bBased = bBracket = FALSE;
85 eCurExpr = SbOPERAND;
86 pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar );
89 SbiExpression::SbiExpression( SbiParser* p, SbiToken t )
91 pParser = p;
92 pNext = NULL;
93 bError = bByVal = bBased = bBracket = FALSE;
94 eCurExpr = SbOPERAND;
95 pExpr = new SbiExprNode( pParser, NULL, t, NULL );
98 SbiExpression::~SbiExpression()
100 delete pExpr;
103 // Einlesen eines kompletten Bezeichners
104 // Ein Bezeichner hat folgende Form:
105 // name[(Parameter)][.Name[(parameter)]]...
106 // Strukturelemente werden ueber das Element pNext verkoppelt,
107 // damit sie nicht im Baum stehen.
109 // Folgen Parameter ohne Klammer? Dies kann eine Zahl, ein String,
110 // ein Symbol oder auch ein Komma sein (wenn der 1. Parameter fehlt)
112 static BOOL DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
114 if( eTok == LPAREN )
115 return TRUE;
116 // Aber nur, wenn CALL-aehnlich!
117 if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
118 return FALSE;
119 if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING
120 || eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT )
122 return TRUE;
124 else // check for default params with reserved names ( e.g. names of tokens )
126 SbiTokenizer tokens( *(SbiTokenizer*)p );
127 // Urk the Next() / Peek() symantics are... weird
128 tokens.Next();
129 if ( tokens.Peek() == ASSIGN )
130 return TRUE;
132 return FALSE;
135 // Definition eines neuen Symbols
137 static SbiSymDef* AddSym
138 ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
139 const String& rName, SbxDataType eType, SbiParameters* pPar )
141 SbiSymDef* pDef;
142 // A= ist keine Prozedur
143 BOOL bHasType = BOOL( eTok == EQ || eTok == DOT );
144 if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
146 // Dies ist also eine Prozedur
147 // da suche man doch den richtigen Pool raus, da Procs
148 // immer in einem Public-Pool landen muessen
149 SbiSymPool* pPool = &rPool;
150 if( pPool->GetScope() != SbPUBLIC )
151 pPool = &rPool.GetParser()->aPublics;
152 SbiProcDef* pProc = pPool->AddProc( rName );
154 // Sonderbehandlung fuer Colls wie Documents(1)
155 if( eCurExpr == SbSTDEXPR )
156 bHasType = TRUE;
158 pDef = pProc;
159 pDef->SetType( bHasType ? eType : SbxEMPTY );
160 if( pPar )
162 // Dummy-Parameter generieren
163 USHORT n = 1;
164 for( short i = 0; i < pPar->GetSize(); i++ )
166 String aPar = String::CreateFromAscii( "PAR" );
167 aPar += ++n;
168 pProc->GetParams().AddSym( aPar );
172 else
174 // oder ein normales Symbol
175 pDef = rPool.AddSym( rName );
176 pDef->SetType( eType );
178 return pDef;
181 // Zur Zeit sind sogar Keywords zugelassen (wg. gleichnamiger Dflt-Properties)
183 SbiExprNode* SbiExpression::Term( void )
185 if( pParser->Peek() == DOT )
187 // eine WITH-Variable
188 SbiExprNode* pWithVar = pParser->GetWithVar();
189 // #26608: Ans Ende der Node-Kette gehen, um richtiges Objekt zu uebergeben
190 SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL;
191 SbiExprNode* pNd = NULL;
192 if( !pDef )
194 pParser->Next();
196 else
198 pNd = ObjTerm( *pDef );
199 if( pNd )
200 pNd->SetWithParent( pWithVar );
202 if( !pNd )
204 pParser->Error( SbERR_UNEXPECTED, DOT );
205 pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
207 return pNd;
210 SbiToken eTok = pParser->Next();
211 // Anfang des Parsings merken
212 pParser->LockColumn();
213 String aSym( pParser->GetSym() );
214 SbxDataType eType = pParser->GetType();
215 SbiParameters* pPar = NULL;
216 SbiExprListVector* pvMoreParLcl = NULL;
217 // Folgen Parameter?
218 SbiToken eNextTok = pParser->Peek();
219 // Ist es ein benannter Parameter?
220 // Dann einfach eine Stringkonstante erzeugen. Diese wird
221 // im SbiParameters-ctor erkannt und weiterverarbeitet
222 if( eNextTok == ASSIGN )
224 pParser->UnlockColumn();
225 return new SbiExprNode( pParser, aSym );
227 // ab hier sind keine Keywords zugelassen!
228 if( pParser->IsKwd( eTok ) )
230 if( pParser->IsCompatible() && eTok == INPUT )
232 eTok = SYMBOL;
234 else
236 pParser->Error( SbERR_SYNTAX );
237 bError = TRUE;
241 if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
243 bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
244 pPar = new SbiParameters( pParser, bStandaloneExpression );
245 bError |= !pPar->IsValid();
246 if( !bError )
247 bBracket = pPar->IsBracket();
248 eTok = pParser->Peek();
250 // i75443 check for additional sets of parameters
251 while( eTok == LPAREN )
253 if( pvMoreParLcl == NULL )
254 pvMoreParLcl = new SbiExprListVector();
255 SbiParameters* pAddPar = new SbiParameters( pParser );
256 pvMoreParLcl->push_back( pAddPar );
257 bError |= !pPar->IsValid();
258 eTok = pParser->Peek();
261 // Es koennte ein Objektteil sein, wenn . oder ! folgt
262 // Bei . muss aber die Variable bereits definiert sein; wenn pDef
263 // nach der Suche NULL ist, isses ein Objekt!
264 BOOL bObj = BOOL( ( eTok == DOT || eTok == EXCLAM )
265 && !pParser->WhiteSpace() );
266 if( bObj )
268 bBracket = FALSE; // Now the bracket for the first term is obsolete
269 if( eType == SbxVARIANT )
270 eType = SbxOBJECT;
271 else
273 // Name%. geht wirklich nicht!
274 pParser->Error( SbERR_BAD_DECLARATION, aSym );
275 bError = TRUE;
278 // Suche:
279 SbiSymDef* pDef = pParser->pPool->Find( aSym );
280 if( !pDef )
282 // Teil der Runtime-Library?
283 // AB 31.3.1996: In Parser-Methode ausgelagert
284 // (wird auch in SbiParser::DefVar() in DIM.CXX benoetigt)
285 pDef = pParser->CheckRTLForSym( aSym, eType );
287 if( !pDef )
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();
300 else
303 // Symbol ist bereits definiert.
304 // Ist es eine Konstante?
305 SbiConstDef* pConst = pDef->GetConstDef();
306 if( pConst )
308 if( pConst->GetType() == SbxSTRING )
309 return new SbiExprNode( pParser, pConst->GetString() );
310 else
311 return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() );
313 // Hat es Dimensionen,
314 // und sind auch Parameter angegeben?
315 // (Wobei 0 Parameter () entsprechen)
316 if( pDef->GetDims() )
318 if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
319 pParser->Error( SbERR_WRONG_DIMS );
321 if( pDef->IsDefinedAs() )
323 SbxDataType eDefType = pDef->GetType();
324 // #119187 Only error if types conflict
325 if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
327 // Wie? Erst mit AS definieren und dann einen Suffix nehmen?
328 pParser->Error( SbERR_BAD_DECLARATION, aSym );
329 bError = TRUE;
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;
337 // Funktion?
338 if( pDef->GetProcDef() )
340 SbiProcDef* pProc = pDef->GetProcDef();
341 if( pPar && pProc->GetLib().Len() ) // DECLARE benutzt?
342 pPar->SetProc( pProc );
343 // Wenn keine Pars, vorerst nichts machen
344 // Pruefung auf Typ-Anzahl waere denkbar
346 // Typcheck bei Variablen:
347 // ist explizit im Scanner etwas anderes angegeben?
348 // Bei Methoden ist dies OK!
349 if( eType != SbxVARIANT && // Variant nimmt alles
350 eType != pDef->GetType() &&
351 !pDef->GetProcDef() )
353 // Es kann sein, dass pDef ein Objekt beschreibt, das bisher
354 // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern
355 // AB, 16.12.95 (Vielleicht noch aehnliche Faelle moeglich ?!?)
356 if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
358 pDef->SetType( SbxOBJECT );
360 else
362 pParser->Error( SbERR_BAD_DECLARATION, aSym );
363 bError = TRUE;
367 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
368 if( !pPar )
369 pPar = new SbiParameters( pParser,FALSE,FALSE );
370 pNd->aVar.pPar = pPar;
371 pNd->aVar.pvMorePar = pvMoreParLcl;
372 if( bObj )
374 // AB, 8.1.95: Objekt kann auch vom Typ SbxVARIANT sein
375 if( pDef->GetType() == SbxVARIANT )
376 pDef->SetType( SbxOBJECT );
377 // Falls wir etwas mit Punkt einscannen, muss der
378 // Typ SbxOBJECT sein
379 if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
381 // defer error until runtime if in vba mode
382 if ( !pParser->IsVBASupportOn() )
384 pParser->Error( SbERR_BAD_DECLARATION, aSym );
385 bError = TRUE;
388 if( !bError )
389 pNd->aVar.pNext = ObjTerm( *pDef );
391 // Merken der Spalte 1 wieder freigeben
392 pParser->UnlockColumn();
393 return pNd;
396 // Aufbau eines Objekt-Terms. Ein derartiger Term ist Teil
397 // eines Ausdrucks, der mit einer Objektvariablen beginnt.
399 SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj )
401 pParser->Next();
402 SbiToken eTok = pParser->Next();
403 if( eTok != SYMBOL && !pParser->IsKwd( eTok ) && !pParser->IsExtra( eTok ) )
405 // #66745 Einige Operatoren koennen in diesem Kontext auch
406 // als Identifier zugelassen werden, wichtig fuer StarOne
407 if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
408 eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
410 pParser->Error( SbERR_VAR_EXPECTED );
411 bError = TRUE;
414 /* #118410 Allow type for Class methods and RTL object, e.g. RTL.Chr$(97)
415 else
417 if( pParser->GetType() != SbxVARIANT )
418 pParser->Error( SbERR_SYNTAX ), bError = TRUE;
421 if( bError )
422 return NULL;
424 String aSym( pParser->GetSym() );
425 SbxDataType eType = pParser->GetType();
426 SbiParameters* pPar = NULL;
427 eTok = pParser->Peek();
428 // Parameter?
429 if( DoParametersFollow( pParser, eCurExpr, eTok ) )
431 pPar = new SbiParameters( pParser );
432 bError |= !pPar->IsValid();
433 eTok = pParser->Peek();
435 BOOL bObj = BOOL( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
436 if( bObj )
438 if( eType == SbxVARIANT )
439 eType = SbxOBJECT;
440 else
442 // Name%. geht wirklich nicht!
443 pParser->Error( SbERR_BAD_DECLARATION, aSym );
444 bError = TRUE;
448 // Der Symbol-Pool eines Objekts ist immer PUBLIC
449 SbiSymPool& rPool = rObj.GetPool();
450 rPool.SetScope( SbPUBLIC );
451 SbiSymDef* pDef = rPool.Find( aSym );
452 if( !pDef )
454 pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar );
455 pDef->SetType( eType );
458 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
459 pNd->aVar.pPar = pPar;
460 if( bObj )
462 // Falls wir etwas mit Punkt einscannen, muss der
463 // Typ SbxOBJECT sein
465 // AB, 3.1.96
466 // Es kann sein, dass pDef ein Objekt beschreibt, das bisher
467 // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern
468 if( pDef->GetType() == SbxVARIANT )
469 pDef->SetType( SbxOBJECT );
471 if( pDef->GetType() != SbxOBJECT )
473 pParser->Error( SbERR_BAD_DECLARATION, aSym );
474 bError = TRUE;
476 if( !bError )
478 pNd->aVar.pNext = ObjTerm( *pDef );
479 pNd->eType = eType;
482 return pNd;
485 // Als Operanden kommen in Betracht:
486 // Konstante
487 // skalare Variable
488 // Strukturelemente
489 // Array-Elemente
490 // Funktionen
491 // geklammerte Ausdruecke
493 SbiExprNode* SbiExpression::Operand()
495 SbiExprNode *pRes;
496 SbiToken eTok;
498 // Operand testen:
499 switch( eTok = pParser->Peek() )
501 case SYMBOL:
502 pRes = Term();
503 // process something like "IF Not r Is Nothing Then .."
504 if( pParser->IsVBASupportOn() && pParser->Peek() == IS )
506 eTok = pParser->Next();
507 pRes = new SbiExprNode( pParser, pRes, eTok, Like() );
509 break;
510 case DOT: // .with
511 pRes = Term(); break;
512 case NUMBER:
513 pParser->Next();
514 pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() );
515 break;
516 case FIXSTRING:
517 pParser->Next();
518 pRes = new SbiExprNode( pParser, pParser->GetSym() ); break;
519 case LPAREN:
520 pParser->Next();
521 if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
523 m_eMode = EXPRMODE_EMPTY_PAREN;
524 pRes = new SbiExprNode(); // Dummy node
525 pParser->Next();
526 break;
528 nParenLevel++;
529 pRes = Boolean();
530 if( pParser->Peek() != RPAREN )
532 // If there was a LPARAM, it does not belong to the expression
533 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
534 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
535 else
536 pParser->Error( SbERR_BAD_BRACKETS );
538 else
540 pParser->Next();
541 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
543 SbiToken eTokAfterRParen = pParser->Peek();
544 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
545 m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
546 else
547 m_eMode = EXPRMODE_STANDARD;
550 nParenLevel--;
551 pRes->bComposite = TRUE;
552 break;
553 default:
554 // Zur Zeit sind Keywords hier OK!
555 if( pParser->IsKwd( eTok ) )
556 pRes = Term();
557 else
559 pParser->Next();
560 pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE ); // bei Fehlern
561 pParser->Error( SbERR_UNEXPECTED, eTok );
564 return pRes;
567 SbiExprNode* SbiExpression::Unary()
569 SbiExprNode* pNd;
570 SbiToken eTok = pParser->Peek();
571 switch( eTok )
573 case MINUS:
574 eTok = NEG;
575 case NOT:
576 pParser->Next();
577 // process something like "Do While Not "foo"="" "
578 if( pParser->IsVBASupportOn() )
579 pNd = new SbiExprNode( pParser, Like(), eTok, NULL );
580 else
581 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
582 break;
583 case PLUS:
584 pParser->Next();
585 pNd = Unary();
586 break;
587 case TYPEOF:
589 pParser->Next();
590 SbiExprNode* pObjNode = Operand();
591 pParser->TestToken( IS );
592 String aDummy;
593 SbiSymDef* pTypeDef = new SbiSymDef( aDummy );
594 pParser->TypeDecl( *pTypeDef, TRUE );
595 pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() );
596 break;
598 default:
599 pNd = Operand();
601 return pNd;
604 SbiExprNode* SbiExpression::Exp()
606 SbiExprNode* pNd = Unary();
607 if( m_eMode != EXPRMODE_EMPTY_PAREN )
609 while( pParser->Peek() == EXPON ) {
610 SbiToken eTok = pParser->Next();
611 pNd = new SbiExprNode( pParser, pNd, eTok, Unary() );
614 return pNd;
617 SbiExprNode* SbiExpression::MulDiv()
619 SbiExprNode* pNd = Exp();
620 if( m_eMode != EXPRMODE_EMPTY_PAREN )
622 for( ;; )
624 SbiToken eTok = pParser->Peek();
625 if( eTok != MUL && eTok != DIV )
626 break;
627 eTok = pParser->Next();
628 pNd = new SbiExprNode( pParser, pNd, eTok, Exp() );
631 return pNd;
634 SbiExprNode* SbiExpression::IntDiv()
636 SbiExprNode* pNd = MulDiv();
637 if( m_eMode != EXPRMODE_EMPTY_PAREN )
639 while( pParser->Peek() == IDIV ) {
640 SbiToken eTok = pParser->Next();
641 pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() );
644 return pNd;
647 SbiExprNode* SbiExpression::Mod()
649 SbiExprNode* pNd = IntDiv();
650 if( m_eMode != EXPRMODE_EMPTY_PAREN )
652 while( pParser->Peek() == MOD ) {
653 SbiToken eTok = pParser->Next();
654 pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() );
657 return pNd;
660 SbiExprNode* SbiExpression::AddSub()
662 SbiExprNode* pNd = Mod();
663 if( m_eMode != EXPRMODE_EMPTY_PAREN )
665 for( ;; )
667 SbiToken eTok = pParser->Peek();
668 if( eTok != PLUS && eTok != MINUS )
669 break;
670 eTok = pParser->Next();
671 pNd = new SbiExprNode( pParser, pNd, eTok, Mod() );
674 return pNd;
677 SbiExprNode* SbiExpression::Cat()
679 SbiExprNode* pNd = AddSub();
680 if( m_eMode != EXPRMODE_EMPTY_PAREN )
682 for( ;; )
684 SbiToken eTok = pParser->Peek();
685 if( eTok != CAT )
686 break;
687 eTok = pParser->Next();
688 pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() );
691 return pNd;
694 SbiExprNode* SbiExpression::Comp()
696 SbiExprNode* pNd = Cat();
697 if( m_eMode != EXPRMODE_EMPTY_PAREN )
699 short nCount = 0;
700 for( ;; )
702 SbiToken eTok = pParser->Peek();
703 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
704 break;
705 if( eTok != EQ && eTok != NE && eTok != LT
706 && eTok != GT && eTok != LE && eTok != GE )
707 break;
708 eTok = pParser->Next();
709 pNd = new SbiExprNode( pParser, pNd, eTok, Cat() );
710 nCount++;
713 return pNd;
716 SbiExprNode* SbiExpression::Like()
718 SbiExprNode* pNd = Comp();
719 if( m_eMode != EXPRMODE_EMPTY_PAREN )
721 short nCount = 0;
722 while( pParser->Peek() == LIKE ) {
723 SbiToken eTok = pParser->Next();
724 pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++;
726 // Mehrere Operatoren hintereinander gehen nicht
727 if( nCount > 1 && !pParser->IsVBASupportOn() )
729 pParser->Error( SbERR_SYNTAX );
730 bError = TRUE;
733 return pNd;
736 SbiExprNode* SbiExpression::Boolean()
738 SbiExprNode* pNd = Like();
739 if( m_eMode != EXPRMODE_EMPTY_PAREN )
741 for( ;; )
743 SbiToken eTok = pParser->Peek();
744 if( eTok != AND && eTok != OR && eTok != XOR
745 && eTok != EQV && eTok != IMP && eTok != IS )
746 break;
747 eTok = pParser->Next();
748 pNd = new SbiExprNode( pParser, pNd, eTok, Like() );
751 return pNd;
754 /***************************************************************************
756 |* SbiConstExpression
758 ***************************************************************************/
760 // Parsing einer Expression, die sich zu einer numerischen
761 // Konstanten verarbeiten laesst.
763 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
765 if( pExpr->IsConstant() )
767 eType = pExpr->GetType();
768 if( pExpr->IsNumber() )
770 nVal = pExpr->nVal;
772 else
774 nVal = 0;
775 aVal = pExpr->aStrVal;
778 else
780 // #40204 Spezialbehandlung fuer BOOL-Konstanten
781 BOOL bIsBool = FALSE;
782 if( pExpr->eNodeType == SbxVARVAL )
784 SbiSymDef* pVarDef = pExpr->GetVar();
786 // Ist es eine BOOL-Konstante?
787 BOOL bBoolVal = FALSE;
788 if( pVarDef->GetName().EqualsIgnoreCaseAscii( "true" ) )
789 //if( pVarDef->GetName().ICompare( "true" ) == COMPARE_EQUAL )
791 bIsBool = TRUE;
792 bBoolVal = TRUE;
794 else if( pVarDef->GetName().EqualsIgnoreCaseAscii( "false" ) )
795 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
797 bIsBool = TRUE;
798 bBoolVal = FALSE;
801 // Wenn es ein BOOL ist, Node austauschen
802 if( bIsBool )
804 delete pExpr;
805 pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
806 eType = pExpr->GetType();
807 nVal = pExpr->nVal;
811 if( !bIsBool )
813 pParser->Error( SbERR_SYNTAX );
814 eType = SbxDOUBLE;
815 nVal = 0;
820 short SbiConstExpression::GetShortValue()
822 if( eType == SbxSTRING )
824 SbxVariableRef refConv = new SbxVariable;
825 refConv->PutString( aVal );
826 return refConv->GetInteger();
828 else
830 double n = nVal;
831 if( n > 0 ) n += .5; else n -= .5;
832 if( n > SbxMAXINT ) n = SbxMAXINT, pParser->Error( SbERR_OUT_OF_RANGE );
833 else
834 if( n < SbxMININT ) n = SbxMININT, pParser->Error( SbERR_OUT_OF_RANGE );
835 return (short) n;
840 /***************************************************************************
842 |* SbiExprList
844 ***************************************************************************/
846 SbiExprList::SbiExprList( SbiParser* p )
848 pParser = p;
849 pFirst = NULL;
850 pProc = NULL;
851 nExpr =
852 nDim = 0;
853 bError =
854 bBracket = FALSE;
857 SbiExprList::~SbiExprList()
859 SbiExpression* p = pFirst;
860 while( p )
862 SbiExpression* q = p->pNext;
863 delete p;
864 p = q;
868 // Parameter anfordern (ab 0)
870 SbiExpression* SbiExprList::Get( short n )
872 SbiExpression* p = pFirst;
873 while( n-- && p )
874 p = p->pNext;
875 return p;
878 void SbiExprList::addExpression( SbiExpression* pExpr )
880 SbiExpression* p = pFirst;
881 while( p && p->pNext )
882 p = p->pNext;
884 p->pNext = pExpr;
888 /***************************************************************************
890 |* SbiParameters
892 ***************************************************************************/
894 // Parsender Konstruktor:
895 // Die Parameterliste wird komplett geparst.
896 // "Prozedurname()" ist OK.
897 // Dann handelt es sich um eine Funktion ohne Parameter
898 // respektive um die Angabe eines Arrays als Prozedurparameter.
900 // #i79918/#i80532: bConst has never been set to true
901 // -> reused as bStandaloneExpression
902 //SbiParameters::SbiParameters( SbiParser* p, BOOL bConst, BOOL bPar) :
903 SbiParameters::SbiParameters( SbiParser* p, BOOL bStandaloneExpression, BOOL bPar) :
904 SbiExprList( p )
906 if( !bPar )
907 return;
909 SbiExpression *pExpr;
910 SbiToken eTok = pParser->Peek();
912 // evtl. Klammer auf weg:
913 bool bAssumeExprLParenMode = false;
914 bool bAssumeArrayMode = false;
915 if( eTok == LPAREN )
917 if( bStandaloneExpression )
919 bAssumeExprLParenMode = true;
921 else
923 bBracket = TRUE;
924 pParser->Next();
925 eTok = pParser->Peek();
929 // Ende-Test
930 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
932 if( eTok == RPAREN )
933 pParser->Next();
934 return;
936 // Parametertabelle einlesen und in richtiger Folge ablegen!
937 SbiExpression* pLast = NULL;
938 String aName;
939 while( !bError )
941 aName.Erase();
942 // Fehlendes Argument
943 if( eTok == COMMA )
945 pExpr = new SbiExpression( pParser, 0, SbxEMPTY );
946 //if( bConst )
947 // pParser->Error( SbERR_SYNTAX ), bError = TRUE;
949 // Benannte Argumente: entweder .name= oder name:=
950 else
952 if( bAssumeExprLParenMode )
954 pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
955 bAssumeExprLParenMode = FALSE;
957 SbiExprMode eModeAfter = pExpr->m_eMode;
958 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
960 bBracket = TRUE;
962 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
964 // Expression "looks" like an array assignment
965 // a(...)[(...)] = ? or a(...).b(...)
966 // RPAREN is already parsed
967 bBracket = TRUE;
968 bAssumeArrayMode = true;
969 eTok = NIL;
971 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
973 bBracket = TRUE;
974 delete pExpr;
975 return;
978 else
979 pExpr = new SbiExpression( pParser );
981 //pExpr = bConst ? new SbiConstExpression( pParser )
982 // : new SbiExpression( pParser );
983 if( !bAssumeArrayMode )
985 if( pParser->Peek() == ASSIGN )
987 // VBA mode: name:=
988 // SbiExpression::Term() hat einen String daraus gemacht
989 aName = pExpr->GetString();
990 delete pExpr;
991 pParser->Next();
992 pExpr = new SbiExpression( pParser );
993 //if( bConst )
994 // pParser->Error( SbERR_SYNTAX ), bError = TRUE;
996 pExpr->GetName() = aName;
999 pExpr->pNext = NULL;
1000 if( !pLast )
1001 pFirst = pLast = pExpr;
1002 else
1003 pLast->pNext = pExpr, pLast = pExpr;
1004 nExpr++;
1005 bError |= !pExpr->IsValid();
1007 if( bAssumeArrayMode )
1008 break;
1010 // Naechstes Element?
1011 eTok = pParser->Peek();
1012 if( eTok != COMMA )
1014 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1015 break;
1016 pParser->Error( bBracket
1017 ? SbERR_BAD_BRACKETS
1018 : SbERR_EXPECTED, COMMA );
1019 bError = TRUE;
1021 else
1023 pParser->Next();
1024 eTok = pParser->Peek();
1025 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1026 break;
1029 // Schliessende Klammer
1030 if( eTok == RPAREN )
1032 pParser->Next();
1033 pParser->Peek();
1034 if( !bBracket )
1036 pParser->Error( SbERR_BAD_BRACKETS );
1037 bError = TRUE;
1040 nDim = nExpr;
1043 /***************************************************************************
1045 |* SbiDimList
1047 ***************************************************************************/
1049 // Parsender Konstruktor:
1050 // Eine Liste von Array-Dimensionen wird geparst. Die Ausdruecke werden
1051 // auf numerisch getestet. Das bCONST-Bit wird gesetzt, wenn alle Ausdruecke
1052 // Integer-Konstanten sind.
1054 SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p )
1056 bConst = TRUE;
1058 if( pParser->Next() != LPAREN )
1060 pParser->Error( SbERR_EXPECTED, LPAREN );
1061 bError = TRUE; return;
1064 if( pParser->Peek() != RPAREN )
1066 SbiExpression *pExpr1, *pExpr2, *pLast = NULL;
1067 SbiToken eTok;
1068 for( ;; )
1070 pExpr1 = new SbiExpression( pParser );
1071 eTok = pParser->Next();
1072 if( eTok == TO )
1074 pExpr2 = new SbiExpression( pParser );
1075 eTok = pParser->Next();
1076 bConst &= pExpr1->IsIntConstant() & pExpr2->IsIntConstant();
1077 bError |= !pExpr1->IsValid();
1078 bError |= !pExpr2->IsValid();
1079 pExpr1->pNext = pExpr2;
1080 if( !pLast )
1081 pFirst = pExpr1;
1082 else
1083 pLast->pNext = pExpr1;
1084 pLast = pExpr2;
1085 nExpr += 2;
1087 else
1089 // Nur eine Dim-Angabe
1090 pExpr1->SetBased();
1091 pExpr1->pNext = NULL;
1092 bConst &= pExpr1->IsIntConstant();
1093 bError |= !pExpr1->IsValid();
1094 if( !pLast )
1095 pFirst = pLast = pExpr1;
1096 else
1097 pLast->pNext = pExpr1, pLast = pExpr1;
1098 nExpr++;
1100 nDim++;
1101 if( eTok == RPAREN ) break;
1102 if( eTok != COMMA )
1104 pParser->Error( SbERR_BAD_BRACKETS );
1105 pParser->Next();
1106 break;
1110 else pParser->Next();