xref: /aoo42x/main/basic/source/comp/loops.cxx (revision 30acf5e8)
1e1f63238SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3e1f63238SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4e1f63238SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5e1f63238SAndrew Rist  * distributed with this work for additional information
6e1f63238SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7e1f63238SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8e1f63238SAndrew Rist  * "License"); you may not use this file except in compliance
9e1f63238SAndrew Rist  * with the License.  You may obtain a copy of the License at
10e1f63238SAndrew Rist  *
11e1f63238SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12e1f63238SAndrew Rist  *
13e1f63238SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14e1f63238SAndrew Rist  * software distributed under the License is distributed on an
15e1f63238SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16e1f63238SAndrew Rist  * KIND, either express or implied.  See the License for the
17e1f63238SAndrew Rist  * specific language governing permissions and limitations
18e1f63238SAndrew Rist  * under the License.
19e1f63238SAndrew Rist  *
20e1f63238SAndrew Rist  *************************************************************/
21e1f63238SAndrew Rist 
22e1f63238SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basic.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "sbcomp.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir // Single-line IF und Multiline IF
30cdf0e10cSrcweir 
If()31cdf0e10cSrcweir void SbiParser::If()
32cdf0e10cSrcweir {
33cdf0e10cSrcweir 	sal_uInt32 nEndLbl;
34cdf0e10cSrcweir 	SbiToken eTok = NIL;
35cdf0e10cSrcweir 	// Ende-Tokens ignorieren:
36cdf0e10cSrcweir 	SbiExpression aCond( this );
37cdf0e10cSrcweir 	aCond.Gen();
38cdf0e10cSrcweir 	TestToken( THEN );
39cdf0e10cSrcweir 	if( IsEoln( Next() ) )
40cdf0e10cSrcweir 	{
41cdf0e10cSrcweir 		// AB 13.5.1996: #27720# Am Ende jeden Blocks muss ein Jump zu ENDIF
42cdf0e10cSrcweir 		// eingefuegt werden, damit bei ELSEIF nicht erneut die Bedingung
43cdf0e10cSrcweir 		// ausgewertet wird. Die Tabelle nimmt alle Absprungstellen auf.
44cdf0e10cSrcweir #define JMP_TABLE_SIZE 100
45cdf0e10cSrcweir 		sal_uInt32 pnJmpToEndLbl[JMP_TABLE_SIZE];	// 100 ELSEIFs zulaessig
46cdf0e10cSrcweir 		sal_uInt16 iJmp = 0;						// aktueller Tabellen-Index
47cdf0e10cSrcweir 
48cdf0e10cSrcweir 		// multiline IF
49cdf0e10cSrcweir 		nEndLbl = aGen.Gen( _JUMPF, 0 );
50cdf0e10cSrcweir 		eTok = Peek();
51cdf0e10cSrcweir 		while( !( eTok == ELSEIF || eTok == ELSE || eTok == ENDIF ) &&
52cdf0e10cSrcweir 				!bAbort && Parse() )
53cdf0e10cSrcweir 		{
54cdf0e10cSrcweir 			eTok = Peek();
55cdf0e10cSrcweir 			if( IsEof() )
56cdf0e10cSrcweir 			{
57cdf0e10cSrcweir 				Error( SbERR_BAD_BLOCK, IF ); bAbort = sal_True; return;
58cdf0e10cSrcweir 			}
59cdf0e10cSrcweir 		}
60cdf0e10cSrcweir 		// ELSEIF?
61cdf0e10cSrcweir 		while( eTok == ELSEIF )
62cdf0e10cSrcweir 		{
63cdf0e10cSrcweir 			// #27720# Bei erfolgreichem IF/ELSEIF auf ENDIF springen
64cdf0e10cSrcweir 			if( iJmp >=	JMP_TABLE_SIZE )
65cdf0e10cSrcweir 			{
66cdf0e10cSrcweir 				Error( SbERR_PROG_TOO_LARGE );	bAbort = sal_True; 	return;
67cdf0e10cSrcweir 			}
68cdf0e10cSrcweir 			pnJmpToEndLbl[iJmp++] = aGen.Gen( _JUMP, 0 );
69cdf0e10cSrcweir 
70cdf0e10cSrcweir 			Next();
71cdf0e10cSrcweir 			aGen.BackChain( nEndLbl );
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 			aGen.Statement();
74cdf0e10cSrcweir 			SbiExpression* pCond = new SbiExpression( this );
75cdf0e10cSrcweir 			pCond->Gen();
76cdf0e10cSrcweir 			nEndLbl = aGen.Gen( _JUMPF, 0 );
77cdf0e10cSrcweir 			delete pCond;
78cdf0e10cSrcweir 			TestToken( THEN );
79cdf0e10cSrcweir 			eTok = Peek();
80cdf0e10cSrcweir 			while( !( eTok == ELSEIF || eTok == ELSE || eTok == ENDIF ) &&
81cdf0e10cSrcweir 					!bAbort && Parse() )
82cdf0e10cSrcweir 			{
83cdf0e10cSrcweir 				eTok = Peek();
84cdf0e10cSrcweir 				if( IsEof() )
85cdf0e10cSrcweir 				{
86cdf0e10cSrcweir 					Error( SbERR_BAD_BLOCK, ELSEIF );  bAbort = sal_True; return;
87cdf0e10cSrcweir 				}
88cdf0e10cSrcweir 			}
89cdf0e10cSrcweir 		}
90cdf0e10cSrcweir 		if( eTok == ELSE )
91cdf0e10cSrcweir 		{
92cdf0e10cSrcweir 			Next();
93cdf0e10cSrcweir 			sal_uInt32 nElseLbl = nEndLbl;
94cdf0e10cSrcweir 			nEndLbl = aGen.Gen( _JUMP, 0 );
95cdf0e10cSrcweir 			aGen.BackChain( nElseLbl );
96cdf0e10cSrcweir 
97cdf0e10cSrcweir 			aGen.Statement();
98cdf0e10cSrcweir 			StmntBlock( ENDIF );
99cdf0e10cSrcweir 		}
100cdf0e10cSrcweir 		else if( eTok == ENDIF )
101cdf0e10cSrcweir 			Next();
102cdf0e10cSrcweir 
103cdf0e10cSrcweir 		// #27720# Jmp-Tabelle abarbeiten
104cdf0e10cSrcweir 		while( iJmp > 0 )
105cdf0e10cSrcweir 		{
106cdf0e10cSrcweir 			iJmp--;
107cdf0e10cSrcweir 			aGen.BackChain( pnJmpToEndLbl[iJmp] );
108cdf0e10cSrcweir 		}
109cdf0e10cSrcweir 	}
110cdf0e10cSrcweir 	else
111cdf0e10cSrcweir 	{
112cdf0e10cSrcweir 		// single line IF
113cdf0e10cSrcweir 		bSingleLineIf = sal_True;
114cdf0e10cSrcweir 		nEndLbl = aGen.Gen( _JUMPF, 0 );
115cdf0e10cSrcweir 		Push( eCurTok );
116cdf0e10cSrcweir 		while( !bAbort )
117cdf0e10cSrcweir 		{
118cdf0e10cSrcweir 			if( !Parse() ) break;
119cdf0e10cSrcweir 			eTok = Peek();
120cdf0e10cSrcweir 			if( eTok == ELSE || eTok == EOLN || eTok == REM )
121cdf0e10cSrcweir 				break;
122cdf0e10cSrcweir 		}
123cdf0e10cSrcweir 		if( eTok == ELSE )
124cdf0e10cSrcweir 		{
125cdf0e10cSrcweir 			Next();
126cdf0e10cSrcweir 			sal_uInt32 nElseLbl = nEndLbl;
127cdf0e10cSrcweir 			nEndLbl = aGen.Gen( _JUMP, 0 );
128cdf0e10cSrcweir 			aGen.BackChain( nElseLbl );
129cdf0e10cSrcweir 			while( !bAbort )
130cdf0e10cSrcweir 			{
131cdf0e10cSrcweir 				if( !Parse() ) break;
132cdf0e10cSrcweir 				eTok = Peek();
13307396187SDamjan Jovanovic 				if( eTok == EOLN || eTok == REM )
134cdf0e10cSrcweir 					break;
135cdf0e10cSrcweir 			}
136cdf0e10cSrcweir 		}
137cdf0e10cSrcweir 		bSingleLineIf = sal_False;
138cdf0e10cSrcweir 	}
139cdf0e10cSrcweir 	aGen.BackChain( nEndLbl );
140cdf0e10cSrcweir }
141cdf0e10cSrcweir 
142cdf0e10cSrcweir // ELSE/ELSEIF/ENDIF ohne IF
143cdf0e10cSrcweir 
NoIf()144cdf0e10cSrcweir void SbiParser::NoIf()
145cdf0e10cSrcweir {
146cdf0e10cSrcweir 	Error( SbERR_NO_IF );
147cdf0e10cSrcweir 	StmntBlock( ENDIF );
148cdf0e10cSrcweir }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir // DO WHILE...LOOP
151cdf0e10cSrcweir // DO ... LOOP WHILE
152cdf0e10cSrcweir 
DoLoop()153cdf0e10cSrcweir void SbiParser::DoLoop()
154cdf0e10cSrcweir {
155cdf0e10cSrcweir 	sal_uInt32 nStartLbl = aGen.GetPC();
156cdf0e10cSrcweir 	OpenBlock( DO );
157cdf0e10cSrcweir 	SbiToken eTok = Next();
158cdf0e10cSrcweir 	if( IsEoln( eTok ) )
159cdf0e10cSrcweir 	{
160cdf0e10cSrcweir 		// DO ... LOOP [WHILE|UNTIL expr]
161cdf0e10cSrcweir 		StmntBlock( LOOP );
162cdf0e10cSrcweir 		eTok = Next();
163cdf0e10cSrcweir 		if( eTok == UNTIL || eTok == WHILE )
164cdf0e10cSrcweir 		{
165cdf0e10cSrcweir 			SbiExpression aExpr( this );
166cdf0e10cSrcweir 			aExpr.Gen();
167cdf0e10cSrcweir 			aGen.Gen( eTok == UNTIL ? _JUMPF : _JUMPT, nStartLbl );
168cdf0e10cSrcweir 		} else
169cdf0e10cSrcweir 			if (eTok == EOLN || eTok == REM)
170cdf0e10cSrcweir 				aGen.Gen (_JUMP, nStartLbl);
171cdf0e10cSrcweir 			else
172cdf0e10cSrcweir 				Error( SbERR_EXPECTED, WHILE );
173cdf0e10cSrcweir 	}
174cdf0e10cSrcweir 	else
175cdf0e10cSrcweir 	{
176cdf0e10cSrcweir 		// DO [WHILE|UNTIL expr] ... LOOP
177cdf0e10cSrcweir 		if( eTok == UNTIL || eTok == WHILE )
178cdf0e10cSrcweir 		{
179cdf0e10cSrcweir 			SbiExpression aCond( this );
180cdf0e10cSrcweir 			aCond.Gen();
181cdf0e10cSrcweir 		}
182cdf0e10cSrcweir 		sal_uInt32 nEndLbl = aGen.Gen( eTok == UNTIL ? _JUMPT : _JUMPF, 0 );
183cdf0e10cSrcweir 		StmntBlock( LOOP );
184cdf0e10cSrcweir 		TestEoln();
185cdf0e10cSrcweir 		aGen.Gen( _JUMP, nStartLbl );
186cdf0e10cSrcweir 		aGen.BackChain( nEndLbl );
187cdf0e10cSrcweir 	}
188cdf0e10cSrcweir 	CloseBlock();
189cdf0e10cSrcweir }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir // WHILE ... WEND
192cdf0e10cSrcweir 
While()193cdf0e10cSrcweir void SbiParser::While()
194cdf0e10cSrcweir {
195cdf0e10cSrcweir 	SbiExpression aCond( this );
196cdf0e10cSrcweir 	sal_uInt32 nStartLbl = aGen.GetPC();
197cdf0e10cSrcweir 	aCond.Gen();
198cdf0e10cSrcweir 	sal_uInt32 nEndLbl = aGen.Gen( _JUMPF, 0 );
199cdf0e10cSrcweir 	StmntBlock( WEND );
200cdf0e10cSrcweir 	aGen.Gen( _JUMP, nStartLbl );
201cdf0e10cSrcweir 	aGen.BackChain( nEndLbl );
202cdf0e10cSrcweir }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir // FOR var = expr TO expr STEP
205cdf0e10cSrcweir 
For()206cdf0e10cSrcweir void SbiParser::For()
207cdf0e10cSrcweir {
208cdf0e10cSrcweir 	bool bForEach = ( Peek() == EACH );
209cdf0e10cSrcweir 	if( bForEach )
210cdf0e10cSrcweir 		Next();
211cdf0e10cSrcweir 	SbiExpression aLvalue( this, SbOPERAND );
212cdf0e10cSrcweir 	aLvalue.Gen();		// Variable auf dem Stack
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 	if( bForEach )
215cdf0e10cSrcweir 	{
216cdf0e10cSrcweir 		TestToken( _IN_ );
217cdf0e10cSrcweir 		SbiExpression aCollExpr( this, SbOPERAND );
218cdf0e10cSrcweir 		aCollExpr.Gen();	// Colletion var to for stack
219cdf0e10cSrcweir 		TestEoln();
220cdf0e10cSrcweir 		aGen.Gen( _INITFOREACH );
221cdf0e10cSrcweir 	}
222cdf0e10cSrcweir 	else
223cdf0e10cSrcweir 	{
224cdf0e10cSrcweir 		TestToken( EQ );
225cdf0e10cSrcweir 		SbiExpression aStartExpr( this );
226cdf0e10cSrcweir 		aStartExpr.Gen();	// Startausdruck auf dem Stack
227cdf0e10cSrcweir 		TestToken( TO );
228cdf0e10cSrcweir 		SbiExpression aStopExpr( this );
229cdf0e10cSrcweir 		aStopExpr.Gen();	// Endausdruck auf dem Stack
230cdf0e10cSrcweir 		if( Peek() == STEP )
231cdf0e10cSrcweir 		{
232cdf0e10cSrcweir 			Next();
233cdf0e10cSrcweir 			SbiExpression aStepExpr( this );
234cdf0e10cSrcweir 			aStepExpr.Gen();
235cdf0e10cSrcweir 		}
236cdf0e10cSrcweir 		else
237cdf0e10cSrcweir 		{
238cdf0e10cSrcweir 			SbiExpression aOne( this, 1, SbxINTEGER );
239cdf0e10cSrcweir 			aOne.Gen();
240cdf0e10cSrcweir 		}
241cdf0e10cSrcweir 		TestEoln();
242cdf0e10cSrcweir 		// Der Stack hat jetzt 4 Elemente: Variable, Start, Ende, Inkrement
243cdf0e10cSrcweir 		// Startwert binden
244cdf0e10cSrcweir 		aGen.Gen( _INITFOR );
245cdf0e10cSrcweir 	}
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 	sal_uInt32 nLoop = aGen.GetPC();
248cdf0e10cSrcweir 	// Test durchfuehren, evtl. Stack freigeben
249cdf0e10cSrcweir 	sal_uInt32 nEndTarget = aGen.Gen( _TESTFOR, 0 );
250cdf0e10cSrcweir 	OpenBlock( FOR );
251cdf0e10cSrcweir 	StmntBlock( NEXT );
252cdf0e10cSrcweir 	aGen.Gen( _NEXT );
253cdf0e10cSrcweir 	aGen.Gen( _JUMP, nLoop );
254cdf0e10cSrcweir 	// Kommen Variable nach NEXT?
255cdf0e10cSrcweir 	if( Peek() == SYMBOL )
256cdf0e10cSrcweir 	{
257cdf0e10cSrcweir 		SbiExpression aVar( this, SbOPERAND );
258cdf0e10cSrcweir 		if( aVar.GetRealVar() != aLvalue.GetRealVar() )
259cdf0e10cSrcweir 			Error( SbERR_EXPECTED, aLvalue.GetRealVar()->GetName() );
260cdf0e10cSrcweir 	}
261cdf0e10cSrcweir 	aGen.BackChain( nEndTarget );
262cdf0e10cSrcweir 	CloseBlock();
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
265cdf0e10cSrcweir // WITH .. END WITH
266cdf0e10cSrcweir 
With()267cdf0e10cSrcweir void SbiParser::With()
268cdf0e10cSrcweir {
269cdf0e10cSrcweir 	SbiExpression aVar( this, SbOPERAND );
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 	// Letzten Knoten in der Objekt-Kette ueberpruefen
272cdf0e10cSrcweir 	SbiExprNode *pNode = aVar.GetExprNode()->GetRealNode();
273cdf0e10cSrcweir 	SbiSymDef* pDef = pNode->GetVar();
274cdf0e10cSrcweir 	// Variant, AB 27.6.1997, #41090: bzw. empty -> mu� Object sein
275cdf0e10cSrcweir 	if( pDef->GetType() == SbxVARIANT || pDef->GetType() == SbxEMPTY )
276cdf0e10cSrcweir 		pDef->SetType( SbxOBJECT );
277cdf0e10cSrcweir 	else if( pDef->GetType() != SbxOBJECT )
278cdf0e10cSrcweir 		Error( SbERR_NEEDS_OBJECT );
279cdf0e10cSrcweir 
280cdf0e10cSrcweir 	// Knoten auch auf SbxOBJECT setzen, damit spaeter Gen() klappt
281cdf0e10cSrcweir 	pNode->SetType( SbxOBJECT );
282cdf0e10cSrcweir 
283cdf0e10cSrcweir 	OpenBlock( NIL, aVar.GetExprNode() );
284cdf0e10cSrcweir 	StmntBlock( ENDWITH );
285cdf0e10cSrcweir 	CloseBlock();
286cdf0e10cSrcweir }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir // LOOP/NEXT/WEND ohne Konstrukt
289cdf0e10cSrcweir 
BadBlock()290cdf0e10cSrcweir void SbiParser::BadBlock()
291cdf0e10cSrcweir {
292cdf0e10cSrcweir 	if( eEndTok )
293cdf0e10cSrcweir 		Error( SbERR_BAD_BLOCK, eEndTok );
294cdf0e10cSrcweir 	else
295cdf0e10cSrcweir 		Error( SbERR_BAD_BLOCK, "Loop/Next/Wend" );
296cdf0e10cSrcweir }
297cdf0e10cSrcweir 
298cdf0e10cSrcweir // On expr Goto/Gosub n,n,n...
299cdf0e10cSrcweir 
OnGoto()300cdf0e10cSrcweir void SbiParser::OnGoto()
301cdf0e10cSrcweir {
302cdf0e10cSrcweir 	SbiExpression aCond( this );
303cdf0e10cSrcweir 	aCond.Gen();
304cdf0e10cSrcweir 	sal_uInt32 nLabelsTarget = aGen.Gen( _ONJUMP, 0 );
305cdf0e10cSrcweir 	SbiToken eTok = Next();
306cdf0e10cSrcweir 	if( eTok != GOTO && eTok != GOSUB )
307cdf0e10cSrcweir 	{
308cdf0e10cSrcweir 		Error( SbERR_EXPECTED, "GoTo/GoSub" );
309cdf0e10cSrcweir 		eTok = GOTO;
310cdf0e10cSrcweir 	}
311cdf0e10cSrcweir 	// Label-Tabelle einlesen:
312cdf0e10cSrcweir 	sal_uInt32 nLbl = 0;
313cdf0e10cSrcweir 	do
314cdf0e10cSrcweir 	{
315cdf0e10cSrcweir 		SbiToken eTok2 = NIL;
316cdf0e10cSrcweir 		eTok2 = Next();	// Label holen
317cdf0e10cSrcweir 		if( MayBeLabel() )
318cdf0e10cSrcweir 		{
319cdf0e10cSrcweir 			sal_uInt32 nOff = pProc->GetLabels().Reference( aSym );
320cdf0e10cSrcweir 			aGen.Gen( _JUMP, nOff );
321cdf0e10cSrcweir 			nLbl++;
322cdf0e10cSrcweir 		}
323cdf0e10cSrcweir 		else Error( SbERR_LABEL_EXPECTED );
324cdf0e10cSrcweir 	}
325cdf0e10cSrcweir 	while( !bAbort && TestComma() );
326cdf0e10cSrcweir 	if( eTok == GOSUB )
327cdf0e10cSrcweir 		nLbl |= 0x8000;
328cdf0e10cSrcweir 	aGen.Patch( nLabelsTarget, nLbl );
329cdf0e10cSrcweir }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir // GOTO/GOSUB
332cdf0e10cSrcweir 
Goto()333cdf0e10cSrcweir void SbiParser::Goto()
334cdf0e10cSrcweir {
335cdf0e10cSrcweir 	SbiOpcode eOp = eCurTok == GOTO ? _JUMP : _GOSUB;
336cdf0e10cSrcweir 	Next();
337cdf0e10cSrcweir 	if( MayBeLabel() )
338cdf0e10cSrcweir 	{
339cdf0e10cSrcweir 		sal_uInt32 nOff = pProc->GetLabels().Reference( aSym );
340cdf0e10cSrcweir 		aGen.Gen( eOp, nOff );
341cdf0e10cSrcweir 	}
342cdf0e10cSrcweir 	else Error( SbERR_LABEL_EXPECTED );
343cdf0e10cSrcweir }
344cdf0e10cSrcweir 
345cdf0e10cSrcweir // RETURN [label]
346cdf0e10cSrcweir 
Return()347cdf0e10cSrcweir void SbiParser::Return()
348cdf0e10cSrcweir {
349cdf0e10cSrcweir 	Next();
350cdf0e10cSrcweir 	if( MayBeLabel() )
351cdf0e10cSrcweir 	{
352cdf0e10cSrcweir 		sal_uInt32 nOff = pProc->GetLabels().Reference( aSym );
353cdf0e10cSrcweir 		aGen.Gen( _RETURN, nOff );
354cdf0e10cSrcweir 	}
355cdf0e10cSrcweir 	else aGen.Gen( _RETURN, 0 );
356cdf0e10cSrcweir }
357cdf0e10cSrcweir 
358cdf0e10cSrcweir // SELECT CASE
359cdf0e10cSrcweir 
Select()360cdf0e10cSrcweir void SbiParser::Select()
361cdf0e10cSrcweir {
362cdf0e10cSrcweir 	TestToken( CASE );
363cdf0e10cSrcweir 	SbiExpression aCase( this );
364cdf0e10cSrcweir 	SbiToken eTok = NIL;
365cdf0e10cSrcweir 	aCase.Gen();
366cdf0e10cSrcweir 	aGen.Gen( _CASE );
367cdf0e10cSrcweir 	TestEoln();
368cdf0e10cSrcweir 	sal_uInt32 nNextTarget = 0;
369cdf0e10cSrcweir 	sal_uInt32 nDoneTarget = 0;
370cdf0e10cSrcweir 	sal_Bool bElse = sal_False;
371cdf0e10cSrcweir 	// Die Cases einlesen:
372cdf0e10cSrcweir 	while( !bAbort )
373cdf0e10cSrcweir 	{
374cdf0e10cSrcweir 		eTok = Next();
375cdf0e10cSrcweir 		if( eTok == CASE )
376cdf0e10cSrcweir 		{
377cdf0e10cSrcweir 			if( nNextTarget )
378cdf0e10cSrcweir 				aGen.BackChain( nNextTarget ), nNextTarget = 0;
379cdf0e10cSrcweir 			aGen.Statement();
380cdf0e10cSrcweir 			// Jeden Case einlesen
381cdf0e10cSrcweir 			sal_Bool bDone = sal_False;
382cdf0e10cSrcweir 			sal_uInt32 nTrueTarget = 0;
383cdf0e10cSrcweir 			if( Peek() == ELSE )
384cdf0e10cSrcweir 			{
385cdf0e10cSrcweir 				// CASE ELSE
386cdf0e10cSrcweir 				Next();
387cdf0e10cSrcweir 				bElse = sal_True;
388cdf0e10cSrcweir 			}
389cdf0e10cSrcweir 			else while( !bDone )
390cdf0e10cSrcweir 			{
391cdf0e10cSrcweir 				if( bElse )
392cdf0e10cSrcweir 					Error( SbERR_SYNTAX );
393cdf0e10cSrcweir 				SbiToken eTok2 = Peek();
394cdf0e10cSrcweir 				if( eTok2 == IS || ( eTok2 >= EQ && eTok2 <= GE ) )
395cdf0e10cSrcweir 				{	// CASE [IS] operator expr
396cdf0e10cSrcweir 					if( eTok2 == IS )
397cdf0e10cSrcweir 						Next();
398cdf0e10cSrcweir 					eTok2 = Peek();
399cdf0e10cSrcweir 					if( eTok2 < EQ || eTok2 > GE )
400cdf0e10cSrcweir 						Error( SbERR_SYNTAX );
401cdf0e10cSrcweir 					else Next();
402cdf0e10cSrcweir 					SbiExpression aCompare( this );
403cdf0e10cSrcweir 					aCompare.Gen();
404cdf0e10cSrcweir 					nTrueTarget = aGen.Gen(
405cdf0e10cSrcweir                         _CASEIS, nTrueTarget,
406cdf0e10cSrcweir                         sal::static_int_cast< sal_uInt16 >(
407cdf0e10cSrcweir                             SbxEQ + ( eTok2 - EQ ) ) );
408cdf0e10cSrcweir 				}
409cdf0e10cSrcweir 				else
410cdf0e10cSrcweir 				{	// CASE expr | expr TO expr
411cdf0e10cSrcweir 					SbiExpression aCase1( this );
412cdf0e10cSrcweir 					aCase1.Gen();
413cdf0e10cSrcweir 					if( Peek() == TO )
414cdf0e10cSrcweir 					{
415cdf0e10cSrcweir 						// CASE a TO b
416cdf0e10cSrcweir 						Next();
417cdf0e10cSrcweir 						SbiExpression aCase2( this );
418cdf0e10cSrcweir 						aCase2.Gen();
419cdf0e10cSrcweir 						nTrueTarget = aGen.Gen( _CASETO, nTrueTarget );
420cdf0e10cSrcweir 					}
421cdf0e10cSrcweir 					else
422cdf0e10cSrcweir 						// CASE a
423cdf0e10cSrcweir 						nTrueTarget = aGen.Gen( _CASEIS, nTrueTarget, SbxEQ );
424cdf0e10cSrcweir 
425cdf0e10cSrcweir 				}
426cdf0e10cSrcweir 				if( Peek() == COMMA ) Next();
427cdf0e10cSrcweir 				else TestEoln(), bDone = sal_True;
428cdf0e10cSrcweir 			}
429cdf0e10cSrcweir 			// Alle Cases abgearbeitet
430cdf0e10cSrcweir 			if( !bElse )
431cdf0e10cSrcweir 			{
432cdf0e10cSrcweir 				nNextTarget = aGen.Gen( _JUMP, nNextTarget );
433cdf0e10cSrcweir 				aGen.BackChain( nTrueTarget );
434cdf0e10cSrcweir 			}
435cdf0e10cSrcweir 			// den Statement-Rumpf bauen
436cdf0e10cSrcweir 			while( !bAbort )
437cdf0e10cSrcweir 			{
438cdf0e10cSrcweir 				eTok = Peek();
439cdf0e10cSrcweir 				if( eTok == CASE || eTok == ENDSELECT )
440cdf0e10cSrcweir 					break;
441cdf0e10cSrcweir 				if( !Parse() ) goto done;
442cdf0e10cSrcweir 				eTok = Peek();
443cdf0e10cSrcweir 				if( eTok == CASE || eTok == ENDSELECT )
444cdf0e10cSrcweir 					break;
445cdf0e10cSrcweir 			}
446cdf0e10cSrcweir 			if( !bElse )
447cdf0e10cSrcweir 				nDoneTarget = aGen.Gen( _JUMP, nDoneTarget );
448cdf0e10cSrcweir 		}
449cdf0e10cSrcweir 		else if( !IsEoln( eTok ) )
450cdf0e10cSrcweir 			break;
451cdf0e10cSrcweir 	}
452cdf0e10cSrcweir done:
453cdf0e10cSrcweir 	if( eTok != ENDSELECT )
454cdf0e10cSrcweir 		Error( SbERR_EXPECTED, ENDSELECT );
455cdf0e10cSrcweir 	if( nNextTarget )
456cdf0e10cSrcweir 		aGen.BackChain( nNextTarget );
457cdf0e10cSrcweir 	aGen.BackChain( nDoneTarget );
458cdf0e10cSrcweir 	aGen.Gen( _ENDCASE );
459cdf0e10cSrcweir }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir // ON Error/Variable
462cdf0e10cSrcweir 
463cdf0e10cSrcweir #ifdef _MSC_VER
464cdf0e10cSrcweir #pragma optimize("",off)
465cdf0e10cSrcweir #endif
466cdf0e10cSrcweir 
On()467cdf0e10cSrcweir void SbiParser::On()
468cdf0e10cSrcweir {
469cdf0e10cSrcweir 	SbiToken eTok = Peek();
470cdf0e10cSrcweir 	String aString = SbiTokenizer::Symbol(eTok);
471cdf0e10cSrcweir 	if (aString.EqualsIgnoreCaseAscii("ERROR"))
472cdf0e10cSrcweir 	//if (!aString.ICompare("ERROR"))
473cdf0e10cSrcweir 		eTok = _ERROR_;	// Error kommt als SYMBOL
474cdf0e10cSrcweir 	if( eTok != _ERROR_ && eTok != LOCAL ) OnGoto();
475cdf0e10cSrcweir 	else
476cdf0e10cSrcweir 	{
477cdf0e10cSrcweir 		if( eTok == LOCAL ) Next();
478cdf0e10cSrcweir 		Next (); // Kein TestToken mehr, da es sonst einen Fehler gibt
479cdf0e10cSrcweir 
480cdf0e10cSrcweir 		Next();	// Token nach Error holen
481cdf0e10cSrcweir 		if( eCurTok == GOTO )
482cdf0e10cSrcweir 		{
483cdf0e10cSrcweir 			// ON ERROR GOTO label|0
484cdf0e10cSrcweir 			Next();
485cdf0e10cSrcweir 			bool bError_ = false;
486cdf0e10cSrcweir 			if( MayBeLabel() )
487cdf0e10cSrcweir 			{
488cdf0e10cSrcweir 				if( eCurTok == NUMBER && !nVal )
489cdf0e10cSrcweir 					aGen.Gen( _STDERROR );
490cdf0e10cSrcweir 				else
491cdf0e10cSrcweir 				{
492cdf0e10cSrcweir 					sal_uInt32 nOff = pProc->GetLabels().Reference( aSym );
493cdf0e10cSrcweir 					aGen.Gen( _ERRHDL, nOff );
494cdf0e10cSrcweir 				}
495cdf0e10cSrcweir 			}
496cdf0e10cSrcweir 			else if( eCurTok == MINUS )
497cdf0e10cSrcweir 			{
498cdf0e10cSrcweir 				Next();
499cdf0e10cSrcweir 				if( eCurTok == NUMBER && nVal == 1 )
500cdf0e10cSrcweir 					aGen.Gen( _STDERROR );
501cdf0e10cSrcweir 				else
502cdf0e10cSrcweir 					bError_ = true;
503cdf0e10cSrcweir 			}
504cdf0e10cSrcweir 			if( bError_ )
505cdf0e10cSrcweir 				Error( SbERR_LABEL_EXPECTED );
506cdf0e10cSrcweir 		}
507cdf0e10cSrcweir 		else if( eCurTok == RESUME )
508cdf0e10cSrcweir 		{
509cdf0e10cSrcweir 			TestToken( NEXT );
510cdf0e10cSrcweir 			aGen.Gen( _NOERROR );
511cdf0e10cSrcweir 		}
512cdf0e10cSrcweir 		else Error( SbERR_EXPECTED, "GoTo/Resume" );
513cdf0e10cSrcweir 	}
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
516cdf0e10cSrcweir #ifdef _MSC_VER
517cdf0e10cSrcweir #pragma optimize("",off)
518cdf0e10cSrcweir #endif
519cdf0e10cSrcweir 
520cdf0e10cSrcweir // RESUME [0]|NEXT|label
521cdf0e10cSrcweir 
Resume()522cdf0e10cSrcweir void SbiParser::Resume()
523cdf0e10cSrcweir {
524cdf0e10cSrcweir 	sal_uInt32 nLbl;
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 	switch( Next() )
527cdf0e10cSrcweir 	{
528cdf0e10cSrcweir 		case EOS:
529cdf0e10cSrcweir 		case EOLN:
530cdf0e10cSrcweir 			aGen.Gen( _RESUME, 0 );
531cdf0e10cSrcweir 			break;
532cdf0e10cSrcweir 		case NEXT:
533cdf0e10cSrcweir 			aGen.Gen( _RESUME, 1 );
534cdf0e10cSrcweir 			Next();
535cdf0e10cSrcweir 			break;
536cdf0e10cSrcweir 		case NUMBER:
537cdf0e10cSrcweir 			if( !nVal )
538cdf0e10cSrcweir 			{
539cdf0e10cSrcweir 				aGen.Gen( _RESUME, 0 );
540cdf0e10cSrcweir 				break;
541*30acf5e8Spfg 			} // fall through
542cdf0e10cSrcweir 		case SYMBOL:
543cdf0e10cSrcweir 			if( MayBeLabel() )
544cdf0e10cSrcweir 			{
545cdf0e10cSrcweir 				nLbl = pProc->GetLabels().Reference( aSym );
546cdf0e10cSrcweir 				aGen.Gen( _RESUME, nLbl );
547cdf0e10cSrcweir 				Next();
548cdf0e10cSrcweir 				break;
549*30acf5e8Spfg 			} // fall through
550cdf0e10cSrcweir 		default:
551cdf0e10cSrcweir 			Error( SbERR_LABEL_EXPECTED );
552cdf0e10cSrcweir 	}
553cdf0e10cSrcweir }
554cdf0e10cSrcweir 
555