1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
35 #include <basic/sbx.hxx> // w.g. ...IMPL_REF(...sbxvariable)
38 /***************************************************************************
42 ***************************************************************************/
44 SbiExpression::SbiExpression( SbiParser
* p
, SbiExprType t
, SbiExprMode eMode
)
47 bError
= bByVal
= bBased
= bBracket
= FALSE
;
52 pExpr
= (t
!= SbSTDEXPR
) ? Term() : Boolean();
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
)
66 bError
= bByVal
= bBased
= bBracket
= FALSE
;
67 pExpr
= new SbiExprNode( pParser
, n
, t
);
71 SbiExpression::SbiExpression( SbiParser
* p
, const String
& r
)
75 bError
= bByVal
= bBased
= bBracket
= FALSE
;
77 pExpr
= new SbiExprNode( pParser
, r
);
80 SbiExpression::SbiExpression( SbiParser
* p
, const SbiSymDef
& r
, SbiExprList
* pPar
)
84 bError
= bByVal
= bBased
= bBracket
= FALSE
;
86 pExpr
= new SbiExprNode( pParser
, r
, SbxVARIANT
, pPar
);
89 SbiExpression::SbiExpression( SbiParser
* p
, SbiToken t
)
93 bError
= bByVal
= bBased
= bBracket
= FALSE
;
95 pExpr
= new SbiExprNode( pParser
, NULL
, t
, NULL
);
98 SbiExpression::~SbiExpression()
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
)
116 // Aber nur, wenn CALL-aehnlich!
117 if( !p
->WhiteSpace() || eCurExpr
!= SbSYMBOL
)
119 if ( eTok
== NUMBER
|| eTok
== MINUS
|| eTok
== FIXSTRING
120 || eTok
== SYMBOL
|| eTok
== COMMA
|| eTok
== DOT
|| eTok
== NOT
)
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
129 if ( tokens
.Peek() == ASSIGN
)
135 // Definition eines neuen Symbols
137 static SbiSymDef
* AddSym
138 ( SbiToken eTok
, SbiSymPool
& rPool
, SbiExprType eCurExpr
,
139 const String
& rName
, SbxDataType eType
, SbiParameters
* pPar
)
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
)
159 pDef
->SetType( bHasType
? eType
: SbxEMPTY
);
162 // Dummy-Parameter generieren
164 for( short i
= 0; i
< pPar
->GetSize(); i
++ )
166 String aPar
= String::CreateFromAscii( "PAR" );
168 pProc
->GetParams().AddSym( aPar
);
174 // oder ein normales Symbol
175 pDef
= rPool
.AddSym( rName
);
176 pDef
->SetType( eType
);
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
;
198 pNd
= ObjTerm( *pDef
);
200 pNd
->SetWithParent( pWithVar
);
204 pParser
->Error( SbERR_UNEXPECTED
, DOT
);
205 pNd
= new SbiExprNode( pParser
, 1.0, SbxDOUBLE
);
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
;
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
)
236 pParser
->Error( SbERR_SYNTAX
);
241 if( DoParametersFollow( pParser
, eCurExpr
, eTok
= eNextTok
) )
243 bool bStandaloneExpression
= (m_eMode
== EXPRMODE_STANDALONE
);
244 pPar
= new SbiParameters( pParser
, bStandaloneExpression
);
245 bError
|= !pPar
->IsValid();
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() );
268 bBracket
= FALSE
; // Now the bracket for the first term is obsolete
269 if( eType
== SbxVARIANT
)
273 // Name%. geht wirklich nicht!
274 pParser
->Error( SbERR_BAD_DECLARATION
, aSym
);
279 SbiSymDef
* pDef
= pParser
->pPool
->Find( aSym
);
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
);
289 // Falls ein Punkt angegeben war, isses Teil eines Objekts,
290 // also muss der Returnwert ein Objekt sein
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
297 if ( !bObj
&& pParser
->pProc
&& pParser
->pProc
->IsStatic() )
303 // Symbol ist bereits definiert.
304 // Ist es eine Konstante?
305 SbiConstDef
* pConst
= pDef
->GetConstDef();
308 if( pConst
->GetType() == SbxSTRING
)
309 return new SbiExprNode( pParser
, pConst
->GetString() );
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
);
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
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
);
362 pParser
->Error( SbERR_BAD_DECLARATION
, aSym
);
367 SbiExprNode
* pNd
= new SbiExprNode( pParser
, *pDef
, eType
);
369 pPar
= new SbiParameters( pParser
,FALSE
,FALSE
);
370 pNd
->aVar
.pPar
= pPar
;
371 pNd
->aVar
.pvMorePar
= pvMoreParLcl
;
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
);
389 pNd
->aVar
.pNext
= ObjTerm( *pDef
);
391 // Merken der Spalte 1 wieder freigeben
392 pParser
->UnlockColumn();
396 // Aufbau eines Objekt-Terms. Ein derartiger Term ist Teil
397 // eines Ausdrucks, der mit einer Objektvariablen beginnt.
399 SbiExprNode
* SbiExpression::ObjTerm( SbiSymDef
& rObj
)
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
);
414 /* #118410 Allow type for Class methods and RTL object, e.g. RTL.Chr$(97)
417 if( pParser->GetType() != SbxVARIANT )
418 pParser->Error( SbERR_SYNTAX ), bError = TRUE;
424 String
aSym( pParser
->GetSym() );
425 SbxDataType eType
= pParser
->GetType();
426 SbiParameters
* pPar
= NULL
;
427 eTok
= pParser
->Peek();
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() );
438 if( eType
== SbxVARIANT
)
442 // Name%. geht wirklich nicht!
443 pParser
->Error( SbERR_BAD_DECLARATION
, aSym
);
448 // Der Symbol-Pool eines Objekts ist immer PUBLIC
449 SbiSymPool
& rPool
= rObj
.GetPool();
450 rPool
.SetScope( SbPUBLIC
);
451 SbiSymDef
* pDef
= rPool
.Find( aSym
);
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
;
462 // Falls wir etwas mit Punkt einscannen, muss der
463 // Typ SbxOBJECT sein
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
);
478 pNd
->aVar
.pNext
= ObjTerm( *pDef
);
485 // Als Operanden kommen in Betracht:
491 // geklammerte Ausdruecke
493 SbiExprNode
* SbiExpression::Operand()
499 switch( eTok
= pParser
->Peek() )
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() );
511 pRes
= Term(); break;
514 pRes
= new SbiExprNode( pParser
, pParser
->GetDbl(), pParser
->GetType() );
518 pRes
= new SbiExprNode( pParser
, pParser
->GetSym() ); break;
521 if( nParenLevel
== 0 && m_eMode
== EXPRMODE_LPAREN_PENDING
&& pParser
->Peek() == RPAREN
)
523 m_eMode
= EXPRMODE_EMPTY_PAREN
;
524 pRes
= new SbiExprNode(); // Dummy node
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
;
536 pParser
->Error( SbERR_BAD_BRACKETS
);
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
;
547 m_eMode
= EXPRMODE_STANDARD
;
551 pRes
->bComposite
= TRUE
;
554 // Zur Zeit sind Keywords hier OK!
555 if( pParser
->IsKwd( eTok
) )
560 pRes
= new SbiExprNode( pParser
, 1.0, SbxDOUBLE
); // bei Fehlern
561 pParser
->Error( SbERR_UNEXPECTED
, eTok
);
567 SbiExprNode
* SbiExpression::Unary()
570 SbiToken eTok
= pParser
->Peek();
577 // process something like "Do While Not "foo"="" "
578 if( pParser
->IsVBASupportOn() )
579 pNd
= new SbiExprNode( pParser
, Like(), eTok
, NULL
);
581 pNd
= new SbiExprNode( pParser
, Unary(), eTok
, NULL
);
590 SbiExprNode
* pObjNode
= Operand();
591 pParser
->TestToken( IS
);
593 SbiSymDef
* pTypeDef
= new SbiSymDef( aDummy
);
594 pParser
->TypeDecl( *pTypeDef
, TRUE
);
595 pNd
= new SbiExprNode( pParser
, pObjNode
, pTypeDef
->GetTypeId() );
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() );
617 SbiExprNode
* SbiExpression::MulDiv()
619 SbiExprNode
* pNd
= Exp();
620 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
624 SbiToken eTok
= pParser
->Peek();
625 if( eTok
!= MUL
&& eTok
!= DIV
)
627 eTok
= pParser
->Next();
628 pNd
= new SbiExprNode( pParser
, pNd
, eTok
, Exp() );
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() );
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() );
660 SbiExprNode
* SbiExpression::AddSub()
662 SbiExprNode
* pNd
= Mod();
663 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
667 SbiToken eTok
= pParser
->Peek();
668 if( eTok
!= PLUS
&& eTok
!= MINUS
)
670 eTok
= pParser
->Next();
671 pNd
= new SbiExprNode( pParser
, pNd
, eTok
, Mod() );
677 SbiExprNode
* SbiExpression::Cat()
679 SbiExprNode
* pNd
= AddSub();
680 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
684 SbiToken eTok
= pParser
->Peek();
687 eTok
= pParser
->Next();
688 pNd
= new SbiExprNode( pParser
, pNd
, eTok
, AddSub() );
694 SbiExprNode
* SbiExpression::Comp()
696 SbiExprNode
* pNd
= Cat();
697 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
702 SbiToken eTok
= pParser
->Peek();
703 if( m_eMode
== EXPRMODE_ARRAY_OR_OBJECT
)
705 if( eTok
!= EQ
&& eTok
!= NE
&& eTok
!= LT
706 && eTok
!= GT
&& eTok
!= LE
&& eTok
!= GE
)
708 eTok
= pParser
->Next();
709 pNd
= new SbiExprNode( pParser
, pNd
, eTok
, Cat() );
716 SbiExprNode
* SbiExpression::Like()
718 SbiExprNode
* pNd
= Comp();
719 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
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
);
736 SbiExprNode
* SbiExpression::Boolean()
738 SbiExprNode
* pNd
= Like();
739 if( m_eMode
!= EXPRMODE_EMPTY_PAREN
)
743 SbiToken eTok
= pParser
->Peek();
744 if( eTok
!= AND
&& eTok
!= OR
&& eTok
!= XOR
745 && eTok
!= EQV
&& eTok
!= IMP
&& eTok
!= IS
)
747 eTok
= pParser
->Next();
748 pNd
= new SbiExprNode( pParser
, pNd
, eTok
, Like() );
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() )
775 aVal
= pExpr
->aStrVal
;
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 )
794 else if( pVarDef
->GetName().EqualsIgnoreCaseAscii( "false" ) )
795 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
801 // Wenn es ein BOOL ist, Node austauschen
805 pExpr
= new SbiExprNode( pParser
, (bBoolVal
? SbxTRUE
: SbxFALSE
), SbxINTEGER
);
806 eType
= pExpr
->GetType();
813 pParser
->Error( SbERR_SYNTAX
);
820 short SbiConstExpression::GetShortValue()
822 if( eType
== SbxSTRING
)
824 SbxVariableRef refConv
= new SbxVariable
;
825 refConv
->PutString( aVal
);
826 return refConv
->GetInteger();
831 if( n
> 0 ) n
+= .5; else n
-= .5;
832 if( n
> SbxMAXINT
) n
= SbxMAXINT
, pParser
->Error( SbERR_OUT_OF_RANGE
);
834 if( n
< SbxMININT
) n
= SbxMININT
, pParser
->Error( SbERR_OUT_OF_RANGE
);
840 /***************************************************************************
844 ***************************************************************************/
846 SbiExprList::SbiExprList( SbiParser
* p
)
857 SbiExprList::~SbiExprList()
859 SbiExpression
* p
= pFirst
;
862 SbiExpression
* q
= p
->pNext
;
868 // Parameter anfordern (ab 0)
870 SbiExpression
* SbiExprList::Get( short n
)
872 SbiExpression
* p
= pFirst
;
878 void SbiExprList::addExpression( SbiExpression
* pExpr
)
880 SbiExpression
* p
= pFirst
;
881 while( p
&& p
->pNext
)
888 /***************************************************************************
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
) :
909 SbiExpression
*pExpr
;
910 SbiToken eTok
= pParser
->Peek();
912 // evtl. Klammer auf weg:
913 bool bAssumeExprLParenMode
= false;
914 bool bAssumeArrayMode
= false;
917 if( bStandaloneExpression
)
919 bAssumeExprLParenMode
= true;
925 eTok
= pParser
->Peek();
930 if( ( bBracket
&& eTok
== RPAREN
) || pParser
->IsEoln( eTok
) )
936 // Parametertabelle einlesen und in richtiger Folge ablegen!
937 SbiExpression
* pLast
= NULL
;
942 // Fehlendes Argument
945 pExpr
= new SbiExpression( pParser
, 0, SbxEMPTY
);
947 // pParser->Error( SbERR_SYNTAX ), bError = TRUE;
949 // Benannte Argumente: entweder .name= oder name:=
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
)
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
968 bAssumeArrayMode
= true;
971 else if( eModeAfter
== EXPRMODE_EMPTY_PAREN
)
979 pExpr
= new SbiExpression( pParser
);
981 //pExpr = bConst ? new SbiConstExpression( pParser )
982 // : new SbiExpression( pParser );
983 if( !bAssumeArrayMode
)
985 if( pParser
->Peek() == ASSIGN
)
988 // SbiExpression::Term() hat einen String daraus gemacht
989 aName
= pExpr
->GetString();
992 pExpr
= new SbiExpression( pParser
);
994 // pParser->Error( SbERR_SYNTAX ), bError = TRUE;
996 pExpr
->GetName() = aName
;
1001 pFirst
= pLast
= pExpr
;
1003 pLast
->pNext
= pExpr
, pLast
= pExpr
;
1005 bError
|= !pExpr
->IsValid();
1007 if( bAssumeArrayMode
)
1010 // Naechstes Element?
1011 eTok
= pParser
->Peek();
1014 if( ( bBracket
&& eTok
== RPAREN
) || pParser
->IsEoln( eTok
) )
1016 pParser
->Error( bBracket
1017 ? SbERR_BAD_BRACKETS
1018 : SbERR_EXPECTED
, COMMA
);
1024 eTok
= pParser
->Peek();
1025 if( ( bBracket
&& eTok
== RPAREN
) || pParser
->IsEoln( eTok
) )
1029 // Schliessende Klammer
1030 if( eTok
== RPAREN
)
1036 pParser
->Error( SbERR_BAD_BRACKETS
);
1043 /***************************************************************************
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
)
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
;
1070 pExpr1
= new SbiExpression( pParser
);
1071 eTok
= pParser
->Next();
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
;
1083 pLast
->pNext
= pExpr1
;
1089 // Nur eine Dim-Angabe
1091 pExpr1
->pNext
= NULL
;
1092 bConst
&= pExpr1
->IsIntConstant();
1093 bError
|= !pExpr1
->IsValid();
1095 pFirst
= pLast
= pExpr1
;
1097 pLast
->pNext
= pExpr1
, pLast
= pExpr1
;
1101 if( eTok
== RPAREN
) break;
1104 pParser
->Error( SbERR_BAD_BRACKETS
);
1110 else pParser
->Next();