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: */
|