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