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