{
scan_error() << "unknown write command" << endl;
}
- output << "<write def_name=\"" << parser->sectionName <<
- "\" what=\"" << tokdata << "\">";
+
+ if ( machineSpec == 0 && machineName == 0 ) {
+ output << "<write def_name=\"" << parser->sectionName <<
+ "\" what=\"" << tokdata << "\">";
+ }
}
}
}
action write_close
{
- if ( active )
+ if ( active && machineSpec == 0 && machineName == 0 )
output << "</write>\n";
}
codeGen->fileName = fileName;
codeGen->fsmName = fsmName;
codeGen->wantComplete = wantComplete;
- codeGen->codeGen = codeGen;
return codeGen;
}
analyzeMachine();
/* Determine if we should use indicies. */
- codeGen->calcIndexSize();
+ calcIndexSize();
}
-void FsmCodeGen::generateGraphviz()
+void FsmCodeGen::finishRagelDef()
{
- /* Do ordering and choose state ids. */
- redFsm->depthFirstOrdering();
- redFsm->sequentialStateIds();
-
- /* For dot file generation we want to pick default transitions. */
- redFsm->chooseDefaultSpan();
+ if ( outputFormat == OutCode ) {
+ prepareMachine();
+ }
+ else if ( outputFormat == OutGraphvizDot && !graphvizDone ) {
+ graphvizDone = true;
- /* Make the generator. */
- GraphvizDotGen dotGen( fsmName, this, redFsm, out );
+ /* Do ordering and choose state ids. */
+ redFsm->depthFirstOrdering();
+ redFsm->sequentialStateIds();
- /* Write out with it. */
- dotGen.writeDotFile();
-}
+ /* For dot file generation we want to pick default transitions. */
+ redFsm->chooseDefaultSpan();
-void FsmCodeGen::generateCode()
-{
- if ( writeOps & WO_NOEND )
- hasEnd = false;
+ /* Make the generator. */
+ GraphvizDotGen dotGen( fsmName, this, redFsm, out );
- if ( writeOps & WO_NOERROR )
- writeErr = false;
-
- if ( writeOps & WO_NOPREFIX )
- dataPrefix = false;
-
- if ( writeOps & WO_NOFF )
- writeFirstFinal = false;
+ /* Write out with it. */
+ dotGen.writeDotFile();
+ }
+}
- if ( writeData || writeInit || writeExec || writeEOF ) {
- prepareMachine();
+void FsmCodeGen::writeStatement( char *what, int nopts, char **options )
+{
+ /* Read the options. FIXME: These should be parsed according to each
+ * particualr function below. */
+ for ( int i = 0; i < nopts; i++ ) {
+ if ( strcmp( options[i], "noend" ) == 0 )
+ hasEnd = false;
+ else if ( strcmp( options[i], "noerror" ) == 0 )
+ writeErr = false;
+ else if ( strcmp( options[i], "noprefix" ) == 0 )
+ dataPrefix = false;
+ else if ( strcmp( options[i], "nofinal" ) == 0 )
+ writeFirstFinal = false;
+ else {
+ //warning($1->loc) << "unrecognized write option" << endl;
+ }
+ }
+ if ( outputFormat == OutCode ) {
/* Force a newline. */
out << "\n";
genLineDirective( out );
- }
-
-
- if ( writeExec ) {
- /* Must set labels immediately before writing because we may depend
- * on the noend write option. */
- codeGen->setLabelsNeeded();
- }
- if ( writeData )
- codeGen->writeOutData();
-
- if ( writeInit )
- codeGen->writeOutInit();
-
- if ( writeExec )
- codeGen->writeOutExec();
-
- if ( writeEOF )
- codeGen->writeOutEOF();
-}
-
-void FsmCodeGen::generate()
-{
- if ( redFsm != 0 ) {
- if ( outputFormat == OutCode )
- generateCode();
- else if ( outputFormat == OutGraphvizDot && !graphvizDone ) {
- graphvizDone = true;
- generateGraphviz();
+ if ( strcmp( what, "data" ) == 0 ) {
+ writeOutData();
+ }
+ else if ( strcmp( what, "init" ) == 0 ) {
+ writeOutInit();
+ }
+ else if ( strcmp( what, "exec" ) == 0 ) {
+ /* Must set labels immediately before writing because we may depend
+ * on the noend write option. */
+ setLabelsNeeded();
+ writeOutExec();
+ }
+ else if ( strcmp( what, "eof" ) == 0 ) {
+ writeOutEOF();
+ }
+ else {
+ /* EMIT An error here. */
}
}
}
-
bool useIndicies;
public:
- void generateGraphviz();
void prepareMachine();
- void generateCode();
- virtual void generate();
+ virtual void finishRagelDef();
+ void writeStatement( char *what, int nopts, char **options );
/* Determine if we should use indicies. */
virtual void calcIndexSize() {}
getKeyExpr(0),
accessExpr(0),
curStateExpr(0),
- codeGen(0),
wantComplete(0),
- writeOps(0),
- writeData(false),
- writeInit(false),
- writeExec(false),
- writeEOF(false),
hasLongestMatch(false),
hasEnd(true),
dataPrefix(true),
}
}
-
-void CodeGenData::finishMachine()
+void CodeGenData::closeMachine()
{
if ( redFsm->forcedErrorState )
redFsm->getErrorState();
* state a default transition. All machines break out of the processing
* loop when in the error state. */
- if ( codeStyle == GenGoto || codeStyle == GenFGoto || codeStyle == GenIpGoto ) {
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
- for ( StateCondList::Iter sci = st->stateCondList; sci.lte(); sci++ )
- st->stateCondVect.append( sci );
- }
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ for ( StateCondList::Iter sci = st->stateCondList; sci.lte(); sci++ )
+ st->stateCondVect.append( sci );
}
}
typedef AvlMap<char *, CodeGenData*, CmpStr> CodeGenMap;
typedef AvlMapEl<char *, CodeGenData*> CodeGenMapEl;
-#define WO_NOEND 0x01
-#define WO_NOERROR 0x02
-#define WO_NOPREFIX 0x04
-#define WO_NOFF 0x08
-
struct CodeGenData
{
CodeGenData( ostream &out );
InlineList *getKeyExpr;
InlineList *accessExpr;
InlineList *curStateExpr;
- FsmCodeGen *codeGen;
KeyOps thisKeyOps;
bool wantComplete;
- int writeOps;
- bool writeData;
- bool writeInit;
- bool writeExec;
- bool writeEOF;
EntryIdVect entryPointIds;
EntryNameVect entryPointNames;
bool hasLongestMatch;
void finishTransList( int snum );
void setStateActions( int snum, long toStateAction,
long fromStateAction, long eofAction );
- void finishMachine();
void setForcedErrorState()
{ redFsm->forcedErrorState = true; }
+
void initCondSpaceList( ulong length );
void condSpaceItem( int cnum, long condActionId );
void findFinalActionRefs();
void analyzeMachine();
+ void closeMachine();
void setValueLimits();
void assignActionIds();
void prepareMachine();
bool hasBeenPrepared;
/* The interface to the code generator. */
- virtual void generate() {}
+ virtual void finishRagelDef() {}
+ virtual void writeStatement( char *what, int nopts, char **options ) {}
};
void lineDirective( ostream &out, char *fileName, int line );
CodeGenData *cgd;
CodeGenMap codeGenMap;
+
+ Vector <char*> writeOptions;
};
%% write token_defs;
*outStream << $3->tag->content;
};
-ragel_def: tag_ragel_def_head ragel_def_item_list '/' TAG_ragel_def;
+ragel_def:
+ tag_ragel_def_head ragel_def_item_list '/' TAG_ragel_def
+ final {
+ cgd->finishRagelDef();
+ };
tag_ragel_def_head: TAG_ragel_def
final {
error($1->loc) << "tag <write> requires a what attribute" << endl;
}
else {
- if ( strcmp( what->value, "data" ) == 0 )
- cgd->writeData = true;
- else if ( strcmp( what->value, "init" ) == 0 )
- cgd->writeInit = true;
- else if ( strcmp( what->value, "exec" ) == 0 )
- cgd->writeExec = true;
- else if ( strcmp( what->value, "eof" ) == 0 )
- cgd->writeEOF = true;
-
- if ( gblErrorCount == 0 )
- cgd->generate();
+ writeOptions.append(0);
+ cgd->writeStatement( what->value, writeOptions.length()-1, writeOptions.data );
+ writeOptions.empty();
}
};
cgd = mapEl->value;
}
- cgd->writeData = false;
- cgd->writeInit = false;
- cgd->writeExec = false;
- cgd->writeEOF = false;
::keyOps = &cgd->thisKeyOps;
$$->tag = $1->tag;
write_option_list: write_option_list tag_option;
write_option_list: ;
+nonterm tag_option
+{
+ char *option;
+};
+
tag_option: TAG_option '/' TAG_option
final {
- char *content = $3->tag->content;
- if ( strcmp( content, "noend" ) == 0 )
- cgd->writeOps |= WO_NOEND;
- else if ( strcmp( content, "noerror" ) == 0 )
- cgd->writeOps |= WO_NOERROR;
- else if ( strcmp( content, "noprefix" ) == 0 )
- cgd->writeOps |= WO_NOPREFIX;
- else if ( strcmp( content, "nofinal" ) == 0 )
- cgd->writeOps |= WO_NOFF;
- else {
- warning($1->loc) << "unrecognized write option" << endl;
- }
+ writeOptions.append( $3->tag->content );
};
tag_machine: tag_machine_head machine_item_list '/' TAG_machine
final {
- cgd->finishMachine();
+ cgd->closeMachine();
};
tag_machine_head: TAG_machine