xref: /trunk/main/basic/source/comp/exprtree.cxx (revision e1f63238)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 
27 #include "sbcomp.hxx"
28 #include <basic/sbx.hxx>		// w.g. ...IMPL_REF(...sbxvariable)
29 #include "expr.hxx"
30 
31 /***************************************************************************
32 |*
33 |*      SbiExpression
34 |*
35 ***************************************************************************/
36 
SbiExpression(SbiParser * p,SbiExprType t,SbiExprMode eMode,const KeywordSymbolInfo * pKeywordSymbolInfo)37 SbiExpression::SbiExpression( SbiParser* p, SbiExprType t,
38 	SbiExprMode eMode, const KeywordSymbolInfo* pKeywordSymbolInfo )
39 {
40 	pParser = p;
41 	bError = bByVal = bBased = bBracket = sal_False;
42 	nParenLevel = 0;
43 	eCurExpr = t;
44 	m_eMode = eMode;
45 	pNext = NULL;
46 	pExpr = (t != SbSTDEXPR ) ? Term( pKeywordSymbolInfo ) : Boolean();
47 	if( t != SbSYMBOL )
48 		pExpr->Optimize();
49 	if( t == SbLVALUE && !pExpr->IsLvalue() )
50 		p->Error( SbERR_LVALUE_EXPECTED );
51 	if( t == SbOPERAND && !IsVariable() )
52 		p->Error( SbERR_VAR_EXPECTED );
53 }
54 
SbiExpression(SbiParser * p,double n,SbxDataType t)55 SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t )
56 {
57 	pParser = p;
58 	eCurExpr = SbOPERAND;
59 	pNext = NULL;
60 	bError = bByVal = bBased = bBracket = sal_False;
61 	pExpr = new SbiExprNode( pParser, n, t );
62 	pExpr->Optimize();
63 }
64 
SbiExpression(SbiParser * p,const String & r)65 SbiExpression::SbiExpression( SbiParser* p, const String& r )
66 {
67 	pParser = p;
68 	pNext = NULL;
69 	bError = bByVal = bBased = bBracket = sal_False;
70 	eCurExpr = SbOPERAND;
71 	pExpr = new SbiExprNode( pParser, r );
72 }
73 
SbiExpression(SbiParser * p,const SbiSymDef & r,SbiExprList * pPar)74 SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar )
75 {
76 	pParser = p;
77 	pNext = NULL;
78 	bError = bByVal = bBased = bBracket = sal_False;
79 	eCurExpr = SbOPERAND;
80 	pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar );
81 }
82 
SbiExpression(SbiParser * p,SbiToken t)83 SbiExpression::SbiExpression( SbiParser* p, SbiToken t )
84 {
85 	pParser = p;
86 	pNext = NULL;
87 	bError = bByVal = bBased = bBracket = sal_False;
88 	eCurExpr = SbOPERAND;
89 	pExpr = new SbiExprNode( pParser, NULL, t, NULL );
90 }
91 
~SbiExpression()92 SbiExpression::~SbiExpression()
93 {
94 	delete pExpr;
95 }
96 
97 // Einlesen eines kompletten Bezeichners
98 // Ein Bezeichner hat folgende Form:
99 // name[(Parameter)][.Name[(parameter)]]...
100 // Strukturelemente werden ueber das Element pNext verkoppelt,
101 // damit sie nicht im Baum stehen.
102 
103 // Folgen Parameter ohne Klammer? Dies kann eine Zahl, ein String,
104 // ein Symbol oder auch ein Komma sein (wenn der 1. Parameter fehlt)
105 
DoParametersFollow(SbiParser * p,SbiExprType eCurExpr,SbiToken eTok)106 static sal_Bool DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
107 {
108 	if( eTok == LPAREN )
109 		return sal_True;
110 	// Aber nur, wenn CALL-aehnlich!
111 	if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
112 		return sal_False;
113 	if (   eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING
114 		|| eTok == SYMBOL || eTok == COMMA  || eTok == DOT || eTok == NOT || eTok == BYVAL )
115 	{
116 		return sal_True;
117 	}
118 	else // check for default params with reserved names ( e.g. names of tokens )
119 	{
120 		SbiTokenizer tokens( *(SbiTokenizer*)p );
121 		// Urk the Next() / Peek() symantics are... weird
122 		tokens.Next();
123 		if ( tokens.Peek() == ASSIGN )
124 			return sal_True;
125 	}
126 	return sal_False;
127 }
128 
129 // Definition eines neuen Symbols
130 
AddSym(SbiToken eTok,SbiSymPool & rPool,SbiExprType eCurExpr,const String & rName,SbxDataType eType,SbiParameters * pPar)131 static SbiSymDef* AddSym
132 	( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr,
133 	  const String& rName, SbxDataType eType, SbiParameters* pPar )
134 {
135 	SbiSymDef* pDef;
136 	// A= ist keine Prozedur
137 	sal_Bool bHasType = sal_Bool( eTok == EQ || eTok == DOT );
138 	if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
139 	{
140 		// Dies ist also eine Prozedur
141 		// da suche man doch den richtigen Pool raus, da Procs
142 		// immer in einem Public-Pool landen muessen
143 		SbiSymPool* pPool = &rPool;
144 		if( pPool->GetScope() != SbPUBLIC )
145 			pPool = &rPool.GetParser()->aPublics;
146 		SbiProcDef* pProc = pPool->AddProc( rName );
147 
148 		// Sonderbehandlung fuer Colls wie Documents(1)
149 		if( eCurExpr == SbSTDEXPR )
150 			bHasType = sal_True;
151 
152 		pDef = pProc;
153 		pDef->SetType( bHasType ? eType : SbxEMPTY );
154 		if( pPar )
155 		{
156 			// Dummy-Parameter generieren
157 			sal_uInt16 n = 1;
158 			for( short i = 0; i < pPar->GetSize(); i++ )
159 			{
160 				String aPar = String::CreateFromAscii( "PAR" );
161 				aPar += ++n;
162 				pProc->GetParams().AddSym( aPar );
163 			}
164 		}
165 	}
166 	else
167 	{
168 		// oder ein normales Symbol
169 		pDef = rPool.AddSym( rName );
170 		pDef->SetType( eType );
171 	}
172 	return pDef;
173 }
174 
175 // Zur Zeit sind sogar Keywords zugelassen (wg. gleichnamiger Dflt-Properties)
176 
Term(const KeywordSymbolInfo * pKeywordSymbolInfo)177 SbiExprNode* SbiExpression::Term( const KeywordSymbolInfo* pKeywordSymbolInfo )
178 {
179 	if( pParser->Peek() == DOT )
180 	{
181 		// eine WITH-Variable
182 		SbiExprNode* pWithVar = pParser->GetWithVar();
183 		// #26608: Ans Ende der Node-Kette gehen, um richtiges Objekt zu uebergeben
184 		SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL;
185 		SbiExprNode* pNd = NULL;
186 		if( !pDef )
187 		{
188 			pParser->Next();
189 		}
190 		else
191 		{
192 			pNd = ObjTerm( *pDef );
193 			if( pNd )
194 				pNd->SetWithParent( pWithVar );
195 		}
196 		if( !pNd )
197 		{
198 			pParser->Error( SbERR_UNEXPECTED, DOT );
199 			pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE );
200 		}
201 		return pNd;
202 	}
203 
204 	SbiToken eTok = (pKeywordSymbolInfo == NULL) ? pParser->Next() : pKeywordSymbolInfo->m_eTok;
205 	// Anfang des Parsings merken
206 	pParser->LockColumn();
207 	String aSym( (pKeywordSymbolInfo == NULL) ? pParser->GetSym() : pKeywordSymbolInfo->m_aKeywordSymbol );
208 	SbxDataType eType = (pKeywordSymbolInfo == NULL) ? pParser->GetType() : pKeywordSymbolInfo->m_eSbxDataType;
209 	SbiParameters* pPar = NULL;
210 	SbiExprListVector* pvMoreParLcl = NULL;
211 	// Folgen Parameter?
212 	SbiToken eNextTok = pParser->Peek();
213 	// Ist es ein benannter Parameter?
214 	// Dann einfach eine Stringkonstante erzeugen. Diese wird
215 	// im SbiParameters-ctor erkannt und weiterverarbeitet
216 	if( eNextTok == ASSIGN )
217 	{
218 		pParser->UnlockColumn();
219 		return new SbiExprNode( pParser, aSym );
220 	}
221 	// ab hier sind keine Keywords zugelassen!
222 	if( pParser->IsKwd( eTok ) )
223 	{
224 		if( pParser->IsCompatible() && eTok == INPUT )
225 		{
226 			eTok = SYMBOL;
227 		}
228 		else
229 		{
230 			pParser->Error( SbERR_SYNTAX );
231 			bError = sal_True;
232 		}
233 	}
234 
235 	if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) )
236 	{
237 		bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE);
238 		pPar = new SbiParameters( pParser, bStandaloneExpression );
239 		bError |= !pPar->IsValid();
240 		if( !bError )
241 			bBracket = pPar->IsBracket();
242 		eTok = pParser->Peek();
243 
244 		// i75443 check for additional sets of parameters
245 		while( eTok == LPAREN )
246 		{
247 			if( pvMoreParLcl == NULL )
248 				pvMoreParLcl = new SbiExprListVector();
249 			SbiParameters* pAddPar = new SbiParameters( pParser );
250 			pvMoreParLcl->push_back( pAddPar );
251 			bError |= !pPar->IsValid();
252 			eTok = pParser->Peek();
253 		}
254 	}
255 	// Es koennte ein Objektteil sein, wenn . oder ! folgt
256 	// Bei . muss aber die Variable bereits definiert sein; wenn pDef
257 	// nach der Suche NULL ist, isses ein Objekt!
258 	sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM )
259 					&& !pParser->WhiteSpace() );
260 	if( bObj )
261 	{
262 		bBracket = sal_False;	// Now the bracket for the first term is obsolete
263 		if( eType == SbxVARIANT )
264 			eType = SbxOBJECT;
265 		else
266 		{
267 			// Name%. geht wirklich nicht!
268 			pParser->Error( SbERR_BAD_DECLARATION, aSym );
269 			bError = sal_True;
270 		}
271 	}
272 	// Suche:
273 	SbiSymDef* pDef = pParser->pPool->Find( aSym );
274 	if( !pDef )
275 	{
276 		// Teil der Runtime-Library?
277 		// AB 31.3.1996: In Parser-Methode ausgelagert
278 		// (wird auch in SbiParser::DefVar() in DIM.CXX benoetigt)
279 		pDef = pParser->CheckRTLForSym( aSym, eType );
280 
281 		// #i109184: Check if symbol is or later will be defined inside module
282 		SbModule& rMod = pParser->aGen.GetModule();
283 		SbxArray* pModMethods = rMod.GetMethods();
284 		if( pModMethods->Find( aSym, SbxCLASS_DONTCARE ) )
285 			pDef = NULL;
286 	}
287 	if( !pDef )
288 	{
289 		// Falls ein Punkt angegeben war, isses Teil eines Objekts,
290 		// also muss der Returnwert ein Objekt sein
291 		if( bObj )
292 			eType = SbxOBJECT;
293 		pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar );
294 		// Looks like this is a local ( but undefined variable )
295 		// if it is in a static procedure then make this Symbol
296 		// static
297 		if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
298 		    pDef->SetStatic();
299 	}
300 	else
301 	{
302 
303 		// Symbol ist bereits definiert.
304 		// Ist es eine Konstante?
305 		SbiConstDef* pConst = pDef->GetConstDef();
306 		if( pConst )
307 		{
308 			if( pConst->GetType() == SbxSTRING )
309 				return new SbiExprNode( pParser, pConst->GetString() );
310 			else
311 				return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() );
312 		}
313 		// Hat es Dimensionen,
314 		// und sind auch Parameter angegeben?
315 		// (Wobei 0 Parameter () entsprechen)
316 		if( pDef->GetDims() )
317 		{
318 			if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
319 				pParser->Error( SbERR_WRONG_DIMS );
320 		}
321 		if( pDef->IsDefinedAs() )
322 		{
323 			SbxDataType eDefType = pDef->GetType();
324 			// #119187 Only error if types conflict
325 			if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
326 			{
327 				// Wie? Erst mit AS definieren und dann einen Suffix nehmen?
328 				pParser->Error( SbERR_BAD_DECLARATION, aSym );
329 				bError = sal_True;
330 			}
331 			else if ( eType == SbxVARIANT )
332 				// Falls nix angegeben, den Typ des Eintrags nehmen
333 				// aber nur, wenn die Var nicht mit AS XXX definiert ist
334 				// damit erwischen wir n% = 5 : print n
335 				eType = eDefType;
336 		}
337 		// Typcheck bei Variablen:
338 		// ist explizit im Scanner etwas anderes angegeben?
339 		// Bei Methoden ist dies OK!
340 		if( eType != SbxVARIANT &&			// Variant nimmt alles
341 			eType != pDef->GetType() &&
342 			!pDef->GetProcDef() )
343 		{
344 			// Es kann sein, dass pDef ein Objekt beschreibt, das bisher
345 			// nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern
346 			// AB, 16.12.95 (Vielleicht noch aehnliche Faelle moeglich ?!?)
347 			if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
348 			{
349 				pDef->SetType( SbxOBJECT );
350 			}
351 			else
352 			{
353 				pParser->Error( SbERR_BAD_DECLARATION, aSym );
354 				bError = sal_True;
355 			}
356 		}
357 	}
358 	SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
359 	if( !pPar )
360 		pPar = new SbiParameters( pParser,sal_False,sal_False );
361 	pNd->aVar.pPar = pPar;
362 	pNd->aVar.pvMorePar = pvMoreParLcl;
363 	if( bObj )
364 	{
365 		// AB, 8.1.95: Objekt kann auch vom Typ SbxVARIANT sein
366 		if( pDef->GetType() == SbxVARIANT )
367 			pDef->SetType( SbxOBJECT );
368 		// Falls wir etwas mit Punkt einscannen, muss der
369 		// Typ SbxOBJECT sein
370 		if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
371 		{
372 			pParser->Error( SbERR_BAD_DECLARATION, aSym );
373 			bError = sal_True;
374 		}
375 		if( !bError )
376 			pNd->aVar.pNext = ObjTerm( *pDef );
377 	}
378 	// Merken der Spalte 1 wieder freigeben
379 	pParser->UnlockColumn();
380 	return pNd;
381 }
382 
383 // Aufbau eines Objekt-Terms. Ein derartiger Term ist Teil
384 // eines Ausdrucks, der mit einer Objektvariablen beginnt.
385 
ObjTerm(SbiSymDef & rObj)386 SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj )
387 {
388 	pParser->Next();
389 	SbiToken eTok = pParser->Next();
390 	if( eTok != SYMBOL && !pParser->IsKwd( eTok ) && !pParser->IsExtra( eTok ) )
391 	{
392 		// #66745 Einige Operatoren koennen in diesem Kontext auch
393 		// als Identifier zugelassen werden, wichtig fuer StarOne
394 		if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
395 			eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
396 		{
397 			pParser->Error( SbERR_VAR_EXPECTED );
398 			bError = sal_True;
399 		}
400 	}
401 	/* #118410 Allow type for Class methods and RTL object, e.g. RTL.Chr$(97)
402 	else
403 	{
404 		if( pParser->GetType() != SbxVARIANT )
405 			pParser->Error( SbERR_SYNTAX ), bError = sal_True;
406 	}
407 	*/
408 	if( bError )
409 		return NULL;
410 
411 	String aSym( pParser->GetSym() );
412 	SbxDataType eType = pParser->GetType();
413 	SbiParameters* pPar = NULL;
414 	SbiExprListVector* pvMoreParLcl = NULL;
415 	eTok = pParser->Peek();
416 	// Parameter?
417 	if( DoParametersFollow( pParser, eCurExpr, eTok ) )
418 	{
419 		bool bStandaloneExpression = false;
420 		pPar = new SbiParameters( pParser, bStandaloneExpression );
421 		bError |= !pPar->IsValid();
422 		eTok = pParser->Peek();
423 
424 		// i109624 check for additional sets of parameters
425 		while( eTok == LPAREN )
426 		{
427 			if( pvMoreParLcl == NULL )
428 				pvMoreParLcl = new SbiExprListVector();
429 			SbiParameters* pAddPar = new SbiParameters( pParser );
430 			pvMoreParLcl->push_back( pAddPar );
431 			bError |= !pPar->IsValid();
432 			eTok = pParser->Peek();
433 		}
434 
435 	}
436 	sal_Bool bObj = sal_Bool( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() );
437 	if( bObj )
438 	{
439 		if( eType == SbxVARIANT )
440 			eType = SbxOBJECT;
441 		else
442 		{
443 			// Name%. geht wirklich nicht!
444 			pParser->Error( SbERR_BAD_DECLARATION, aSym );
445 			bError = sal_True;
446 		}
447 	}
448 
449 	// Der Symbol-Pool eines Objekts ist immer PUBLIC
450 	SbiSymPool& rPool = rObj.GetPool();
451 	rPool.SetScope( SbPUBLIC );
452 	SbiSymDef* pDef = rPool.Find( aSym );
453 	if( !pDef )
454 	{
455 		pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar );
456 		pDef->SetType( eType );
457 	}
458 
459 	SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType );
460 	pNd->aVar.pPar = pPar;
461 	pNd->aVar.pvMorePar = pvMoreParLcl;
462 	if( bObj )
463 	{
464 		// Falls wir etwas mit Punkt einscannen, muss der
465 		// Typ SbxOBJECT sein
466 
467 		// AB, 3.1.96
468 		// Es kann sein, dass pDef ein Objekt beschreibt, das bisher
469 		// nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern
470 		if( pDef->GetType() == SbxVARIANT )
471 			pDef->SetType( SbxOBJECT );
472 
473 		if( pDef->GetType() != SbxOBJECT )
474 		{
475 			pParser->Error( SbERR_BAD_DECLARATION, aSym );
476 			bError = sal_True;
477 		}
478 		if( !bError )
479 		{
480 			pNd->aVar.pNext = ObjTerm( *pDef );
481 			pNd->eType = eType;
482 		}
483 	}
484 	return pNd;
485 }
486 
487 // Als Operanden kommen in Betracht:
488 //      Konstante
489 //      skalare Variable
490 //      Strukturelemente
491 //      Array-Elemente
492 //      Funktionen
493 //      geklammerte Ausdruecke
494 
Operand(bool bUsedForTypeOf)495 SbiExprNode* SbiExpression::Operand( bool bUsedForTypeOf )
496 {
497 	SbiExprNode *pRes;
498 	SbiToken eTok;
499 
500 	// Operand testen:
501 	switch( eTok = pParser->Peek() )
502 	{
503 		case SYMBOL:
504 			pRes = Term();
505 			// process something like "IF Not r Is Nothing Then .."
506 			if( !bUsedForTypeOf && pParser->IsVBASupportOn() && pParser->Peek() == IS )
507 			{
508 				eTok = pParser->Next();
509 				pRes = new SbiExprNode( pParser, pRes, eTok, Like() );
510 			}
511 			break;
512 		case DOT:	// .with
513 			pRes = Term(); break;
514 		case NUMBER:
515 			pParser->Next();
516 			pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() );
517 			break;
518 		case FIXSTRING:
519 			pParser->Next();
520 			pRes = new SbiExprNode( pParser, pParser->GetSym() ); break;
521 		case LPAREN:
522 			pParser->Next();
523 			if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN )
524 			{
525 				m_eMode = EXPRMODE_EMPTY_PAREN;
526 				pRes = new SbiExprNode();	// Dummy node
527 				pParser->Next();
528 				break;
529 			}
530 			nParenLevel++;
531 			pRes = Boolean();
532 			if( pParser->Peek() != RPAREN )
533 			{
534 				// If there was a LPARAM, it does not belong to the expression
535 				if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
536 					m_eMode = EXPRMODE_LPAREN_NOT_NEEDED;
537 				else
538 					pParser->Error( SbERR_BAD_BRACKETS );
539 			}
540 			else
541 			{
542 				pParser->Next();
543 				if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING )
544 				{
545 					SbiToken eTokAfterRParen = pParser->Peek();
546 					if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT )
547 						m_eMode = EXPRMODE_ARRAY_OR_OBJECT;
548 					else
549 						m_eMode = EXPRMODE_STANDARD;
550 				}
551 			}
552 			nParenLevel--;
553 			pRes->bComposite = sal_True;
554 			break;
555 		default:
556 			// Zur Zeit sind Keywords hier OK!
557 			if( pParser->IsKwd( eTok ) )
558 				pRes = Term();
559 			else
560 			{
561 				pParser->Next();
562 				pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE ); // bei Fehlern
563 				pParser->Error( SbERR_UNEXPECTED, eTok );
564 			}
565 	}
566 	return pRes;
567 }
568 
Unary()569 SbiExprNode* SbiExpression::Unary()
570 {
571 	SbiExprNode* pNd;
572 	SbiToken eTok = pParser->Peek();
573 	switch( eTok )
574 	{
575 		case MINUS:
576 			eTok = NEG;
577 			pParser->Next();
578 			pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
579 			break;
580 		case NOT:
581 			if( pParser->IsVBASupportOn() )
582 			{
583 				pNd = Operand();
584 			}
585 			else
586 			{
587 				pParser->Next();
588 				pNd = new SbiExprNode( pParser, Unary(), eTok, NULL );
589 			}
590 			break;
591 		case PLUS:
592 			pParser->Next();
593 			pNd = Unary();
594 			break;
595 		case TYPEOF:
596 		{
597 			pParser->Next();
598 			bool bUsedForTypeOf = true;
599 			SbiExprNode* pObjNode = Operand( bUsedForTypeOf );
600 			pParser->TestToken( IS );
601 			String aDummy;
602 			SbiSymDef* pTypeDef = new SbiSymDef( aDummy );
603 			pParser->TypeDecl( *pTypeDef, sal_True );
604 			pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() );
605 			break;
606 		}
607 		case NEW:
608 		{
609 			pParser->Next();
610 			String aStr;
611 			SbiSymDef* pTypeDef = new SbiSymDef( aStr );
612 			pParser->TypeDecl( *pTypeDef, sal_True );
613 			pNd = new SbiExprNode( pParser, pTypeDef->GetTypeId() );
614 			break;
615 		}
616 		default:
617 			pNd = Operand();
618 	}
619 	return pNd;
620 }
621 
Exp()622 SbiExprNode* SbiExpression::Exp()
623 {
624 	SbiExprNode* pNd = Unary();
625 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
626 	{
627 		while( pParser->Peek() == EXPON ) {
628 			SbiToken eTok = pParser->Next();
629 			pNd = new SbiExprNode( pParser, pNd, eTok, Unary() );
630 		}
631 	}
632 	return pNd;
633 }
634 
MulDiv()635 SbiExprNode* SbiExpression::MulDiv()
636 {
637 	SbiExprNode* pNd = Exp();
638 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
639 	{
640 		for( ;; )
641 		{
642 			SbiToken eTok = pParser->Peek();
643 			if( eTok != MUL && eTok != DIV )
644 				break;
645 			eTok = pParser->Next();
646 			pNd = new SbiExprNode( pParser, pNd, eTok, Exp() );
647 		}
648 	}
649 	return pNd;
650 }
651 
IntDiv()652 SbiExprNode* SbiExpression::IntDiv()
653 {
654 	SbiExprNode* pNd = MulDiv();
655 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
656 	{
657 		while( pParser->Peek() == IDIV ) {
658 			SbiToken eTok = pParser->Next();
659 			pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() );
660 		}
661 	}
662 	return pNd;
663 }
664 
Mod()665 SbiExprNode* SbiExpression::Mod()
666 {
667 	SbiExprNode* pNd = IntDiv();
668 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
669 	{
670 		while( pParser->Peek() == MOD ) {
671 			SbiToken eTok = pParser->Next();
672 			pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() );
673 		}
674 	}
675 	return pNd;
676 }
677 
AddSub()678 SbiExprNode* SbiExpression::AddSub()
679 {
680 	SbiExprNode* pNd = Mod();
681 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
682 	{
683 		for( ;; )
684 		{
685 			SbiToken eTok = pParser->Peek();
686 			if( eTok != PLUS && eTok != MINUS )
687 				break;
688 			eTok = pParser->Next();
689 			pNd = new SbiExprNode( pParser, pNd, eTok, Mod() );
690 		}
691 	}
692 	return pNd;
693 }
694 
Cat()695 SbiExprNode* SbiExpression::Cat()
696 {
697 	SbiExprNode* pNd = AddSub();
698 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
699 	{
700 		for( ;; )
701 		{
702 			SbiToken eTok = pParser->Peek();
703 			if( eTok != CAT )
704 				break;
705 			eTok = pParser->Next();
706 			pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() );
707 		}
708 	}
709 	return pNd;
710 }
711 
Comp()712 SbiExprNode* SbiExpression::Comp()
713 {
714 	SbiExprNode* pNd = Cat();
715 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
716 	{
717 		short nCount = 0;
718 		for( ;; )
719 		{
720 			SbiToken eTok = pParser->Peek();
721 			if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT )
722 				break;
723 			if( eTok != EQ && eTok != NE && eTok != LT
724 			 && eTok != GT && eTok != LE && eTok != GE )
725 				break;
726 			eTok = pParser->Next();
727 			pNd = new SbiExprNode( pParser, pNd, eTok, Cat() );
728 			nCount++;
729 		}
730 	}
731 	return pNd;
732 }
733 
VBA_Not()734 SbiExprNode* SbiExpression::VBA_Not()
735 {
736 	SbiExprNode* pNd = NULL;
737 
738 	SbiToken eTok = pParser->Peek();
739 	if( eTok == NOT )
740 	{
741 		pParser->Next();
742 		pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL );
743 	}
744 	else
745 	{
746 		pNd = Comp();
747 	}
748 	return pNd;
749 }
750 
Like()751 SbiExprNode* SbiExpression::Like()
752 {
753 	SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp();
754 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
755 	{
756 		short nCount = 0;
757 		while( pParser->Peek() == LIKE ) {
758 			SbiToken eTok = pParser->Next();
759 			pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++;
760 		}
761 		// Mehrere Operatoren hintereinander gehen nicht
762 		if( nCount > 1 )
763 		{
764 			pParser->Error( SbERR_SYNTAX );
765 			bError = sal_True;
766 		}
767 	}
768 	return pNd;
769 }
770 
Boolean()771 SbiExprNode* SbiExpression::Boolean()
772 {
773 	SbiExprNode* pNd = Like();
774 	if( m_eMode != EXPRMODE_EMPTY_PAREN )
775 	{
776 		for( ;; )
777 		{
778 			SbiToken eTok = pParser->Peek();
779 			if( eTok != AND && eTok != OR && eTok != XOR
780 			 && eTok != EQV && eTok != IMP && eTok != IS )
781 				break;
782 			eTok = pParser->Next();
783 			pNd = new SbiExprNode( pParser, pNd, eTok, Like() );
784 		}
785 	}
786 	return pNd;
787 }
788 
789 /***************************************************************************
790 |*
791 |*      SbiConstExpression
792 |*
793 ***************************************************************************/
794 
795 // Parsing einer Expression, die sich zu einer numerischen
796 // Konstanten verarbeiten laesst.
797 
SbiConstExpression(SbiParser * p)798 SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p )
799 {
800 	if( pExpr->IsConstant() )
801 	{
802 		eType = pExpr->GetType();
803 		if( pExpr->IsNumber() )
804 		{
805 			nVal = pExpr->nVal;
806 		}
807 		else
808 		{
809 			nVal = 0;
810 			aVal = pExpr->aStrVal;
811 		}
812 	}
813 	else
814 	{
815 		// #40204 Spezialbehandlung fuer sal_Bool-Konstanten
816 		sal_Bool bIsBool = sal_False;
817 		if( pExpr->eNodeType == SbxVARVAL )
818 		{
819 			SbiSymDef* pVarDef = pExpr->GetVar();
820 
821 			// Ist es eine sal_Bool-Konstante?
822 			sal_Bool bBoolVal = sal_False;
823 			if( pVarDef->GetName().EqualsIgnoreCaseAscii( "true" ) )
824 			//if( pVarDef->GetName().ICompare( "true" ) == COMPARE_EQUAL )
825 			{
826 				bIsBool = sal_True;
827 				bBoolVal = sal_True;
828 			}
829 			else if( pVarDef->GetName().EqualsIgnoreCaseAscii( "false" ) )
830 			//else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL )
831 			{
832 				bIsBool = sal_True;
833 				bBoolVal = sal_False;
834 			}
835 
836 			// Wenn es ein sal_Bool ist, Node austauschen
837 			if( bIsBool )
838 			{
839 				delete pExpr;
840 				pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER );
841 				eType = pExpr->GetType();
842 				nVal = pExpr->nVal;
843 			}
844 		}
845 
846 		if( !bIsBool )
847 		{
848 			pParser->Error( SbERR_SYNTAX );
849 			eType = SbxDOUBLE;
850 			nVal = 0;
851 		}
852 	}
853 }
854 
GetShortValue()855 short SbiConstExpression::GetShortValue()
856 {
857 	if( eType == SbxSTRING )
858 	{
859 		SbxVariableRef refConv = new SbxVariable;
860 		refConv->PutString( aVal );
861 		return refConv->GetInteger();
862 	}
863 	else
864 	{
865 		double n = nVal;
866 		if( n > 0 ) n += .5; else n -= .5;
867 		if( n > SbxMAXINT ) n = SbxMAXINT, pParser->Error( SbERR_OUT_OF_RANGE );
868 		else
869 		if( n < SbxMININT ) n = SbxMININT, pParser->Error( SbERR_OUT_OF_RANGE );
870 		return (short) n;
871 	}
872 }
873 
874 
875 /***************************************************************************
876 |*
877 |*      SbiExprList
878 |*
879 ***************************************************************************/
880 
SbiExprList(SbiParser * p)881 SbiExprList::SbiExprList( SbiParser* p )
882 {
883 	pParser = p;
884 	pFirst = NULL;
885 	nExpr  =
886 	nDim   = 0;
887 	bError =
888 	bBracket = sal_False;
889 }
890 
~SbiExprList()891 SbiExprList::~SbiExprList()
892 {
893 	SbiExpression* p = pFirst;
894 	while( p )
895 	{
896 		SbiExpression* q = p->pNext;
897 		delete p;
898 		p = q;
899 	}
900 }
901 
902 // Parameter anfordern (ab 0)
903 
Get(short n)904 SbiExpression* SbiExprList::Get( short n )
905 {
906 	SbiExpression* p = pFirst;
907 	while( n-- && p )
908 		p = p->pNext;
909 	return p;
910 }
911 
addExpression(SbiExpression * pExpr)912 void SbiExprList::addExpression( SbiExpression* pExpr )
913 {
914 	SbiExpression* p = pFirst;
915 	while( p && p->pNext )
916 		p = p->pNext;
917 
918 	p->pNext = pExpr;
919 }
920 
921 
922 /***************************************************************************
923 |*
924 |*      SbiParameters
925 |*
926 ***************************************************************************/
927 
928 // Parsender Konstruktor:
929 // Die Parameterliste wird komplett geparst.
930 // "Prozedurname()" ist OK.
931 // Dann handelt es sich um eine Funktion ohne Parameter
932 // respektive um die Angabe eines Arrays als Prozedurparameter.
933 
934 // #i79918/#i80532: bConst has never been set to true
935 // -> reused as bStandaloneExpression
936 //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
SbiParameters(SbiParser * p,sal_Bool bStandaloneExpression,sal_Bool bPar)937 SbiParameters::SbiParameters( SbiParser* p, sal_Bool bStandaloneExpression, sal_Bool bPar) :
938 	SbiExprList( p )
939 {
940 	if( !bPar )
941 		return;
942 
943 	SbiExpression *pExpr;
944 	SbiToken eTok = pParser->Peek();
945 
946 	// evtl. Klammer auf weg:
947 	bool bAssumeExprLParenMode = false;
948 	bool bAssumeArrayMode = false;
949 	if( eTok == LPAREN )
950 	{
951 		if( bStandaloneExpression )
952 		{
953 			bAssumeExprLParenMode = true;
954 		}
955 		else
956 		{
957 			bBracket = sal_True;
958 			pParser->Next();
959 			eTok = pParser->Peek();
960 		}
961 	}
962 
963 	// Ende-Test
964 	if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
965 	{
966 		if( eTok == RPAREN )
967 			pParser->Next();
968 		return;
969 	}
970 	// Parametertabelle einlesen und in richtiger Folge ablegen!
971 	SbiExpression* pLast = NULL;
972 	String aName;
973 	while( !bError )
974 	{
975 		aName.Erase();
976 		// Fehlendes Argument
977 		if( eTok == COMMA )
978 		{
979 			pExpr = new SbiExpression( pParser, 0, SbxEMPTY );
980 			//if( bConst )
981 			//	pParser->Error( SbERR_SYNTAX ), bError = sal_True;
982 		}
983 		// Benannte Argumente: entweder .name= oder name:=
984 		else
985 		{
986 			bool bByVal = false;
987 			if( eTok == BYVAL )
988 			{
989 				bByVal = true;
990 				pParser->Next();
991 				eTok = pParser->Peek();
992 			}
993 
994 			if( bAssumeExprLParenMode )
995 			{
996 				pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING );
997 				bAssumeExprLParenMode = sal_False;
998 
999 				SbiExprMode eModeAfter = pExpr->m_eMode;
1000 				if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED )
1001 				{
1002 					bBracket = sal_True;
1003 				}
1004 				else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT )
1005 				{
1006 					// Expression "looks" like an array assignment
1007 					// a(...)[(...)] = ? or a(...).b(...)
1008 					// RPAREN is already parsed
1009 					bBracket = sal_True;
1010 					bAssumeArrayMode = true;
1011 					eTok = NIL;
1012 				}
1013 				else if( eModeAfter == EXPRMODE_EMPTY_PAREN )
1014 				{
1015 					bBracket = sal_True;
1016 					delete pExpr;
1017 					if( bByVal )
1018 						pParser->Error( SbERR_LVALUE_EXPECTED );
1019 					return;
1020 				}
1021 			}
1022 			else
1023 				pExpr = new SbiExpression( pParser );
1024 
1025 			if( bByVal && pExpr->IsLvalue() )
1026 				pExpr->SetByVal();
1027 
1028 			//pExpr = bConst ? new SbiConstExpression( pParser )
1029 			//				: new SbiExpression( pParser );
1030 			if( !bAssumeArrayMode )
1031 			{
1032 				if( pParser->Peek() == ASSIGN )
1033 				{
1034 					// VBA mode: name:=
1035 					// SbiExpression::Term() hat einen String daraus gemacht
1036 					aName = pExpr->GetString();
1037 					delete pExpr;
1038 					pParser->Next();
1039 					pExpr = new SbiExpression( pParser );
1040 					//if( bConst )
1041 					//	pParser->Error( SbERR_SYNTAX ), bError = sal_True;
1042 				}
1043 				pExpr->GetName() = aName;
1044 			}
1045 		}
1046 		pExpr->pNext = NULL;
1047 		if( !pLast )
1048 			pFirst = pLast = pExpr;
1049 		else
1050 			pLast->pNext = pExpr, pLast = pExpr;
1051 		nExpr++;
1052 		bError |= !pExpr->IsValid();
1053 
1054 		if( bAssumeArrayMode )
1055 			break;
1056 
1057 		// Naechstes Element?
1058 		eTok = pParser->Peek();
1059 		if( eTok != COMMA )
1060 		{
1061 			if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1062 				break;
1063 			pParser->Error( bBracket
1064 							? SbERR_BAD_BRACKETS
1065 							: SbERR_EXPECTED, COMMA );
1066 			bError = sal_True;
1067 		}
1068 		else
1069 		{
1070 			pParser->Next();
1071 			eTok = pParser->Peek();
1072 			if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) )
1073 				break;
1074 		}
1075 	}
1076 	// Schliessende Klammer
1077 	if( eTok == RPAREN )
1078 	{
1079 		pParser->Next();
1080 		pParser->Peek();
1081 		if( !bBracket )
1082 		{
1083 			pParser->Error( SbERR_BAD_BRACKETS );
1084 			bError = sal_True;
1085 		}
1086 	}
1087 	nDim = nExpr;
1088 }
1089 
1090 /***************************************************************************
1091 |*
1092 |*      SbiDimList
1093 |*
1094 ***************************************************************************/
1095 
1096 // Parsender Konstruktor:
1097 // Eine Liste von Array-Dimensionen wird geparst. Die Ausdruecke werden
1098 // auf numerisch getestet. Das bCONST-Bit wird gesetzt, wenn alle Ausdruecke
1099 // Integer-Konstanten sind.
1100 
SbiDimList(SbiParser * p)1101 SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p )
1102 {
1103 	bConst = sal_True;
1104 
1105 	if( pParser->Next() != LPAREN )
1106 	{
1107 		pParser->Error( SbERR_EXPECTED, LPAREN );
1108 		bError = sal_True; return;
1109 	}
1110 
1111 	if( pParser->Peek() != RPAREN )
1112 	{
1113 		SbiExpression *pExpr1, *pExpr2, *pLast = NULL;
1114 		SbiToken eTok;
1115 		for( ;; )
1116 		{
1117 			pExpr1 = new SbiExpression( pParser );
1118 			eTok = pParser->Next();
1119 			if( eTok == TO )
1120 			{
1121 				pExpr2 = new SbiExpression( pParser );
1122 				eTok = pParser->Next();
1123 				bConst &= pExpr1->IsIntConstant() & pExpr2->IsIntConstant();
1124 				bError |= !pExpr1->IsValid();
1125 				bError |= !pExpr2->IsValid();
1126 				pExpr1->pNext = pExpr2;
1127 				if( !pLast )
1128 					pFirst = pExpr1;
1129 				else
1130 					pLast->pNext = pExpr1;
1131 				pLast = pExpr2;
1132 				nExpr += 2;
1133 			}
1134 			else
1135 			{
1136 				// Nur eine Dim-Angabe
1137 				pExpr1->SetBased();
1138 				pExpr1->pNext = NULL;
1139 				bConst &= pExpr1->IsIntConstant();
1140 				bError |= !pExpr1->IsValid();
1141 				if( !pLast )
1142 					pFirst = pLast = pExpr1;
1143 				else
1144 					pLast->pNext = pExpr1, pLast = pExpr1;
1145 				nExpr++;
1146 			}
1147 			nDim++;
1148 			if( eTok == RPAREN ) break;
1149 			if( eTok != COMMA )
1150 			{
1151 				pParser->Error( SbERR_BAD_BRACKETS );
1152 				pParser->Next();
1153 				break;
1154 			}
1155 		}
1156 	}
1157 	else pParser->Next();
1158 }
1159 
1160