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