1 /*
2 * Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
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 "ragel.h"
25 #include "gofgoto.h"
26 #include "redfsm.h"
27 #include "gendata.h"
28 #include "bstmap.h"
29
30 using std::endl;
31
EXEC_ACTIONS()32 std::ostream &GoFGotoCodeGen::EXEC_ACTIONS()
33 {
34 /* Loop the actions. */
35 for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
36 if ( redAct->numTransRefs > 0 ) {
37 /* We are at the start of a glob, write the case. */
38 out << "f" << redAct->actListId << ":" << endl;
39
40 /* Write each action in the list of action items. */
41 for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
42 ACTION( out, item->value, 0, false, false );
43
44 out << TABS(1) << "goto _again" << endl;
45 }
46 }
47 return out;
48 }
49
50 /* Write out the function switch. This switch is keyed on the values
51 * of the func index. */
TO_STATE_ACTION_SWITCH(int level)52 std::ostream &GoFGotoCodeGen::TO_STATE_ACTION_SWITCH( int level )
53 {
54 /* Loop the actions. */
55 for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
56 if ( redAct->numToStateRefs > 0 ) {
57 /* Write the entry label. */
58 out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl;
59
60 /* Write each action in the list of action items. */
61 for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
62 ACTION( out, item->value, 0, false, false );
63 }
64 }
65
66 genLineDirective( out );
67 return out;
68 }
69
70 /* Write out the function switch. This switch is keyed on the values
71 * of the func index. */
FROM_STATE_ACTION_SWITCH(int level)72 std::ostream &GoFGotoCodeGen::FROM_STATE_ACTION_SWITCH( int level )
73 {
74 /* Loop the actions. */
75 for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
76 if ( redAct->numFromStateRefs > 0 ) {
77 /* Write the entry label. */
78 out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl;
79
80 /* Write each action in the list of action items. */
81 for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
82 ACTION( out, item->value, 0, false, false );
83 }
84 }
85
86 genLineDirective( out );
87 return out;
88 }
89
EOF_ACTION_SWITCH(int level)90 std::ostream &GoFGotoCodeGen::EOF_ACTION_SWITCH( int level )
91 {
92 /* Loop the actions. */
93 for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
94 if ( redAct->numEofRefs > 0 ) {
95 /* Write the entry label. */
96 out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl;
97
98 /* Write each action in the list of action items. */
99 for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
100 ACTION( out, item->value, 0, true, false );
101 }
102 }
103
104 genLineDirective( out );
105 return out;
106 }
107
108
FINISH_CASES()109 std::ostream &GoFGotoCodeGen::FINISH_CASES()
110 {
111 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
112 /* States that are final and have an out action need a case. */
113 if ( st->eofAction != 0 ) {
114 /* Write the case label. */
115 out << TABS(2) << "case " << st->id << ":" << endl;
116
117 /* Jump to the func. */
118 out << TABS(3) << "goto f" << st->eofAction->actListId << endl;
119 }
120 }
121
122 return out;
123 }
124
TO_STATE_ACTION(RedStateAp * state)125 unsigned int GoFGotoCodeGen::TO_STATE_ACTION( RedStateAp *state )
126 {
127 int act = 0;
128 if ( state->toStateAction != 0 )
129 act = state->toStateAction->actListId+1;
130 return act;
131 }
132
FROM_STATE_ACTION(RedStateAp * state)133 unsigned int GoFGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state )
134 {
135 int act = 0;
136 if ( state->fromStateAction != 0 )
137 act = state->fromStateAction->actListId+1;
138 return act;
139 }
140
EOF_ACTION(RedStateAp * state)141 unsigned int GoFGotoCodeGen::EOF_ACTION( RedStateAp *state )
142 {
143 int act = 0;
144 if ( state->eofAction != 0 )
145 act = state->eofAction->actListId+1;
146 return act;
147 }
148
writeData()149 void GoFGotoCodeGen::writeData()
150 {
151 if ( redFsm->anyToStateActions() ) {
152 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
153 TO_STATE_ACTIONS();
154 CLOSE_ARRAY() <<
155 endl;
156 }
157
158 if ( redFsm->anyFromStateActions() ) {
159 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
160 FROM_STATE_ACTIONS();
161 CLOSE_ARRAY() <<
162 endl;
163 }
164
165 if ( redFsm->anyEofActions() ) {
166 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
167 EOF_ACTIONS();
168 CLOSE_ARRAY() <<
169 endl;
170 }
171
172 STATE_IDS();
173 }
174
writeExec()175 void GoFGotoCodeGen::writeExec()
176 {
177 testEofUsed = false;
178 outLabelUsed = false;
179
180 out << " {" << endl;
181
182 if ( redFsm->anyRegCurStateRef() )
183 out << " var _ps " << INT() << " = 0" << endl;
184
185 if ( redFsm->anyConditions() )
186 out << " var _widec " << WIDE_ALPH_TYPE() << endl;
187
188 if ( !noEnd ) {
189 testEofUsed = true;
190 out <<
191 " if " << P() << " == " << PE() << " {" << endl <<
192 " goto _test_eof" << endl <<
193 " }" << endl;
194 }
195
196 if ( redFsm->errState != 0 ) {
197 outLabelUsed = true;
198 out <<
199 " if " << vCS() << " == " << redFsm->errState->id << " {" << endl <<
200 " goto _out" << endl <<
201 " }" << endl;
202 }
203
204 out << "_resume:" << endl;
205
206 if ( redFsm->anyFromStateActions() ) {
207 out <<
208 " switch " << FSA() << "[" << vCS() << "] {" << endl;
209 FROM_STATE_ACTION_SWITCH(1);
210 out <<
211 " }" << endl <<
212 endl;
213 }
214
215 out <<
216 " switch " << vCS() << " {" << endl;
217 STATE_GOTOS(1);
218 out <<
219 " }" << endl <<
220 endl;
221 TRANSITIONS() <<
222 endl;
223
224 if ( redFsm->anyRegActions() )
225 EXEC_ACTIONS() << endl;
226
227 out << "_again:" << endl;
228
229 if ( redFsm->anyToStateActions() ) {
230 out <<
231 " switch " << TSA() << "[" << vCS() << "] {" << endl;
232 TO_STATE_ACTION_SWITCH(1);
233 out <<
234 " }" << endl <<
235 endl;
236 }
237
238 if ( redFsm->errState != 0 ) {
239 outLabelUsed = true;
240 out <<
241 " if " << vCS() << " == " << redFsm->errState->id << " {" << endl <<
242 " goto _out" << endl <<
243 " }" << endl;
244 }
245
246 if ( !noEnd ) {
247 out <<
248 " if " << P() << "++; " << P() << " != " << PE() << " {" << endl <<
249 " goto _resume" << endl <<
250 " }" << endl;
251 }
252 else {
253 out <<
254 " " << P() << "++" << endl <<
255 " goto _resume" << endl;
256 }
257
258 if ( testEofUsed )
259 out << " _test_eof: {}" << endl;
260
261 if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
262 out <<
263 " if " << P() << " == " << vEOF() << " {" << endl;
264
265 if ( redFsm->anyEofTrans() ) {
266 out <<
267 " switch " << vCS() << " {" << endl;
268
269 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
270 if ( st->eofTrans != 0 )
271 out <<
272 " case " << st->id << ":" << endl <<
273 " goto tr" << st->eofTrans->id << endl;
274 }
275
276 out <<
277 " }" << endl;
278 }
279
280 if ( redFsm->anyEofActions() ) {
281 out <<
282 " switch " << EA() << "[" << vCS() << "] {" << endl;
283 EOF_ACTION_SWITCH(2);
284 out <<
285 " }" << endl;
286 }
287
288 out <<
289 " }" << endl <<
290 endl;
291 }
292
293 if ( outLabelUsed )
294 out << " _out: {}" << endl;
295
296 out << " }" << endl;
297 }
298