The spelling of Erich's name has changed. Now updated throughout.
[external/ragel.git] / rlcodegen / 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 "rlcodegen.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::writeOutData()
153 {
154         if ( anyConditions() ) {
155                 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
156                 COND_KEYS();
157                 CLOSE_ARRAY() <<
158                 "\n";
159
160                 OPEN_ARRAY( ARRAY_TYPE(maxCondSpan), CSP() );
161                 COND_KEY_SPANS();
162                 CLOSE_ARRAY() <<
163                 "\n";
164
165                 OPEN_ARRAY( ARRAY_TYPE(maxCond), C() );
166                 CONDS();
167                 CLOSE_ARRAY() <<
168                 "\n";
169
170                 OPEN_ARRAY( ARRAY_TYPE(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(maxSpan), SP() );
182         KEY_SPANS();
183         CLOSE_ARRAY() <<
184         "\n";
185
186         OPEN_ARRAY( ARRAY_TYPE(maxFlatIndexOffset), IO() );
187         FLAT_INDEX_OFFSET();
188         CLOSE_ARRAY() <<
189         "\n";
190
191         OPEN_ARRAY( ARRAY_TYPE(maxIndex), I() );
192         INDICIES();
193         CLOSE_ARRAY() <<
194         "\n";
195
196         OPEN_ARRAY( ARRAY_TYPE(maxState), TT() );
197         TRANS_TARGS();
198         CLOSE_ARRAY() <<
199         "\n";
200
201         if ( anyActions() ) {
202                 OPEN_ARRAY( ARRAY_TYPE(maxActListId), TA() );
203                 TRANS_ACTIONS();
204                 CLOSE_ARRAY() <<
205                 "\n";
206         }
207
208         if ( anyToStateActions() ) {
209                 OPEN_ARRAY( ARRAY_TYPE(maxActionLoc),  TSA() );
210                 TO_STATE_ACTIONS();
211                 CLOSE_ARRAY() <<
212                 "\n";
213         }
214
215         if ( anyFromStateActions() ) {
216                 OPEN_ARRAY( ARRAY_TYPE(maxActionLoc), FSA() );
217                 FROM_STATE_ACTIONS();
218                 CLOSE_ARRAY() <<
219                 "\n";
220         }
221
222         if ( anyEofActions() ) {
223                 OPEN_ARRAY( ARRAY_TYPE(maxActListId), EA() );
224                 EOF_ACTIONS();
225                 CLOSE_ARRAY() <<
226                 "\n";
227         }
228
229         out <<
230                 "static const int " << START() << " = " << START_STATE_ID() << ";\n"
231                 "\n";
232
233         if ( cgd->writeFirstFinal ) {
234                 out <<
235                         "static const int " << FIRST_FINAL() << " = " << FIRST_FINAL_STATE() << ";\n"
236                         "\n";
237         }
238
239         if ( cgd->writeErr ) {
240                 out <<
241                         "static const int " << ERROR() << " = " << ERROR_STATE() << ";\n"
242                         "\n";
243         }
244 }
245
246 void FFlatCodeGen::writeOutExec()
247 {
248         outLabelUsed = false;
249
250         out << 
251                 "       {\n"
252                 "       int _slen";
253
254         if ( anyRegCurStateRef() )
255                 out << ", _ps";
256         
257         out << ";\n";
258         out << "        int _trans";
259
260         if ( anyConditions() )
261                 out << ", _cond";
262
263         out << ";\n";
264
265         out <<
266                 "       " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
267                 "       " << PTR_CONST() << ARRAY_TYPE(maxIndex) << POINTER() << "_inds;\n";
268
269         if ( anyConditions() ) {
270                 out << 
271                         "       " << PTR_CONST() << ARRAY_TYPE(maxCond) << POINTER() << "_conds;\n"
272                         "       " << WIDE_ALPH_TYPE() << " _widec;\n";
273         }
274
275         if ( cgd->hasEnd ) {
276                 outLabelUsed = true;
277                 out << 
278                         "       if ( " << P() << " == " << PE() << " )\n"
279                         "               goto _out;\n";
280         }
281
282         out << "_resume:\n";
283
284         if ( redFsm->errState != 0 ) {
285                 outLabelUsed = true;
286                 out << 
287                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
288                         "               goto _out;\n";
289         }
290
291         if ( anyFromStateActions() ) {
292                 out <<
293                         "       switch ( " << FSA() << "[" << CS() << "] ) {\n";
294                         FROM_STATE_ACTION_SWITCH();
295                         SWITCH_DEFAULT() <<
296                         "       }\n"
297                         "\n";
298         }
299
300         if ( anyConditions() )
301                 COND_TRANSLATE();
302
303         LOCATE_TRANS();
304         
305         if ( anyRegCurStateRef() )
306                 out << "        _ps = " << CS() << ";\n";
307
308         out << 
309                 "       " << CS() << " = " << TT() << "[_trans];\n\n";
310
311         if ( anyRegActions() ) {
312                 out << 
313                         "       if ( " << TA() << "[_trans] == 0 )\n"
314                         "               goto _again;\n"
315                         "\n"
316                         "       switch ( " << TA() << "[_trans] ) {\n";
317                         ACTION_SWITCH();
318                         SWITCH_DEFAULT() <<
319                         "       }\n"
320                         "\n";
321         }
322
323         if ( anyRegActions() || anyActionGotos() || anyActionCalls() || anyActionRets() )
324                 out << "_again:\n";
325
326         if ( anyToStateActions() ) {
327                 out <<
328                         "       switch ( " << TSA() << "[" << CS() << "] ) {\n";
329                         TO_STATE_ACTION_SWITCH();
330                         SWITCH_DEFAULT() <<
331                         "       }\n"
332                         "\n";
333         }
334
335         if ( cgd->hasEnd ) {
336                 out << 
337                         "       if ( ++" << P() << " != " << PE() << " )\n"
338                         "               goto _resume;\n";
339         }
340         else {
341                 out << 
342                         "       " << P() << " += 1;\n"
343                         "       goto _resume;\n";
344         }
345
346         if ( outLabelUsed )
347                 out << "        _out: {}\n";
348
349         out << "        }\n";
350 }
351
352 void FFlatCodeGen::writeOutEOF()
353 {
354         if ( anyEofActions() ) {
355                 out <<
356                         "       {\n"
357                         "       switch ( " << EA() << "[" << CS() << "] ) {\n";
358                         EOF_ACTION_SWITCH();
359                         SWITCH_DEFAULT() <<
360                         "       }\n"
361                         "       }\n"
362                         "\n";
363         }
364 }