update(add) packaging directory and spec file from OBSTF:Private, OBS
[external/ragel.git] / ragel / rubyfflat.cpp
1 /*
2  *  2007 Victor Hugo Borja <vic@rubyforge.org>
3  *  Copyright 2001-2007 Adrian Thurston <thurston@complang.org>
4  */
5
6 /*  This file is part of Ragel.
7  *
8  *  Ragel is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  * 
13  *  Ragel is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  * 
18  *  You should have received a copy of the GNU General Public License
19  *  along with Ragel; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
21  */
22
23 #include "rubyfflat.h"
24
25 void RubyFFlatCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish )
26 {
27         out << 
28                 "       begin\n"
29                 "               " << vCS() << " = " << gotoDest << "\n"
30                 "               _goto_level = _again\n"
31                 "               next\n"
32                 "       end\n";
33 }
34
35 void RubyFFlatCodeGen::GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish )
36 {
37         out << 
38                 "       begin\n"
39                 "               " << vCS() << " = (";
40         INLINE_LIST( out, ilItem->children, 0, inFinish );
41         out << ")\n";
42         out <<
43                 "               _goto_level = _again\n"
44                 "               next\n"
45                 "       end\n";
46 }
47
48 void RubyFFlatCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish )
49 {
50         if ( prePushExpr != 0 ) {
51                 out << "begin\n";
52                 INLINE_LIST( out, prePushExpr, 0, false );
53         }
54
55         out <<
56                 "       begin\n"
57                 "               " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
58                 "               " << TOP() << "+= 1\n"
59                 "               " << vCS() << " = " << callDest << "\n"
60                 "               _goto_level = _again\n"
61                 "               next\n"
62                 "       end\n";
63
64         if ( prePushExpr != 0 )
65                 out << "end\n";
66 }
67
68 void RubyFFlatCodeGen::CALL_EXPR(ostream &out, GenInlineItem *ilItem, 
69                 int targState, bool inFinish )
70 {
71         if ( prePushExpr != 0 ) {
72                 out << "begin\n";
73                 INLINE_LIST( out, prePushExpr, 0, false );
74         }
75
76         out <<
77                 "       begin\n"
78                 "               " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
79                 "               " << TOP() << " += 1\n"
80                 "               " << vCS() << " = (";
81         INLINE_LIST( out, ilItem->children, targState, inFinish );
82         out << ")\n";
83
84         out << 
85                 "               _goto_level = _again\n"
86                 "               next\n"
87                 "       end\n";
88
89         if ( prePushExpr != 0 )
90                 out << "end\n";
91 }
92
93 void RubyFFlatCodeGen::RET( ostream &out, bool inFinish )
94 {
95         out <<
96                 "       begin\n"
97                 "               " << TOP() << " -= 1\n"
98                 "               " << vCS() << " = " << STACK() << "[" << TOP() << "]\n";
99
100         if ( postPopExpr != 0 ) {
101                 out << "begin\n";
102                 INLINE_LIST( out, postPopExpr, 0, false );
103                 out << "end\n";
104         }
105
106         out <<
107                 "               _goto_level = _again\n"
108                 "               next\n"
109                 "       end\n";
110 }
111
112 void RubyFFlatCodeGen::BREAK( ostream &out, int targState )
113 {
114         out << 
115                 "       begin\n"
116                 "               " << P() << " += 1\n"
117                 "               _goto_level = _out\n"
118                 "               next\n"
119                 "       end\n";
120 }
121
122
123 int RubyFFlatCodeGen::TO_STATE_ACTION( RedStateAp *state )
124 {
125         int act = 0;
126         if ( state->toStateAction != 0 )
127                 act = state->toStateAction->actListId+1;
128         return act;
129 }
130
131 int RubyFFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state )
132 {
133         int act = 0;
134         if ( state->fromStateAction != 0 )
135                 act = state->fromStateAction->actListId+1;
136         return act;
137 }
138
139 int RubyFFlatCodeGen::EOF_ACTION( RedStateAp *state )
140 {
141         int act = 0;
142         if ( state->eofAction != 0 )
143                 act = state->eofAction->actListId+1;
144         return act;
145 }
146
147 /* Write out the function for a transition. */
148 int RubyFFlatCodeGen::TRANS_ACTION( RedTransAp *trans )
149 {
150         int action = 0;
151         if ( trans->action != 0 )
152                 action = trans->action->actListId+1;
153         return action;
154 }
155
156 /* Write out the function switch. This switch is keyed on the values
157  * of the func index. */
158 std::ostream &RubyFFlatCodeGen::TO_STATE_ACTION_SWITCH()
159 {
160         /* Loop the actions. */
161         for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
162                 if ( redAct->numToStateRefs > 0 ) {
163                         /* Write the entry label. */
164                         out << "\twhen " << redAct->actListId+1 << " then\n";
165
166                         /* Write each action in the list of action items. */
167                         for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
168                                 ACTION( out, item->value, 0, false );
169                 }
170         }
171
172         genLineDirective( out );
173         return out;
174 }
175
176 /* Write out the function switch. This switch is keyed on the values
177  * of the func index. */
178 std::ostream &RubyFFlatCodeGen::FROM_STATE_ACTION_SWITCH()
179 {
180         /* Loop the actions. */
181         for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
182                 if ( redAct->numFromStateRefs > 0 ) {
183                         /* Write the entry label. */
184                         out << "\twhen " << redAct->actListId+1 << " then\n";
185
186                         /* Write each action in the list of action items. */
187                         for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
188                                 ACTION( out, item->value, 0, false );
189                 }
190         }
191
192         genLineDirective( out );
193         return out;
194 }
195
196 std::ostream &RubyFFlatCodeGen::EOF_ACTION_SWITCH()
197 {
198         /* Loop the actions. */
199         for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
200                 if ( redAct->numEofRefs > 0 ) {
201                         /* Write the entry label. */
202                         out << "\twhen " << redAct->actListId+1 << " then\n";
203
204                         /* Write each action in the list of action items. */
205                         for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
206                                 ACTION( out, item->value, 0, true );
207                 }
208         }
209
210         genLineDirective( out );
211         return out;
212 }
213
214 /* Write out the function switch. This switch is keyed on the values
215  * of the func index. */
216 std::ostream &RubyFFlatCodeGen::ACTION_SWITCH()
217 {
218         /* Loop the actions. */
219         for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
220                 if ( redAct->numTransRefs > 0 ) {
221                         /* Write the entry label. */
222                         out << "\twhen " << redAct->actListId+1 << " then\n";
223
224                         /* Write each action in the list of action items. */
225                         for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
226                                 ACTION( out, item->value, 0, false );
227
228                 }
229         }
230
231         genLineDirective( out );
232         return out;
233 }
234
235 void RubyFFlatCodeGen::writeData()
236 {
237         if ( redFsm->anyConditions() ) {
238                 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
239                 COND_KEYS();
240                 CLOSE_ARRAY() <<
241                 "\n";
242
243                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
244                 COND_KEY_SPANS();
245                 CLOSE_ARRAY() <<
246                 "\n";
247
248                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
249                 CONDS();
250                 CLOSE_ARRAY() <<
251                 "\n";
252
253                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
254                 COND_INDEX_OFFSET();
255                 CLOSE_ARRAY() <<
256                 "\n";
257         }
258
259         OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
260         KEYS();
261         CLOSE_ARRAY() <<
262         "\n";
263
264         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
265         KEY_SPANS();
266         CLOSE_ARRAY() <<
267         "\n";
268
269         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
270         FLAT_INDEX_OFFSET();
271         CLOSE_ARRAY() <<
272         "\n";
273
274         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
275         INDICIES();
276         CLOSE_ARRAY() <<
277         "\n";
278
279         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
280         TRANS_TARGS();
281         CLOSE_ARRAY() <<
282         "\n";
283
284         if ( redFsm->anyActions() ) {
285                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() );
286                 TRANS_ACTIONS();
287                 CLOSE_ARRAY() <<
288                 "\n";
289         }
290
291         if ( redFsm->anyToStateActions() ) {
292                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc),  TSA() );
293                 TO_STATE_ACTIONS();
294                 CLOSE_ARRAY() <<
295                 "\n";
296         }
297
298         if ( redFsm->anyFromStateActions() ) {
299                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
300                 FROM_STATE_ACTIONS();
301                 CLOSE_ARRAY() <<
302                 "\n";
303         }
304
305         if ( redFsm->anyEofActions() ) {
306                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() );
307                 EOF_ACTIONS();
308                 CLOSE_ARRAY() <<
309                 "\n";
310         }
311
312         if ( redFsm->anyEofTrans() ) {
313                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
314                 EOF_TRANS();
315                 CLOSE_ARRAY() <<
316                 "\n";
317         }
318
319         STATE_IDS();
320 }
321
322 void RubyFFlatCodeGen::writeExec()
323 {
324         out << 
325                 "begin\n"
326                 "       testEof = false\n"
327                 "       _slen, _trans, _keys, _inds";
328         if ( redFsm->anyRegCurStateRef() )
329                 out << ", _ps";
330         if ( redFsm->anyConditions() )
331                 out << ", _cond, _conds, _widec";
332         if ( redFsm->anyToStateActions() || redFsm->anyRegActions() 
333                         || redFsm->anyFromStateActions() )
334                 out << ", _acts, _nacts";
335         
336         out << " = nil\n";
337
338         out << 
339                 "       _goto_level = 0\n"
340                 "       _resume = 10\n"
341                 "       _eof_trans = 15\n"
342                 "       _again = 20\n"
343                 "       _test_eof = 30\n"
344                 "       _out = 40\n";
345
346         out << 
347                 "       while true\n"
348                 "       if _goto_level <= 0\n";
349         
350         if ( !noEnd ) {
351                 out << 
352                         "       if " << P() << " == " << PE() << "\n"
353                         "               _goto_level = _test_eof\n"
354                         "               next\n"
355                         "       end\n";
356         }
357
358         if ( redFsm->errState != 0 ) {
359                 out << 
360                         "       if " << vCS() << " == " << redFsm->errState->id << "\n"
361                         "               _goto_level = _out\n"
362                         "               next\n"
363                         "       end\n";
364         }
365
366         /* The resume label. */
367         out << 
368                 "       end\n"
369                 "       if _goto_level <= _resume\n";
370         
371         if ( redFsm->anyFromStateActions() ) {
372                 out <<
373                         "       case " << FSA() << "[" << vCS() << "] \n";
374                         FROM_STATE_ACTION_SWITCH() <<
375                         "       end\n";
376         }
377
378         if ( redFsm->anyConditions() )
379                 COND_TRANSLATE();
380         
381         LOCATE_TRANS();
382
383         if ( redFsm->anyEofTrans() ) {
384                 out << 
385                         "       end\n"
386                         "       if _goto_level <= _eof_trans\n";
387         }
388
389         if ( redFsm->anyRegCurStateRef() )
390                 out << "        _ps = " << vCS() << "\n";
391
392         out << "        " << vCS() << " = " << TT() << "[_trans]\n";
393
394         if ( redFsm->anyRegActions() ) {
395                 /* break _again */
396                 out << 
397                         "       if " << TA() << "[_trans] != 0\n"
398                         "       case " << TA() << "[_trans]" << "\n";
399                         ACTION_SWITCH() <<
400                         "       end\n"
401                         "       end\n";
402         }
403
404         /* The again label. */
405         out <<
406                 "       end\n"
407                 "       if _goto_level <= _again\n";
408
409         if ( redFsm->anyToStateActions() ) {
410                 out <<
411                         "       case " << TSA() << "[" << vCS() << "] \n";
412                         TO_STATE_ACTION_SWITCH() <<
413                         "       end\n"
414                         "\n";
415         }
416
417         if ( redFsm->errState != 0 ) {
418                 out << 
419                         "       if " << vCS() << " == " << redFsm->errState->id << "\n"
420                         "               _goto_level = _out\n"
421                         "               next\n"
422                         "       end\n";
423         }
424
425         out << "        " << P() << " += 1\n";
426
427         if ( !noEnd ) {
428                 out << 
429                         "       if " << P() << " != " << PE() << "\n"
430                         "               _goto_level = _resume\n"
431                         "               next\n"
432                         "       end\n";
433         }
434         else {
435                 out <<
436                         "       _goto_level = _resume\n"
437                         "       next\n";
438         }
439         
440         /* The test eof label. */
441         out <<
442                 "       end\n"
443                 "       if _goto_level <= _test_eof\n";
444
445         if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
446                 out <<
447                         "       if " << P() << " == " << vEOF() << "\n";
448         
449                 if ( redFsm->anyEofTrans() ) {
450                         out <<
451                                 "       if " << ET() << "[" << vCS() << "] > 0\n"
452                                 "               _trans = " << ET() << "[" << vCS() << "] - 1;\n"
453                                 "               _goto_level = _eof_trans\n"
454                                 "               next;\n"
455                                 "       end\n";
456                 }
457
458                 if ( redFsm->anyEofActions() ) {
459                         out <<
460                                 "         case " << EA() << "[" << vCS() << "]\n";
461                                 EOF_ACTION_SWITCH() <<
462                                 "         end\n";
463                 }
464
465                 out <<
466                         "       end\n"
467                         "\n";
468         }
469
470         out << 
471                 "       end\n"
472                 "       if _goto_level <= _out\n"
473                 "               break\n"
474                 "       end\n"
475                 "end\n";
476
477         /* Wrapping the execute block. */
478         out << "        end\n";
479 }
480
481 /*
482  * Local Variables:
483  * mode: c++
484  * indent-tabs-mode: 1
485  * c-file-style: "bsd"
486  * End:
487  */
488