summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2009-02-08 23:38:50 +0000
committerAdrian Thurston <thurston@complang.org>2009-02-08 23:38:50 +0000
commitba86e1650f475034ef4ae4d03da4a5f17b81830b (patch)
tree20fc6be1bd0aa09c3cd70d27d99c1577ce20de76
parent29a5bbb93eb3cccc042e2b0987d728ccd74488a1 (diff)
downloadcolm-ba86e1650f475034ef4ae4d03da4a5f17b81830b.tar.gz
got graphviz output working
-rw-r--r--colm/colm.h4
-rw-r--r--colm/dotgen.cpp310
-rw-r--r--colm/fsmcodegen.cpp1
-rw-r--r--colm/main.cpp29
-rw-r--r--colm/parsedata.cpp11
-rw-r--r--colm/parsedata.h11
6 files changed, 62 insertions, 304 deletions
diff --git a/colm/colm.h b/colm/colm.h
index b3a99e0d..721529bd 100644
--- a/colm/colm.h
+++ b/colm/colm.h
@@ -35,9 +35,7 @@
#define PROGNAME "colm"
/* IO filenames and stream. */
-extern bool printPrintables;
-extern bool graphvizDone;
-
+extern bool genGraphviz;
extern int gblErrorCount;
std::ostream &error();
diff --git a/colm/dotgen.cpp b/colm/dotgen.cpp
index fd8af6b8..2fd9bf09 100644
--- a/colm/dotgen.cpp
+++ b/colm/dotgen.cpp
@@ -20,272 +20,13 @@
*/
-#include "dotgen.h"
+#include "colm.h"
#include "parsedata.h"
-#include "pdacodegen.h"
using namespace std;
-#if 0
-std::ostream &GraphvizDotGen::KEY( Key key )
-{
- if ( printPrintables && key.isPrintable() ) {
- // Output values as characters, ensuring we escape the quote (") character
- char cVal = (char) key.getVal();
- out << "'";
- switch ( cVal ) {
- case '"': case '\\':
- out << "\\" << cVal;
- break;
- default:
- out << cVal;
- break;
- }
- out << "'";
- }
- else {
- if ( keyOps->isSigned )
- out << key.getVal();
- else
- out << (unsigned long) key.getVal();
- }
-
- return out;
-}
-
-std::ostream &GraphvizDotGen::TRANS_ACTION( RedState *fromState, RedTrans *trans )
-{
- int n = 0;
- RedAction *actions[3];
-
- if ( fromState->fromStateAction != 0 )
- actions[n++] = fromState->fromStateAction;
- if ( trans->action != 0 )
- actions[n++] = trans->action;
- if ( trans->targ != 0 && trans->targ->toStateAction != 0 )
- actions[n++] = trans->targ->toStateAction;
-
- if ( n > 0 )
- out << " / ";
-
- /* Loop the existing actions and write out what's there. */
- for ( int a = 0; a < n; a++ ) {
- for ( GenActionTable::Iter actIt = actions[a]->key.first(); actIt.lte(); actIt++ ) {
- GenAction *action = actIt->value;
- out << action->nameOrLoc();
- if ( a < n-1 || !actIt.last() )
- out << ", ";
- }
- }
- return out;
-}
-
-std::ostream &GraphvizDotGen::ACTION( RedAction *action )
-{
- /* The action. */
- out << " / ";
- for ( GenActionTable::Iter actIt = action->key.first(); actIt.lte(); actIt++ ) {
- GenAction *action = actIt->value;
- if ( action->name != 0 )
- out << action->name;
- else
- out << action->loc.line << ":" << action->loc.col;
- if ( !actIt.last() )
- out << ", ";
- }
- return out;
-}
-
-std::ostream &GraphvizDotGen::ONCHAR( Key lowKey, Key highKey )
-{
- if ( lowKey > keyOps->maxKey ) {
- GenCondSpace *condSpace = redFsm->findCondSpace( lowKey, highKey );
- Key values = ( lowKey - condSpace->baseKey ) / keyOps->alphSize();
-
- lowKey = keyOps->minKey +
- (lowKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
- highKey = keyOps->minKey +
- (highKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
- KEY( lowKey );
- if ( lowKey != highKey ) {
- out << "..";
- KEY( highKey );
- }
- out << "(";
-
- for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
- bool set = values & (1 << csi.pos());
- if ( !set )
- out << "!";
- out << (*csi)->nameOrLoc();
- if ( !csi.last() )
- out << ", ";
- }
- out << ")";
- }
- else {
- /* Output the key. Possibly a range. */
- KEY( lowKey );
- if ( highKey != lowKey ) {
- out << "..";
- KEY( highKey );
- }
- }
- return out;
-}
-
-void GraphvizDotGen::writeTransList( RedState *state )
-{
- /* Build the set of unique transitions out of this state. */
- RedTransPtrSet stTransSet;
- for ( RedTransList::Iter tel = state->outRange; tel.lte(); tel++ ) {
- /* If we haven't seen the transitions before, the move forward
- * emitting all the transitions on the same character. */
- if ( stTransSet.insert( tel->value ) ) {
- /* Write out the from and to states. */
- out << "\t" << state->id << " -> ";
-
- if ( tel->value->targ == 0 )
- out << "err_" << state->id;
- else
- out << tel->value->targ->id;
-
- /* Begin the label. */
- out << " [ label = \"";
- ONCHAR( tel->lowKey, tel->highKey );
-
- /* Walk the transition list, finding the same. */
- for ( RedTransList::Iter mtel = tel.next(); mtel.lte(); mtel++ ) {
- if ( mtel->value == tel->value ) {
- out << ", ";
- ONCHAR( mtel->lowKey, mtel->highKey );
- }
- }
-
- /* Write the action and close the transition. */
- TRANS_ACTION( state, tel->value );
- out << "\" ];\n";
- }
- }
-
- /* Write the default transition. */
- if ( state->defTrans != 0 ) {
- /* Write out the from and to states. */
- out << "\t" << state->id << " -> ";
-
- if ( state->defTrans->targ == 0 )
- out << "err_" << state->id;
- else
- out << state->defTrans->targ->id;
-
- /* Begin the label. */
- out << " [ label = \"DEF";
-
- /* Write the action and close the transition. */
- TRANS_ACTION( state, state->defTrans );
- out << "\" ];\n";
- }
-}
-void GraphvizDotGen::writeDotFile( )
-{
- out <<
- "digraph " << fsmName << " {\n"
- " rankdir=LR;\n";
-
- /* Define the psuedo states. Transitions will be done after the states
- * have been defined as either final or not final. */
- out << " node [ shape = point ];\n";
- out << " ENTRY;\n";
-
- /* Psuedo states for entry points in the entry map. */
- for ( EntryIdVect::Iter en = redFsm->entryPointIds; en.lte(); en++ ) {
- RedState *state = redFsm->allStates + *en;
- out << " en_" << state->id << ";\n";
- }
-
- /* Psuedo states for final states with eof actions. */
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
- if ( st->eofAction != 0 )
- out << " eof_" << st->id << ";\n";
- }
-
- out << " node [ shape = circle, height = 0.2 ];\n";
-
- /* Psuedo states for states whose default actions go to error. */
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
- bool needsErr = false;
- if ( st->defTrans != 0 && st->defTrans->targ == 0 )
- needsErr = true;
- else {
- for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) {
- if ( tel->value->targ == 0 ) {
- needsErr = true;
- break;
- }
- }
- }
-
- if ( needsErr )
- out << " err_" << st->id << " [ label=\"\"];\n";
- }
-
- /* Attributes common to all nodes, plus double circle for final states. */
- out << " node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n";
-
- /* List Final states. */
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
- if ( st->isFinal )
- out << " " << st->id << ";\n";
- }
-
- /* List transitions. */
- out << " node [ shape = circle ];\n";
-
- /* Walk the states. */
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
- writeTransList( st );
-
- /* Transitions into the start state. */
- out << " ENTRY -> " << redFsm->startState->id << " [ label = \"IN";
- out << "\" ];\n";
-
- /* Transitions into the entry points. */
- for ( EntryIdVect::Iter en = redFsm->entryPointIds; en.lte(); en++ ) {
- RedState *state = redFsm->allStates + *en;
- char *name = redFsm->entryPointNames[en.pos()];
- out << " en_" << state->id << " -> " << state->id <<
- " [ label = \"" << name << "\" ];\n";
- }
-
- /* Out action transitions. */
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
- if ( st->eofAction != 0 ) {
- out << " " << st->id << " -> eof_" <<
- st->id << " [ label = \"EOF";
- ACTION( st->eofAction ) << "\" ];\n";
- }
- }
-
- out <<
- "}\n";
-}
-
-void GraphvizDotGen::finishRagelDef()
-{
- if ( !graphvizDone ) {
- graphvizDone = true;
-
- /* For dot file generation we want to pick default transitions. */
- redFsm->chooseDefaultSpan();
-
- /* Write out with it. */
- writeDotFile();
- }
-}
-
-
-void PdaCodeGen::writeTransList( PdaState *state )
+void ParseData::writeTransList( PdaState *state )
{
for ( TransMap::Iter trans = state->transMap; trans.lte(); trans++ ) {
/* Write out the from and to states. */
@@ -294,9 +35,9 @@ void PdaCodeGen::writeTransList( PdaState *state )
/* Begin the label. */
out << " [ label = \"";
long key = trans->key;
- KlangEl *lel = pd->langElIndex[key];
+ KlangEl *lel = langElIndex[key];
if ( lel != 0 )
- out << lel->data;
+ out << lel->name;
else
out << (char)key;
@@ -308,12 +49,12 @@ void PdaCodeGen::writeTransList( PdaState *state )
out << "S(" << trans->value->actOrds[act.pos()] << ")";
break;
case 2: {
- out << "R(" << pd->prodIdIndex[(*act >> 2)]->data <<
+ out << "R(" << prodIdIndex[(*act >> 2)]->data <<
", " << trans->value->actOrds[act.pos()] << ")";
break;
}
case 3: {
- out << "SR(" << pd->prodIdIndex[(*act >> 2)]->data <<
+ out << "SR(" << prodIdIndex[(*act >> 2)]->data <<
", " << trans->value->actOrds[act.pos()] << ")";
break;
}}
@@ -326,44 +67,45 @@ void PdaCodeGen::writeTransList( PdaState *state )
}
}
-void PdaCodeGen::writeDotFile( PdaGraph *graph )
+void ParseData::writeDotFile( PdaGraph *graph )
{
out <<
"digraph " << parserName << " {\n"
- " rankdir=LR;\n";
+ " rankdir=LR;\n"
+ " ranksep=\"0\"\n"
+ " nodesep=\"0.25\"\n"
+ "\n";
/* Define the psuedo states. Transitions will be done after the states
* have been defined as either final or not final. */
- out << " node [ shape = point ];\n";
- out << " ENTRY;\n";
-
- out << " node [ shape = circle, height = 0.2 ];\n";
-
- /* Attributes common to all nodes, plus double circle for final states. */
- out << " node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n";
+ out <<
+ " node [ shape = point ];\n"
+ " ENTRY [ label = \"\" ];\n"
+ "\n"
+ " node [ shape = circle, fixedsize = true, height = 0.2 ];\n";
- /* List Final states. */
- for ( PdaStateSet::Iter st = graph->finStateSet; st.lte(); st++ )
- out << " " << (*st)->stateNum << ";\n";
+ /* Walk the states. */
+ for ( PdaStateList::Iter st = graph->stateList; st.lte(); st++ )
+ out << " " << st->stateNum << " [ label = \"\" ];\n";
- /* List transitions. */
- out << " node [ shape = circle ];\n";
+ out << "\n";
/* Walk the states. */
for ( PdaStateList::Iter st = graph->stateList; st.lte(); st++ )
writeTransList( st );
/* Transitions into the start state. */
- out << " ENTRY -> " << graph->startState->stateNum << " [ label = \"START\" ];\n";
+ out << " ENTRY -> " << graph->startState->stateNum << " [ label = \"\" ];\n";
out <<
"}\n";
}
-void PdaCodeGen::writeDotFile( )
+void ParseData::writeDotFile()
{
- writeDotFile( pd->pdaGraph );
+ for ( LelList::Iter lel = langEls; lel.lte(); lel++ ) {
+ if ( lel->parserId >= 0 )
+ writeDotFile( lel->pdaGraph );
+ }
}
-#endif
-
diff --git a/colm/fsmcodegen.cpp b/colm/fsmcodegen.cpp
index 29d840ee..e0eb3d9d 100644
--- a/colm/fsmcodegen.cpp
+++ b/colm/fsmcodegen.cpp
@@ -22,7 +22,6 @@
#include "parsedata.h"
#include "fsmcodegen.h"
#include "redfsm.h"
-#include "dotgen.h"
#include "bstmap.h"
#include "fsmrun.h"
#include <sstream>
diff --git a/colm/main.cpp b/colm/main.cpp
index fd403313..a6170f0d 100644
--- a/colm/main.cpp
+++ b/colm/main.cpp
@@ -37,7 +37,6 @@
#include "vector.h"
#include "version.h"
#include "fsmcodegen.h"
-#include "dotgen.h"
using std::istream;
using std::ifstream;
@@ -49,9 +48,7 @@ using std::cerr;
using std::endl;
/* Graphviz dot file generation. */
-bool graphvizDone = false;
-
-bool printPrintables = false;
+bool genGraphviz = false;
using std::ostream;
using std::istream;
@@ -308,7 +305,7 @@ void compileOutput( const char *argv0 )
void process_args( int argc, const char **argv )
{
- ParamCheck pc( "vlio:S:M:vHh?-:s", argc, argv );
+ ParamCheck pc( "vlio:S:M:vHh?-:sV", argc, argv );
while ( pc.check() ) {
switch ( pc.state ) {
@@ -341,6 +338,9 @@ void process_args( int argc, const char **argv )
case 's':
printStatistics = true;
break;
+ case 'V':
+ generateGraphviz = true;
+ break;
case '-':
if ( strcasecmp(pc.parameterArg, "help") == 0 ) {
usage();
@@ -429,10 +429,21 @@ int main(int argc, const char **argv)
/* Initiate a compile following a parse. */
scanner.parser->pd->semanticAnalysis();
- if ( outStream != 0 )
- delete outStream;
-
- compileOutput( argv[0] );
+ /*
+ * Write output.
+ */
+ if ( generateGraphviz ) {
+ outStream = &cout;
+ scanner.parser->pd->writeDotFile();
+ }
+ else {
+ openOutput();
+ scanner.parser->pd->generateOutput();
+
+ if ( outStream != 0 )
+ delete outStream;
+ compileOutput( argv[0] );
+ }
return 0;
}
diff --git a/colm/parsedata.cpp b/colm/parsedata.cpp
index 1ed0403d..ba7f14cd 100644
--- a/colm/parsedata.cpp
+++ b/colm/parsedata.cpp
@@ -1747,7 +1747,7 @@ void ParseData::semanticAnalysis()
/* Make the reduced fsm. */
RedFsmBuild reduce( sectionName, this, fsmGraph );
- RedFsm *redFsm = reduce.reduceMachine();
+ redFsm = reduce.reduceMachine();
/* Build the parsers used for patterns and replacements. */
makePatternParsers();
@@ -1774,13 +1774,10 @@ void ParseData::semanticAnalysis()
/* Parse patterns and replacements. */
parsePatterns();
+}
- /*
- * Write output.
- */
-
- openOutput();
-
+void ParseData::generateOutput()
+{
FsmCodeGen *fsmGen = new FsmCodeGen("<INPUT>", sectionName,
*outStream, redFsm, fsmTables );
diff --git a/colm/parsedata.h b/colm/parsedata.h
index 9bf464b4..f2c382f5 100644
--- a/colm/parsedata.h
+++ b/colm/parsedata.h
@@ -743,6 +743,15 @@ struct ParseData
void resolveUses();
void createDefaultScanner();
void semanticAnalysis();
+ void generateOutput();
+
+ /*
+ * Graphviz Generation
+ */
+ void writeTransList( PdaState *state );
+ void writeDotFile( PdaGraph *graph );
+ void writeDotFile( );
+
/*
* Data collected during the parse.
@@ -885,6 +894,8 @@ struct ParseData
ObjFieldMap *objFieldMap;
bool revertOn;
+
+ RedFsm *redFsm;
};
void afterOpMinimize( FsmGraph *fsm, bool lastInSeq = true );