2 * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca>
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
23 #include "rlcodegen.h"
30 GraphvizDotGen::GraphvizDotGen( char *fsmName, CodeGenData *cgd,
31 RedFsmAp *redFsm, ostream &out )
40 std::ostream &GraphvizDotGen::KEY( Key key )
42 if ( printPrintables && key.isPrintable() ) {
43 // Output values as characters, ensuring we escape the quote (") character
44 char cVal = (char) key.getVal();
57 if ( keyOps->isSigned )
60 out << (unsigned long) key.getVal();
66 std::ostream &GraphvizDotGen::TRANS_ACTION( RedStateAp *fromState, RedTransAp *trans )
69 RedAction *actions[3];
71 if ( fromState->fromStateAction != 0 )
72 actions[n++] = fromState->fromStateAction;
73 if ( trans->action != 0 )
74 actions[n++] = trans->action;
75 if ( trans->targ != 0 && trans->targ->toStateAction != 0 )
76 actions[n++] = trans->targ->toStateAction;
81 /* Loop the existing actions and write out what's there. */
82 for ( int a = 0; a < n; a++ ) {
83 for ( ActionTable::Iter actIt = actions[a]->key.first(); actIt.lte(); actIt++ ) {
84 Action *action = actIt->value;
85 out << action->nameOrLoc();
86 if ( a < n-1 || !actIt.last() )
93 std::ostream &GraphvizDotGen::ACTION( RedAction *action )
97 for ( ActionTable::Iter actIt = action->key.first(); actIt.lte(); actIt++ ) {
98 Action *action = actIt->value;
99 if ( action->name != 0 )
102 out << action->loc.line << ":" << action->loc.col;
109 std::ostream &GraphvizDotGen::ONCHAR( Key lowKey, Key highKey )
111 if ( lowKey > keyOps->maxKey ) {
112 CondSpace *condSpace = cgd->findCondSpace( lowKey, highKey );
113 Key values = ( lowKey - condSpace->baseKey ) / keyOps->alphSize();
115 lowKey = keyOps->minKey +
116 (lowKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
117 highKey = keyOps->minKey +
118 (highKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
120 if ( lowKey != highKey ) {
126 for ( CondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
127 bool set = values & (1 << csi.pos());
130 out << (*csi)->nameOrLoc();
137 /* Output the key. Possibly a range. */
139 if ( highKey != lowKey ) {
147 void GraphvizDotGen::writeTransList( RedStateAp *state )
149 /* Build the set of unique transitions out of this state. */
150 RedTransSet stTransSet;
151 for ( RedTransList::Iter tel = state->outRange; tel.lte(); tel++ ) {
152 /* If we haven't seen the transitions before, the move forward
153 * emitting all the transitions on the same character. */
154 if ( stTransSet.insert( tel->value ) ) {
155 /* Write out the from and to states. */
156 out << "\t" << state->id << " -> ";
158 if ( tel->value->targ == 0 )
159 out << "err_" << state->id;
161 out << tel->value->targ->id;
163 /* Begin the label. */
164 out << " [ label = \"";
165 ONCHAR( tel->lowKey, tel->highKey );
167 /* Walk the transition list, finding the same. */
168 for ( RedTransList::Iter mtel = tel.next(); mtel.lte(); mtel++ ) {
169 if ( mtel->value == tel->value ) {
171 ONCHAR( mtel->lowKey, mtel->highKey );
175 /* Write the action and close the transition. */
176 TRANS_ACTION( state, tel->value );
181 /* Write the default transition. */
182 if ( state->defTrans != 0 ) {
183 /* Write out the from and to states. */
184 out << "\t" << state->id << " -> ";
186 if ( state->defTrans->targ == 0 )
187 out << "err_" << state->id;
189 out << state->defTrans->targ->id;
191 /* Begin the label. */
192 out << " [ label = \"DEF";
194 /* Write the action and close the transition. */
195 TRANS_ACTION( state, state->defTrans );
200 void GraphvizDotGen::writeDotFile( )
203 "digraph " << fsmName << " {\n"
206 /* Define the psuedo states. Transitions will be done after the states
207 * have been defined as either final or not final. */
208 out << " node [ shape = point ];\n";
211 /* Psuedo states for entry points in the entry map. */
212 for ( EntryIdVect::Iter en = cgd->entryPointIds; en.lte(); en++ ) {
213 RedStateAp *state = cgd->allStates + *en;
214 out << " en_" << state->id << ";\n";
217 /* Psuedo states for final states with eof actions. */
218 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
219 if ( st->eofAction != 0 )
220 out << " eof_" << st->id << ";\n";
223 out << " node [ shape = circle, height = 0.2 ];\n";
225 /* Psuedo states for states whose default actions go to error. */
226 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
227 bool needsErr = false;
228 if ( st->defTrans != 0 && st->defTrans->targ == 0 )
231 for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) {
232 if ( tel->value->targ == 0 ) {
240 out << " err_" << st->id << " [ label=\"\"];\n";
243 /* Attributes common to all nodes, plus double circle for final states. */
244 out << " node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n";
246 /* List Final states. */
247 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
249 out << " " << st->id << ";\n";
252 /* List transitions. */
253 out << " node [ shape = circle ];\n";
255 /* Walk the states. */
256 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
257 writeTransList( st );
259 /* Transitions into the start state. */
260 out << " ENTRY -> " << redFsm->startState->id << " [ label = \"IN";
263 /* Transitions into the entry points. */
264 for ( EntryIdVect::Iter en = cgd->entryPointIds; en.lte(); en++ ) {
265 RedStateAp *state = cgd->allStates + *en;
266 char *name = cgd->entryPointNames[en.pos()];
267 out << " en_" << state->id << " -> " << state->id <<
268 " [ label = \"" << name << "\" ];\n";
271 /* Out action transitions. */
272 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
273 if ( st->eofAction != 0 ) {
274 out << " " << st->id << " -> eof_" <<
275 st->id << " [ label = \"EOF";
276 ACTION( st->eofAction ) << "\" ];\n";