From 903c852152da7f5381fa4d27ffceb47720a7c8ff Mon Sep 17 00:00:00 2001 From: thurston Date: Mon, 5 Feb 2007 01:31:52 +0000 Subject: [PATCH] The writeStatement function is now part of CodeGenData. Leading code which is common to all finishRagelDef() functions has been moved to the parser class, immediately before calling finishRagelDef(). The setLabelsNeeded() function is now called from writeExec in code generators that require it (in-place goto and split goto). The hasBeenPrepared variable is no longer needed, removed. git-svn-id: http://svn.complang.org/ragel/trunk@78 052ea7fc-9027-0410-9066-f65837a77df0 --- redfsm/gendata.cpp | 73 ++++++++++++++++++++++++++++++++++++++-- redfsm/gendata.h | 25 ++++++++++---- redfsm/xmlparse.kl | 16 +++++++++ rlcodegen/fsmcodegen.cpp | 81 +-------------------------------------------- rlcodegen/fsmcodegen.h | 15 +-------- rlcodegen/ipgotocodegen.cpp | 3 ++ rlcodegen/splitcodegen.cpp | 3 ++ rlgen-java/javacodegen.cpp | 78 +------------------------------------------ rlgen-java/javacodegen.h | 13 +------- rlgen-ruby/rubycodegen.cpp | 78 +------------------------------------------ rlgen-ruby/rubycodegen.h | 15 +++------ 11 files changed, 121 insertions(+), 279 deletions(-) diff --git a/redfsm/gendata.cpp b/redfsm/gendata.cpp index 475af26..a5e90f3 100644 --- a/redfsm/gendata.cpp +++ b/redfsm/gendata.cpp @@ -44,11 +44,11 @@ CodeGenData::CodeGenData( ostream &out ) curStateExpr(0), wantComplete(0), hasLongestMatch(false), + codeGenErrCount(0), hasEnd(true), dataPrefix(true), writeFirstFinal(true), - writeErr(true), - hasBeenPrepared(false) + writeErr(true) {} @@ -636,3 +636,72 @@ void CodeGenData::analyzeMachine() /* Set the maximums of various values used for deciding types. */ setValueLimits(); } + +void CodeGenData::writeStatement( InputLoc &loc, int nargs, char **args ) +{ + /* Force a newline. */ + out << "\n"; + genLineDirective( out ); + + if ( strcmp( args[0], "data" ) == 0 ) { + for ( int i = 1; i < nargs; i++ ) { + if ( strcmp( args[i], "noerror" ) == 0 ) + writeErr = false; + else if ( strcmp( args[i], "noprefix" ) == 0 ) + dataPrefix = false; + else if ( strcmp( args[i], "nofinal" ) == 0 ) + writeFirstFinal = false; + else { + source_warning(loc) << "unrecognized write option \"" << + args[i] << "\"" << endl; + } + } + writeOutData(); + } + else if ( strcmp( args[0], "init" ) == 0 ) { + for ( int i = 1; i < nargs; i++ ) { + source_warning(loc) << "unrecognized write option \"" << + args[i] << "\"" << endl; + } + writeOutInit(); + } + else if ( strcmp( args[0], "exec" ) == 0 ) { + for ( int i = 1; i < nargs; i++ ) { + if ( strcmp( args[i], "noend" ) == 0 ) + hasEnd = false; + else { + source_warning(loc) << "unrecognized write option \"" << + args[i] << "\"" << endl; + } + } + writeOutExec(); + } + else if ( strcmp( args[0], "eof" ) == 0 ) { + for ( int i = 1; i < nargs; i++ ) { + source_warning(loc) << "unrecognized write option \"" << + args[i] << "\"" << endl; + } + writeOutEOF(); + } + else { + /* EMIT An error here. */ + source_error(loc) << "unrecognized write command \"" << + args[0] << "\"" << endl; + } +} + +ostream &CodeGenData::source_warning( const InputLoc &loc ) +{ + cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: "; + return cerr; +} + +ostream &CodeGenData::source_error( const InputLoc &loc ) +{ + codeGenErrCount += 1; + assert( sourceFileName != 0 ); + cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": "; + return cerr; +} + + diff --git a/redfsm/gendata.h b/redfsm/gendata.h index a195dab..facec5f 100644 --- a/redfsm/gendata.h +++ b/redfsm/gendata.h @@ -43,20 +43,34 @@ typedef AvlMapEl CodeGenMapEl; * The interface to the parser */ -/* These two functions must be implemented by the code generation executable. +/* These functions must be implemented by the code generation executable. * The openOutput function is invoked when the root element is opened. The * makeCodeGen function is invoked when a ragel_def element is opened. */ std::ostream *openOutput( char *inputFile ); CodeGenData *makeCodeGen( char *sourceFileName, char *fsmName, ostream &out, bool wantComplete ); +void lineDirective( ostream &out, char *fileName, int line ); +void genLineDirective( ostream &out ); + +/*********************************/ + struct CodeGenData { /* * The interface to the code generator. */ virtual void finishRagelDef() {} - virtual void writeStatement( InputLoc &loc, int nargs, char **args ) {} + + /* These are invoked by the corresponding write statements. */ + virtual void writeOutData() {}; + virtual void writeOutInit() {}; + virtual void writeOutExec() {}; + virtual void writeOutEOF() {}; + + /* This can also be overwridden to modify the processing of write + * statements. */ + virtual void writeStatement( InputLoc &loc, int nargs, char **args ); /********************/ @@ -90,6 +104,7 @@ struct CodeGenData EntryIdVect entryPointIds; EntryNameVect entryPointNames; bool hasLongestMatch; + int codeGenErrCount; /* Write options. */ bool hasEnd; @@ -141,12 +156,10 @@ struct CodeGenData void closeMachine(); void setValueLimits(); void assignActionIds(); - void prepareMachine(); - bool hasBeenPrepared; + ostream &source_warning( const InputLoc &loc ); + ostream &source_error( const InputLoc &loc ); }; -void lineDirective( ostream &out, char *fileName, int line ); -void genLineDirective( ostream &out ); #endif /* _GENDATA_H */ diff --git a/redfsm/xmlparse.kl b/redfsm/xmlparse.kl index 15b4a11..45376a6 100644 --- a/redfsm/xmlparse.kl +++ b/redfsm/xmlparse.kl @@ -118,6 +118,16 @@ tag_host: ragel_def: tag_ragel_def_head ragel_def_item_list '/' TAG_ragel_def final { + /* Do this before distributing transitions out to singles and defaults + * makes life easier. */ + cgd->redFsm->maxKey = cgd->findMaxKey(); + + cgd->redFsm->assignActionLocs(); + + /* Find the first final state (The final state with the lowest id). */ + cgd->redFsm->findFirstFinState(); + + /* Call the user's callback. */ cgd->finishRagelDef(); }; @@ -176,8 +186,14 @@ tag_curstate_expr: TAG_curstate inline_list '/' TAG_curstate tag_write: tag_write_head write_option_list '/' TAG_write final { + /* Terminate the options list and call the write statement handler. */ writeOptions.append(0); cgd->writeStatement( $1->loc, writeOptions.length()-1, writeOptions.data ); + + /* CodeGenData may have issued an error. */ + errCount += cgd->codeGenErrCount; + + /* Clear the options in prep for the next write statement. */ writeOptions.empty(); }; diff --git a/rlcodegen/fsmcodegen.cpp b/rlcodegen/fsmcodegen.cpp index 42314bb..d3f33b5 100644 --- a/rlcodegen/fsmcodegen.cpp +++ b/rlcodegen/fsmcodegen.cpp @@ -629,20 +629,8 @@ string DCodeGen::CTRL_FLOW() return "if (true) "; } -/* Generate the code for an fsm. Assumes parseData is set up properly. Called - * by parser code. */ -void FsmCodeGen::prepareMachine() +void FsmCodeGen::finishRagelDef() { - if ( hasBeenPrepared ) - return; - hasBeenPrepared = true; - - /* Do this before distributing transitions out to singles and defaults - * makes life easier. */ - redFsm->maxKey = findMaxKey(); - - redFsm->assignActionLocs(); - if ( codeStyle == GenGoto || codeStyle == GenFGoto || codeStyle == GenIpGoto || codeStyle == GenSplit ) { @@ -657,10 +645,6 @@ void FsmCodeGen::prepareMachine() redFsm->sortByStateId(); } - /* Find the first final state. This is the final state with the lowest - * id. */ - redFsm->findFirstFinState(); - /* Choose default transitions and the single transition. */ redFsm->chooseDefaultSpan(); @@ -689,69 +673,6 @@ void FsmCodeGen::prepareMachine() calcIndexSize(); } -void FsmCodeGen::finishRagelDef() -{ - assert( outputFormat == OutCode ); - prepareMachine(); -} - -void FsmCodeGen::writeStatement( InputLoc &loc, int nargs, char **args ) -{ - if ( outputFormat == OutCode ) { - /* Force a newline. */ - out << "\n"; - genLineDirective( out ); - - if ( strcmp( args[0], "data" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - if ( strcmp( args[i], "noerror" ) == 0 ) - writeErr = false; - else if ( strcmp( args[i], "noprefix" ) == 0 ) - dataPrefix = false; - else if ( strcmp( args[i], "nofinal" ) == 0 ) - writeFirstFinal = false; - else { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - } - writeOutData(); - } - else if ( strcmp( args[0], "init" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - writeOutInit(); - } - else if ( strcmp( args[0], "exec" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - if ( strcmp( args[i], "noend" ) == 0 ) - hasEnd = false; - else { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - } - - /* Must set labels immediately before writing because we may depend - * on the noend write option. */ - setLabelsNeeded(); - writeOutExec(); - } - else if ( strcmp( args[0], "eof" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - writeOutEOF(); - } - else { - /* EMIT An error here. */ - } - } -} - ostream &FsmCodeGen::source_warning( const InputLoc &loc ) { cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: "; diff --git a/rlcodegen/fsmcodegen.h b/rlcodegen/fsmcodegen.h index 4207a55..0e75d08 100644 --- a/rlcodegen/fsmcodegen.h +++ b/rlcodegen/fsmcodegen.h @@ -64,11 +64,8 @@ public: FsmCodeGen( ostream &out ); virtual ~FsmCodeGen() {} - virtual void writeOutData() = 0; + virtual void finishRagelDef(); virtual void writeOutInit(); - virtual void writeOutExec() = 0; - virtual void writeOutEOF() = 0; - protected: string FSM_NAME(); @@ -168,21 +165,11 @@ protected: unsigned int arrayTypeSize( unsigned long maxVal ); - /* Set up labelNeeded flag for each state. Differs for each goto style so - * is virtual. */ - virtual void setLabelsNeeded() {} - bool outLabelUsed; bool againLabelUsed; - bool useIndicies; public: - void prepareMachine(); - - virtual void finishRagelDef(); - virtual void writeStatement( InputLoc &loc, int nargs, char **args ); - /* Determine if we should use indicies. */ virtual void calcIndexSize() {} }; diff --git a/rlcodegen/ipgotocodegen.cpp b/rlcodegen/ipgotocodegen.cpp index bb87446..773e1f3 100644 --- a/rlcodegen/ipgotocodegen.cpp +++ b/rlcodegen/ipgotocodegen.cpp @@ -353,6 +353,9 @@ void IpGotoCodeGen::writeOutData() void IpGotoCodeGen::writeOutExec() { + /* Must set labels immediately before writing because we may depend on the + * noend write option. */ + setLabelsNeeded(); outLabelUsed = false; out << " {\n"; diff --git a/rlcodegen/splitcodegen.cpp b/rlcodegen/splitcodegen.cpp index 5b3a836..0621083 100644 --- a/rlcodegen/splitcodegen.cpp +++ b/rlcodegen/splitcodegen.cpp @@ -373,6 +373,9 @@ std::ostream &SplitCodeGen::ALL_PARTITIONS() void SplitCodeGen::writeOutExec() { + /* Must set labels immediately before writing because we may depend on the + * noend write option. */ + setLabelsNeeded(); out << " {\n" " int _stat = 0;\n"; diff --git a/rlgen-java/javacodegen.cpp b/rlgen-java/javacodegen.cpp index 2446f8f..2f0fcce 100644 --- a/rlgen-java/javacodegen.cpp +++ b/rlgen-java/javacodegen.cpp @@ -1442,28 +1442,12 @@ void JavaTabCodeGen::writeOutInit() out << " }\n"; } -/* Generate the code for an fsm. Assumes parseData is set up properly. Called - * by parser code. */ -void JavaTabCodeGen::prepareMachine() +void JavaTabCodeGen::finishRagelDef() { - if ( hasBeenPrepared ) - return; - hasBeenPrepared = true; - - /* Do this before distributing transitions out to singles and defaults - * makes life easier. */ - redFsm->maxKey = findMaxKey(); - - redFsm->assignActionLocs(); - /* The frontend will do this for us, but it may be a good idea to force it * if the intermediate file is edited. */ redFsm->sortByStateId(); - /* Find the first final state. This is the final state with the lowest - * id. */ - redFsm->findFirstFinState(); - /* Choose default transitions and the single transition. */ redFsm->chooseDefaultSpan(); @@ -1483,66 +1467,6 @@ void JavaTabCodeGen::prepareMachine() calcIndexSize(); } -void JavaTabCodeGen::finishRagelDef() -{ - prepareMachine(); -} - -void JavaTabCodeGen::writeStatement( InputLoc &loc, int nargs, char **args ) -{ - /* Force a newline. */ - out << "\n"; - genLineDirective( out ); - - if ( strcmp( args[0], "data" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - if ( strcmp( args[i], "noerror" ) == 0 ) - writeErr = false; - else if ( strcmp( args[i], "noprefix" ) == 0 ) - dataPrefix = false; - else if ( strcmp( args[i], "nofinal" ) == 0 ) - writeFirstFinal = false; - else { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - } - writeOutData(); - } - else if ( strcmp( args[0], "init" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - writeOutInit(); - } - else if ( strcmp( args[0], "exec" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - if ( strcmp( args[i], "noend" ) == 0 ) - hasEnd = false; - else { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - } - - /* Must set labels immediately before writing because we may depend - * on the noend write option. */ - setLabelsNeeded(); - writeOutExec(); - } - else if ( strcmp( args[0], "eof" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - writeOutEOF(); - } - else { - /* EMIT An error here. */ - } -} - ostream &JavaTabCodeGen::source_warning( const InputLoc &loc ) { cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: "; diff --git a/rlgen-java/javacodegen.h b/rlgen-java/javacodegen.h index 66000a9..eaf932a 100644 --- a/rlgen-java/javacodegen.h +++ b/rlgen-java/javacodegen.h @@ -77,6 +77,7 @@ struct JavaTabCodeGen : public CodeGenData virtual void writeOutEOF(); virtual void writeOutData(); virtual void writeOutInit(); + virtual void finishRagelDef(); void NEXT( ostream &ret, int nextDest, bool inFinish ); void NEXT_EXPR( ostream &ret, InlineItem *ilItem, bool inFinish ); @@ -177,21 +178,9 @@ public: unsigned int arrayTypeSize( unsigned long maxVal ); - /* Set up labelNeeded flag for each state. Differs for each goto style so - * is virtual. */ - virtual void setLabelsNeeded() {} - bool outLabelUsed; bool againLabelUsed; - bool useIndicies; - -public: - void prepareMachine(); - - virtual void finishRagelDef(); - virtual void writeStatement( InputLoc &loc, int nargs, char **args ); - }; diff --git a/rlgen-ruby/rubycodegen.cpp b/rlgen-ruby/rubycodegen.cpp index 202fa51..1e3ae36 100644 --- a/rlgen-ruby/rubycodegen.cpp +++ b/rlgen-ruby/rubycodegen.cpp @@ -1431,28 +1431,12 @@ string RubyCodeGen::FIRST_FINAL_STATE() return ret.str(); } -/* Generate the code for an fsm. Assumes parseData is set up properly. Called - * by parser code. */ -void RubyCodeGen::prepareMachine() +void RubyCodeGen::finishRagelDef() { - if ( hasBeenPrepared ) - return; - hasBeenPrepared = true; - - /* Do this before distributing transitions out to singles and defaults - * makes life easier. */ - redFsm->maxKey = findMaxKey(); - - redFsm->assignActionLocs(); - /* The frontend will do this for us, but it may be a good idea to force it * if the intermediate file is edited. */ redFsm->sortByStateId(); - /* Find the first final state. This is the final state with the lowest - * id. */ - redFsm->findFirstFinState(); - /* Choose default transitions and the single transition. */ redFsm->chooseDefaultSpan(); @@ -1472,66 +1456,6 @@ void RubyCodeGen::prepareMachine() calcIndexSize(); } -void RubyCodeGen::finishRagelDef() -{ - prepareMachine(); -} - -void RubyCodeGen::writeStatement( InputLoc &loc, int nargs, char **args ) -{ - /* Force a newline. */ - out << "\n"; - genLineDirective( out ); - - if ( strcmp( args[0], "data" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - if ( strcmp( args[i], "noerror" ) == 0 ) - writeErr = false; - else if ( strcmp( args[i], "noprefix" ) == 0 ) - dataPrefix = false; - else if ( strcmp( args[i], "nofinal" ) == 0 ) - writeFirstFinal = false; - else { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - } - writeOutData(); - } - else if ( strcmp( args[0], "init" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - writeOutInit(); - } - else if ( strcmp( args[0], "exec" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - if ( strcmp( args[i], "noend" ) == 0 ) - hasEnd = false; - else { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - } - - /* Must set labels immediately before writing because we may depend - * on the noend write option. */ - setLabelsNeeded(); - writeOutExec(); - } - else if ( strcmp( args[0], "eof" ) == 0 ) { - for ( int i = 1; i < nargs; i++ ) { - source_warning(loc) << "unrecognized write option \"" << - args[i] << "\"" << endl; - } - writeOutEOF(); - } - else { - /* EMIT An error here. */ - } -} - ostream &RubyCodeGen::source_warning( const InputLoc &loc ) { cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: "; diff --git a/rlgen-ruby/rubycodegen.h b/rlgen-ruby/rubycodegen.h index 31d9377..1e72d7b 100644 --- a/rlgen-ruby/rubycodegen.h +++ b/rlgen-ruby/rubycodegen.h @@ -51,8 +51,12 @@ public: void COND_TRANSLATE(); void LOCATE_TRANS(); + virtual void writeOutExec(); virtual void writeOutEOF(); + virtual void writeOutInit(); + virtual void writeOutData(); + virtual void finishRagelDef(); protected: std::ostream &TO_STATE_ACTION_SWITCH(); @@ -78,7 +82,6 @@ public: std::ostream &TRANS_TARGS_WI(); std::ostream &TRANS_ACTIONS_WI(); - virtual void writeOutData(); void NEXT( ostream &ret, int nextDest, bool inFinish ); void NEXT_EXPR( ostream &ret, InlineItem *ilItem, bool inFinish ); @@ -170,21 +173,12 @@ public: unsigned int arrayTypeSize( unsigned long maxVal ); - /* Set up labelNeeded flag for each state. Differs for each goto style so - * is virtual. */ - virtual void setLabelsNeeded() {} - bool outLabelUsed; bool againLabelUsed; bool useIndicies; public: - void prepareMachine(); - - virtual void finishRagelDef(); - virtual void writeStatement( InputLoc &loc, int nargs, char **args ); - virtual string NULL_ITEM(); virtual ostream &OPEN_ARRAY( string type, string name ); virtual ostream &CLOSE_ARRAY(); @@ -193,7 +187,6 @@ public: virtual string GET_KEY(); virtual string CTRL_FLOW(); virtual void ACTION( ostream &ret, Action *action, int targState, bool inFinish ); - virtual void writeOutInit(); protected: virtual string INDENT_S(); -- 2.7.4