bump product version to 4.1.6.2
[LibreOffice.git] / basic / source / comp / exprtree.cxx
blobfe5077b3ad4214886719915911eccced441aef65
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "sbcomp.hxx"
22 #include <basic/sbx.hxx> // because of ...IMPL_REF(...sbxvariable)
23 #include "expr.hxx"
25 /***************************************************************************
27 |* SbiExpression
29 ***************************************************************************/
31 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
32 SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
34 pParser = p;
35 bBased = bError = bByVal = bBracket = false;
36 nParenLevel = 0;
37 eCurExpr = t;
38 m_eMode = eMode;
39 pNext = NULL;
40 pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean();
41 if( t != SbSYMBOL )
43 pExpr->Optimize();
45 if( t == SbLVALUE && !pExpr->IsLvalue() )
47 p->Error( SbERR_LVALUE_EXPECTED );
49 if( t == SbOPERAND && !IsVariable() )
51 p->Error( SbERR_VAR_EXPECTED );
55 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t )
57 pParser = p;
58 eCurExpr = SbOPERAND;
59 pNext = NULL;
60 bBased = bError = bByVal = bBracket = false;
61 pExpr = new SbiExprNode( pParser, n, t );
62 pExpr->Optimize();
65 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar )
67 pParser = p;
68 pNext = NULL;
69 bBased = bError = bByVal = bBracket = false;
70 eCurExpr = SbOPERAND;
71 pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar );
74 SbiExpression::~SbiExpression()
76 delete pExpr;
79 // reading in a complete identifier
80 // an identifier has the following form:
81 // name[(Parameter)][.Name[(parameter)]]...
82 // structure elements are coupled via the element pNext,
83 // so that they're not in the tree.
85 // Are there parameters without brackets following? This may be a number,
86 // a string, a symbol or also a comma (if the 1st parameter is missing)
88 static sal_Bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
90 if( eTok == LPAREN )
92 return sal_True;
94 // but only if similar to CALL!
95 if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
97 return sal_False;
99 if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
100 eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL )
102 return sal_True;
104 else // check for default params with reserved names ( e.g. names of tokens )
106 SbiTokenizer tokens( *(SbiTokenizer*)p );
107 // Urk the Next() / Peek() symantics are... weird
108 tokens.Next();
109 if ( tokens.Peek() == ASSIGN )
111 return sal_True;
114 return sal_False;
117 // definition of a new symbol
119 static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
120 const OUString& rName, SbxDataType eType, SbiParameters* pPar )
122 SbiSymDef* pDef;
123 // A= is not a procedure
124 sal_Bool bHasType = sal_Bool( eTok == EQ || eTok == DOT );
125 if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
127 // so this is a procedure
128 // the correct pool should be found out, as
129 // procs must always get into a public pool
130 SbiSymPool* pPool = &rPool;
131 if( pPool->GetScope() != SbPUBLIC )
133 pPool = &rPool.GetParser()->aPublics;
135 SbiProcDef* pProc = pPool->AddProc( rName );
137 // special treatment for Colls like Documents(1)
138 if( eCurExpr == SbSTDEXPR )
140 bHasType = sal_True;
142 pDef = pProc;
143 pDef->SetType( bHasType ? eType : SbxEMPTY );
144 if( pPar )
146 // generate dummy parameters
147 sal_Int32 n = 1;
148 for( short i = 0; i < pPar->GetSize(); i++ )
150 n += 1;
151 OUStringBuffer aPar("PAR");
152 aPar.append(n);
153 pProc->GetParams().AddSym( aPar.makeStringAndClear() );
157 else
159 // or a normal symbol
160 pDef = rPool.AddSym( rName );
161 pDef->SetType( eType );
163 return pDef;
166 // currently even keywords are allowed (because of Dflt properties of the same name)
168 SbiExprNode* SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
170 if( pParser->Peek() == DOT )
172 SbiExprNode* pWithVar = pParser->GetWithVar();
173 // #26608: get to the node-chain's end to pass the correct object
174 SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL;
175 SbiExprNode* pNd = NULL;
176 if( !pDef )
178 pParser->Next();
180 else
182 pNd = ObjTerm( *pDef );
183 if( pNd )
185 pNd->SetWithParent( pWithVar );
188 if( !pNd )
190 pParser->Error( SbERR_UNEXPECTED, DOT );
191 pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
193 return pNd;
196 SbiToken eTok = (pKeywordSymbolInfo == NULL) ? pParser->Next() : pKeywordSymbolInfo->m_eTok;
197 // memorize the parsing's begin
198 pParser->LockColumn();
199 OUString aSym( (pKeywordSymbolInfo == NULL) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol );
200 SbxDataType eType = (pKeywordSymbolInfo == NULL) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType;
201 SbiParameters* pPar = NULL;
202 SbiExprListVector* pvMoreParLcl = NULL;
203 // are there parameters following?
204 SbiToken eNextTok = pParser->Peek();
205 // is it a known parameter?
206 // create a string constant then, which will be recognized
207 // in the SbiParameters-ctor and is continued to be handled
208 if( eNextTok == ASSIGN )
210 pParser->UnlockColumn();
211 return new SbiExprNode( pParser, aSym );
213 // no keywords allowed from here on!
214 if( pParser->IsKwd( eTok ) )
216 if( pParser->IsCompatible() && eTok == INPUT )
218 eTok = SYMBOL;
220 else
222 pParser->Error( SbERR_SYNTAX );
223 bError = true;
227 if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
229 bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
230 pPar = new SbiParameters( pParser, bStandaloneExpression );
231 bError = bError || !pPar->IsValid();
232 if( !bError )
233 bBracket = pPar->IsBracket();
234 eTok = pParser->Peek();
236 // i75443 check for additional sets of parameters
237 while( eTok == LPAREN )
239 if( pvMoreParLcl == NULL )
241 pvMoreParLcl = new SbiExprListVector();
243 SbiParameters* pAddPar = new SbiParameters( pParser );
244 pvMoreParLcl->push_back( pAddPar );
245 bError = bError || !pAddPar->IsValid();
246 eTok = pParser->Peek();
249 // It might be an object part, if . or ! is following.
250 // In case of . the variable must already be defined;
251 // it's an object, if pDef is NULL after the search.
252 sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM )
253 && !pParser->WhiteSpace() );
254 if( bObj )
256 bBracket = false; // Now the bracket for the first term is obsolete
257 if( eType == SbxVARIANT )
259 eType = SbxOBJECT;
261 else
263 // Name%. really does not work!
264 pParser->Error( SbERR_BAD_DECLARATION, aSym );
265 bError = true;
268 // Search:
269 SbiSymDef* pDef = pParser->pPool->Find( aSym );
270 if( !pDef )
272 // Part of the Runtime-Library?
273 // from 31.3.1996: swapped out to parser-method
274 // (is also needed in SbiParser::DefVar() in DIM.CXX)
275 pDef = pParser->CheckRTLForSym( aSym, eType );
277 // #i109184: Check if symbol is or later will be defined inside module
278 SbModule& rMod = pParser->aGen.GetModule();
279 SbxArray* pModMethods = rMod.GetMethods();
280 if( pModMethods->Find( aSym, SbxCLASS_DONTCARE ) )
282 pDef = NULL;
285 if( !pDef )
287 if( bObj )
289 eType = SbxOBJECT;
291 pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar );
292 // Looks like this is a local ( but undefined variable )
293 // if it is in a static procedure then make this Symbol
294 // static
295 if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
297 pDef->SetStatic();
300 else
303 SbiConstDef* pConst = pDef->GetConstDef();
304 if( pConst )
306 delete pPar;
307 delete pvMoreParLcl;
308 if( pConst->GetType() == SbxSTRING )
310 return new SbiExprNode( pParser, pConst->GetString() );
312 else
314 return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() );
318 // 0 parameters come up to ()
319 if( pDef->GetDims() )
321 if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
323 pParser->Error( SbERR_WRONG_DIMS );
326 if( pDef->IsDefinedAs() )
328 SbxDataType eDefType = pDef->GetType();
329 // #119187 Only error if types conflict
330 if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
332 // How? Define with AS first and take a Suffix then?
333 pParser->Error( SbERR_BAD_DECLARATION, aSym );
334 bError = true;
336 else if ( eType == SbxVARIANT )
338 // if there's nothing named, take the type of the entry,
339 // but only if the var hasn't been defined with AS XXX
340 // so that we catch n% = 5 : print n
341 eType = eDefType;
344 // checking type of variables:
345 // is there named anything different in the scanner?
346 // That's OK for methods!
347 if( eType != SbxVARIANT && // Variant takes everything
348 eType != pDef->GetType() &&
349 !pDef->GetProcDef() )
351 // maybe pDef describes an object that so far has only been
352 // recognized as SbxVARIANT - then change type of pDef
353 // from 16.12.95 (similar cases possible perhaps?!?)
354 if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
356 pDef->SetType( SbxOBJECT );
358 else
360 pParser->Error( SbERR_BAD_DECLARATION, aSym );
361 bError = true;
365 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
366 if( !pPar )
368 pPar = new SbiParameters( pParser,sal_False,sal_False );
370 pNd->aVar.pPar = pPar;
371 pNd->aVar.pvMorePar = pvMoreParLcl;
372 if( bObj )
374 // from 8.1.95: Object may also be of the type SbxVARIANT
375 if( pDef->GetType() == SbxVARIANT )
376 pDef->SetType( SbxOBJECT );
377 // if we scan something with point,
378 // the type must be SbxOBJECT
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 )
390 pNd->aVar.pNext = ObjTerm( *pDef );
394 pParser->UnlockColumn();
395 return pNd;
398 // construction of an object term. A term of this kind is part
399 // of an expression that begins with an object variable.
401 SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj )
403 pParser->Next();
404 SbiToken eTok = pParser->Next();
405 if( eTok != SYMBOL && !pParser->IsKwd( eTok ) && !pParser->IsExtra( eTok ) )
407 // #66745 Some operators can also be allowed
408 // as identifiers, important for StarOne
409 if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
410 eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
412 pParser->Error( SbERR_VAR_EXPECTED );
413 bError = true;
417 if( bError )
419 return NULL;
421 OUString aSym( pParser->GetSym() );
422 SbxDataType eType = pParser->GetType();
423 SbiParameters* pPar = NULL;
424 SbiExprListVector* pvMoreParLcl = NULL;
425 eTok = pParser->Peek();
427 if( DoParametersFollow( pParser, eCurExpr, eTok ) )
429 bool bStandaloneExpression = false;
430 pPar = new SbiParameters( pParser, bStandaloneExpression );
431 bError = bError || !pPar->IsValid();
432 eTok = pParser->Peek();
434 // i109624 check for additional sets of parameters
435 while( eTok == LPAREN )
437 if( pvMoreParLcl == NULL )
439 pvMoreParLcl = new SbiExprListVector();
441 SbiParameters* pAddPar = new SbiParameters( pParser );
442 pvMoreParLcl->push_back( pAddPar );
443 bError = bError || !pPar->IsValid();
444 eTok = pParser->Peek();
447 sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
448 if( bObj )
450 if( eType == SbxVARIANT )
452 eType = SbxOBJECT;
454 else
456 // Name%. does really not work!
457 pParser->Error( SbERR_BAD_DECLARATION, aSym );
458 bError = true;
462 // an object's symbol pool is always PUBLIC
463 SbiSymPool& rPool = rObj.GetPool();
464 rPool.SetScope( SbPUBLIC );
465 SbiSymDef* pDef = rPool.Find( aSym );
466 if( !pDef )
468 pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar );
469 pDef->SetType( eType );
472 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
473 pNd->aVar.pPar = pPar;
474 pNd->aVar.pvMorePar = pvMoreParLcl;
475 if( bObj )
477 if( pDef->GetType() == SbxVARIANT )
479 pDef->SetType( SbxOBJECT );
481 if( pDef->GetType() != SbxOBJECT )
483 pParser->Error( SbERR_BAD_DECLARATION, aSym );
484 bError = true;
486 if( !bError )
488 pNd->aVar.pNext = ObjTerm( *pDef );
489 pNd->eType = eType;
492 return pNd;
495 // an operand can be:
496 // constant
497 // scalar variable
498 // structure elements
499 // array elements
500 // functions
501 // bracketed expressions
503 SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf )
505 SbiExprNode *pRes;
506 SbiToken eTok;
508 // test operand:
509 switch( eTok = pParser->Peek() )
511 case SYMBOL:
512 pRes = Term();
513 // process something like "IF Not r Is Nothing Then .."
514 if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
516 eTok = pParser->Next();
517 pRes = new SbiExprNode( pParser, pRes, eTok, Like() );
519 break;
520 case DOT: // .with
521 pRes = Term(); break;
522 case NUMBER:
523 pParser->Next();
524 pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() );
525 break;
526 case FIXSTRING:
527 pParser->Next();
528 pRes = new SbiExprNode( pParser, pParser->GetSym() ); break;
529 case LPAREN:
530 pParser->Next();
531 if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
533 m_eMode = EXPRMODE_EMPTY_PAREN;
534 pRes = new SbiExprNode(); // Dummy node
535 pParser->Next();
536 break;
538 nParenLevel++;
539 pRes = Boolean();
540 if( pParser->Peek() != RPAREN )
542 // If there was a LPARAM, it does not belong to the expression
543 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
545 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
547 else
549 pParser->Error( SbERR_BAD_BRACKETS );
552 else
554 pParser->Next();
555 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
557 SbiToken eTokAfterRParen = pParser->Peek();
558 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
560 m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
562 else
564 m_eMode = EXPRMODE_STANDARD;
568 nParenLevel--;
569 break;
570 default:
571 // keywords here are OK at the moment!
572 if( pParser->IsKwd( eTok ) )
574 pRes = Term();
576 else
578 pParser->Next();
579 pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
580 pParser->Error( SbERR_UNEXPECTED, eTok );
582 break;
584 return pRes;
587 SbiExprNode* SbiExpression::Unary()
589 SbiExprNode* pNd;
590 SbiToken eTok = pParser->Peek();
591 switch( eTok )
593 case MINUS:
594 eTok = NEG;
595 pParser->Next();
596 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
597 break;
598 case NOT:
599 if( pParser->IsVBASupportOn() )
601 pNd = Operand();
603 else
605 pParser->Next();
606 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
608 break;
609 case PLUS:
610 pParser->Next();
611 pNd = Unary();
612 break;
613 case TYPEOF:
615 pParser->Next();
616 bool bUsedForTypeOf = true;
617 SbiExprNode* pObjNode = Operand( bUsedForTypeOf );
618 pParser->TestToken( IS );
619 OUString aDummy;
620 SbiSymDef* pTypeDef = new SbiSymDef( aDummy );
621 pParser->TypeDecl( *pTypeDef, sal_True );
622 pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() );
623 break;
625 case NEW:
627 pParser->Next();
628 OUString aStr;
629 SbiSymDef* pTypeDef = new SbiSymDef( aStr );
630 pParser->TypeDecl( *pTypeDef, sal_True );
631 pNd = new SbiExprNode( pParser, pTypeDef->GetTypeId() );
632 break;
634 default:
635 pNd = Operand();
637 return pNd;
640 SbiExprNode* SbiExpression::Exp()
642 SbiExprNode* pNd = Unary();
643 if( m_eMode != EXPRMODE_EMPTY_PAREN )
645 while( pParser->Peek() == EXPON )
647 SbiToken eTok = pParser->Next();
648 pNd = new SbiExprNode( pParser, pNd, eTok, Unary() );
651 return pNd;
654 SbiExprNode* SbiExpression::MulDiv()
656 SbiExprNode* pNd = Exp();
657 if( m_eMode != EXPRMODE_EMPTY_PAREN )
659 for( ;; )
661 SbiToken eTok = pParser->Peek();
662 if( eTok != MUL && eTok != DIV )
664 break;
666 eTok = pParser->Next();
667 pNd = new SbiExprNode( pParser, pNd, eTok, Exp() );
670 return pNd;
673 SbiExprNode* SbiExpression::IntDiv()
675 SbiExprNode* pNd = MulDiv();
676 if( m_eMode != EXPRMODE_EMPTY_PAREN )
678 while( pParser->Peek() == IDIV )
680 SbiToken eTok = pParser->Next();
681 pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() );
684 return pNd;
687 SbiExprNode* SbiExpression::Mod()
689 SbiExprNode* pNd = IntDiv();
690 if( m_eMode != EXPRMODE_EMPTY_PAREN )
692 while( pParser->Peek() == MOD )
694 SbiToken eTok = pParser->Next();
695 pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() );
698 return pNd;
701 SbiExprNode* SbiExpression::AddSub()
703 SbiExprNode* pNd = Mod();
704 if( m_eMode != EXPRMODE_EMPTY_PAREN )
706 for( ;; )
708 SbiToken eTok = pParser->Peek();
709 if( eTok != PLUS && eTok != MINUS )
711 break;
713 eTok = pParser->Next();
714 pNd = new SbiExprNode( pParser, pNd, eTok, Mod() );
717 return pNd;
720 SbiExprNode* SbiExpression::Cat()
722 SbiExprNode* pNd = AddSub();
723 if( m_eMode != EXPRMODE_EMPTY_PAREN )
725 for( ;; )
727 SbiToken eTok = pParser->Peek();
728 if( eTok != CAT )
730 break;
732 eTok = pParser->Next();
733 pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() );
736 return pNd;
739 SbiExprNode* SbiExpression::Comp()
741 SbiExprNode* pNd = Cat();
742 if( m_eMode != EXPRMODE_EMPTY_PAREN )
744 short nCount = 0;
745 for( ;; )
747 SbiToken eTok = pParser->Peek();
748 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
750 break;
752 if( eTok != EQ && eTok != NE && eTok != LT &&
753 eTok != GT && eTok != LE && eTok != GE )
755 break;
757 eTok = pParser->Next();
758 pNd = new SbiExprNode( pParser, pNd, eTok, Cat() );
759 nCount++;
762 return pNd;
766 SbiExprNode* SbiExpression::VBA_Not()
768 SbiExprNode* pNd = NULL;
770 SbiToken eTok = pParser->Peek();
771 if( eTok == NOT )
773 pParser->Next();
774 pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL );
776 else
778 pNd = Comp();
780 return pNd;
783 SbiExprNode* SbiExpression::Like()
785 SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
786 if( m_eMode != EXPRMODE_EMPTY_PAREN )
788 short nCount = 0;
789 while( pParser->Peek() == LIKE )
791 SbiToken eTok = pParser->Next();
792 pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++;
794 // multiple operands in a row does not work
795 if( nCount > 1 && !pParser->IsVBASupportOn() )
797 pParser->Error( SbERR_SYNTAX );
798 bError = true;
801 return pNd;
804 SbiExprNode* SbiExpression::Boolean()
806 SbiExprNode* pNd = Like();
807 if( m_eMode != EXPRMODE_EMPTY_PAREN )
809 for( ;; )
811 SbiToken eTok = pParser->Peek();
812 if( (eTok != AND) && (eTok != OR) &&
813 (eTok != XOR) && (eTok != EQV) &&
814 (eTok != IMP) && (eTok != IS) )
816 break;
818 eTok = pParser->Next();
819 pNd = new SbiExprNode( pParser, pNd, eTok, Like() );
822 return pNd;
825 /***************************************************************************
827 |* SbiConstExpression
829 ***************************************************************************/
831 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
833 if( pExpr->IsConstant() )
835 eType = pExpr->GetType();
836 if( pExpr->IsNumber() )
838 nVal = pExpr->nVal;
840 else
842 nVal = 0;
843 aVal = pExpr->aStrVal;
846 else
848 // #40204 special treatment for sal_Bool-constants
849 sal_Bool bIsBool = sal_False;
850 if( pExpr->eNodeType == SbxVARVAL )
852 SbiSymDef* pVarDef = pExpr->GetVar();
854 sal_Bool bBoolVal = sal_False;
855 if( pVarDef->GetName().equalsIgnoreAsciiCase( "true" ) )
857 bIsBool = sal_True;
858 bBoolVal = sal_True;
860 else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
861 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
863 bIsBool = sal_True;
864 bBoolVal = sal_False;
867 if( bIsBool )
869 delete pExpr;
870 pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
871 eType = pExpr->GetType();
872 nVal = pExpr->nVal;
876 if( !bIsBool )
878 pParser->Error( SbERR_SYNTAX );
879 eType = SbxDOUBLE;
880 nVal = 0;
885 short SbiConstExpression::GetShortValue()
887 if( eType == SbxSTRING )
889 SbxVariableRef refConv = new SbxVariable;
890 refConv->PutString( aVal );
891 return refConv->GetInteger();
893 else
895 double n = nVal;
896 if( n > 0 )
898 n += .5;
900 else
902 n -= .5;
904 if( n > SbxMAXINT )
906 n = SbxMAXINT;
907 pParser->Error( SbERR_OUT_OF_RANGE );
909 else if( n < SbxMININT )
911 n = SbxMININT;
912 pParser->Error( SbERR_OUT_OF_RANGE );
915 return (short) n;
920 /***************************************************************************
922 |* SbiExprList
924 ***************************************************************************/
926 SbiExprList::SbiExprList( SbiParser* p )
928 pParser = p;
929 pFirst = NULL;
930 nExpr =
931 nDim = 0;
932 bError = false;
933 bBracket = false;
936 SbiExprList::~SbiExprList()
938 SbiExpression* p = pFirst;
939 while( p )
941 SbiExpression* q = p->pNext;
942 delete p;
943 p = q;
948 SbiExpression* SbiExprList::Get( short n )
950 SbiExpression* p = pFirst;
951 while( n-- && p )
953 p = p->pNext;
955 return p;
958 void SbiExprList::addExpression( SbiExpression* pExpr )
960 if( !pFirst )
962 pFirst = pExpr;
963 return;
966 SbiExpression* p = pFirst;
967 while( p->pNext )
969 p = p->pNext;
971 p->pNext = pExpr;
975 /***************************************************************************
977 |* SbiParameters
979 ***************************************************************************/
981 // parsing constructor:
982 // the parameter list is completely parsed
983 // "procedurename()" is OK
984 // it's a function without parameters then
985 // i. e. you give an array as procedure parameter
987 // #i79918/#i80532: bConst has never been set to true
988 // -> reused as bStandaloneExpression
989 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
990 SbiParameters::SbiParameters( SbiParser* p, bool bStandaloneExpression, bool bPar) :
991 SbiExprList( p )
993 if( !bPar )
995 return;
997 SbiExpression *pExpr;
998 SbiToken eTok = pParser->Peek();
1000 bool bAssumeExprLParenMode = false;
1001 bool bAssumeArrayMode = false;
1002 if( eTok == LPAREN )
1004 if( bStandaloneExpression )
1006 bAssumeExprLParenMode = true;
1008 else
1010 bBracket = true;
1011 pParser->Next();
1012 eTok = pParser->Peek();
1017 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1019 if( eTok == RPAREN )
1021 pParser->Next();
1023 return;
1025 // read in parameter table and lay down in correct order!
1026 SbiExpression* pLast = NULL;
1027 OUString aName;
1028 while( !bError )
1030 aName = "";
1031 // missing argument
1032 if( eTok == COMMA )
1034 pExpr = new SbiExpression( pParser, 0, SbxEMPTY );
1036 // named arguments: either .name= or name:=
1037 else
1039 bool bByVal = false;
1040 if( eTok == BYVAL )
1042 bByVal = true;
1043 pParser->Next();
1044 eTok = pParser->Peek();
1047 if( bAssumeExprLParenMode )
1049 pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
1050 bAssumeExprLParenMode = sal_False;
1052 SbiExprMode eModeAfter = pExpr->m_eMode;
1053 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
1055 bBracket = true;
1057 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
1059 // Expression "looks" like an array assignment
1060 // a(...)[(...)] = ? or a(...).b(...)
1061 // RPAREN is already parsed
1062 bBracket = true;
1063 bAssumeArrayMode = true;
1064 eTok = NIL;
1066 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1068 bBracket = true;
1069 delete pExpr;
1070 if( bByVal )
1072 pParser->Error( SbERR_LVALUE_EXPECTED );
1074 return;
1077 else
1079 pExpr = new SbiExpression( pParser );
1081 if( bByVal && pExpr->IsLvalue() )
1083 pExpr->SetByVal();
1085 if( !bAssumeArrayMode )
1087 if( pParser->Peek() == ASSIGN )
1089 // VBA mode: name:=
1090 // SbiExpression::Term() has made as string out of it
1091 aName = pExpr->GetString();
1092 delete pExpr;
1093 pParser->Next();
1094 pExpr = new SbiExpression( pParser );
1096 pExpr->GetName() = aName;
1099 pExpr->pNext = NULL;
1100 if( !pLast )
1102 pFirst = pLast = pExpr;
1104 else
1106 pLast->pNext = pExpr, pLast = pExpr;
1108 nExpr++;
1109 bError = bError || !pExpr->IsValid();
1111 if( bAssumeArrayMode )
1113 break;
1115 // next element?
1116 eTok = pParser->Peek();
1117 if( eTok != COMMA )
1119 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1121 break;
1123 pParser->Error( bBracket ? SbERR_BAD_BRACKETS : SbERR_EXPECTED, COMMA );
1124 bError = true;
1126 else
1128 pParser->Next();
1129 eTok = pParser->Peek();
1130 if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1132 break;
1136 // closing bracket
1137 if( eTok == RPAREN )
1139 pParser->Next();
1140 pParser->Peek();
1141 if( !bBracket )
1143 pParser->Error( SbERR_BAD_BRACKETS );
1144 bError = true;
1147 nDim = nExpr;
1150 /***************************************************************************
1152 |* SbiDimList
1154 ***************************************************************************/
1156 // parsing constructor:
1157 // A list of array dimensions is parsed. The expressions are tested for being
1158 // numeric. The bCONST-Bit is reset when all expressions are Integer constants.
1160 SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p )
1162 bConst = true;
1164 if( pParser->Next() != LPAREN )
1166 pParser->Error( SbERR_EXPECTED, LPAREN );
1167 bError = true; return;
1170 if( pParser->Peek() != RPAREN )
1172 SbiExpression *pExpr1, *pExpr2, *pLast = NULL;
1173 SbiToken eTok;
1174 for( ;; )
1176 pExpr1 = new SbiExpression( pParser );
1177 eTok = pParser->Next();
1178 if( eTok == TO )
1180 pExpr2 = new SbiExpression( pParser );
1181 eTok = pParser->Next();
1182 bConst = bConst && pExpr1->IsIntConstant() && pExpr2->IsIntConstant();
1183 bError = bError || !pExpr1->IsValid() || !pExpr2->IsValid();
1184 pExpr1->pNext = pExpr2;
1185 if( !pLast )
1187 pFirst = pExpr1;
1189 else
1191 pLast->pNext = pExpr1;
1193 pLast = pExpr2;
1194 nExpr += 2;
1196 else
1198 pExpr1->SetBased();
1199 pExpr1->pNext = NULL;
1200 bConst = bConst && pExpr1->IsIntConstant();
1201 bError = bError || !pExpr1->IsValid();
1202 if( !pLast )
1204 pFirst = pLast = pExpr1;
1206 else
1208 pLast->pNext = pExpr1, pLast = pExpr1;
1210 nExpr++;
1212 nDim++;
1213 if( eTok == RPAREN ) break;
1214 if( eTok != COMMA )
1216 pParser->Error( SbERR_BAD_BRACKETS );
1217 pParser->Next();
1218 break;
1222 else pParser->Next();
1225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */