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