The p varialbe is now set up at the beginning of a scanner action, rather than
[external/ragel.git] / rlgen-cd / fgotocodegen.cpp
1 /*
2  *  Copyright 2001-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 "fgotocodegen.h"
26 #include "redfsm.h"
27 #include "gendata.h"
28 #include "bstmap.h"
29
30 std::ostream &FGotoCodeGen::EXEC_ACTIONS()
31 {
32         /* Loop the actions. */
33         for ( ActionTableMap::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 ( ActionTable::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. */
50 std::ostream &FGotoCodeGen::TO_STATE_ACTION_SWITCH()
51 {
52         /* Loop the actions. */
53         for ( ActionTableMap::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 ( ActionTable::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. */
72 std::ostream &FGotoCodeGen::FROM_STATE_ACTION_SWITCH()
73 {
74         /* Loop the actions. */
75         for ( ActionTableMap::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 ( ActionTable::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
92 std::ostream &FGotoCodeGen::EOF_ACTION_SWITCH()
93 {
94         /* Loop the actions. */
95         for ( ActionTableMap::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 ( ActionTable::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
113 std::ostream &FGotoCodeGen::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
129 unsigned int FGotoCodeGen::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
137 unsigned int FGotoCodeGen::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
145 unsigned int FGotoCodeGen::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
153 void FGotoCodeGen::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
179 void FGotoCodeGen::writeExec()
180 {
181         outLabelUsed = false;
182
183         out << "        {\n";
184
185         if ( redFsm->anyRegCurStateRef() )
186                 out << "        int _ps = 0;\n";
187
188         if ( redFsm->anyConditions() )
189                 out << "        " << WIDE_ALPH_TYPE() << " _widec;\n";
190
191         if ( hasEnd ) {
192                 outLabelUsed = true;
193                 out << 
194                         "       if ( " << P() << " == " << PE() << " )\n"
195                         "               goto _out;\n";
196         }
197
198         if ( redFsm->errState != 0 ) {
199                 outLabelUsed = true;
200                 out << 
201                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
202                         "               goto _out;\n";
203         }
204
205         out << "_resume:\n";
206
207         if ( redFsm->anyFromStateActions() ) {
208                 out <<
209                         "       switch ( " << FSA() << "[" << CS() << "] ) {\n";
210                         FROM_STATE_ACTION_SWITCH();
211                         SWITCH_DEFAULT() <<
212                         "       }\n"
213                         "\n";
214         }
215
216         out << 
217                 "       switch ( " << CS() << " ) {\n";
218                 STATE_GOTOS();
219                 SWITCH_DEFAULT() <<
220                 "       }\n"
221                 "\n";
222                 TRANSITIONS() << 
223                 "\n";
224
225         if ( redFsm->anyRegActions() )
226                 EXEC_ACTIONS() << "\n";
227
228         out << "_again:\n";
229
230         if ( redFsm->anyToStateActions() ) {
231                 out <<
232                         "       switch ( " << TSA() << "[" << CS() << "] ) {\n";
233                         TO_STATE_ACTION_SWITCH();
234                         SWITCH_DEFAULT() <<
235                         "       }\n"
236                         "\n";
237         }
238
239         if ( redFsm->errState != 0 ) {
240                 outLabelUsed = true;
241                 out << 
242                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
243                         "               goto _out;\n";
244         }
245
246         if ( hasEnd ) {
247                 out << 
248                         "       if ( ++" << P() << " != " << PE() << " )\n"
249                         "               goto _resume;\n";
250         }
251         else {
252                 out << 
253                         "       " << P() << " += 1;\n"
254                         "       goto _resume;\n";
255         }
256
257
258         if ( outLabelUsed )
259                 out << "        _out: {}\n";
260
261         out << "        }\n";
262 }
263
264 void FGotoCodeGen::writeEOF()
265 {
266         if ( redFsm->anyEofActions() ) {
267                 out <<
268                         "       {\n"
269                         "       switch ( " << EA() << "[" << CS() << "] ) {\n";
270                         EOF_ACTION_SWITCH();
271                         SWITCH_DEFAULT() <<
272                         "       }\n"
273                         "       }\n"
274                         "\n";
275         }
276 }