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 "parser.hxx"
22 : #include <basic/sbx.hxx>
23 : #include "expr.hxx"
24 :
25 : /***************************************************************************
26 : |*
27 : |* SbiExpression
28 : |*
29 : ***************************************************************************/
30 :
31 12343 : SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
32 12343 : SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
33 : {
34 12343 : pParser = p;
35 12343 : bBased = bError = bByVal = bBracket = false;
36 12343 : nParenLevel = 0;
37 12343 : eCurExpr = t;
38 12343 : m_eMode = eMode;
39 12343 : pNext = NULL;
40 12343 : pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean();
41 12343 : if( t != SbSYMBOL )
42 : {
43 8649 : pExpr->Optimize();
44 : }
45 12343 : if( t == SbLVALUE && !pExpr->IsLvalue() )
46 : {
47 0 : p->Error( SbERR_LVALUE_EXPECTED );
48 : }
49 12343 : if( t == SbOPERAND && !IsVariable() )
50 : {
51 0 : p->Error( SbERR_VAR_EXPECTED );
52 : }
53 12343 : }
54 :
55 44 : SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t )
56 : {
57 44 : pParser = p;
58 44 : bBased = bError = bByVal = bBracket = false;
59 44 : nParenLevel = 0;
60 44 : eCurExpr = SbOPERAND;
61 44 : m_eMode = EXPRMODE_STANDARD;
62 44 : pNext = NULL;
63 44 : pExpr = new SbiExprNode( pParser, n, t );
64 44 : pExpr->Optimize();
65 44 : }
66 :
67 295 : SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar )
68 : {
69 295 : pParser = p;
70 295 : bBased = bError = bByVal = bBracket = false;
71 295 : nParenLevel = 0;
72 295 : eCurExpr = SbOPERAND;
73 295 : m_eMode = EXPRMODE_STANDARD;
74 295 : pNext = NULL;
75 295 : pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar );
76 295 : }
77 :
78 25364 : SbiExpression::~SbiExpression()
79 : {
80 12682 : delete pExpr;
81 12682 : }
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 12720 : static bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
93 : {
94 12720 : if( eTok == LPAREN )
95 : {
96 3026 : return true;
97 : }
98 : // but only if similar to CALL!
99 9694 : if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
100 : {
101 7169 : return false;
102 : }
103 2525 : if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
104 2248 : eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL )
105 : {
106 277 : return true;
107 : }
108 : else // check for default params with reserved names ( e.g. names of tokens )
109 : {
110 2248 : SbiTokenizer tokens( *static_cast<SbiTokenizer*>(p) );
111 : // Urk the Next() / Peek() symantics are... weird
112 2248 : tokens.Next();
113 2248 : if ( tokens.Peek() == ASSIGN )
114 : {
115 1 : return true;
116 2247 : }
117 : }
118 2247 : return false;
119 : }
120 :
121 : // definition of a new symbol
122 :
123 1646 : 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 1646 : bool bHasType = ( eTok == EQ || eTok == DOT );
129 1646 : 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 587 : SbiSymPool* pPool = &rPool;
135 587 : if( pPool->GetScope() != SbPUBLIC )
136 : {
137 284 : pPool = &rPool.GetParser()->aPublics;
138 : }
139 587 : SbiProcDef* pProc = pPool->AddProc( rName );
140 :
141 : // special treatment for Colls like Documents(1)
142 587 : if( eCurExpr == SbSTDEXPR )
143 : {
144 208 : bHasType = true;
145 : }
146 587 : pDef = pProc;
147 587 : pDef->SetType( bHasType ? eType : SbxEMPTY );
148 587 : if( pPar )
149 : {
150 : // generate dummy parameters
151 377 : sal_Int32 n = 1;
152 890 : for( short i = 0; i < pPar->GetSize(); i++ )
153 : {
154 513 : n += 1;
155 513 : OUStringBuffer aPar("PAR");
156 513 : aPar.append(n);
157 513 : pProc->GetParams().AddSym( aPar.makeStringAndClear() );
158 513 : }
159 587 : }
160 : }
161 : else
162 : {
163 : // or a normal symbol
164 1059 : pDef = rPool.AddSym( rName );
165 1059 : pDef->SetType( eType );
166 : }
167 1646 : return pDef;
168 : }
169 :
170 : // currently even keywords are allowed (because of Dflt properties of the same name)
171 :
172 10041 : SbiExprNode* SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
173 : {
174 10041 : if( pParser->Peek() == DOT )
175 : {
176 113 : SbiExprNode* pWithVar = pParser->GetWithVar();
177 : // #26608: get to the node-chain's end to pass the correct object
178 113 : SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL;
179 113 : SbiExprNode* pNd = NULL;
180 113 : if( !pDef )
181 : {
182 0 : pParser->Next();
183 : }
184 : else
185 : {
186 113 : pNd = ObjTerm( *pDef );
187 113 : if( pNd )
188 : {
189 113 : pNd->SetWithParent( pWithVar );
190 : }
191 : }
192 113 : if( !pNd )
193 : {
194 0 : pParser->Error( SbERR_UNEXPECTED, DOT );
195 0 : pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
196 : }
197 113 : return pNd;
198 : }
199 :
200 9928 : SbiToken eTok = (pKeywordSymbolInfo == NULL) ? pParser->Next() : pKeywordSymbolInfo->m_eTok;
201 : // memorize the parsing's begin
202 9928 : pParser->LockColumn();
203 9928 : OUString aSym( (pKeywordSymbolInfo == NULL) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol );
204 9928 : SbxDataType eType = (pKeywordSymbolInfo == NULL) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType;
205 9928 : SbiParameters* pPar = NULL;
206 9928 : SbiExprListVector* pvMoreParLcl = NULL;
207 : // are there parameters following?
208 9928 : 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 9928 : if( eNextTok == ASSIGN )
213 : {
214 156 : pParser->UnlockColumn();
215 156 : return new SbiExprNode( pParser, aSym );
216 : }
217 : // no keywords allowed from here on!
218 9772 : if( SbiTokenizer::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 9772 : if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
232 : {
233 2591 : bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
234 2591 : pPar = new SbiParameters( pParser, bStandaloneExpression );
235 2591 : bError = bError || !pPar->IsValid();
236 2591 : if( !bError )
237 2591 : bBracket = pPar->IsBracket();
238 2591 : eTok = pParser->Peek();
239 :
240 : // i75443 check for additional sets of parameters
241 5182 : 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 7754 : bool bObj = ( ( eTok == DOT || eTok == EXCLAM )
257 11790 : && !pParser->WhiteSpace() );
258 9772 : if( bObj )
259 : {
260 2018 : bBracket = false; // Now the bracket for the first term is obsolete
261 2018 : if( eType == SbxVARIANT )
262 : {
263 2018 : 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 9772 : SbiSymDef* pDef = pParser->pPool->Find( aSym );
274 9772 : 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 980 : pDef = pParser->CheckRTLForSym( aSym, eType );
280 :
281 : // #i109184: Check if symbol is or later will be defined inside module
282 980 : SbModule& rMod = pParser->aGen.GetModule();
283 980 : SbxArray* pModMethods = rMod.GetMethods();
284 980 : if( pModMethods->Find( aSym, SbxCLASS_DONTCARE ) )
285 : {
286 219 : pDef = NULL;
287 : }
288 : }
289 9772 : if( !pDef )
290 : {
291 753 : if( bObj )
292 : {
293 117 : eType = SbxOBJECT;
294 : }
295 753 : 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 753 : if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
300 : {
301 0 : pDef->SetStatic();
302 : }
303 : }
304 : else
305 : {
306 :
307 9019 : SbiConstDef* pConst = pDef->GetConstDef();
308 9019 : if( pConst )
309 : {
310 261 : delete pPar;
311 261 : delete pvMoreParLcl;
312 261 : if( pConst->GetType() == SbxSTRING )
313 : {
314 151 : return new SbiExprNode( pParser, pConst->GetString() );
315 : }
316 : else
317 : {
318 110 : return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() );
319 : }
320 : }
321 :
322 : // 0 parameters come up to ()
323 8758 : if( pDef->GetDims() )
324 : {
325 134 : if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
326 : {
327 0 : pParser->Error( SbERR_WRONG_DIMS );
328 : }
329 : }
330 8758 : if( pDef->IsDefinedAs() )
331 : {
332 4403 : SbxDataType eDefType = pDef->GetType();
333 : // #119187 Only error if types conflict
334 4403 : 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 4403 : 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 3486 : 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 14394 : if( eType != SbxVARIANT && // Variant takes everything
352 8807 : eType != pDef->GetType() &&
353 49 : !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 43 : if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
359 : {
360 43 : pDef->SetType( SbxOBJECT );
361 : }
362 : else
363 : {
364 0 : pParser->Error( SbERR_BAD_DECLARATION, aSym );
365 0 : bError = true;
366 : }
367 : }
368 : }
369 9511 : SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
370 9511 : if( !pPar )
371 : {
372 6920 : pPar = new SbiParameters( pParser,false,false );
373 : }
374 9511 : pNd->aVar.pPar = pPar;
375 9511 : pNd->aVar.pvMorePar = pvMoreParLcl;
376 9511 : if( bObj )
377 : {
378 : // from 8.1.95: Object may also be of the type SbxVARIANT
379 2018 : if( pDef->GetType() == SbxVARIANT )
380 6 : pDef->SetType( SbxOBJECT );
381 : // if we scan something with point,
382 : // the type must be SbxOBJECT
383 2018 : 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 2018 : if( !bError )
393 : {
394 2018 : pNd->aVar.pNext = ObjTerm( *pDef );
395 : }
396 : }
397 :
398 9511 : pParser->UnlockColumn();
399 9511 : 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 2948 : SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj )
406 : {
407 2948 : pParser->Next();
408 2948 : SbiToken eTok = pParser->Next();
409 2948 : if( eTok != SYMBOL && !SbiTokenizer::IsKwd( eTok ) && !SbiTokenizer::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 2948 : if( bError )
422 : {
423 0 : return NULL;
424 : }
425 2948 : OUString aSym( pParser->GetSym() );
426 2948 : SbxDataType eType = pParser->GetType();
427 2948 : SbiParameters* pPar = NULL;
428 2948 : SbiExprListVector* pvMoreParLcl = NULL;
429 2948 : eTok = pParser->Peek();
430 :
431 2948 : if( DoParametersFollow( pParser, eCurExpr, eTok ) )
432 : {
433 713 : bool bStandaloneExpression = false;
434 713 : pPar = new SbiParameters( pParser, bStandaloneExpression );
435 713 : bError = bError || !pPar->IsValid();
436 713 : eTok = pParser->Peek();
437 :
438 : // i109624 check for additional sets of parameters
439 1426 : 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 2948 : bool bObj = ( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
452 2948 : if( bObj )
453 : {
454 817 : if( eType == SbxVARIANT )
455 : {
456 817 : 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 2948 : SbiSymPool& rPool = rObj.GetPool();
468 2948 : rPool.SetScope( SbPUBLIC );
469 2948 : SbiSymDef* pDef = rPool.Find( aSym );
470 2948 : if( !pDef )
471 : {
472 893 : pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar );
473 893 : pDef->SetType( eType );
474 : }
475 :
476 2948 : SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
477 2948 : pNd->aVar.pPar = pPar;
478 2948 : pNd->aVar.pvMorePar = pvMoreParLcl;
479 2948 : if( bObj )
480 : {
481 817 : if( pDef->GetType() == SbxVARIANT )
482 : {
483 9 : pDef->SetType( SbxOBJECT );
484 : }
485 817 : if( pDef->GetType() != SbxOBJECT )
486 : {
487 0 : pParser->Error( SbERR_BAD_DECLARATION, aSym );
488 0 : bError = true;
489 : }
490 817 : if( !bError )
491 : {
492 817 : pNd->aVar.pNext = ObjTerm( *pDef );
493 817 : pNd->eType = eType;
494 : }
495 : }
496 2948 : 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 12216 : SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf )
508 : {
509 : SbiExprNode *pRes;
510 : SbiToken eTok;
511 :
512 : // test operand:
513 12216 : switch( eTok = pParser->Peek() )
514 : {
515 : case SYMBOL:
516 6018 : pRes = Term();
517 : // process something like "IF Not r Is Nothing Then .."
518 6018 : if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
519 : {
520 2 : eTok = pParser->Next();
521 2 : pRes = new SbiExprNode( pParser, pRes, eTok, Like() );
522 : }
523 6018 : break;
524 : case DOT: // .with
525 85 : pRes = Term(); break;
526 : case NUMBER:
527 1784 : pParser->Next();
528 1784 : pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() );
529 1784 : break;
530 : case FIXSTRING:
531 3269 : pParser->Next();
532 3269 : pRes = new SbiExprNode( pParser, pParser->GetSym() ); break;
533 : case LPAREN:
534 1058 : pParser->Next();
535 1058 : 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 1058 : nParenLevel++;
543 1058 : pRes = Boolean();
544 1058 : if( pParser->Peek() != RPAREN )
545 : {
546 : // If there was a LPARAM, it does not belong to the expression
547 1 : if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
548 : {
549 1 : m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
550 : }
551 : else
552 : {
553 0 : pParser->Error( SbERR_BAD_BRACKETS );
554 : }
555 : }
556 : else
557 : {
558 1057 : pParser->Next();
559 1057 : if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
560 : {
561 513 : SbiToken eTokAfterRParen = pParser->Peek();
562 513 : if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
563 : {
564 331 : m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
565 : }
566 : else
567 : {
568 182 : m_eMode = EXPRMODE_STANDARD;
569 : }
570 : }
571 : }
572 1058 : nParenLevel--;
573 1058 : break;
574 : default:
575 : // keywords here are OK at the moment!
576 2 : if( SbiTokenizer::IsKwd( eTok ) )
577 : {
578 2 : 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 2 : break;
587 : }
588 12216 : return pRes;
589 : }
590 :
591 12335 : SbiExprNode* SbiExpression::Unary()
592 : {
593 : SbiExprNode* pNd;
594 12335 : SbiToken eTok = pParser->Peek();
595 12335 : switch( eTok )
596 : {
597 : case MINUS:
598 102 : eTok = NEG;
599 102 : pParser->Next();
600 102 : pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
601 102 : break;
602 : case NOT:
603 17 : if( pParser->IsVBASupportOn() )
604 : {
605 0 : pNd = Operand();
606 : }
607 : else
608 : {
609 17 : pParser->Next();
610 17 : pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
611 : }
612 17 : 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 12216 : pNd = Operand();
640 : }
641 12335 : return pNd;
642 : }
643 :
644 12216 : SbiExprNode* SbiExpression::Exp()
645 : {
646 12216 : SbiExprNode* pNd = Unary();
647 12216 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
648 : {
649 24432 : while( pParser->Peek() == EXPON )
650 : {
651 0 : SbiToken eTok = pParser->Next();
652 0 : pNd = new SbiExprNode( pParser, pNd, eTok, Unary() );
653 : }
654 : }
655 12216 : return pNd;
656 : }
657 :
658 12202 : SbiExprNode* SbiExpression::MulDiv()
659 : {
660 12202 : SbiExprNode* pNd = Exp();
661 12202 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
662 : {
663 : for( ;; )
664 : {
665 12216 : SbiToken eTok = pParser->Peek();
666 12216 : if( eTok != MUL && eTok != DIV )
667 : {
668 12202 : break;
669 : }
670 14 : eTok = pParser->Next();
671 14 : pNd = new SbiExprNode( pParser, pNd, eTok, Exp() );
672 14 : }
673 : }
674 12202 : return pNd;
675 : }
676 :
677 12202 : SbiExprNode* SbiExpression::IntDiv()
678 : {
679 12202 : SbiExprNode* pNd = MulDiv();
680 12202 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
681 : {
682 24404 : while( pParser->Peek() == IDIV )
683 : {
684 0 : SbiToken eTok = pParser->Next();
685 0 : pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() );
686 : }
687 : }
688 12202 : return pNd;
689 : }
690 :
691 12202 : SbiExprNode* SbiExpression::Mod()
692 : {
693 12202 : SbiExprNode* pNd = IntDiv();
694 12202 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
695 : {
696 24404 : while( pParser->Peek() == MOD )
697 : {
698 0 : SbiToken eTok = pParser->Next();
699 0 : pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() );
700 : }
701 : }
702 12202 : return pNd;
703 : }
704 :
705 11503 : SbiExprNode* SbiExpression::AddSub()
706 : {
707 11503 : SbiExprNode* pNd = Mod();
708 11503 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
709 : {
710 : for( ;; )
711 : {
712 12202 : SbiToken eTok = pParser->Peek();
713 12202 : if( eTok != PLUS && eTok != MINUS )
714 : {
715 11503 : break;
716 : }
717 699 : eTok = pParser->Next();
718 699 : pNd = new SbiExprNode( pParser, pNd, eTok, Mod() );
719 699 : }
720 : }
721 11503 : return pNd;
722 : }
723 :
724 10465 : SbiExprNode* SbiExpression::Cat()
725 : {
726 10465 : SbiExprNode* pNd = AddSub();
727 10465 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
728 : {
729 : for( ;; )
730 : {
731 11503 : SbiToken eTok = pParser->Peek();
732 11503 : if( eTok != CAT )
733 : {
734 10465 : break;
735 : }
736 1038 : eTok = pParser->Next();
737 1038 : pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() );
738 1038 : }
739 : }
740 10465 : return pNd;
741 : }
742 :
743 9594 : SbiExprNode* SbiExpression::Comp()
744 : {
745 9594 : SbiExprNode* pNd = Cat();
746 9594 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
747 : {
748 9594 : short nCount = 0;
749 : for( ;; )
750 : {
751 10465 : SbiToken eTok = pParser->Peek();
752 10465 : if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
753 : {
754 331 : break;
755 : }
756 10134 : if( eTok != EQ && eTok != NE && eTok != LT &&
757 9267 : eTok != GT && eTok != LE && eTok != GE )
758 : {
759 9263 : break;
760 : }
761 871 : eTok = pParser->Next();
762 871 : pNd = new SbiExprNode( pParser, pNd, eTok, Cat() );
763 871 : nCount++;
764 871 : }
765 : }
766 9594 : return pNd;
767 : }
768 :
769 :
770 7837 : SbiExprNode* SbiExpression::VBA_Not()
771 : {
772 7837 : SbiExprNode* pNd = NULL;
773 :
774 7837 : SbiToken eTok = pParser->Peek();
775 7837 : if( eTok == NOT )
776 : {
777 81 : pParser->Next();
778 81 : pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL );
779 : }
780 : else
781 : {
782 7756 : pNd = Comp();
783 : }
784 7837 : return pNd;
785 : }
786 :
787 9594 : SbiExprNode* SbiExpression::Like()
788 : {
789 9594 : SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
790 9594 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
791 : {
792 9594 : short nCount = 0;
793 19188 : 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 9594 : if( nCount > 1 && !pParser->IsVBASupportOn() )
800 : {
801 0 : pParser->Error( SbERR_SYNTAX );
802 0 : bError = true;
803 : }
804 : }
805 9594 : return pNd;
806 : }
807 :
808 9465 : SbiExprNode* SbiExpression::Boolean()
809 : {
810 9465 : SbiExprNode* pNd = Like();
811 9465 : if( m_eMode != EXPRMODE_EMPTY_PAREN )
812 : {
813 : for( ;; )
814 : {
815 9592 : SbiToken eTok = pParser->Peek();
816 9592 : if( (eTok != AND) && (eTok != OR) &&
817 9465 : (eTok != XOR) && (eTok != EQV) &&
818 9465 : (eTok != IMP) && (eTok != IS) )
819 : {
820 9465 : break;
821 : }
822 127 : eTok = pParser->Next();
823 127 : pNd = new SbiExprNode( pParser, pNd, eTok, Like() );
824 127 : }
825 : }
826 9465 : return pNd;
827 : }
828 :
829 : /***************************************************************************
830 : |*
831 : |* SbiConstExpression
832 : |*
833 : ***************************************************************************/
834 :
835 122 : SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
836 : {
837 122 : if( pExpr->IsConstant() )
838 : {
839 122 : eType = pExpr->GetType();
840 122 : if( pExpr->IsNumber() )
841 : {
842 60 : nVal = pExpr->nVal;
843 : }
844 : else
845 : {
846 62 : nVal = 0;
847 62 : 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 122 : }
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 10269 : SbiExprList::SbiExprList( SbiParser* p )
931 : {
932 10269 : pParser = p;
933 10269 : pFirst = NULL;
934 : nExpr =
935 10269 : nDim = 0;
936 10269 : bError = false;
937 10269 : bBracket = false;
938 10269 : }
939 :
940 10269 : SbiExprList::~SbiExprList()
941 : {
942 10269 : SbiExpression* p = pFirst;
943 25518 : while( p )
944 : {
945 4980 : SbiExpression* q = p->pNext;
946 4980 : delete p;
947 4980 : p = q;
948 : }
949 10269 : }
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 10224 : SbiParameters::SbiParameters( SbiParser* p, bool bStandaloneExpression, bool bPar) :
995 10224 : SbiExprList( p )
996 : {
997 10224 : if( !bPar )
998 : {
999 13920 : return;
1000 : }
1001 : SbiExpression *pExpr;
1002 3304 : SbiToken eTok = pParser->Peek();
1003 :
1004 3304 : bool bAssumeExprLParenMode = false;
1005 3304 : bool bAssumeArrayMode = false;
1006 3304 : if( eTok == LPAREN )
1007 : {
1008 3026 : if( bStandaloneExpression )
1009 : {
1010 514 : bAssumeExprLParenMode = true;
1011 : }
1012 : else
1013 : {
1014 2512 : bBracket = true;
1015 2512 : pParser->Next();
1016 2512 : eTok = pParser->Peek();
1017 : }
1018 : }
1019 :
1020 :
1021 3304 : if( ( bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1022 : {
1023 80 : if( eTok == RPAREN )
1024 : {
1025 80 : pParser->Next();
1026 : }
1027 80 : return;
1028 : }
1029 : // read in parameter table and lay down in correct order!
1030 3224 : SbiExpression* pLast = NULL;
1031 3224 : OUString aName;
1032 3224 : while( !bError )
1033 : {
1034 4952 : aName.clear();
1035 : // missing argument
1036 4952 : if( eTok == COMMA )
1037 : {
1038 4 : pExpr = new SbiExpression( pParser, 0, SbxEMPTY );
1039 : }
1040 : // named arguments: either .name= or name:=
1041 : else
1042 : {
1043 4948 : bool bByVal = false;
1044 4948 : if( eTok == BYVAL )
1045 : {
1046 0 : bByVal = true;
1047 0 : pParser->Next();
1048 0 : eTok = pParser->Peek();
1049 : }
1050 :
1051 4948 : if( bAssumeExprLParenMode )
1052 : {
1053 514 : pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
1054 514 : bAssumeExprLParenMode = false;
1055 :
1056 514 : SbiExprMode eModeAfter = pExpr->m_eMode;
1057 514 : if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
1058 : {
1059 1 : bBracket = true;
1060 : }
1061 513 : 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 331 : bBracket = true;
1067 331 : bAssumeArrayMode = true;
1068 331 : eTok = NIL;
1069 : }
1070 182 : else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1071 : {
1072 0 : bBracket = true;
1073 0 : delete pExpr;
1074 0 : return;
1075 : }
1076 : }
1077 : else
1078 : {
1079 4434 : pExpr = new SbiExpression( pParser );
1080 : }
1081 4948 : if( bByVal && pExpr->IsLvalue() )
1082 : {
1083 0 : pExpr->SetByVal();
1084 : }
1085 4948 : if( !bAssumeArrayMode )
1086 : {
1087 4617 : 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 4617 : pExpr->GetName() = aName;
1097 : }
1098 : }
1099 4952 : pExpr->pNext = NULL;
1100 4952 : if( !pLast )
1101 : {
1102 3224 : pFirst = pLast = pExpr;
1103 : }
1104 : else
1105 : {
1106 1728 : pLast->pNext = pExpr, pLast = pExpr;
1107 : }
1108 4952 : nExpr++;
1109 4952 : bError = bError || !pExpr->IsValid();
1110 :
1111 4952 : if( bAssumeArrayMode )
1112 : {
1113 331 : break;
1114 : }
1115 : // next element?
1116 4621 : eTok = pParser->Peek();
1117 4621 : if( eTok != COMMA )
1118 : {
1119 2893 : if( ( bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1120 : {
1121 2893 : break;
1122 : }
1123 0 : pParser->Error( bBracket ? SbERR_BAD_BRACKETS : SbERR_EXPECTED, COMMA );
1124 0 : bError = true;
1125 : }
1126 : else
1127 : {
1128 1728 : pParser->Next();
1129 1728 : eTok = pParser->Peek();
1130 1728 : if( ( bBracket && eTok == RPAREN ) || SbiTokenizer::IsEoln( eTok ) )
1131 : {
1132 0 : break;
1133 : }
1134 : }
1135 : }
1136 : // closing bracket
1137 3224 : if( eTok == RPAREN )
1138 : {
1139 2433 : pParser->Next();
1140 2433 : pParser->Peek();
1141 2433 : if( !bBracket )
1142 : {
1143 0 : pParser->Error( SbERR_BAD_BRACKETS );
1144 0 : bError = true;
1145 : }
1146 : }
1147 3224 : 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 45 : SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p )
1161 : {
1162 45 : bConst = true;
1163 :
1164 45 : if( pParser->Next() != LPAREN )
1165 : {
1166 0 : pParser->Error( SbERR_EXPECTED, LPAREN );
1167 45 : bError = true; return;
1168 : }
1169 :
1170 45 : if( pParser->Peek() != RPAREN )
1171 : {
1172 26 : SbiExpression *pExpr1, *pExpr2, *pLast = NULL;
1173 : SbiToken eTok;
1174 : for( ;; )
1175 : {
1176 28 : pExpr1 = new SbiExpression( pParser );
1177 28 : eTok = pParser->Next();
1178 28 : 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 28 : pExpr1->SetBased();
1199 28 : pExpr1->pNext = NULL;
1200 28 : bConst = bConst && pExpr1->IsIntConstant();
1201 28 : bError = bError || !pExpr1->IsValid();
1202 28 : if( !pLast )
1203 : {
1204 26 : pFirst = pLast = pExpr1;
1205 : }
1206 : else
1207 : {
1208 2 : pLast->pNext = pExpr1, pLast = pExpr1;
1209 : }
1210 28 : nExpr++;
1211 : }
1212 28 : nDim++;
1213 28 : 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: */
|