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