Introcuded the "eof" variable for indicating the end of file. The p variable is
[external/ragel.git] / rlgen-cd / fflatcodegen.cpp
1 /*
2  *  Copyright 2004-2006 Adrian Thurston <thurston@cs.queensu.ca>
3  *            2004 Erich Ocean <eric.ocean@ampede.com>
4  *            2005 Alan West <alan@alanz.com>
5  */
6
7 /*  This file is part of Ragel.
8  *
9  *  Ragel is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  * 
14  *  Ragel is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  * 
19  *  You should have received a copy of the GNU General Public License
20  *  along with Ragel; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
22  */
23
24 #include "rlgen-cd.h"
25 #include "fflatcodegen.h"
26 #include "redfsm.h"
27 #include "gendata.h"
28
29 std::ostream &FFlatCodeGen::TO_STATE_ACTION( RedStateAp *state )
30 {
31         int act = 0;
32         if ( state->toStateAction != 0 )
33                 act = state->toStateAction->actListId+1;
34         out << act;
35         return out;
36 }
37
38 std::ostream &FFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state )
39 {
40         int act = 0;
41         if ( state->fromStateAction != 0 )
42                 act = state->fromStateAction->actListId+1;
43         out << act;
44         return out;
45 }
46
47 std::ostream &FFlatCodeGen::EOF_ACTION( RedStateAp *state )
48 {
49         int act = 0;
50         if ( state->eofAction != 0 )
51                 act = state->eofAction->actListId+1;
52         out << act;
53         return out;
54 }
55
56 /* Write out the function for a transition. */
57 std::ostream &FFlatCodeGen::TRANS_ACTION( RedTransAp *trans )
58 {
59         int action = 0;
60         if ( trans->action != 0 )
61                 action = trans->action->actListId+1;
62         out << action;
63         return out;
64 }
65
66 /* Write out the function switch. This switch is keyed on the values
67  * of the func index. */
68 std::ostream &FFlatCodeGen::TO_STATE_ACTION_SWITCH()
69 {
70         /* Loop the actions. */
71         for ( ActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
72                 if ( redAct->numToStateRefs > 0 ) {
73                         /* Write the entry label. */
74                         out << "\tcase " << redAct->actListId+1 << ":\n";
75
76                         /* Write each action in the list of action items. */
77                         for ( ActionTable::Iter item = redAct->key; item.lte(); item++ )
78                                 ACTION( out, item->value, 0, false );
79
80                         out << "\tbreak;\n";
81                 }
82         }
83
84         genLineDirective( out );
85         return out;
86 }
87
88 /* Write out the function switch. This switch is keyed on the values
89  * of the func index. */
90 std::ostream &FFlatCodeGen::FROM_STATE_ACTION_SWITCH()
91 {
92         /* Loop the actions. */
93         for ( ActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
94                 if ( redAct->numFromStateRefs > 0 ) {
95                         /* Write the entry label. */
96                         out << "\tcase " << redAct->actListId+1 << ":\n";
97
98                         /* Write each action in the list of action items. */
99                         for ( ActionTable::Iter item = redAct->key; item.lte(); item++ )
100                                 ACTION( out, item->value, 0, false );
101
102                         out << "\tbreak;\n";
103                 }
104         }
105
106         genLineDirective( out );
107         return out;
108 }
109
110 std::ostream &FFlatCodeGen::EOF_ACTION_SWITCH()
111 {
112         /* Loop the actions. */
113         for ( ActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
114                 if ( redAct->numEofRefs > 0 ) {
115                         /* Write the entry label. */
116                         out << "\tcase " << redAct->actListId+1 << ":\n";
117
118                         /* Write each action in the list of action items. */
119                         for ( ActionTable::Iter item = redAct->key; item.lte(); item++ )
120                                 ACTION( out, item->value, 0, true );
121
122                         out << "\tbreak;\n";
123                 }
124         }
125
126         genLineDirective( out );
127         return out;
128 }
129
130 /* Write out the function switch. This switch is keyed on the values
131  * of the func index. */
132 std::ostream &FFlatCodeGen::ACTION_SWITCH()
133 {
134         /* Loop the actions. */
135         for ( ActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
136                 if ( redAct->numTransRefs > 0 ) {
137                         /* Write the entry label. */
138                         out << "\tcase " << redAct->actListId+1 << ":\n";
139
140                         /* Write each action in the list of action items. */
141                         for ( ActionTable::Iter item = redAct->key; item.lte(); item++ )
142                                 ACTION( out, item->value, 0, false );
143
144                         out << "\tbreak;\n";
145                 }
146         }
147
148         genLineDirective( out );
149         return out;
150 }
151
152 void FFlatCodeGen::writeData()
153 {
154         if ( redFsm->anyConditions() ) {
155                 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
156                 COND_KEYS();
157                 CLOSE_ARRAY() <<
158                 "\n";
159
160                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
161                 COND_KEY_SPANS();
162                 CLOSE_ARRAY() <<
163                 "\n";
164
165                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
166                 CONDS();
167                 CLOSE_ARRAY() <<
168                 "\n";
169
170                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
171                 COND_INDEX_OFFSET();
172                 CLOSE_ARRAY() <<
173                 "\n";
174         }
175
176         OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
177         KEYS();
178         CLOSE_ARRAY() <<
179         "\n";
180
181         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
182         KEY_SPANS();
183         CLOSE_ARRAY() <<
184         "\n";
185
186         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
187         FLAT_INDEX_OFFSET();
188         CLOSE_ARRAY() <<
189         "\n";
190
191         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
192         INDICIES();
193         CLOSE_ARRAY() <<
194         "\n";
195
196         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
197         TRANS_TARGS();
198         CLOSE_ARRAY() <<
199         "\n";
200
201         if ( redFsm->anyActions() ) {
202                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() );
203                 TRANS_ACTIONS();
204                 CLOSE_ARRAY() <<
205                 "\n";
206         }
207
208         if ( redFsm->anyToStateActions() ) {
209                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc),  TSA() );
210                 TO_STATE_ACTIONS();
211                 CLOSE_ARRAY() <<
212                 "\n";
213         }
214
215         if ( redFsm->anyFromStateActions() ) {
216                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
217                 FROM_STATE_ACTIONS();
218                 CLOSE_ARRAY() <<
219                 "\n";
220         }
221
222         if ( redFsm->anyEofActions() ) {
223                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() );
224                 EOF_ACTIONS();
225                 CLOSE_ARRAY() <<
226                 "\n";
227         }
228
229         STATE_IDS();
230 }
231
232 void FFlatCodeGen::writeExec()
233 {
234         testEofUsed = false;
235         outLabelUsed = false;
236
237         out << 
238                 "       {\n"
239                 "       int _slen";
240
241         if ( redFsm->anyRegCurStateRef() )
242                 out << ", _ps";
243         
244         out << ";\n";
245         out << "        int _trans";
246
247         if ( redFsm->anyConditions() )
248                 out << ", _cond";
249
250         out << ";\n";
251
252         out <<
253                 "       " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
254                 "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxIndex) << POINTER() << "_inds;\n";
255
256         if ( redFsm->anyConditions() ) {
257                 out << 
258                         "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxCond) << POINTER() << "_conds;\n"
259                         "       " << WIDE_ALPH_TYPE() << " _widec;\n";
260         }
261
262         if ( hasEnd ) {
263                 testEofUsed = true;
264                 out << 
265                         "       if ( " << P() << " == " << PE() << " )\n"
266                         "               goto _test_eof;\n";
267         }
268
269         if ( redFsm->errState != 0 ) {
270                 outLabelUsed = true;
271                 out << 
272                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
273                         "               goto _out;\n";
274         }
275
276         out << "_resume:\n";
277
278         if ( redFsm->anyFromStateActions() ) {
279                 out <<
280                         "       switch ( " << FSA() << "[" << CS() << "] ) {\n";
281                         FROM_STATE_ACTION_SWITCH();
282                         SWITCH_DEFAULT() <<
283                         "       }\n"
284                         "\n";
285         }
286
287         if ( redFsm->anyConditions() )
288                 COND_TRANSLATE();
289
290         LOCATE_TRANS();
291         
292         if ( redFsm->anyRegCurStateRef() )
293                 out << "        _ps = " << CS() << ";\n";
294
295         out << 
296                 "       " << CS() << " = " << TT() << "[_trans];\n\n";
297
298         if ( redFsm->anyRegActions() ) {
299                 out << 
300                         "       if ( " << TA() << "[_trans] == 0 )\n"
301                         "               goto _again;\n"
302                         "\n"
303                         "       switch ( " << TA() << "[_trans] ) {\n";
304                         ACTION_SWITCH();
305                         SWITCH_DEFAULT() <<
306                         "       }\n"
307                         "\n";
308         }
309
310         if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || 
311                         redFsm->anyActionCalls() || redFsm->anyActionRets() )
312                 out << "_again:\n";
313
314         if ( redFsm->anyToStateActions() ) {
315                 out <<
316                         "       switch ( " << TSA() << "[" << CS() << "] ) {\n";
317                         TO_STATE_ACTION_SWITCH();
318                         SWITCH_DEFAULT() <<
319                         "       }\n"
320                         "\n";
321         }
322
323         if ( redFsm->errState != 0 ) {
324                 outLabelUsed = true;
325                 out << 
326                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
327                         "               goto _out;\n";
328         }
329
330         if ( hasEnd ) {
331                 out << 
332                         "       if ( ++" << P() << " != " << PE() << " )\n"
333                         "               goto _resume;\n";
334         }
335         else {
336                 out << 
337                         "       " << P() << " += 1;\n"
338                         "       goto _resume;\n";
339         }
340
341         if ( testEofUsed )
342                 out << "        _test_eof: {}\n";
343
344         if ( redFsm->anyEofActions() ) {
345                 out <<
346                         "       if ( " << P() << " == " << EOFV() << " )\n"
347                         "       {\n"
348                         "       switch ( " << EA() << "[" << CS() << "] ) {\n";
349                         EOF_ACTION_SWITCH();
350                         SWITCH_DEFAULT() <<
351                         "       }\n"
352                         "       }\n"
353                         "\n";
354         }
355
356         if ( outLabelUsed )
357                 out << "        _out: {}\n";
358
359         out << "        }\n";
360 }
361
362 void FFlatCodeGen::writeEOF()
363 {
364 }