removed unused case
[ragel.git] / rlgen-dot / gvdotgen.cpp
blob631f3cb21d72bd17300c1b5071bb1019f79e6ffa
1 /*
2 * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
3 */
5 /* This file is part of Ragel.
7 * Ragel is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * Ragel is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Ragel; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "rlgen-dot.h"
23 #include "gvdotgen.h"
24 #include "gendata.h"
26 using namespace std;
28 void lineDirective( ostream &out, char *fileName, int line )
32 void genLineDirective( ostream &out )
36 /* Override this so that write statement processing is ignored */
37 void GraphvizDotGen::writeStatement( InputLoc &, int, char ** )
41 std::ostream &GraphvizDotGen::KEY( Key key )
43 if ( displayPrintables && key.isPrintable() ) {
44 // Output values as characters, ensuring we escape the quote (") character
45 char cVal = (char) key.getVal();
46 switch ( cVal ) {
47 case '"': case '\\':
48 out << "'\\" << cVal << "'";
49 break;
50 case '\a':
51 out << "'\\\\a'";
52 break;
53 case '\b':
54 out << "'\\\\b'";
55 break;
56 case '\t':
57 out << "'\\\\t'";
58 break;
59 case '\n':
60 out << "'\\\\n'";
61 break;
62 case '\v':
63 out << "'\\\\v'";
64 break;
65 case '\f':
66 out << "'\\\\f'";
67 break;
68 case '\r':
69 out << "'\\\\r'";
70 break;
71 case ' ':
72 out << "SP";
73 break;
74 default:
75 out << "'" << cVal << "'";
76 break;
79 else {
80 if ( keyOps->isSigned )
81 out << key.getVal();
82 else
83 out << (unsigned long) key.getVal();
86 return out;
89 std::ostream &GraphvizDotGen::TRANS_ACTION( RedStateAp *fromState, RedTransAp *trans )
91 int n = 0;
92 RedAction *actions[3];
94 if ( fromState->fromStateAction != 0 )
95 actions[n++] = fromState->fromStateAction;
96 if ( trans->action != 0 )
97 actions[n++] = trans->action;
98 if ( trans->targ != 0 && trans->targ->toStateAction != 0 )
99 actions[n++] = trans->targ->toStateAction;
101 if ( n > 0 )
102 out << " / ";
104 /* Loop the existing actions and write out what's there. */
105 for ( int a = 0; a < n; a++ ) {
106 for ( ActionTable::Iter actIt = actions[a]->key.first(); actIt.lte(); actIt++ ) {
107 Action *action = actIt->value;
108 out << action->nameOrLoc();
109 if ( a < n-1 || !actIt.last() )
110 out << ", ";
113 return out;
116 std::ostream &GraphvizDotGen::ACTION( RedAction *action )
118 /* The action. */
119 out << " / ";
120 for ( ActionTable::Iter actIt = action->key.first(); actIt.lte(); actIt++ ) {
121 Action *action = actIt->value;
122 if ( action->name != 0 )
123 out << action->name;
124 else
125 out << action->loc.line << ":" << action->loc.col;
126 if ( !actIt.last() )
127 out << ", ";
129 return out;
132 std::ostream &GraphvizDotGen::ONCHAR( Key lowKey, Key highKey )
134 if ( lowKey > keyOps->maxKey ) {
135 CondSpace *condSpace = findCondSpace( lowKey, highKey );
136 Key values = ( lowKey - condSpace->baseKey ) / keyOps->alphSize();
138 lowKey = keyOps->minKey +
139 (lowKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
140 highKey = keyOps->minKey +
141 (highKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
142 KEY( lowKey );
143 if ( lowKey != highKey ) {
144 out << "..";
145 KEY( highKey );
147 out << "(";
149 for ( CondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
150 bool set = values & (1 << csi.pos());
151 if ( !set )
152 out << "!";
153 out << (*csi)->nameOrLoc();
154 if ( !csi.last() )
155 out << ", ";
157 out << ")";
159 else {
160 /* Output the key. Possibly a range. */
161 KEY( lowKey );
162 if ( highKey != lowKey ) {
163 out << "..";
164 KEY( highKey );
167 return out;
170 void GraphvizDotGen::writeTransList( RedStateAp *state )
172 /* Build the set of unique transitions out of this state. */
173 RedTransSet stTransSet;
174 for ( RedTransList::Iter tel = state->outRange; tel.lte(); tel++ ) {
175 /* If we haven't seen the transitions before, the move forward
176 * emitting all the transitions on the same character. */
177 if ( stTransSet.insert( tel->value ) ) {
178 /* Write out the from and to states. */
179 out << "\t" << state->id << " -> ";
181 if ( tel->value->targ == 0 )
182 out << "err_" << state->id;
183 else
184 out << tel->value->targ->id;
186 /* Begin the label. */
187 out << " [ label = \"";
188 ONCHAR( tel->lowKey, tel->highKey );
190 /* Walk the transition list, finding the same. */
191 for ( RedTransList::Iter mtel = tel.next(); mtel.lte(); mtel++ ) {
192 if ( mtel->value == tel->value ) {
193 out << ", ";
194 ONCHAR( mtel->lowKey, mtel->highKey );
198 /* Write the action and close the transition. */
199 TRANS_ACTION( state, tel->value );
200 out << "\" ];\n";
204 /* Write the default transition. */
205 if ( state->defTrans != 0 ) {
206 /* Write out the from and to states. */
207 out << "\t" << state->id << " -> ";
209 if ( state->defTrans->targ == 0 )
210 out << "err_" << state->id;
211 else
212 out << state->defTrans->targ->id;
214 /* Begin the label. */
215 out << " [ label = \"DEF";
217 /* Write the action and close the transition. */
218 TRANS_ACTION( state, state->defTrans );
219 out << "\" ];\n";
223 void GraphvizDotGen::writeDotFile( )
225 out <<
226 "digraph " << fsmName << " {\n"
227 " rankdir=LR;\n";
229 /* Define the psuedo states. Transitions will be done after the states
230 * have been defined as either final or not final. */
231 out << " node [ shape = point ];\n";
233 if ( redFsm->startState != 0 )
234 out << " ENTRY;\n";
236 /* Psuedo states for entry points in the entry map. */
237 for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
238 RedStateAp *state = allStates + *en;
239 out << " en_" << state->id << ";\n";
242 /* Psuedo states for final states with eof actions. */
243 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
244 if ( st->eofTrans != 0 && st->eofTrans->action != 0 )
245 out << " eof_" << st->id << ";\n";
246 if ( st->eofAction != 0 )
247 out << " eof_" << st->id << ";\n";
250 out << " node [ shape = circle, height = 0.2 ];\n";
252 /* Psuedo states for states whose default actions go to error. */
253 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
254 bool needsErr = false;
255 if ( st->defTrans != 0 && st->defTrans->targ == 0 )
256 needsErr = true;
257 else {
258 for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) {
259 if ( tel->value->targ == 0 ) {
260 needsErr = true;
261 break;
266 if ( needsErr )
267 out << " err_" << st->id << " [ label=\"\"];\n";
270 /* Attributes common to all nodes, plus double circle for final states. */
271 out << " node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n";
273 /* List Final states. */
274 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
275 if ( st->isFinal )
276 out << " " << st->id << ";\n";
279 /* List transitions. */
280 out << " node [ shape = circle ];\n";
282 /* Walk the states. */
283 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
284 writeTransList( st );
286 /* Transitions into the start state. */
287 if ( redFsm->startState != 0 )
288 out << " ENTRY -> " << redFsm->startState->id << " [ label = \"IN\" ];\n";
290 /* Transitions into the entry points. */
291 for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
292 RedStateAp *state = allStates + *en;
293 char *name = entryPointNames[en.pos()];
294 out << " en_" << state->id << " -> " << state->id <<
295 " [ label = \"" << name << "\" ];\n";
298 /* Out action transitions. */
299 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
300 if ( st->eofTrans != 0 && st->eofTrans->action != 0 ) {
301 out << " " << st->id << " -> eof_" <<
302 st->id << " [ label = \"EOF";
303 ACTION( st->eofTrans->action ) << "\" ];\n";
305 if ( st->eofAction != 0 ) {
306 out << " " << st->id << " -> eof_" <<
307 st->id << " [ label = \"EOF";
308 ACTION( st->eofAction ) << "\" ];\n";
312 out <<
313 "}\n";
316 void GraphvizDotGen::finishRagelDef()
318 if ( !graphvizDone ) {
319 graphvizDone = true;
321 /* For dot file generation we want to pick default transitions. */
322 redFsm->chooseDefaultSpan();
324 /* Write out with it. */
325 writeDotFile();