curStateExpr(0),
wantComplete(0),
hasLongestMatch(false),
+ codeGenErrCount(0),
hasEnd(true),
dataPrefix(true),
writeFirstFinal(true),
- writeErr(true),
- hasBeenPrepared(false)
+ writeErr(true)
{}
/* 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;
+}
+
+
* 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 );
/********************/
EntryIdVect entryPointIds;
EntryNameVect entryPointNames;
bool hasLongestMatch;
+ int codeGenErrCount;
/* Write options. */
bool hasEnd;
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 */
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();
};
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();
};
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 )
{
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();
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: ";
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();
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() {}
};
void IpGotoCodeGen::writeOutExec()
{
+ /* Must set labels immediately before writing because we may depend on the
+ * noend write option. */
+ setLabelsNeeded();
outLabelUsed = false;
out << " {\n";
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";
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();
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: ";
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 );
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 );
-
};
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();
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: ";
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();
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 );
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();
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();