xref: /AOO42X/main/basic/source/comp/loops.cxx (revision 30acf5e801d38c3701bf451b42e514ce81855b4c)
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 
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 
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 
144cdf0e10cSrcweir void SbiParser::NoIf()
145cdf0e10cSrcweir {
146cdf0e10cSrcweir     Error( SbERR_NO_IF );
147cdf0e10cSrcweir     StmntBlock( ENDIF );
148cdf0e10cSrcweir }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir // DO WHILE...LOOP
151cdf0e10cSrcweir // DO ... LOOP WHILE
152cdf0e10cSrcweir 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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