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