Implemented an export feature, for exporting single-character machine
authorthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Sat, 10 Mar 2007 23:21:36 +0000 (23:21 +0000)
committerthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Sat, 10 Mar 2007 23:21:36 +0000 (23:21 +0000)
definitions in #define format.

Changed function names: writeOut*() => write*().

git-svn-id: http://svn.complang.org/ragel/trunk@134 052ea7fc-9027-0410-9066-f65837a77df0

41 files changed:
common/Makefile.in
common/common.h
ragel.vim
ragel/Makefile.in
ragel/fsmgraph.cpp
ragel/fsmgraph.h
ragel/parsedata.cpp
ragel/parsedata.h
ragel/parsetree.cpp
ragel/parsetree.h
ragel/rlparse.kh
ragel/rlparse.kl
ragel/rlscan.rl
ragel/xmlcodegen.cpp
ragel/xmlcodegen.h
redfsm/Makefile.in
redfsm/gendata.cpp
redfsm/gendata.h
redfsm/xmlparse.kh
redfsm/xmlparse.kl
redfsm/xmlscan.rl
redfsm/xmltags.gperf
rlgen-cd/fflatcodegen.cpp
rlgen-cd/fflatcodegen.h
rlgen-cd/fgotocodegen.cpp
rlgen-cd/fgotocodegen.h
rlgen-cd/flatcodegen.cpp
rlgen-cd/flatcodegen.h
rlgen-cd/fsmcodegen.cpp
rlgen-cd/fsmcodegen.h
rlgen-cd/ftabcodegen.cpp
rlgen-cd/ftabcodegen.h
rlgen-cd/gotocodegen.cpp
rlgen-cd/gotocodegen.h
rlgen-cd/ipgotocodegen.cpp
rlgen-cd/ipgotocodegen.h
rlgen-cd/main.cpp
rlgen-cd/splitcodegen.cpp
rlgen-cd/splitcodegen.h
rlgen-cd/tabcodegen.cpp
rlgen-cd/tabcodegen.h

index 47dc356..c584dee 100644 (file)
@@ -18,7 +18,7 @@
 #   along with Ragel; if not, write to the Free Software
 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
-INCS += 
+INCS += -I../aapl
 DEFS +=
 
 CFLAGS += -g -Wall
index 29dcf38..6c6720b 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <fstream>
 #include <climits>
+#include "dlist.h"
 
 typedef unsigned long long Size;
 
@@ -291,4 +292,17 @@ public:
 char *findFileExtension( char *stemFile );
 char *fileNameFromStem( char *stemFile, char *suffix );
 
+struct Export
+{
+       Export( char *name, Key key )
+               : name(name), key(key) {}
+
+       char *name;
+       Key key;
+
+       Export *prev, *next;
+};
+
+typedef DList<Export> ExportList;
+
 #endif /* _COMMON_H */
index 2f09b60..88a5c31 100644 (file)
--- a/ragel.vim
+++ b/ragel.vim
@@ -98,7 +98,7 @@ syntax match rlOtherOps "<:" contained
 " Keywords
 " FIXME: Enable the range keyword post 5.17.
 " syntax keyword rlKeywords machine action context include range contained
-syntax keyword rlKeywords machine action context include contained
+syntax keyword rlKeywords machine action context include export entry contained
 syntax keyword rlExprKeywords when err lerr eof from to contained
 
 " Case Labels
@@ -126,7 +126,7 @@ syntax region rlCodeSemi matchgroup=Type start="\<alphtype\>" start="\<getkey\>"
 
 syntax region rlWrite matchgroup=Type start="\<write\>" matchgroup=NONE end=";" contained contains=rlWriteKeywords,rlWriteOptions
 
-syntax keyword rlWriteKeywords init data exec eof contained
+syntax keyword rlWriteKeywords init data exec eof exports contained
 syntax keyword rlWriteOptions noerror nofinal noprefix noend contained
 
 "
index dd88190..30bd0ac 100644 (file)
@@ -61,7 +61,7 @@ rlparse.cpp: rlparse.kl rlparse.kh
        kelbt -o $@ $<
 
 rlscan.cpp: rlscan.rl
-       ragel $< | rlcodegen -G2 -o $@
+       ragel $< | rlgen-cd -G2 -o $@
 
 endif
 
index 41c4b44..d7d0ba4 100644 (file)
@@ -1397,3 +1397,30 @@ void FsmAp::embedCondition( MergeData &md, StateAp *state, Action *condAction )
        doRemove( md, state, expList );
        expList.empty();
 }
+
+/* Check if a machine defines a single character. This is useful in validating
+ * ranges and machines to export. */
+bool FsmAp::checkSingleCharMachine()
+{
+       /* Must have two states. */
+       if ( stateList.length() != 2 )
+               return false;
+       /* The start state cannot be final. */
+       if ( startState->isFinState() )
+               return false;
+       /* There should be only one final state. */
+       if ( finStateSet.length() != 1 )
+               return false;
+       /* The final state cannot have any transitions out. */
+       if ( finStateSet[0]->outList.length() != 0 )
+               return false;
+       /* The start state should have only one transition out. */
+       if ( startState->outList.length() != 1 )
+               return false;
+       /* The singe transition out of the start state should not be a range. */
+       TransAp *startTrans = startState->outList.head;
+       if ( startTrans->lowKey != startTrans->highKey )
+               return false;
+       return true;
+}
+
index f3a16b9..3c58644 100644 (file)
@@ -1472,6 +1472,10 @@ struct FsmAp
        bool checkErrTrans( StateAp *state, TransAp *trans );
        bool checkErrTransFinish( StateAp *state );
        bool hasErrorTrans();
+
+       /* Check if a machine defines a single character. This is useful in
+        * validating ranges and machines to export. */
+       bool checkSingleCharMachine( );
 };
 
 
index 881f5ab..6b417e4 100644 (file)
@@ -438,6 +438,7 @@ ParseData::ParseData( char *fileName, char *sectionName,
        curActionOrd(0),
        curPriorOrd(0),
        rootName(0),
+       exportsRootName(0),
        nextEpsilonResolvedLink(0),
        nextLongestMatchId(1),
        lmRequiresErrorState(false)
@@ -475,6 +476,12 @@ void ParseData::initNameWalk()
        curNameChild = 0;
 }
 
+void ParseData::initExportsNameWalk()
+{
+       curNameInst = exportsRootName;
+       curNameChild = 0;
+}
+
 /* Goes into the next child scope. The number of the child is already set up.
  * We need this for the syncronous name tree and parse tree walk to work
  * properly. It is reset on entry into a scope and advanced on poping of a
@@ -767,18 +774,18 @@ void ParseData::fillNameIndex( NameInst *from )
                fillNameIndex( *name );
 }
 
-void ParseData::makeRootName()
+void ParseData::makeRootNames()
 {
        /* Create the root name. */
        rootName = new NameInst( InputLoc(), 0, 0, nextNameId++, false );
+       exportsRootName = new NameInst( InputLoc(), 0, 0, nextNameId++, false );
 }
 
 /* Build the name tree and supporting data structures. */
 void ParseData::makeNameTree( GraphDictEl *dictEl )
 {
        /* Set up curNameInst for the walk. */
-       curNameInst = rootName;
-       curNameChild = 0;
+       initNameWalk();
 
        if ( dictEl != 0 ) {
                /* A start location has been specified. */
@@ -798,6 +805,7 @@ void ParseData::makeNameTree( GraphDictEl *dictEl )
        fillNameIndex( rootName );
 }
 
+
 void ParseData::createBuiltin( char *name, BuiltinMachine builtin )
 {
        Expression *expression = new Expression( builtin );
@@ -1288,11 +1296,59 @@ void ParseData::analyzeGraph( FsmAp *graph )
                checkAction( act );
 }
 
+void ParseData::makeExportsNameTree()
+{
+       /* Make a name tree for the exports. */
+       initExportsNameWalk();
+
+       /* First make the name tree. */
+       for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) {
+               if ( gdel->value->isExport ) {
+                       /* Recurse on the instance. */
+                       gdel->value->makeNameTree( gdel->loc, this );
+               }
+       }
+}
+
+void ParseData::makeExports()
+{
+       makeExportsNameTree();
+
+       /* Resove name references in the tree. */
+       initExportsNameWalk();
+       for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) {
+               if ( gdel->value->isExport )
+                       gdel->value->resolveNameRefs( this );
+       }
+
+       /* Make all the instantiations, we know that main exists in this list. */
+       initExportsNameWalk();
+       for ( GraphDict::Iter gdel = graphDict; gdel.lte();  gdel++ ) {
+               /* Check if this var def is an export. */
+               if ( gdel->value->isExport ) {
+                       /* Build the graph from a walk of the parse tree. */
+                       FsmAp *graph = gdel->value->walk( this );
+
+                       /* Build the graph from a walk of the parse tree. */
+                       if ( !graph->checkSingleCharMachine() ) {
+                               error(gdel->loc) << "bad export machine, must define "
+                                               "a single character" << endl;
+                       }
+                       else {
+                               /* Safe to extract the key and declare the export. */
+                               Key exportKey = graph->startState->outList.head->lowKey;
+                               exportList.append( new Export( gdel->value->name, exportKey ) );
+                       }
+               }
+       }
+
+}
+
 void ParseData::prepareMachineGen( GraphDictEl *graphDictEl )
 {
        beginProcessing();
        initKeyOps();
-       makeRootName();
+       makeRootNames();
        initLongestMatchData();
 
        /* Make the graph, do minimization. */
@@ -1300,6 +1356,9 @@ void ParseData::prepareMachineGen( GraphDictEl *graphDictEl )
                sectionGraph = makeAll();
        else
                sectionGraph = makeSpecific( graphDictEl );
+       
+       /* Compute exports from the export definitions. */
+       makeExports();
 
        /* If any errors have occured in the input file then don't write anything. */
        if ( gblErrorCount > 0 )
index 55c69ef..330d96a 100644 (file)
@@ -167,8 +167,9 @@ struct ParseData
        /* Make a name id in the current name instantiation scope if it is not
         * already there. */
        NameInst *addNameInst( const InputLoc &loc, char *data, bool isLabel );
-       void makeRootName();
+       void makeRootNames();
        void makeNameTree( GraphDictEl *gdNode );
+       void makeExportsNameTree();
        void fillNameIndex( NameInst *from );
        void printNameTree();
 
@@ -206,6 +207,7 @@ struct ParseData
 
        void analyzeAction( Action *action, InlineList *inlineList );
        void analyzeGraph( FsmAp *graph );
+       void makeExports();
 
        void prepareMachineGen( GraphDictEl *graphDictEl );
        void generateXML( ostream &out );
@@ -271,8 +273,12 @@ struct ParseData
        int curActionOrd;
        int curPriorOrd;
 
-       /* Root of the name tree. */
+       /* Root of the name tree. One root is for the instantiated machines. The
+        * other root is for exported definitions. */
        NameInst *rootName;
+       NameInst *exportsRootName;
+       
+       /* Name tree walking. */
        NameInst *curNameInst;
        int curNameChild;
 
@@ -289,6 +295,7 @@ struct ParseData
        void initLongestMatchData();
        void setLongestMatchData( FsmAp *graph );
        void initNameWalk();
+       void initExportsNameWalk();
        NameInst *nextNameScope() { return curNameInst->childVect[curNameChild]; }
        NameFrame enterNameScope( bool isLocal, int numScopes );
        void popNameScope( const NameFrame &frame );
@@ -326,6 +333,8 @@ struct ParseData
 
        CondData thisCondData;
        KeyOps thisKeyOps;
+
+       ExportList exportList;
 };
 
 void afterOpMinimize( FsmAp *fsm, bool lastInSeq = true );
index 16bc17d..72ef0d9 100644 (file)
@@ -112,7 +112,7 @@ FsmAp *VarDef::walk( ParseData *pd )
         * the graph. */
        if ( pd->curNameInst->numRefs > 0 )
                rtnVal->setEntry( pd->curNameInst->id, rtnVal->startState );
-       
+
        /* Pop the name scope. */
        pd->popNameScope( nameFrame );
        return rtnVal;
@@ -1793,43 +1793,19 @@ Range::~Range()
        delete upperLit;
 }
 
-bool Range::verifyRangeFsm( FsmAp *rangeEnd )
-{
-       /* Must have two states. */
-       if ( rangeEnd->stateList.length() != 2 )
-               return false;
-       /* The start state cannot be final. */
-       if ( rangeEnd->startState->isFinState() )
-               return false;
-       /* There should be only one final state. */
-       if ( rangeEnd->finStateSet.length() != 1 )
-               return false;
-       /* The final state cannot have any transitions out. */
-       if ( rangeEnd->finStateSet[0]->outList.length() != 0 )
-               return false;
-       /* The start state should have only one transition out. */
-       if ( rangeEnd->startState->outList.length() != 1 )
-               return false;
-       /* The singe transition out of the start state should not be a range. */
-       TransAp *startTrans = rangeEnd->startState->outList.head;
-       if ( startTrans->lowKey != startTrans->highKey )
-               return false;
-       return true;
-}
-
 /* Evaluate a range. Gets the lower an upper key and makes an fsm range. */
 FsmAp *Range::walk( ParseData *pd )
 {
        /* Construct and verify the suitability of the lower end of the range. */
        FsmAp *lowerFsm = lowerLit->walk( pd );
-       if ( !verifyRangeFsm( lowerFsm ) ) {
+       if ( !lowerFsm->checkSingleCharMachine() ) {
                error(lowerLit->token.loc) << 
                        "bad range lower end, must be a single character" << endl;
        }
 
        /* Construct and verify the upper end. */
        FsmAp *upperFsm = upperLit->walk( pd );
-       if ( !verifyRangeFsm( upperFsm ) ) {
+       if ( !upperFsm->checkSingleCharMachine() ) {
                error(upperLit->token.loc) << 
                        "bad range upper end, must be a single character" << endl;
        }
index 9a86bb5..84fa9e0 100644 (file)
@@ -218,6 +218,9 @@ struct VarDef
 
        char *name;
        JoinOrLm *joinOrLm;
+
+       bool isExport;
+       bool isEntry;
 };
 
 
@@ -600,7 +603,6 @@ struct Range
 
        ~Range();
        FsmAp *walk( ParseData *pd );
-       bool verifyRangeFsm( FsmAp *rangeEnd );
 
        Literal *lowerLit;
        Literal *upperLit;
index ac8cb47..3af05b9 100644 (file)
@@ -78,7 +78,8 @@ struct Parser
 
        # Keywords.
        token KW_Action, KW_AlphType, KW_Range, KW_GetKey, KW_Include, KW_Write,
-               KW_Machine, KW_When, KW_Eof, KW_Err, KW_Lerr, KW_To, KW_From;
+               KW_Machine, KW_When, KW_Eof, KW_Err, KW_Lerr, KW_To, KW_From,
+               KW_Export, KW_Entry;
 
        # Specials in code blocks.
        token KW_Break, KW_Exec, KW_Hold, KW_PChar, KW_Char, KW_Goto, KW_Call,
@@ -100,6 +101,8 @@ struct Parser
                : sectionName(sectionName)
        {
                pd = new ParseData( fileName, sectionName, sectionLoc );
+               exportContext.append( false );
+               entryContext.append( false );
        }
 
        int token( InputLoc &loc, int tokId, char *tokstart, int toklen );
@@ -116,6 +119,9 @@ struct Parser
 
        NameRef nameRef;
        NameRefList nameRefList;
+
+       Vector<bool> exportContext;
+       Vector<bool> entryContext;
 };
 
 %% write token_defs;
index 4fb7976..051bcc0 100644 (file)
@@ -53,26 +53,74 @@ statement: range_spec commit;
 statement: getkey_spec commit;
 statement: access_spec commit;
 statement: variable_spec commit;
+statement: export_block commit;
+statement: entry_block commit;
+
+export_open: KW_Export 
+       final {
+               exportContext.append( true );
+       };
+
+nonterm opt_export
+{
+       bool isSet;
+};
+
+opt_export: export_open final { $$->isSet = true; };
+opt_export: final { $$->isSet = false; };
+
+export_block: export_open '{' statement_list '}' 
+       final {
+               exportContext.remove( exportContext.length()-1 );
+       };
+
+nonterm opt_entry
+{
+       bool isSet;
+};
+
+entry_open: KW_Entry
+       final {
+               entryContext.append( true );
+       };
+
+opt_entry: entry_open final { $$->isSet = true; };
+opt_entry: final { $$->isSet = false; };
+
+entry_block: entry_open '{' statement_list '}'
+       final {
+               entryContext.remove( entryContext.length()-1 );
+       };
 
 assignment:
-       machine_name '=' join ';' final {
+       opt_export opt_entry machine_name '=' join ';' final {
                /* Main machine must be an instance. */
                bool isInstance = false;
-               if ( strcmp($1->token.data, machineMain) == 0 ) {
-                       warning($1->token.loc) << 
+               if ( strcmp($3->token.data, machineMain) == 0 ) {
+                       warning($3->token.loc) << 
                                        "main machine will be implicitly instantiated" << endl;
                        isInstance = true;
                }
 
                /* Generic creation of machine for instantiation and assignment. */
-               JoinOrLm *joinOrLm = new JoinOrLm( $3->join );
-               tryMachineDef( $1->token.loc, $1->token.data, joinOrLm, isInstance );
+               JoinOrLm *joinOrLm = new JoinOrLm( $5->join );
+               tryMachineDef( $3->token.loc, $3->token.data, joinOrLm, isInstance );
+
+               if ( $1->isSet )
+                       exportContext.remove( exportContext.length()-1 );
+               if ( $2->isSet )
+                       entryContext.remove( entryContext.length()-1 );
        };
 
 instantiation: 
-       machine_name TK_ColonEquals join_or_lm ';' final {
+       opt_export opt_entry machine_name TK_ColonEquals join_or_lm ';' final {
                /* Generic creation of machine for instantiation and assignment. */
-               tryMachineDef( $1->token.loc, $1->token.data, $3->joinOrLm, true );
+               tryMachineDef( $3->token.loc, $3->token.data, $5->joinOrLm, true );
+
+               if ( $1->isSet )
+                       exportContext.remove( exportContext.length()-1 );
+               if ( $2->isSet )
+                       entryContext.remove( entryContext.length()-1 );
        };
 
 type token_type
@@ -1369,6 +1417,8 @@ void Parser::tryMachineDef( InputLoc &loc, char *name,
                newEl->value = new VarDef( name, joinOrLm );
                newEl->isInstance = isInstance;
                newEl->loc = loc;
+               newEl->value->isExport = exportContext[exportContext.length()-1];
+               newEl->value->isEntry = entryContext[entryContext.length()-1];
 
                /* It it is an instance, put on the instance list. */
                if ( isInstance )
index 882e3ba..36f628b 100644 (file)
@@ -70,7 +70,8 @@ struct Scanner
                line(1), column(1), lastnl(0), 
                parser(0), ignoreSection(false), 
                parserExistsError(false),
-               whitespaceOn(true)
+               whitespaceOn(true),
+               lastToken(0)
                {}
 
        bool recursiveInclude( char *inclFileName, char *inclSectionName );
@@ -125,6 +126,9 @@ struct Scanner
        /* This is for inline code. By default it is on. It goes off for
         * statements and values in inline blocks which are parsed. */
        bool whitespaceOn;
+
+       /* Keeps a record of the previous token sent to the section parser. */
+       int lastToken;
 };
 
 %%{
@@ -379,6 +383,10 @@ void Scanner::token( int type, char *start, char *end )
        }%%
 
        updateCol();
+
+       /* Record the last token for use in controlling the scan of subsequent
+        * tokens. */
+       lastToken = type;
 }
 
 void Scanner::startSection( )
@@ -666,6 +674,8 @@ void Scanner::endSection( )
                'lerr' => { token( KW_Lerr ); };
                'to' => { token( KW_To ); };
                'from' => { token( KW_From ); };
+               'export' => { token( KW_Export ); };
+               'entry' => { token( KW_Entry ); };
 
                # Identifiers.
                ident => { token( TK_Word, tokstart, tokend ); } ;
@@ -767,10 +777,14 @@ void Scanner::endSection( )
                };
 
                '{' => { 
-                       token( '{' );
-                       curly_count = 1; 
-                       inlineBlockType = CurlyDelimited;
-                       fgoto inline_code;
+                       if ( lastToken == KW_Export || lastToken == KW_Entry )
+                               token( '{' );
+                       else {
+                               token( '{' );
+                               curly_count = 1; 
+                               inlineBlockType = CurlyDelimited;
+                               fgoto inline_code;
+                       }
                };
 
                EOF => {
index f2bb591..b07c82a 100644 (file)
@@ -656,6 +656,19 @@ void XMLCodeGen::writeConditions()
        }
 }
 
+void XMLCodeGen::writeExports()
+{
+       if ( pd->exportList.length() > 0 ) {
+               out << "  <exports>\n";
+               for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
+                       out << "    <ex name=\"" << exp->name << "\">";
+                       writeKey( exp->key );
+                       out << "</ex>\n";
+               }
+               out << "  </exports>\n";
+       }
+}
+
 void XMLCodeGen::writeXML()
 {
        /* Open the definition. */
@@ -671,6 +684,8 @@ void XMLCodeGen::writeXML()
        if ( pd->curStateExpr != 0 )
                writeCurStateExpr();
        
+       writeExports();
+       
        writeMachine();
 
        out <<
index ab08bc2..c93b4a8 100644 (file)
@@ -104,6 +104,7 @@ private:
        void writeLmOnNext( InlineItem *item );
        void writeLmOnLagBehind( InlineItem *item );
 
+       void writeExports();
        void writeEntryPoints();
        void writeGetKeyExpr();
        void writeAccessExpr();
index 46971e3..e8bb35c 100644 (file)
@@ -57,7 +57,7 @@ xmlparse.cpp: xmlparse.kl xmlparse.kh
        kelbt -o $@ $<
 
 xmlscan.cpp: xmlscan.rl
-       ragel xmlscan.rl | rlcodegen -G2 -o xmlscan.cpp
+       ragel xmlscan.rl | rlgen-cd -G2 -o xmlscan.cpp
 
 xmltags.cpp: xmltags.gperf
        gperf -L C++ -t $< > $@
@@ -76,7 +76,7 @@ EXTRA_CLEAN = $(GEN_SRC)
 endif
 
 clean:
-       rm -f tags .*.d *.o rlcodegen $(EXTRA_CLEAN)
+       rm -f tags .*.d *.o rlgen-cd $(EXTRA_CLEAN)
 
 install:
        @true
index fbf5256..7a8d19c 100644 (file)
@@ -659,14 +659,14 @@ void CodeGenData::writeStatement( InputLoc &loc, int nargs, char **args )
                                                args[i] << "\"" << endl;
                        }
                }
-               writeOutData();
+               writeData();
        }
        else if ( strcmp( args[0], "init" ) == 0 ) {
                for ( int i = 1; i < nargs; i++ ) {
                        source_warning(loc) << "unrecognized write option \"" << 
                                        args[i] << "\"" << endl;
                }
-               writeOutInit();
+               writeInit();
        }
        else if ( strcmp( args[0], "exec" ) == 0 ) {
                for ( int i = 1; i < nargs; i++ ) {
@@ -677,14 +677,21 @@ void CodeGenData::writeStatement( InputLoc &loc, int nargs, char **args )
                                                args[i] << "\"" << endl;
                        }
                }
-               writeOutExec();
+               writeExec();
        }
        else if ( strcmp( args[0], "eof" ) == 0 ) {
                for ( int i = 1; i < nargs; i++ ) {
                        source_warning(loc) << "unrecognized write option \"" << 
                                        args[i] << "\"" << endl;
                }
-               writeOutEOF();
+               writeEOF();
+       }
+       else if ( strcmp( args[0], "exports" ) == 0 ) {
+               for ( int i = 1; i < nargs; i++ ) {
+                       source_warning(loc) << "unrecognized write option \"" << 
+                                       args[i] << "\"" << endl;
+               }
+               writeExports();
        }
        else {
                /* EMIT An error here. */
index facec5f..855e071 100644 (file)
@@ -63,10 +63,11 @@ struct CodeGenData
        virtual void finishRagelDef() {}
 
        /* These are invoked by the corresponding write statements. */
-       virtual void writeOutData() {};
-       virtual void writeOutInit() {};
-       virtual void writeOutExec() {};
-       virtual void writeOutEOF() {};
+       virtual void writeData() {};
+       virtual void writeInit() {};
+       virtual void writeExec() {};
+       virtual void writeEOF() {};
+       virtual void writeExports() {};
 
        /* This can also be overwridden to modify the processing of write
         * statements. */
@@ -105,6 +106,7 @@ struct CodeGenData
        EntryNameVect entryPointNames;
        bool hasLongestMatch;
        int codeGenErrCount;
+       ExportList exportList;
 
        /* Write options. */
        bool hasEnd;
index b148d89..8526196 100644 (file)
@@ -103,7 +103,8 @@ struct Parser
                        TAG_error_state, TAG_action_list, TAG_action_table_list,
                        TAG_action, TAG_action_table, TAG_alphtype, TAG_element,
                        TAG_getkey, TAG_state_actions, TAG_entry_points, TAG_sub_action,
-                       TAG_cond_space_list, TAG_cond_space, TAG_cond_list, TAG_c;
+                       TAG_cond_space_list, TAG_cond_space, TAG_cond_list, TAG_c,
+                       TAG_exports, TAG_ex;
 
                # Inline block tokens.
                token TAG_text, TAG_goto, TAG_call, TAG_next, TAG_goto_expr,
index c63a1c4..4df9cb1 100644 (file)
@@ -162,8 +162,26 @@ ragel_def_item: tag_alph_type;
 ragel_def_item: tag_getkey_expr;
 ragel_def_item: tag_access_expr;
 ragel_def_item: tag_curstate_expr;
+ragel_def_item: tag_export_list;
 ragel_def_item: tag_machine;
 
+tag_export_list: TAG_exports export_list '/' TAG_exports;
+
+export_list: export_list tag_export;
+export_list: ;
+
+tag_export: TAG_ex '/' TAG_ex
+       final {
+               Attribute *nameAttr = $1->tag->findAttr( "name" );
+               if ( nameAttr == 0 )
+                       error($1->loc) << "tag <ex> requires a name attribute" << endl;
+               else {
+                       char *td = $3->tag->content;
+                       Key exportKey = readKey( td, &td );
+                       cgd->exportList.append( new Export( nameAttr->value, exportKey ) );
+               }
+       };
+
 tag_alph_type: TAG_alphtype '/' TAG_alphtype
        final {
                if ( ! cgd->setAlphType( $3->tag->content ) )
index 988f589..13798ca 100644 (file)
@@ -315,7 +315,7 @@ int xml_parse( std::istream &input, char *fileName,
                                        case TAG_set_act: case TAG_start_state:
                                        case TAG_error_state: case TAG_state_actions: 
                                        case TAG_action_table: case TAG_cond_space: 
-                                       case TAG_c:
+                                       case TAG_c: case TAG_ex:
                                                tag->content = new char[scanner.buffer.length+1];
                                                memcpy( tag->content, scanner.buffer.data,
                                                                scanner.buffer.length );
index ca7baac..7185bab 100644 (file)
@@ -80,3 +80,5 @@ cond_space_list, TAG_cond_space_list
 cond_space, TAG_cond_space
 cond_list, TAG_cond_list
 c, TAG_c
+exports, TAG_exports
+ex, TAG_ex
index 266ea54..c629d59 100644 (file)
@@ -149,7 +149,7 @@ std::ostream &FFlatCodeGen::ACTION_SWITCH()
        return out;
 }
 
-void FFlatCodeGen::writeOutData()
+void FFlatCodeGen::writeData()
 {
        if ( redFsm->anyConditions() ) {
                OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
@@ -243,7 +243,7 @@ void FFlatCodeGen::writeOutData()
        }
 }
 
-void FFlatCodeGen::writeOutExec()
+void FFlatCodeGen::writeExec()
 {
        outLabelUsed = false;
 
@@ -350,7 +350,7 @@ void FFlatCodeGen::writeOutExec()
        out << "        }\n";
 }
 
-void FFlatCodeGen::writeOutEOF()
+void FFlatCodeGen::writeEOF()
 {
        if ( redFsm->anyEofActions() ) {
                out <<
index 67780df..cf92fd9 100644 (file)
@@ -48,9 +48,9 @@ protected:
        virtual std::ostream &EOF_ACTION( RedStateAp *state );
        virtual std::ostream &TRANS_ACTION( RedTransAp *trans );
 
-       virtual void writeOutData();
-       virtual void writeOutEOF();
-       virtual void writeOutExec();
+       virtual void writeData();
+       virtual void writeEOF();
+       virtual void writeExec();
 };
 
 /*
index 3ad5ea3..9b08033 100644 (file)
@@ -150,7 +150,7 @@ unsigned int FGotoCodeGen::EOF_ACTION( RedStateAp *state )
        return act;
 }
 
-void FGotoCodeGen::writeOutData()
+void FGotoCodeGen::writeData()
 {
        out <<
                "static const int " << START() << " = " << START_STATE_ID() << ";\n"
@@ -190,7 +190,7 @@ void FGotoCodeGen::writeOutData()
        }
 }
 
-void FGotoCodeGen::writeOutExec()
+void FGotoCodeGen::writeExec()
 {
        outLabelUsed = false;
 
@@ -261,7 +261,7 @@ void FGotoCodeGen::writeOutExec()
        out << "        }\n";
 }
 
-void FGotoCodeGen::writeOutEOF()
+void FGotoCodeGen::writeEOF()
 {
        if ( redFsm->anyEofActions() ) {
                out <<
index 870defd..076f5c4 100644 (file)
@@ -48,9 +48,9 @@ public:
        unsigned int FROM_STATE_ACTION( RedStateAp *state );
        unsigned int EOF_ACTION( RedStateAp *state );
 
-       virtual void writeOutData();
-       virtual void writeOutEOF();
-       virtual void writeOutExec();
+       virtual void writeData();
+       virtual void writeEOF();
+       virtual void writeExec();
 };
 
 /*
index 12c9805..65d60f6 100644 (file)
@@ -486,7 +486,7 @@ void FlatCodeGen::BREAK( ostream &ret, int targState )
        ret << CTRL_FLOW() << "goto _out;";
 }
 
-void FlatCodeGen::writeOutData()
+void FlatCodeGen::writeData()
 {
        /* If there are any transtion functions then output the array. If there
         * are none, don't bother emitting an empty array that won't be used. */
@@ -630,7 +630,7 @@ void FlatCodeGen::COND_TRANSLATE()
                "       }\n";
 }
 
-void FlatCodeGen::writeOutExec()
+void FlatCodeGen::writeExec()
 {
        outLabelUsed = false;
 
@@ -760,7 +760,7 @@ void FlatCodeGen::writeOutExec()
        out << "        }\n";
 }
 
-void FlatCodeGen::writeOutEOF()
+void FlatCodeGen::writeEOF()
 {
        if ( redFsm->anyEofActions() ) {
                out << 
index 51b0923..27dee2e 100644 (file)
@@ -80,9 +80,9 @@ protected:
        virtual std::ostream &EOF_ACTION( RedStateAp *state );
        virtual std::ostream &TRANS_ACTION( RedTransAp *trans );
 
-       virtual void writeOutData();
-       virtual void writeOutEOF();
-       virtual void writeOutExec();
+       virtual void writeData();
+       virtual void writeEOF();
+       virtual void writeExec();
 };
 
 /*
index edc06e5..3ef4eea 100644 (file)
@@ -454,7 +454,7 @@ string FsmCodeGen::FIRST_FINAL_STATE()
        return ret.str();
 }
 
-void FsmCodeGen::writeOutInit()
+void FsmCodeGen::writeInit()
 {
        out << "        {\n";
        out << "\t" << CS() << " = " << START() << ";\n";
@@ -510,6 +510,17 @@ string FsmCodeGen::WIDE_ALPH_TYPE()
        return ret;
 }
 
+void FsmCodeGen::writeExports()
+{
+       if ( exportList.length() > 0 ) {
+               for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
+                       out << "#define " << DATA_PREFIX() << ex->name << " " << 
+                                       KEY(ex->key) << "\n";
+               }
+               out << "\n";
+       }
+}
+
 
 /*
  * Language specific, but style independent code generators functions.
index 0e75d08..615fa36 100644 (file)
@@ -65,7 +65,8 @@ public:
        virtual ~FsmCodeGen() {}
 
        virtual void finishRagelDef();
-       virtual void writeOutInit();
+       virtual void writeInit();
+       virtual void writeExports();
 
 protected:
        string FSM_NAME();
index 03b04c1..3cda8f4 100644 (file)
@@ -178,7 +178,7 @@ std::ostream &FTabCodeGen::ACTION_SWITCH()
        return out;
 }
 
-void FTabCodeGen::writeOutData()
+void FTabCodeGen::writeData()
 {
        if ( redFsm->anyConditions() ) {
                OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
@@ -297,7 +297,7 @@ void FTabCodeGen::writeOutData()
        }
 }
 
-void FTabCodeGen::writeOutExec()
+void FTabCodeGen::writeExec()
 {
        outLabelUsed = false;
 
@@ -404,7 +404,7 @@ void FTabCodeGen::writeOutExec()
 }
 
 
-void FTabCodeGen::writeOutEOF()
+void FTabCodeGen::writeEOF()
 {
        if ( redFsm->anyEofActions() ) {
                out <<
index f51d0ef..9d26d1c 100644 (file)
@@ -48,9 +48,9 @@ protected:
        virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state );
        virtual std::ostream &EOF_ACTION( RedStateAp *state );
        virtual std::ostream &TRANS_ACTION( RedTransAp *trans );
-       virtual void writeOutData();
-       virtual void writeOutEOF();
-       virtual void writeOutExec();
+       virtual void writeData();
+       virtual void writeEOF();
+       virtual void writeExec();
        virtual void calcIndexSize();
 };
 
index 977666f..28552e8 100644 (file)
@@ -601,7 +601,7 @@ void GotoCodeGen::BREAK( ostream &ret, int targState )
        ret << CTRL_FLOW() << "goto _out;";
 }
 
-void GotoCodeGen::writeOutData()
+void GotoCodeGen::writeData()
 {
        out <<
                "static const int " << START() << " = " << START_STATE_ID() << ";\n"
@@ -648,7 +648,7 @@ void GotoCodeGen::writeOutData()
        }
 }
 
-void GotoCodeGen::writeOutExec()
+void GotoCodeGen::writeExec()
 {
        outLabelUsed = false;
 
@@ -736,7 +736,7 @@ void GotoCodeGen::writeOutExec()
        out << "        }\n";
 }
 
-void GotoCodeGen::writeOutEOF()
+void GotoCodeGen::writeEOF()
 {
        if ( redFsm->anyEofActions() ) {
                out << 
index dec9882..625c2c2 100644 (file)
@@ -82,9 +82,9 @@ public:
        virtual void GOTO_HEADER( RedStateAp *state );
        virtual void STATE_GOTO_ERROR();
 
-       virtual void writeOutData();
-       virtual void writeOutEOF();
-       virtual void writeOutExec();
+       virtual void writeData();
+       virtual void writeEOF();
+       virtual void writeExec();
 };
 
 /*
index d03ae66..0cd19af 100644 (file)
@@ -332,7 +332,7 @@ void IpGotoCodeGen::setLabelsNeeded()
        }
 }
 
-void IpGotoCodeGen::writeOutData()
+void IpGotoCodeGen::writeData()
 {
        out <<
                "static const int " << START() << " = " << START_STATE_ID() << ";\n"
@@ -351,7 +351,7 @@ void IpGotoCodeGen::writeOutData()
        }
 }
 
-void IpGotoCodeGen::writeOutExec()
+void IpGotoCodeGen::writeExec()
 {
        /* Must set labels immediately before writing because we may depend on the
         * noend write option. */
@@ -413,7 +413,7 @@ void IpGotoCodeGen::writeOutExec()
                "       }\n";
 }
 
-void IpGotoCodeGen::writeOutEOF()
+void IpGotoCodeGen::writeEOF()
 {
        if ( redFsm->anyEofActions() ) {
                out <<
index cdac17b..f32678b 100644 (file)
@@ -54,9 +54,9 @@ public:
        void TARGS( ostream &ret, bool inFinish, int targState );
        void BREAK( ostream &ret, int targState );
 
-       virtual void writeOutData();
-       virtual void writeOutEOF();
-       virtual void writeOutExec();
+       virtual void writeData();
+       virtual void writeEOF();
+       virtual void writeExec();
 
 protected:
        bool useAgainLabel();
index 899b27e..e1138fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2005 Adrian Thurston <thurston@cs.queensu.ca>
+ *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
  */
 
 /*  This file is part of Ragel.
index 7be111a..d703b37 100644 (file)
@@ -295,7 +295,7 @@ std::ostream &SplitCodeGen::PART_MAP()
        return out;
 }
 
-void SplitCodeGen::writeOutData()
+void SplitCodeGen::writeData()
 {
        out <<
                "static const int " << START() << " = " << START_STATE_ID() << ";\n"
@@ -371,7 +371,7 @@ std::ostream &SplitCodeGen::ALL_PARTITIONS()
 }
 
 
-void SplitCodeGen::writeOutExec()
+void SplitCodeGen::writeExec()
 {
        /* Must set labels immediately before writing because we may depend on the
         * noend write option. */
index 34067cd..82fc371 100644 (file)
@@ -39,9 +39,9 @@ public:
        std::ostream &STATE_GOTOS( int partition );
        std::ostream &PARTITION( int partition );
        std::ostream &ALL_PARTITIONS();
-       void writeOutData();
-       void writeOutExec();
-       void writeOutParts();
+       void writeData();
+       void writeExec();
+       void writeParts();
 
        void setLabelsNeeded( RedStateAp *fromState, InlineList *inlineList );
        void setLabelsNeeded( RedStateAp *fromState, RedTransAp *trans );
index 9e950d0..d377dc9 100644 (file)
@@ -674,7 +674,7 @@ void TabCodeGen::BREAK( ostream &ret, int targState )
        ret << CTRL_FLOW() << "goto _out;";
 }
 
-void TabCodeGen::writeOutData()
+void TabCodeGen::writeData()
 {
        /* If there are any transtion functions then output the array. If there
         * are none, don't bother emitting an empty array that won't be used. */
@@ -852,7 +852,7 @@ void TabCodeGen::COND_TRANSLATE()
                "\n";
 }
 
-void TabCodeGen::writeOutExec()
+void TabCodeGen::writeExec()
 {
        outLabelUsed = false;
 
@@ -979,7 +979,7 @@ void TabCodeGen::writeOutExec()
 }
 
 
-void TabCodeGen::writeOutEOF()
+void TabCodeGen::writeEOF()
 {
        if ( redFsm->anyEofActions() ) {
                out << 
index c946e80..745eb18 100644 (file)
@@ -41,8 +41,8 @@ class TabCodeGen : virtual public FsmCodeGen
 public:
        TabCodeGen( ostream &out ) : FsmCodeGen(out) {}
        virtual ~TabCodeGen() { }
-       virtual void writeOutData();
-       virtual void writeOutExec();
+       virtual void writeData();
+       virtual void writeExec();
 
 protected:
        std::ostream &TO_STATE_ACTION_SWITCH();
@@ -87,7 +87,7 @@ protected:
        virtual std::ostream &EOF_ACTION( RedStateAp *state );
        virtual std::ostream &TRANS_ACTION( RedTransAp *trans );
        virtual void calcIndexSize();
-       virtual void writeOutEOF();
+       virtual void writeEOF();
 };