bump product version to 5.0.4.1
[LibreOffice.git] / basic / source / comp / exprtree.cxx
blob2e133b88c487e436758bd9a36cbd17980f256684
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 "parser.hxx"
22 #include <basic/sbx.hxx>
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 bBased = bError = bByVal = bBracket = false;
59 nParenLevel = 0;
60 eCurExpr = SbOPERAND;
61 m_eMode = EXPRMODE_STANDARD;
62 pNext = NULL;
63 pExpr = new SbiExprNode( pParser, n, t );
64 pExpr->Optimize();
67 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar )
69 pParser = p;
70 bBased = bError = bByVal = bBracket = false;
71 nParenLevel = 0;
72 eCurExpr = SbOPERAND;
73 m_eMode = EXPRMODE_STANDARD;
74 pNext = NULL;
75 pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar );
78 SbiExpression::~SbiExpression()
80 delete pExpr;
83 // reading in a complete identifier
84 // an identifier has the following form:
85 // name[(Parameter)][.Name[(parameter)]]...
86 // structure elements are coupled via the element pNext,
87 // so that they're not in the tree.
89 // Are there parameters without brackets following? This may be a number,
90 // a string, a symbol or also a comma (if the 1st parameter is missing)
92 static bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
94 if( eTok == LPAREN )
96 return true;
98 // but only if similar to CALL!
99 if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
101 return false;
103 if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
104 eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL )
106 return true;
108 else // check for default params with reserved names ( e.g. names of tokens )
110 SbiTokenizer tokens( *(SbiTokenizer*)p );
111 // Urk the Next() / Peek() symantics are... weird
112 tokens.Next();
113 if ( tokens.Peek() == ASSIGN )
115 return true;
118 return false;
121 // definition of a new symbol
123 static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
124 const OUString& rName, SbxDataType eType, SbiParameters* pPar )
126 SbiSymDef* pDef;
127 // A= is not a procedure
128 bool bHasType = ( eTok == EQ || eTok == DOT );
129 if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
131 // so this is a procedure
132 // the correct pool should be found out, as
133 // procs must always get into a public pool
134 SbiSymPool* pPool = &rPool;
135 if( pPool->GetScope() != SbPUBLIC )
137 pPool = &rPool.GetParser()->aPublics;
139 SbiProcDef* pProc = pPool->AddProc( rName );
141 // special treatment for Colls like Documents(1)
142 if( eCurExpr == SbSTDEXPR )
144 bHasType = true;
146 pDef = pProc;
147 pDef->SetType( bHasType ? eType : SbxEMPTY );
148 if( pPar )
150 // generate dummy parameters
151 sal_Int32 n = 1;
152 for( short i = 0; i < pPar->GetSize(); i++ )
154 n += 1;
155 OUStringBuffer aPar("PAR");
156 aPar.append(n);
157 pProc->GetParams().AddSym( aPar.makeStringAndClear() );
161 else
163 // or a normal symbol
164 pDef = rPool.AddSym( rName );
165 pDef->SetType( eType );
167 return pDef;
170 // currently even keywords are allowed (because of Dflt properties of the same name)
172 SbiExprNode* SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
174 if( pParser->Peek() == DOT )
176 SbiExprNode* pWithVar = pParser->GetWithVar();
177 // #26608: get to the node-chain's end to pass the correct object
178 SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL;
179 SbiExprNode* pNd = NULL;
180 if( !pDef )
182 pParser->Next();
184 else
186 pNd = ObjTerm( *pDef );
187 if( pNd )
189 pNd->SetWithParent( pWithVar );
192 if( !pNd )
194 pParser->Error( SbERR_UNEXPECTED, DOT );
195 pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
197 return pNd;
200 SbiToken eTok = (pKeywordSymbolInfo == NULL) ? pParser->Next() : pKeywordSymbolInfo->m_eTok;
201 // memorize the parsing's begin
202 pParser->LockColumn();
203 OUString aSym( (pKeywordSymbolInfo == NULL) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol );
204 SbxDataType eType = (pKeywordSymbolInfo == NULL) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType;
205 SbiParameters* pPar = NULL;
206 SbiExprListVector* pvMoreParLcl = NULL;
207 // are there parameters following?
208 SbiToken eNextTok = pParser->Peek();
209 // is it a known parameter?
210 // create a string constant then, which will be recognized
211 // in the SbiParameters-ctor and is continued to be handled
212 if( eNextTok == ASSIGN )
214 pParser->UnlockColumn();
215 return new SbiExprNode( pParser, aSym );
217 // no keywords allowed from here on!
218 if( SbiTokenizer::IsKwd( eTok ) )
220 if( pParser->IsCompatible() && eTok == INPUT )
222 eTok = SYMBOL;
224 else
226 pParser->Error( SbERR_SYNTAX );
227 bError = true;
231 if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
233 bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
234 pPar = new SbiParameters( pParser, bStandaloneExpression );
235 bError = bError || !pPar->IsValid();
236 if( !bError )
237 bBracket = pPar->IsBracket();
238 eTok = pParser->Peek();
240 // i75443 check for additional sets of parameters
241 while( eTok == LPAREN )
243 if( pvMoreParLcl == NULL )
245 pvMoreParLcl = new SbiExprListVector();
247 SbiParameters* pAddPar = new SbiParameters( pParser );
248 pvMoreParLcl->push_back( pAddPar );
249 bError = bError || !pAddPar->IsValid();
250 eTok = pParser->Peek();
253 // It might be an object part, if . or ! is following.
254 // In case of . the variable must already be defined;
255 // it's an object, if pDef is NULL after the search.
256 bool bObj = ( ( eTok == DOT || eTok == EXCLAM )
257 && !pParser->WhiteSpace() );
258 if( bObj )
260 bBracket = false; // Now the bracket for the first term is obsolete
261 if( eType == SbxVARIANT )
263 eType = SbxOBJECT;
265 else
267 // Name%. really does not work!
268 pParser->Error( SbERR_BAD_DECLARATION, aSym );
269 bError = true;
272 // Search:
273 SbiSymDef* pDef = pParser->pPool->Find( aSym );
274 if( !pDef )
276 // Part of the Runtime-Library?
277 // from 31.3.1996: swapped out to parser-method
278 // (is also needed in SbiParser::DefVar() in DIM.CXX)
279 pDef = pParser->CheckRTLForSym( aSym, eType );
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 ) )
286 pDef = NULL;
289 if( !pDef )
291 if( bObj )
293 eType = SbxOBJECT;
295 pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar );
296 // Looks like this is a local ( but undefined variable )
297 // if it is in a static procedure then make this Symbol
298 // static
299 if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
301 pDef->SetStatic();
304 else
307 SbiConstDef* pConst = pDef->GetConstDef();
308 if( pConst )
310 delete pPar;
311 delete pvMoreParLcl;
312 if( pConst->GetType() == SbxSTRING )
314 return new SbiExprNode( pParser, pConst->GetString() );
316 else
318 return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() );
322 // 0 parameters come up to ()
323 if( pDef->GetDims() )
325 if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
327 pParser->Error( SbERR_WRONG_DIMS );
330 if( pDef->IsDefinedAs() )
332 SbxDataType eDefType = pDef->GetType();
333 // #119187 Only error if types conflict
334 if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
336 // How? Define with AS first and take a Suffix then?
337 pParser->Error( SbERR_BAD_DECLARATION, aSym );
338 bError = true;
340 else if ( eType == SbxVARIANT )
342 // if there's nothing named, take the type of the entry,
343 // but only if the var hasn't been defined with AS XXX
344 // so that we catch n% = 5 : print n
345 eType = eDefType;
348 // checking type of variables:
349 // is there named anything different in the scanner?
350 // That's OK for methods!
351 if( eType != SbxVARIANT && // Variant takes everything
352 eType != pDef->GetType() &&
353 !pDef->GetProcDef() )
355 // maybe pDef describes an object that so far has only been
356 // recognized as SbxVARIANT - then change type of pDef
357 // from 16.12.95 (similar cases possible perhaps?!?)
358 if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
360 pDef->SetType( SbxOBJECT );
362 else
364 pParser->Error( SbERR_BAD_DECLARATION, aSym );
365 bError = true;
369 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
370 if( !pPar )
372 pPar = new SbiParameters( pParser,false,false );
374 pNd->aVar.pPar = pPar;
375 pNd->aVar.pvMorePar = pvMoreParLcl;
376 if( bObj )
378 // from 8.1.95: Object may also be of the type SbxVARIANT
379 if( pDef->GetType() == SbxVARIANT )
380 pDef->SetType( SbxOBJECT );
381 // if we scan something with point,
382 // the type must be SbxOBJECT
383 if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
385 // defer error until runtime if in vba mode
386 if ( !pParser->IsVBASupportOn() )
388 pParser->Error( SbERR_BAD_DECLARATION, aSym );
389 bError = true;
392 if( !bError )
394 pNd->aVar.pNext = ObjTerm( *pDef );
398 pParser->UnlockColumn();
399 return pNd;
402 // construction of an object term. A term of this kind is part
403 // of an expression that begins with an object variable.
405 SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj )
407 pParser->Next();
408 SbiToken eTok = pParser->Next();
409 if( eTok != SYMBOL && !SbiTokenizer::IsKwd( eTok ) && !SbiTokenizer::IsExtra( eTok ) )
411 // #66745 Some operators can also be allowed
412 // as identifiers, important for StarOne
413 if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
414 eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
416 pParser->Error( SbERR_VAR_EXPECTED );
417 bError = true;
421 if( bError )
423 return NULL;
425 OUString aSym( pParser->GetSym() );
426 SbxDataType eType = pParser->GetType();
427 SbiParameters* pPar = NULL;
428 SbiExprListVector* pvMoreParLcl = NULL;
429 eTok = pParser->Peek();
431 if( DoParametersFollow( pParser, eCurExpr, eTok ) )
433 bool bStandaloneExpression = false;
434 pPar = new SbiParameters( pParser, bStandaloneExpression );
435 bError = bError || !pPar->IsValid();
436 eTok = pParser->Peek();
438 // i109624 check for additional sets of parameters
439 while( eTok == LPAREN )
441 if( pvMoreParLcl == NULL )
443 pvMoreParLcl = new SbiExprListVector();
445 SbiParameters* pAddPar = new SbiParameters( pParser );
446 pvMoreParLcl->push_back( pAddPar );
447 bError = bError || !pPar->IsValid();
448 eTok = pParser->Peek();
451 bool bObj = ( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
452 if( bObj )
454 if( eType == SbxVARIANT )
456 eType = SbxOBJECT;
458 else
460 // Name%. does really not work!
461 pParser->Error( SbERR_BAD_DECLARATION, aSym );
462 bError = true;
466 // an object's symbol pool is always PUBLIC
467 SbiSymPool& rPool = rObj.GetPool();
468 rPool.SetScope( SbPUBLIC );
469 SbiSymDef* pDef = rPool.Find( aSym );
470 if( !pDef )
472 pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar );
473 pDef->SetType( eType );
476 SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
477 pNd->aVar.pPar = pPar;
478 pNd->aVar.pvMorePar = pvMoreParLcl;
479 if( bObj )
481 if( pDef->GetType() == SbxVARIANT )
483 pDef->SetType( SbxOBJECT );
485 if( pDef->GetType() != SbxOBJECT )
487 pParser->Error( SbERR_BAD_DECLARATION, aSym );
488 bError = true;
490 if( !bError )
492 pNd->aVar.pNext = ObjTerm( *pDef );
493 pNd->eType = eType;
496 return pNd;
499 // an operand can be:
500 // constant
501 // scalar variable
502 // structure elements
503 // array elements
504 // functions
505 // bracketed expressions
507 SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf )
509 SbiExprNode *pRes;
510 SbiToken eTok;
512 // test operand:
513 switch( eTok = pParser->Peek() )
515 case SYMBOL:
516 pRes = Term();
517 // process something like "IF Not r Is Nothing Then .."
518 if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
520 eTok = pParser->Next();
521 pRes = new SbiExprNode( pParser, pRes, eTok, Like() );
523 break;
524 case DOT: // .with
525 pRes = Term(); break;
526 case NUMBER:
527 pParser->Next();
528 pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() );
529 break;
530 case FIXSTRING:
531 pParser->Next();
532 pRes = new SbiExprNode( pParser, pParser->GetSym() ); break;
533 case LPAREN:
534 pParser->Next();
535 if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
537 m_eMode = EXPRMODE_EMPTY_PAREN;
538 pRes = new SbiExprNode(); // Dummy node
539 pParser->Next();
540 break;
542 nParenLevel++;
543 pRes = Boolean();
544 if( pParser->Peek() != RPAREN )
546 // If there was a LPARAM, it does not belong to the expression
547 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
549 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
551 else
553 pParser->Error( SbERR_BAD_BRACKETS );
556 else
558 pParser->Next();
559 if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
561 SbiToken eTokAfterRParen = pParser->Peek();
562 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
564 m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
566 else
568 m_eMode = EXPRMODE_STANDARD;
572 nParenLevel--;
573 break;
574 default:
575 // keywords here are OK at the moment!
576 if( SbiTokenizer::IsKwd( eTok ) )
578 pRes = Term();
580 else
582 pParser->Next();
583 pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
584 pParser->Error( SbERR_UNEXPECTED, eTok );
586 break;
588 return pRes;
591 SbiExprNode* SbiExpression::Unary()
593 SbiExprNode* pNd;
594 SbiToken eTok = pParser->Peek();
595 switch( eTok )
597 case MINUS:
598 eTok = NEG;
599 pParser->Next();
600 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
601 break;
602 case NOT:
603 if( pParser->IsVBASupportOn() )
605 pNd = Operand();
607 else
609 pParser->Next();
610 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
612 break;
613 case PLUS:
614 pParser->Next();
615 pNd = Unary();
616 break;
617 case TYPEOF:
619 pParser->Next();
620 bool bUsedForTypeOf = true;
621 SbiExprNode* pObjNode = Operand( bUsedForTypeOf );
622 pParser->TestToken( IS );
623 OUString aDummy;
624 SbiSymDef* pTypeDef = new SbiSymDef( aDummy );
625 pParser->TypeDecl( *pTypeDef, true );
626 pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() );
627 break;
629 case NEW:
631 pParser->Next();
632 OUString aStr;
633 SbiSymDef* pTypeDef = new SbiSymDef( aStr );
634 pParser->TypeDecl( *pTypeDef, true );
635 pNd = new SbiExprNode( pParser, pTypeDef->GetTypeId() );
636 break;
638 default:
639 pNd = Operand();
641 return pNd;
644 SbiExprNode* SbiExpression::Exp()
646 SbiExprNode* pNd = Unary();
647 if( m_eMode != EXPRMODE_EMPTY_PAREN )
649 while( pParser->Peek() == EXPON )
651 SbiToken eTok = pParser->Next();
652 pNd = new SbiExprNode( pParser, pNd, eTok, Unary() );
655 return pNd;
658 SbiExprNode* SbiExpression::MulDiv()
660 SbiExprNode* pNd = Exp();
661 if( m_eMode != EXPRMODE_EMPTY_PAREN )
663 for( ;; )
665 SbiToken eTok = pParser->Peek();
666 if( eTok != MUL && eTok != DIV )
668 break;
670 eTok = pParser->Next();
671 pNd = new SbiExprNode( pParser, pNd, eTok, Exp() );
674 return pNd;
677 SbiExprNode* SbiExpression::IntDiv()
679 SbiExprNode* pNd = MulDiv();
680 if( m_eMode != EXPRMODE_EMPTY_PAREN )
682 while( pParser->Peek() == IDIV )
684 SbiToken eTok = pParser->Next();
685 pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() );
688 return pNd;
691 SbiExprNode* SbiExpression::Mod()
693 SbiExprNode* pNd = IntDiv();
694 if( m_eMode != EXPRMODE_EMPTY_PAREN )
696 while( pParser->Peek() == MOD )
698 SbiToken eTok = pParser->Next();
699 pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() );
702 return pNd;
705 SbiExprNode* SbiExpression::AddSub()
707 SbiExprNode* pNd = Mod();
708 if( m_eMode != EXPRMODE_EMPTY_PAREN )
710 for( ;; )
712 SbiToken eTok = pParser->Peek();
713 if( eTok != PLUS && eTok != MINUS )
715 break;
717 eTok = pParser->Next();
718 pNd = new SbiExprNode( pParser, pNd, eTok, Mod() );
721 return pNd;
724 SbiExprNode* SbiExpression::Cat()
726 SbiExprNode* pNd = AddSub();
727 if( m_eMode != EXPRMODE_EMPTY_PAREN )
729 for( ;; )
731 SbiToken eTok = pParser->Peek();
732 if( eTok != CAT )
734 break;
736 eTok = pParser->Next();
737 pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() );
740 return pNd;
743 SbiExprNode* SbiExpression::Comp()
745 SbiExprNode* pNd = Cat();
746 if( m_eMode != EXPRMODE_EMPTY_PAREN )
748 short nCount = 0;
749 for( ;; )
751 SbiToken eTok = pParser->Peek();
752 if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
754 break;
756 if( eTok != EQ && eTok != NE && eTok != LT &&
757 eTok != GT && eTok != LE && eTok != GE )
759 break;
761 eTok = pParser->Next();
762 pNd = new SbiExprNode( pParser, pNd, eTok, Cat() );
763 nCount++;
766 return pNd;
770 SbiExprNode* SbiExpression::VBA_Not()
772 SbiExprNode* pNd = NULL;
774 SbiToken eTok = pParser->Peek();
775 if( eTok == NOT )
777 pParser->Next();
778 pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL );
780 else
782 pNd = Comp();
784 return pNd;
787 SbiExprNode* SbiExpression::Like()
789 SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
790 if( m_eMode != EXPRMODE_EMPTY_PAREN )
792 short nCount = 0;
793 while( pParser->Peek() == LIKE )
795 SbiToken eTok = pParser->Next();
796 pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++;
798 // multiple operands in a row does not work
799 if( nCount > 1 && !pParser->IsVBASupportOn() )
801 pParser->Error( SbERR_SYNTAX );
802 bError = true;
805 return pNd;
808 SbiExprNode* SbiExpression::Boolean()
810 SbiExprNode* pNd = Like();
811 if( m_eMode != EXPRMODE_EMPTY_PAREN )
813 for( ;; )
815 SbiToken eTok = pParser->Peek();
816 if( (eTok != AND) && (eTok != OR) &&
817 (eTok != XOR) && (eTok != EQV) &&
818 (eTok != IMP) && (eTok != IS) )
820 break;
822 eTok = pParser->Next();
823 pNd = new SbiExprNode( pParser, pNd, eTok, Like() );
826 return pNd;
829 /***************************************************************************
831 |* SbiConstExpression
833 ***************************************************************************/
835 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
837 if( pExpr->IsConstant() )
839 eType = pExpr->GetType();
840 if( pExpr->IsNumber() )
842 nVal = pExpr->nVal;
844 else
846 nVal = 0;
847 aVal = pExpr->aStrVal;
850 else
852 // #40204 special treatment for sal_Bool-constants
853 bool bIsBool = false;
854 if( pExpr->eNodeType == SbxVARVAL )
856 SbiSymDef* pVarDef = pExpr->GetVar();
858 bool bBoolVal = false;
859 if( pVarDef->GetName().equalsIgnoreAsciiCase( "true" ) )
861 bIsBool = true;
862 bBoolVal = true;
864 else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
865 //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
867 bIsBool = true;
868 bBoolVal = false;
871 if( bIsBool )
873 delete pExpr;
874 pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
875 eType = pExpr->GetType();
876 nVal = pExpr->nVal;
880 if( !bIsBool )
882 pParser->Error( SbERR_SYNTAX );
883 eType = SbxDOUBLE;
884 nVal = 0;
889 short SbiConstExpression::GetShortValue()
891 if( eType == SbxSTRING )
893 SbxVariableRef refConv = new SbxVariable;
894 refConv->PutString( aVal );
895 return refConv->GetInteger();
897 else
899 double n = nVal;
900 if( n > 0 )
902 n += .5;
904 else
906 n -= .5;
908 if( n > SbxMAXINT )
910 n = SbxMAXINT;
911 pParser->Error( SbERR_OUT_OF_RANGE );
913 else if( n < SbxMININT )
915 n = SbxMININT;
916 pParser->Error( SbERR_OUT_OF_RANGE );
919 return (short) n;
924 /***************************************************************************
926 |* SbiExprList
928 ***************************************************************************/
930 SbiExprList::SbiExprList( SbiParser* p )
932 pParser = p;
933 pFirst = NULL;
934 nExpr =
935 nDim = 0;
936 bError = false;
937 bBracket = false;
940 SbiExprList::~SbiExprList()
942 SbiExpression* p = pFirst;
943 while( p )
945 SbiExpression* q = p->pNext;
946 delete p;
947 p = q;
952 SbiExpression* SbiExprList::Get( short n )
954 SbiExpression* p = pFirst;
955 while( n-- && p )
957 p = p->pNext;
959 return p;
962 void SbiExprList::addExpression( SbiExpression* pExpr )
964 if( !pFirst )
966 pFirst = pExpr;
967 return;
970 SbiExpression* p = pFirst;
971 while( p->pNext )
973 p = p->pNext;
975 p->pNext = pExpr;
979 /***************************************************************************
981 |* SbiParameters
983 ***************************************************************************/
985 // parsing constructor:
986 // the parameter list is completely parsed
987 // "procedurename()" is OK
988 // it's a function without parameters then
989 // i. e. you give an array as procedure parameter
991 // #i79918/#i80532: bConst has never been set to true
992 // -> reused as bStandaloneExpression
993 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
994 SbiParameters::SbiParameters( SbiParser* p, bool bStandaloneExpression, bool bPar) :
995 SbiExprList( p )
997 if( !bPar )
999 return;
1001 SbiExpression *pExpr;
1002 SbiToken eTok = pParser->Peek();
1004 bool bAssumeExprLParenMode = false;
1005 bool bAssumeArrayMode = false;
1006 if( eTok == LPAREN )
1008 if( bStandaloneExpression )
1010 bAssumeExprLParenMode = true;
1012 else
1014 bBracket = true;
1015 pParser->Next();
1016 eTok = pParser->Peek();
1021 if( ( bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1023 if( eTok == RPAREN )
1025 pParser->Next();
1027 return;
1029 // read in parameter table and lay down in correct order!
1030 SbiExpression* pLast = NULL;
1031 OUString aName;
1032 while( !bError )
1034 aName.clear();
1035 // missing argument
1036 if( eTok == COMMA )
1038 pExpr = new SbiExpression( pParser, 0, SbxEMPTY );
1040 // named arguments: either .name= or name:=
1041 else
1043 bool bByVal = false;
1044 if( eTok == BYVAL )
1046 bByVal = true;
1047 pParser->Next();
1048 eTok = pParser->Peek();
1051 if( bAssumeExprLParenMode )
1053 pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
1054 bAssumeExprLParenMode = false;
1056 SbiExprMode eModeAfter = pExpr->m_eMode;
1057 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
1059 bBracket = true;
1061 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
1063 // Expression "looks" like an array assignment
1064 // a(...)[(...)] = ? or a(...).b(...)
1065 // RPAREN is already parsed
1066 bBracket = true;
1067 bAssumeArrayMode = true;
1068 eTok = NIL;
1070 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1072 bBracket = true;
1073 delete pExpr;
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 ) || SbiTokenizer::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 ) || SbiTokenizer::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: */