LCOV - code coverage report
Current view: top level - libreoffice/basic/source/comp - exprtree.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 272 570 47.7 %
Date: 2012-12-27 Functions: 21 29 72.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : #include "sbcomp.hxx"
      22             : #include <basic/sbx.hxx>        // because of ...IMPL_REF(...sbxvariable)
      23             : #include "expr.hxx"
      24             : 
      25             : /***************************************************************************
      26             : |*
      27             : |*      SbiExpression
      28             : |*
      29             : ***************************************************************************/
      30             : 
      31          60 : SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
      32          60 :     SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
      33             : {
      34          60 :     pParser = p;
      35          60 :     bBased = bError = bByVal = bBracket = false;
      36          60 :     nParenLevel = 0;
      37          60 :     eCurExpr = t;
      38          60 :     m_eMode = eMode;
      39          60 :     pNext = NULL;
      40          60 :     pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean();
      41          60 :     if( t != SbSYMBOL )
      42             :     {
      43          33 :         pExpr->Optimize();
      44             :     }
      45          60 :     if( t == SbLVALUE && !pExpr->IsLvalue() )
      46             :     {
      47           0 :         p->Error( SbERR_LVALUE_EXPECTED );
      48             :     }
      49          60 :     if( t == SbOPERAND && !IsVariable() )
      50             :     {
      51           0 :         p->Error( SbERR_VAR_EXPECTED );
      52             :     }
      53          60 : }
      54             : 
      55           0 : SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t )
      56             : {
      57           0 :     pParser = p;
      58           0 :     eCurExpr = SbOPERAND;
      59           0 :     pNext = NULL;
      60           0 :     bBased = bError = bByVal = bBracket = false;
      61           0 :     pExpr = new SbiExprNode( pParser, n, t );
      62           0 :     pExpr->Optimize();
      63           0 : }
      64             : 
      65           6 : SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar )
      66             : {
      67           6 :     pParser = p;
      68           6 :     pNext = NULL;
      69           6 :     bBased = bError = bByVal = bBracket = false;
      70           6 :     eCurExpr = SbOPERAND;
      71           6 :     pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar );
      72           6 : }
      73             : 
      74         132 : SbiExpression::~SbiExpression()
      75             : {
      76          66 :     delete pExpr;
      77          66 : }
      78             : 
      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.
      84             : 
      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)
      87             : 
      88          70 : static sal_Bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
      89             : {
      90          70 :     if( eTok == LPAREN )
      91             :     {
      92           2 :         return sal_True;
      93             :     }
      94             :     // but only if similar to CALL!
      95          68 :     if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
      96             :     {
      97          41 :         return sal_False;
      98             :     }
      99          27 :     if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
     100             :          eTok == SYMBOL || eTok == COMMA  || eTok == DOT || eTok == NOT || eTok == BYVAL )
     101             :     {
     102           0 :         return sal_True;
     103             :     }
     104             :     else // check for default params with reserved names ( e.g. names of tokens )
     105             :     {
     106          27 :         SbiTokenizer tokens( *(SbiTokenizer*)p );
     107             :         // Urk the Next() / Peek() symantics are... weird
     108          27 :         tokens.Next();
     109          27 :         if ( tokens.Peek() == ASSIGN )
     110             :         {
     111           0 :             return sal_True;
     112          27 :         }
     113             :     }
     114          27 :     return sal_False;
     115             : }
     116             : 
     117             : // definition of a new symbol
     118             : 
     119          12 : static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
     120             :                            const OUString& rName, SbxDataType eType, SbiParameters* pPar )
     121             : {
     122             :     SbiSymDef* pDef;
     123             :     // A= is not a procedure
     124          12 :     sal_Bool bHasType = sal_Bool( eTok == EQ || eTok == DOT );
     125          12 :     if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
     126             :     {
     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           0 :         SbiSymPool* pPool = &rPool;
     131           0 :         if( pPool->GetScope() != SbPUBLIC )
     132             :         {
     133           0 :             pPool = &rPool.GetParser()->aPublics;
     134             :         }
     135           0 :         SbiProcDef* pProc = pPool->AddProc( rName );
     136             : 
     137             :         // special treatment for Colls like Documents(1)
     138           0 :         if( eCurExpr == SbSTDEXPR )
     139             :         {
     140           0 :             bHasType = sal_True;
     141             :         }
     142           0 :         pDef = pProc;
     143           0 :         pDef->SetType( bHasType ? eType : SbxEMPTY );
     144           0 :         if( pPar )
     145             :         {
     146             :             // generate dummy parameters
     147           0 :             sal_Int32 n = 1;
     148           0 :             for( short i = 0; i < pPar->GetSize(); i++ )
     149             :             {
     150           0 :                 n += 1;
     151           0 :                 OUStringBuffer aPar("PAR");
     152           0 :                 aPar.append(n);
     153           0 :                 pProc->GetParams().AddSym( aPar.makeStringAndClear() );
     154           0 :             }
     155           0 :         }
     156             :     }
     157             :     else
     158             :     {
     159             :         // or a normal symbol
     160          12 :         pDef = rPool.AddSym( rName );
     161          12 :         pDef->SetType( eType );
     162             :     }
     163          12 :     return pDef;
     164             : }
     165             : 
     166             : // currently even keywords are allowed (because of Dflt properties of the same name)
     167             : 
     168          47 : SbiExprNode* SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
     169             : {
     170          47 :     if( pParser->Peek() == DOT )
     171             :     {
     172           0 :         SbiExprNode* pWithVar = pParser->GetWithVar();
     173             :         // #26608: get to the node-chain's end to pass the correct object
     174           0 :         SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL;
     175           0 :         SbiExprNode* pNd = NULL;
     176           0 :         if( !pDef )
     177             :         {
     178           0 :             pParser->Next();
     179             :         }
     180             :         else
     181             :         {
     182           0 :             pNd = ObjTerm( *pDef );
     183           0 :             if( pNd )
     184             :             {
     185           0 :                 pNd->SetWithParent( pWithVar );
     186             :             }
     187             :         }
     188           0 :         if( !pNd )
     189             :         {
     190           0 :             pParser->Error( SbERR_UNEXPECTED, DOT );
     191           0 :             pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
     192             :         }
     193           0 :         return pNd;
     194             :     }
     195             : 
     196          47 :     SbiToken eTok = (pKeywordSymbolInfo == NULL) ? pParser->Next() : pKeywordSymbolInfo->m_eTok;
     197             :     // memorize the parsing's begin
     198          47 :     pParser->LockColumn();
     199          47 :     OUString aSym( (pKeywordSymbolInfo == NULL) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol );
     200          47 :     SbxDataType eType = (pKeywordSymbolInfo == NULL) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType;
     201          47 :     SbiParameters* pPar = NULL;
     202          47 :     SbiExprListVector* pvMoreParLcl = NULL;
     203             :     // are there parameters following?
     204          47 :     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          47 :     if( eNextTok == ASSIGN )
     209             :     {
     210           0 :         pParser->UnlockColumn();
     211           0 :         return new SbiExprNode( pParser, aSym );
     212             :     }
     213             :     // no keywords allowed from here on!
     214          47 :     if( pParser->IsKwd( eTok ) )
     215             :     {
     216           0 :         if( pParser->IsCompatible() && eTok == INPUT )
     217             :         {
     218           0 :             eTok = SYMBOL;
     219             :         }
     220             :         else
     221             :         {
     222           0 :             pParser->Error( SbERR_SYNTAX );
     223           0 :             bError = true;
     224             :         }
     225             :     }
     226             : 
     227          47 :     if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
     228             :     {
     229           2 :         bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
     230           2 :         pPar = new SbiParameters( pParser, bStandaloneExpression );
     231           2 :         bError = bError || !pPar->IsValid();
     232           2 :         if( !bError )
     233           2 :             bBracket = pPar->IsBracket();
     234           2 :         eTok = pParser->Peek();
     235             : 
     236             :         // i75443 check for additional sets of parameters
     237           4 :         while( eTok == LPAREN )
     238             :         {
     239           0 :             if( pvMoreParLcl == NULL )
     240             :             {
     241           0 :                 pvMoreParLcl = new SbiExprListVector();
     242             :             }
     243           0 :             SbiParameters* pAddPar = new SbiParameters( pParser );
     244           0 :             pvMoreParLcl->push_back( pAddPar );
     245           0 :             bError = bError || !pAddPar->IsValid();
     246           0 :             eTok = pParser->Peek();
     247             :         }
     248             :     }
     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          47 :                     && !pParser->WhiteSpace() );
     254          47 :     if( bObj )
     255             :     {
     256          18 :         bBracket = false;   // Now the bracket for the first term is obsolete
     257          18 :         if( eType == SbxVARIANT )
     258             :         {
     259          18 :             eType = SbxOBJECT;
     260             :         }
     261             :         else
     262             :         {
     263             :             // Name%. really does not work!
     264           0 :             pParser->Error( SbERR_BAD_DECLARATION, aSym );
     265           0 :             bError = true;
     266             :         }
     267             :     }
     268             :     // Search:
     269          47 :     SbiSymDef* pDef = pParser->pPool->Find( aSym );
     270          47 :     if( !pDef )
     271             :     {
     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           3 :         pDef = pParser->CheckRTLForSym( aSym, eType );
     276             : 
     277             :         // #i109184: Check if symbol is or later will be defined inside module
     278           3 :         SbModule& rMod = pParser->aGen.GetModule();
     279           3 :         SbxArray* pModMethods = rMod.GetMethods();
     280           3 :         if( pModMethods->Find( aSym, SbxCLASS_DONTCARE ) )
     281             :         {
     282           0 :             pDef = NULL;
     283             :         }
     284             :     }
     285          47 :     if( !pDef )
     286             :     {
     287           1 :         if( bObj )
     288             :         {
     289           0 :             eType = SbxOBJECT;
     290             :         }
     291           1 :         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           1 :         if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
     296             :         {
     297           0 :             pDef->SetStatic();
     298             :         }
     299             :     }
     300             :     else
     301             :     {
     302             : 
     303          46 :         SbiConstDef* pConst = pDef->GetConstDef();
     304          46 :         if( pConst )
     305             :         {
     306           0 :             if( pConst->GetType() == SbxSTRING )
     307             :             {
     308           0 :                 return new SbiExprNode( pParser, pConst->GetString() );
     309             :             }
     310             :             else
     311             :             {
     312           0 :                 return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() );
     313             :             }
     314             :         }
     315             : 
     316             :         // 0 parameters come up to ()
     317          46 :         if( pDef->GetDims() )
     318             :         {
     319           0 :             if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
     320             :             {
     321           0 :                 pParser->Error( SbERR_WRONG_DIMS );
     322             :             }
     323             :         }
     324          46 :         if( pDef->IsDefinedAs() )
     325             :         {
     326          31 :             SbxDataType eDefType = pDef->GetType();
     327             :             // #119187 Only error if types conflict
     328          31 :             if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
     329             :             {
     330             :                 // How? Define with AS first and take a Suffix then?
     331           0 :                 pParser->Error( SbERR_BAD_DECLARATION, aSym );
     332           0 :                 bError = true;
     333             :             }
     334          31 :             else if ( eType == SbxVARIANT )
     335             :             {
     336             :                 // if there's nothing named, take the type of the entry,
     337             :                 // but only if the var hasn't been defined with AS XXX
     338             :                 // so that we catch n% = 5 : print n
     339          16 :                 eType = eDefType;
     340             :             }
     341             :         }
     342             :         // checking type of variables:
     343             :         // is there named anything different in the scanner?
     344             :         // That's OK for methods!
     345          81 :         if( eType != SbxVARIANT &&          // Variant takes everything
     346          34 :             eType != pDef->GetType() &&
     347           1 :             !pDef->GetProcDef() )
     348             :         {
     349             :             // maybe pDef describes an object that so far has only been
     350             :             // recognized as SbxVARIANT - then change type of pDef
     351             :             // from 16.12.95 (similar cases possible perhaps?!?)
     352           1 :             if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
     353             :             {
     354           1 :                 pDef->SetType( SbxOBJECT );
     355             :             }
     356             :             else
     357             :             {
     358           0 :                 pParser->Error( SbERR_BAD_DECLARATION, aSym );
     359           0 :                 bError = true;
     360             :             }
     361             :         }
     362             :     }
     363          47 :     SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
     364          47 :     if( !pPar )
     365             :     {
     366          45 :         pPar = new SbiParameters( pParser,sal_False,sal_False );
     367             :     }
     368          47 :     pNd->aVar.pPar = pPar;
     369          47 :     pNd->aVar.pvMorePar = pvMoreParLcl;
     370          47 :     if( bObj )
     371             :     {
     372             :         // from 8.1.95: Object may also be of the type SbxVARIANT
     373          18 :         if( pDef->GetType() == SbxVARIANT )
     374           0 :             pDef->SetType( SbxOBJECT );
     375             :         // if we scan something with point,
     376             :         // the type must be SbxOBJECT
     377          18 :         if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
     378             :         {
     379             :             // defer error until runtime if in vba mode
     380           0 :             if ( !pParser->IsVBASupportOn() )
     381             :             {
     382           0 :                 pParser->Error( SbERR_BAD_DECLARATION, aSym );
     383           0 :                 bError = true;
     384             :             }
     385             :         }
     386          18 :         if( !bError )
     387             :         {
     388          18 :             pNd->aVar.pNext = ObjTerm( *pDef );
     389             :         }
     390             :     }
     391             : 
     392          47 :     pParser->UnlockColumn();
     393          47 :     return pNd;
     394             : }
     395             : 
     396             : // construction of an object term. A term of this kind is part
     397             : // of an expression that begins with an object variable.
     398             : 
     399          23 : SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj )
     400             : {
     401          23 :     pParser->Next();
     402          23 :     SbiToken eTok = pParser->Next();
     403          23 :     if( eTok != SYMBOL && !pParser->IsKwd( eTok ) && !pParser->IsExtra( eTok ) )
     404             :     {
     405             :         // #66745 Some operators can also be allowed
     406             :         // as identifiers, important for StarOne
     407           0 :         if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
     408             :             eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
     409             :         {
     410           0 :             pParser->Error( SbERR_VAR_EXPECTED );
     411           0 :             bError = true;
     412             :         }
     413             :     }
     414             : 
     415          23 :     if( bError )
     416             :     {
     417           0 :         return NULL;
     418             :     }
     419          23 :     OUString aSym( pParser->GetSym() );
     420          23 :     SbxDataType eType = pParser->GetType();
     421          23 :     SbiParameters* pPar = NULL;
     422          23 :     SbiExprListVector* pvMoreParLcl = NULL;
     423          23 :     eTok = pParser->Peek();
     424             : 
     425          23 :     if( DoParametersFollow( pParser, eCurExpr, eTok ) )
     426             :     {
     427           0 :         bool bStandaloneExpression = false;
     428           0 :         pPar = new SbiParameters( pParser, bStandaloneExpression );
     429           0 :         bError = bError || !pPar->IsValid();
     430           0 :         eTok = pParser->Peek();
     431             : 
     432             :         // i109624 check for additional sets of parameters
     433           0 :         while( eTok == LPAREN )
     434             :         {
     435           0 :             if( pvMoreParLcl == NULL )
     436             :             {
     437           0 :                 pvMoreParLcl = new SbiExprListVector();
     438             :             }
     439           0 :             SbiParameters* pAddPar = new SbiParameters( pParser );
     440           0 :             pvMoreParLcl->push_back( pAddPar );
     441           0 :             bError = bError || !pPar->IsValid();
     442           0 :             eTok = pParser->Peek();
     443             :         }
     444             :     }
     445          23 :     sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
     446          23 :     if( bObj )
     447             :     {
     448           5 :         if( eType == SbxVARIANT )
     449             :         {
     450           5 :             eType = SbxOBJECT;
     451             :         }
     452             :         else
     453             :         {
     454             :             // Name%. does really not work!
     455           0 :             pParser->Error( SbERR_BAD_DECLARATION, aSym );
     456           0 :             bError = true;
     457             :         }
     458             :     }
     459             : 
     460             :     // an object's symbol pool is always PUBLIC
     461          23 :     SbiSymPool& rPool = rObj.GetPool();
     462          23 :     rPool.SetScope( SbPUBLIC );
     463          23 :     SbiSymDef* pDef = rPool.Find( aSym );
     464          23 :     if( !pDef )
     465             :     {
     466          11 :         pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar );
     467          11 :         pDef->SetType( eType );
     468             :     }
     469             : 
     470          23 :     SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
     471          23 :     pNd->aVar.pPar = pPar;
     472          23 :     pNd->aVar.pvMorePar = pvMoreParLcl;
     473          23 :     if( bObj )
     474             :     {
     475           5 :         if( pDef->GetType() == SbxVARIANT )
     476             :         {
     477           3 :             pDef->SetType( SbxOBJECT );
     478             :         }
     479           5 :         if( pDef->GetType() != SbxOBJECT )
     480             :         {
     481           0 :             pParser->Error( SbERR_BAD_DECLARATION, aSym );
     482           0 :             bError = true;
     483             :         }
     484           5 :         if( !bError )
     485             :         {
     486           5 :             pNd->aVar.pNext = ObjTerm( *pDef );
     487           5 :             pNd->eType = eType;
     488             :         }
     489             :     }
     490          23 :     return pNd;
     491             : }
     492             : 
     493             : // an operand can be:
     494             : //      constant
     495             : //      scalar variable
     496             : //      structure elements
     497             : //      array elements
     498             : //      functions
     499             : //      bracketed expressions
     500             : 
     501          38 : SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf )
     502             : {
     503             :     SbiExprNode *pRes;
     504             :     SbiToken eTok;
     505             : 
     506             :     // test operand:
     507          38 :     switch( eTok = pParser->Peek() )
     508             :     {
     509             :     case SYMBOL:
     510          20 :         pRes = Term();
     511             :         // process something like "IF Not r Is Nothing Then .."
     512          20 :         if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
     513             :         {
     514           0 :             eTok = pParser->Next();
     515           0 :             pRes = new SbiExprNode( pParser, pRes, eTok, Like() );
     516             :         }
     517          20 :         break;
     518             :     case DOT:   // .with
     519           0 :         pRes = Term(); break;
     520             :     case NUMBER:
     521          14 :         pParser->Next();
     522          14 :         pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() );
     523          14 :         break;
     524             :     case FIXSTRING:
     525           4 :         pParser->Next();
     526           4 :         pRes = new SbiExprNode( pParser, pParser->GetSym() ); break;
     527             :     case LPAREN:
     528           0 :         pParser->Next();
     529           0 :         if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
     530             :         {
     531           0 :             m_eMode = EXPRMODE_EMPTY_PAREN;
     532           0 :             pRes = new SbiExprNode();   // Dummy node
     533           0 :             pParser->Next();
     534           0 :             break;
     535             :         }
     536           0 :         nParenLevel++;
     537           0 :         pRes = Boolean();
     538           0 :         if( pParser->Peek() != RPAREN )
     539             :         {
     540             :             // If there was a LPARAM, it does not belong to the expression
     541           0 :             if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
     542             :             {
     543           0 :                 m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
     544             :             }
     545             :             else
     546             :             {
     547           0 :                 pParser->Error( SbERR_BAD_BRACKETS );
     548             :             }
     549             :         }
     550             :         else
     551             :         {
     552           0 :             pParser->Next();
     553           0 :             if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
     554             :             {
     555           0 :                 SbiToken eTokAfterRParen = pParser->Peek();
     556           0 :                 if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
     557             :                 {
     558           0 :                     m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
     559             :                 }
     560             :                 else
     561             :                 {
     562           0 :                     m_eMode = EXPRMODE_STANDARD;
     563             :                 }
     564             :             }
     565             :         }
     566           0 :         nParenLevel--;
     567           0 :         break;
     568             :     default:
     569             :         // keywords here are OK at the moment!
     570           0 :         if( pParser->IsKwd( eTok ) )
     571             :         {
     572           0 :             pRes = Term();
     573             :         }
     574             :         else
     575             :         {
     576           0 :             pParser->Next();
     577           0 :             pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
     578           0 :             pParser->Error( SbERR_UNEXPECTED, eTok );
     579             :         }
     580           0 :         break;
     581             :     }
     582          38 :     return pRes;
     583             : }
     584             : 
     585          38 : SbiExprNode* SbiExpression::Unary()
     586             : {
     587             :     SbiExprNode* pNd;
     588          38 :     SbiToken eTok = pParser->Peek();
     589          38 :     switch( eTok )
     590             :     {
     591             :         case MINUS:
     592           0 :             eTok = NEG;
     593           0 :             pParser->Next();
     594           0 :             pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
     595           0 :             break;
     596             :         case NOT:
     597           0 :             if( pParser->IsVBASupportOn() )
     598             :             {
     599           0 :                 pNd = Operand();
     600             :             }
     601             :             else
     602             :             {
     603           0 :                 pParser->Next();
     604           0 :                 pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
     605             :             }
     606           0 :             break;
     607             :         case PLUS:
     608           0 :             pParser->Next();
     609           0 :             pNd = Unary();
     610           0 :             break;
     611             :         case TYPEOF:
     612             :         {
     613           0 :             pParser->Next();
     614           0 :             bool bUsedForTypeOf = true;
     615           0 :             SbiExprNode* pObjNode = Operand( bUsedForTypeOf );
     616           0 :             pParser->TestToken( IS );
     617           0 :             OUString aDummy;
     618           0 :             SbiSymDef* pTypeDef = new SbiSymDef( aDummy );
     619           0 :             pParser->TypeDecl( *pTypeDef, sal_True );
     620           0 :             pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() );
     621           0 :             break;
     622             :         }
     623             :         case NEW:
     624             :         {
     625           0 :             pParser->Next();
     626           0 :             OUString aStr;
     627           0 :             SbiSymDef* pTypeDef = new SbiSymDef( aStr );
     628           0 :             pParser->TypeDecl( *pTypeDef, sal_True );
     629           0 :             pNd = new SbiExprNode( pParser, pTypeDef->GetTypeId() );
     630           0 :             break;
     631             :         }
     632             :         default:
     633          38 :             pNd = Operand();
     634             :     }
     635          38 :     return pNd;
     636             : }
     637             : 
     638          38 : SbiExprNode* SbiExpression::Exp()
     639             : {
     640          38 :     SbiExprNode* pNd = Unary();
     641          38 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     642             :     {
     643          76 :         while( pParser->Peek() == EXPON )
     644             :         {
     645           0 :             SbiToken eTok = pParser->Next();
     646           0 :             pNd = new SbiExprNode( pParser, pNd, eTok, Unary() );
     647             :         }
     648             :     }
     649          38 :     return pNd;
     650             : }
     651             : 
     652          38 : SbiExprNode* SbiExpression::MulDiv()
     653             : {
     654          38 :     SbiExprNode* pNd = Exp();
     655          38 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     656             :     {
     657           0 :         for( ;; )
     658             :         {
     659          38 :             SbiToken eTok = pParser->Peek();
     660          38 :             if( eTok != MUL && eTok != DIV )
     661             :             {
     662          38 :                 break;
     663             :             }
     664           0 :             eTok = pParser->Next();
     665           0 :             pNd = new SbiExprNode( pParser, pNd, eTok, Exp() );
     666             :         }
     667             :     }
     668          38 :     return pNd;
     669             : }
     670             : 
     671          38 : SbiExprNode* SbiExpression::IntDiv()
     672             : {
     673          38 :     SbiExprNode* pNd = MulDiv();
     674          38 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     675             :     {
     676          76 :         while( pParser->Peek() == IDIV )
     677             :         {
     678           0 :             SbiToken eTok = pParser->Next();
     679           0 :             pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() );
     680             :         }
     681             :     }
     682          38 :     return pNd;
     683             : }
     684             : 
     685          38 : SbiExprNode* SbiExpression::Mod()
     686             : {
     687          38 :     SbiExprNode* pNd = IntDiv();
     688          38 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     689             :     {
     690          76 :         while( pParser->Peek() == MOD )
     691             :         {
     692           0 :             SbiToken eTok = pParser->Next();
     693           0 :             pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() );
     694             :         }
     695             :     }
     696          38 :     return pNd;
     697             : }
     698             : 
     699          35 : SbiExprNode* SbiExpression::AddSub()
     700             : {
     701          35 :     SbiExprNode* pNd = Mod();
     702          35 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     703             :     {
     704           3 :         for( ;; )
     705             :         {
     706          38 :             SbiToken eTok = pParser->Peek();
     707          38 :             if( eTok != PLUS && eTok != MINUS )
     708             :             {
     709          35 :                 break;
     710             :             }
     711           3 :             eTok = pParser->Next();
     712           3 :             pNd = new SbiExprNode( pParser, pNd, eTok, Mod() );
     713             :         }
     714             :     }
     715          35 :     return pNd;
     716             : }
     717             : 
     718          35 : SbiExprNode* SbiExpression::Cat()
     719             : {
     720          35 :     SbiExprNode* pNd = AddSub();
     721          35 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     722             :     {
     723           0 :         for( ;; )
     724             :         {
     725          35 :             SbiToken eTok = pParser->Peek();
     726          35 :             if( eTok != CAT )
     727             :             {
     728          35 :                 break;
     729             :             }
     730           0 :             eTok = pParser->Next();
     731           0 :             pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() );
     732             :         }
     733             :     }
     734          35 :     return pNd;
     735             : }
     736             : 
     737          33 : SbiExprNode* SbiExpression::Comp()
     738             : {
     739          33 :     SbiExprNode* pNd = Cat();
     740          33 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     741             :     {
     742          33 :         short nCount = 0;
     743           2 :         for( ;; )
     744             :         {
     745          35 :             SbiToken eTok = pParser->Peek();
     746          35 :             if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
     747             :             {
     748           0 :                 break;
     749             :             }
     750          35 :             if( eTok != EQ && eTok != NE && eTok != LT &&
     751             :                 eTok != GT && eTok != LE && eTok != GE )
     752             :             {
     753          33 :                 break;
     754             :             }
     755           2 :             eTok = pParser->Next();
     756           2 :             pNd = new SbiExprNode( pParser, pNd, eTok, Cat() );
     757           2 :             nCount++;
     758             :         }
     759             :     }
     760          33 :     return pNd;
     761             : }
     762             : 
     763             : 
     764           0 : SbiExprNode* SbiExpression::VBA_Not()
     765             : {
     766           0 :     SbiExprNode* pNd = NULL;
     767             : 
     768           0 :     SbiToken eTok = pParser->Peek();
     769           0 :     if( eTok == NOT )
     770             :     {
     771           0 :         pParser->Next();
     772           0 :         pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL );
     773             :     }
     774             :     else
     775             :     {
     776           0 :         pNd = Comp();
     777             :     }
     778           0 :     return pNd;
     779             : }
     780             : 
     781          33 : SbiExprNode* SbiExpression::Like()
     782             : {
     783          33 :     SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
     784          33 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     785             :     {
     786          33 :         short nCount = 0;
     787          66 :         while( pParser->Peek() == LIKE )
     788             :         {
     789           0 :             SbiToken eTok = pParser->Next();
     790           0 :             pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++;
     791             :         }
     792             :         // multiple operands in a row does not work
     793          33 :         if( nCount > 1 && !pParser->IsVBASupportOn() )
     794             :         {
     795           0 :             pParser->Error( SbERR_SYNTAX );
     796           0 :             bError = true;
     797             :         }
     798             :     }
     799          33 :     return pNd;
     800             : }
     801             : 
     802          33 : SbiExprNode* SbiExpression::Boolean()
     803             : {
     804          33 :     SbiExprNode* pNd = Like();
     805          33 :     if( m_eMode != EXPRMODE_EMPTY_PAREN )
     806             :     {
     807           0 :         for( ;; )
     808             :         {
     809          33 :             SbiToken eTok = pParser->Peek();
     810          33 :             if( (eTok != AND) && (eTok != OR) &&
     811             :                 (eTok != XOR) && (eTok != EQV) &&
     812             :                 (eTok != IMP) && (eTok != IS) )
     813             :             {
     814          33 :                 break;
     815             :             }
     816           0 :             eTok = pParser->Next();
     817           0 :             pNd = new SbiExprNode( pParser, pNd, eTok, Like() );
     818             :         }
     819             :     }
     820          33 :     return pNd;
     821             : }
     822             : 
     823             : /***************************************************************************
     824             : |*
     825             : |*      SbiConstExpression
     826             : |*
     827             : ***************************************************************************/
     828             : 
     829           0 : SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
     830             : {
     831           0 :     if( pExpr->IsConstant() )
     832             :     {
     833           0 :         eType = pExpr->GetType();
     834           0 :         if( pExpr->IsNumber() )
     835             :         {
     836           0 :             nVal = pExpr->nVal;
     837             :         }
     838             :         else
     839             :         {
     840           0 :             nVal = 0;
     841           0 :             aVal = pExpr->aStrVal;
     842             :         }
     843             :     }
     844             :     else
     845             :     {
     846             :         // #40204 special treatment for sal_Bool-constants
     847           0 :         sal_Bool bIsBool = sal_False;
     848           0 :         if( pExpr->eNodeType == SbxVARVAL )
     849             :         {
     850           0 :             SbiSymDef* pVarDef = pExpr->GetVar();
     851             : 
     852           0 :             sal_Bool bBoolVal = sal_False;
     853           0 :             if( pVarDef->GetName().equalsIgnoreAsciiCase( "true" ) )
     854             :             {
     855           0 :                 bIsBool = sal_True;
     856           0 :                 bBoolVal = sal_True;
     857             :             }
     858           0 :             else if( pVarDef->GetName().equalsIgnoreAsciiCase( "false" ) )
     859             :             //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
     860             :             {
     861           0 :                 bIsBool = sal_True;
     862           0 :                 bBoolVal = sal_False;
     863             :             }
     864             : 
     865           0 :             if( bIsBool )
     866             :             {
     867           0 :                 delete pExpr;
     868           0 :                 pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
     869           0 :                 eType = pExpr->GetType();
     870           0 :                 nVal = pExpr->nVal;
     871             :             }
     872             :         }
     873             : 
     874           0 :         if( !bIsBool )
     875             :         {
     876           0 :             pParser->Error( SbERR_SYNTAX );
     877           0 :             eType = SbxDOUBLE;
     878           0 :             nVal = 0;
     879             :         }
     880             :     }
     881           0 : }
     882             : 
     883           0 : short SbiConstExpression::GetShortValue()
     884             : {
     885           0 :     if( eType == SbxSTRING )
     886             :     {
     887           0 :         SbxVariableRef refConv = new SbxVariable;
     888           0 :         refConv->PutString( aVal );
     889           0 :         return refConv->GetInteger();
     890             :     }
     891             :     else
     892             :     {
     893           0 :         double n = nVal;
     894           0 :         if( n > 0 )
     895             :         {
     896           0 :             n += .5;
     897             :         }
     898             :         else
     899             :         {
     900           0 :             n -= .5;
     901             :         }
     902           0 :         if( n > SbxMAXINT )
     903             :         {
     904           0 :             n = SbxMAXINT;
     905           0 :             pParser->Error( SbERR_OUT_OF_RANGE );
     906             :         }
     907           0 :         else if( n < SbxMININT )
     908             :         {
     909           0 :             n = SbxMININT;
     910           0 :             pParser->Error( SbERR_OUT_OF_RANGE );
     911             :         }
     912             : 
     913           0 :         return (short) n;
     914             :     }
     915             : }
     916             : 
     917             : 
     918             : /***************************************************************************
     919             : |*
     920             : |*      SbiExprList
     921             : |*
     922             : ***************************************************************************/
     923             : 
     924          47 : SbiExprList::SbiExprList( SbiParser* p )
     925             : {
     926          47 :     pParser = p;
     927          47 :     pFirst = NULL;
     928             :     nExpr  =
     929          47 :     nDim   = 0;
     930          47 :     bError = false;
     931          47 :     bBracket = false;
     932          47 : }
     933             : 
     934          47 : SbiExprList::~SbiExprList()
     935             : {
     936          47 :     SbiExpression* p = pFirst;
     937          98 :     while( p )
     938             :     {
     939           4 :         SbiExpression* q = p->pNext;
     940           4 :         delete p;
     941           4 :         p = q;
     942             :     }
     943          47 : }
     944             : 
     945             : 
     946           0 : SbiExpression* SbiExprList::Get( short n )
     947             : {
     948           0 :     SbiExpression* p = pFirst;
     949           0 :     while( n-- && p )
     950             :     {
     951           0 :         p = p->pNext;
     952             :     }
     953           0 :     return p;
     954             : }
     955             : 
     956           0 : void SbiExprList::addExpression( SbiExpression* pExpr )
     957             : {
     958           0 :     if( !pFirst )
     959             :     {
     960           0 :         pFirst = pExpr;
     961           0 :         return;
     962             :     }
     963             : 
     964           0 :     SbiExpression* p = pFirst;
     965           0 :     while( p->pNext )
     966             :     {
     967           0 :         p = p->pNext;
     968             :     }
     969           0 :     p->pNext = pExpr;
     970             : }
     971             : 
     972             : 
     973             : /***************************************************************************
     974             : |*
     975             : |*      SbiParameters
     976             : |*
     977             : ***************************************************************************/
     978             : 
     979             : // parsing constructor:
     980             : // the parameter list is completely parsed
     981             : // "procedurename()" is OK
     982             : // it's a function without parameters then
     983             : // i. e. you give an array as procedure parameter
     984             : 
     985             : // #i79918/#i80532: bConst has never been set to true
     986             : // -> reused as bStandaloneExpression
     987             : //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
     988          47 : SbiParameters::SbiParameters( SbiParser* p, bool bStandaloneExpression, bool bPar) :
     989          47 :     SbiExprList( p )
     990             : {
     991          47 :     if( !bPar )
     992             :     {
     993             :         return;
     994             :     }
     995             :     SbiExpression *pExpr;
     996           2 :     SbiToken eTok = pParser->Peek();
     997             : 
     998           2 :     bool bAssumeExprLParenMode = false;
     999           2 :     bool bAssumeArrayMode = false;
    1000           2 :     if( eTok == LPAREN )
    1001             :     {
    1002           2 :         if( bStandaloneExpression )
    1003             :         {
    1004           0 :             bAssumeExprLParenMode = true;
    1005             :         }
    1006             :         else
    1007             :         {
    1008           2 :             bBracket = true;
    1009           2 :             pParser->Next();
    1010           2 :             eTok = pParser->Peek();
    1011             :         }
    1012             :     }
    1013             : 
    1014             : 
    1015           2 :     if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
    1016             :     {
    1017           0 :         if( eTok == RPAREN )
    1018             :         {
    1019           0 :             pParser->Next();
    1020             :         }
    1021             :         return;
    1022             :     }
    1023             :     // read in parameter table and lay down in correct order!
    1024           2 :     SbiExpression* pLast = NULL;
    1025           2 :     OUString aName;
    1026           2 :     while( !bError )
    1027             :     {
    1028           4 :         aName = "";
    1029             :         // missing argument
    1030           4 :         if( eTok == COMMA )
    1031             :         {
    1032           0 :             pExpr = new SbiExpression( pParser, 0, SbxEMPTY );
    1033             :         }
    1034             :         // named arguments: either .name= or name:=
    1035             :         else
    1036             :         {
    1037           4 :             bool bByVal = false;
    1038           4 :             if( eTok == BYVAL )
    1039             :             {
    1040           0 :                 bByVal = true;
    1041           0 :                 pParser->Next();
    1042           0 :                 eTok = pParser->Peek();
    1043             :             }
    1044             : 
    1045           4 :             if( bAssumeExprLParenMode )
    1046             :             {
    1047           0 :                 pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
    1048           0 :                 bAssumeExprLParenMode = sal_False;
    1049             : 
    1050           0 :                 SbiExprMode eModeAfter = pExpr->m_eMode;
    1051           0 :                 if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
    1052             :                 {
    1053           0 :                     bBracket = true;
    1054             :                 }
    1055           0 :                 else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
    1056             :                 {
    1057             :                     // Expression "looks" like an array assignment
    1058             :                     // a(...)[(...)] = ? or a(...).b(...)
    1059             :                     // RPAREN is already parsed
    1060           0 :                     bBracket = true;
    1061           0 :                     bAssumeArrayMode = true;
    1062           0 :                     eTok = NIL;
    1063             :                 }
    1064           0 :                 else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
    1065             :                 {
    1066           0 :                     bBracket = true;
    1067           0 :                     delete pExpr;
    1068           0 :                     if( bByVal )
    1069             :                     {
    1070           0 :                         pParser->Error( SbERR_LVALUE_EXPECTED );
    1071             :                     }
    1072             :                     return;
    1073             :                 }
    1074             :             }
    1075             :             else
    1076             :             {
    1077           4 :                 pExpr = new SbiExpression( pParser );
    1078             :             }
    1079           4 :             if( bByVal && pExpr->IsLvalue() )
    1080             :             {
    1081           0 :                 pExpr->SetByVal();
    1082             :             }
    1083           4 :             if( !bAssumeArrayMode )
    1084             :             {
    1085           4 :                 if( pParser->Peek() == ASSIGN )
    1086             :                 {
    1087             :                     // VBA mode: name:=
    1088             :                     // SbiExpression::Term() has made as string out of it
    1089           0 :                     aName = pExpr->GetString();
    1090           0 :                     delete pExpr;
    1091           0 :                     pParser->Next();
    1092           0 :                     pExpr = new SbiExpression( pParser );
    1093             :                 }
    1094           4 :                 pExpr->GetName() = aName;
    1095             :             }
    1096             :         }
    1097           4 :         pExpr->pNext = NULL;
    1098           4 :         if( !pLast )
    1099             :         {
    1100           2 :             pFirst = pLast = pExpr;
    1101             :         }
    1102             :         else
    1103             :         {
    1104           2 :             pLast->pNext = pExpr, pLast = pExpr;
    1105             :         }
    1106           4 :         nExpr++;
    1107           4 :         bError = bError || !pExpr->IsValid();
    1108             : 
    1109           4 :         if( bAssumeArrayMode )
    1110             :         {
    1111           0 :             break;
    1112             :         }
    1113             :         // next element?
    1114           4 :         eTok = pParser->Peek();
    1115           4 :         if( eTok != COMMA )
    1116             :         {
    1117           2 :             if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
    1118             :             {
    1119           2 :                 break;
    1120             :             }
    1121           0 :             pParser->Error( bBracket ? SbERR_BAD_BRACKETS : SbERR_EXPECTED, COMMA );
    1122           0 :             bError = true;
    1123             :         }
    1124             :         else
    1125             :         {
    1126           2 :             pParser->Next();
    1127           2 :             eTok = pParser->Peek();
    1128           2 :             if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
    1129             :             {
    1130           0 :                 break;
    1131             :             }
    1132             :         }
    1133             :     }
    1134             :     // closing bracket
    1135           2 :     if( eTok == RPAREN )
    1136             :     {
    1137           2 :         pParser->Next();
    1138           2 :         pParser->Peek();
    1139           2 :         if( !bBracket )
    1140             :         {
    1141           0 :             pParser->Error( SbERR_BAD_BRACKETS );
    1142           0 :             bError = true;
    1143             :         }
    1144             :     }
    1145           2 :     nDim = nExpr;
    1146             : }
    1147             : 
    1148             : /***************************************************************************
    1149             : |*
    1150             : |*      SbiDimList
    1151             : |*
    1152             : ***************************************************************************/
    1153             : 
    1154             : // parsing constructor:
    1155             : // A list of array dimensions is parsed. The expressions are tested for being
    1156             : // numeric. The bCONST-Bit is reset when all expressions are Integer constants.
    1157             : 
    1158           0 : SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p )
    1159             : {
    1160           0 :     bConst = true;
    1161             : 
    1162           0 :     if( pParser->Next() != LPAREN )
    1163             :     {
    1164           0 :         pParser->Error( SbERR_EXPECTED, LPAREN );
    1165           0 :         bError = true; return;
    1166             :     }
    1167             : 
    1168           0 :     if( pParser->Peek() != RPAREN )
    1169             :     {
    1170           0 :         SbiExpression *pExpr1, *pExpr2, *pLast = NULL;
    1171             :         SbiToken eTok;
    1172           0 :         for( ;; )
    1173             :         {
    1174           0 :             pExpr1 = new SbiExpression( pParser );
    1175           0 :             eTok = pParser->Next();
    1176           0 :             if( eTok == TO )
    1177             :             {
    1178           0 :                 pExpr2 = new SbiExpression( pParser );
    1179           0 :                 eTok = pParser->Next();
    1180           0 :                 bConst = bConst && pExpr1->IsIntConstant() && pExpr2->IsIntConstant();
    1181           0 :                 bError = bError || !pExpr1->IsValid() || !pExpr2->IsValid();
    1182           0 :                 pExpr1->pNext = pExpr2;
    1183           0 :                 if( !pLast )
    1184             :                 {
    1185           0 :                     pFirst = pExpr1;
    1186             :                 }
    1187             :                 else
    1188             :                 {
    1189           0 :                     pLast->pNext = pExpr1;
    1190             :                 }
    1191           0 :                 pLast = pExpr2;
    1192           0 :                 nExpr += 2;
    1193             :             }
    1194             :             else
    1195             :             {
    1196           0 :                 pExpr1->SetBased();
    1197           0 :                 pExpr1->pNext = NULL;
    1198           0 :                 bConst = bConst && pExpr1->IsIntConstant();
    1199           0 :                 bError = bError || !pExpr1->IsValid();
    1200           0 :                 if( !pLast )
    1201             :                 {
    1202           0 :                     pFirst = pLast = pExpr1;
    1203             :                 }
    1204             :                 else
    1205             :                 {
    1206           0 :                     pLast->pNext = pExpr1, pLast = pExpr1;
    1207             :                 }
    1208           0 :                 nExpr++;
    1209             :             }
    1210           0 :             nDim++;
    1211           0 :             if( eTok == RPAREN ) break;
    1212           0 :             if( eTok != COMMA )
    1213             :             {
    1214           0 :                 pParser->Error( SbERR_BAD_BRACKETS );
    1215           0 :                 pParser->Next();
    1216           0 :                 break;
    1217             :             }
    1218             :         }
    1219             :     }
    1220           0 :     else pParser->Next();
    1221             : }
    1222             : 
    1223             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10