The p varialbe is now set up at the beginning of a scanner action, rather than
authorthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Sat, 9 Jun 2007 22:01:46 +0000 (22:01 +0000)
committerthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Sat, 9 Jun 2007 22:01:46 +0000 (22:01 +0000)
at the end. This leaves scanner actions free to manipulate p and removes the
need for the special holdTE and execTE (TE for tokend) versions of hold and
exec. It also removes the need to set p = tokend-1 immediately before any
control flow.

The error handler in LmSwitch actions is now generated by the frontend, rather
than the backend. This became possible when the creation of the error state was
moved to the frontend.

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

ragel/xmlcodegen.cpp
redfsm/gendata.cpp
redfsm/redfsm.cpp
redfsm/redfsm.h
redfsm/xmlparse.kl
rlgen-cd/fsmcodegen.cpp
rlgen-cd/ipgotocodegen.cpp
rlgen-cd/splitcodegen.cpp
rlgen-java/javacodegen.cpp
rlgen-ruby/rubycodegen.cpp
test/scan1.rl [new file with mode: 0644]

index a12c56b..f5d210a 100644 (file)
@@ -195,11 +195,6 @@ bool isLmItem( InlineItem *context )
 
 void XMLCodeGen::writeCtrlFlow( InlineItem *item, InlineItem *context )
 {
-       if ( isLmItem( context ) ) {
-               out << "<sub_action>";
-               out << "<exec><get_tokend></get_tokend></exec>";
-       }
-
        switch ( item->type ) {
        case InlineItem::Goto:
                writeGoto( item, context );
@@ -227,34 +222,18 @@ void XMLCodeGen::writeCtrlFlow( InlineItem *item, InlineItem *context )
                break;
        default: break;
        }
-
-       if ( isLmItem( context ) )
-               out << "</sub_action>";
 }
 
-void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem * )
 {
-       if ( isLmItem( context ) ) {
-               switch ( item->type ) {
-               case InlineItem::Hold:
-                       out << "<holdte></holdte>";
-                       break;
-               case InlineItem::Exec:
-                       writeActionExecTE( item );
-                       break;
-               default: break;
-               }
-       }
-       else {
-               switch ( item->type ) {
-               case InlineItem::Hold:
-                       out << "<hold></hold>";
-                       break;
-               case InlineItem::Exec:
-                       writeActionExec( item );
-                       break;
-               default: break;
-               }
+       switch ( item->type ) {
+       case InlineItem::Hold:
+               out << "<hold></hold>";
+               break;
+       case InlineItem::Exec:
+               writeActionExec( item );
+               break;
+       default: break;
        }
 }
 
@@ -337,55 +316,65 @@ void XMLCodeGen::writeActionExecTE( InlineItem *item )
 void XMLCodeGen::writeLmOnLast( InlineItem *item )
 {
        out << "<set_tokend>1</set_tokend>";
+
        if ( item->longestMatchPart->action != 0 ) {
                out << "<sub_action>";
                writeInlineList( item->longestMatchPart->action->inlineList, item );
                out << "</sub_action>";
        }
-       out << "<exec><get_tokend></get_tokend></exec>";
 }
 
 void XMLCodeGen::writeLmOnNext( InlineItem *item )
 {
        out << "<set_tokend>0</set_tokend>";
+       out << "<hold></hold>";
+
        if ( item->longestMatchPart->action != 0 ) {
                out << "<sub_action>";
                writeInlineList( item->longestMatchPart->action->inlineList, item );
                out << "</sub_action>";
        }
-       out << "<exec><get_tokend></get_tokend></exec>";
 }
 
 void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
 {
+       out << "<exec><get_tokend></get_tokend></exec>";
+
        if ( item->longestMatchPart->action != 0 ) {
                out << "<sub_action>";
                writeInlineList( item->longestMatchPart->action->inlineList, item );
                out << "</sub_action>";
        }
-       out << "<exec><get_tokend></get_tokend></exec>";
 }
 
 void XMLCodeGen::writeLmSwitch( InlineItem *item )
 {
+
        LongestMatch *longestMatch = item->longestMatch;
+       out << "<lm_switch>\n";
 
-       out << "<lm_switch";
-       if ( longestMatch->lmSwitchHandlesError )
-               out << " handles_error=\"t\"";
-       out << ">\n";
+       if ( longestMatch->lmSwitchHandlesError ) {
+               /* If the switch handles error then we should have also forced the
+                * error state. */
+               assert( fsm->errState != 0 );
+
+               out << "      <sub_action id=\"0\">";
+               out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
+               out << "</sub_action>\n";
+       }
        
        for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
                if ( lmi->inLmSelect && lmi->action != 0 ) {
                        /* Open the action. Write it with the context that sets up _p 
                         * when doing control flow changes from inside the machine. */
                        out << "      <sub_action id=\"" << lmi->longestMatchId << "\">";
+                       out << "<exec><get_tokend></get_tokend></exec>";
                        writeInlineList( lmi->action->inlineList, item );
                        out << "</sub_action>\n";
                }
        }
 
-       out << "    </lm_switch><exec><get_tokend></get_tokend></exec>";
+       out << "    </lm_switch>";
 }
 
 void XMLCodeGen::writeInlineList( InlineList *inlineList, InlineItem *context )
index 8f06de0..dac4f6b 100644 (file)
@@ -451,9 +451,6 @@ void CodeGenData::analyzeAction( Action *act, InlineList *inlineList )
 
                        if ( item->type == InlineItem::Break )
                                redFsm->bAnyRegBreak = true;
-
-                       if ( item->type == InlineItem::LmSwitch && item->handlesError )
-                               redFsm->bAnyLmSwitchError = true;
                }
 
                if ( item->children != 0 )
index 73e3b7e..2eadcd2 100644 (file)
@@ -62,7 +62,6 @@ RedFsmAp::RedFsmAp()
        bAnyRegNextStmt(false),
        bAnyRegCurStateRef(false),
        bAnyRegBreak(false),
-       bAnyLmSwitchError(false),
        bAnyConditions(false)
 {
 }
index 8098a3c..85e49f4 100644 (file)
@@ -73,7 +73,7 @@ struct InlineItem
        InlineItem( const InputLoc &loc, Type type ) : 
                loc(loc), data(0), targId(0), targState(0), 
                lmId(0), children(0), offset(0),
-               handlesError(false), type(type) { }
+               type(type) { }
        
        InputLoc loc;
        char *data;
@@ -82,7 +82,6 @@ struct InlineItem
        int lmId;
        InlineList *children;
        int offset;
-       bool handlesError;
        Type type;
 
        InlineItem *prev, *next;
@@ -429,7 +428,6 @@ struct RedFsmAp
        bool bAnyRegNextStmt;
        bool bAnyRegCurStateRef;
        bool bAnyRegBreak;
-       bool bAnyLmSwitchError;
        bool bAnyConditions;
 
        int maxState;
@@ -464,7 +462,6 @@ struct RedFsmAp
        bool anyRegNextStmt()           { return bAnyRegNextStmt; }
        bool anyRegCurStateRef()        { return bAnyRegCurStateRef; }
        bool anyRegBreak()              { return bAnyRegBreak; }
-       bool anyLmSwitchError()         { return bAnyLmSwitchError; }
        bool anyConditions()            { return bAnyConditions; }
 
 
index 30f6d3a..cf3be17 100644 (file)
@@ -717,14 +717,8 @@ tag_sub_action: TAG_sub_action inline_list '/' TAG_sub_action
 # Action switches.
 tag_lm_switch: TAG_lm_switch lm_action_list '/' TAG_lm_switch
        final {
-               bool handlesError = false;
-               Attribute *handlesErrorAttr = $1->tag->findAttr( "handles_error" );
-               if ( handlesErrorAttr != 0 )
-                       handlesError = true;
-
                $$->inlineItem = new InlineItem( InputLoc(), InlineItem::LmSwitch );
                $$->inlineItem->children = $2->inlineList;
-               $$->inlineItem->handlesError = handlesError;
        };
 
 nonterm lm_action_list
index 7fc8d5e..93a5150 100644 (file)
@@ -333,14 +333,6 @@ void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
        ret << 
                "       switch( " << ACT() << " ) {\n";
 
-       /* If the switch handles error then we also forced the error state. It
-        * will exist. */
-       if ( item->handlesError ) {
-               ret << "        case 0: " << TOKEND() << " = " << TOKSTART() << "; ";
-               GOTO( ret, redFsm->errState->id, inFinish );
-               ret << "\n";
-       }
-
        for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
                ret << "        case " << lma->lmId << ":\n";
index ed65be5..4e55e1f 100644 (file)
@@ -293,9 +293,6 @@ void IpGotoCodeGen::setLabelsNeeded()
                for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
                        st->labelNeeded = false;
 
-               if ( redFsm->errState != 0 && redFsm->anyLmSwitchError() )
-                       redFsm->errState->labelNeeded = true;
-
                /* Walk all transitions and set only those that have targs. */
                for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
                        /* If there is no action with a next statement, then the label will be
index d703b37..f43362e 100644 (file)
@@ -486,9 +486,6 @@ void SplitCodeGen::setLabelsNeeded()
                for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
                        trans->labelNeeded = false;
 
-               if ( redFsm->errState != 0 && redFsm->anyLmSwitchError() )
-                       redFsm->errState->labelNeeded = true;
-
                /* Walk all transitions and set only those that have targs. */
                for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
                        for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ )
index bbce5bb..c941ea7 100644 (file)
@@ -1369,14 +1369,6 @@ void JavaTabCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
        ret << 
                "       switch( " << ACT() << " ) {\n";
 
-       /* If the switch handles error then we also forced the error state. It
-        * will exist. */
-       if ( item->handlesError ) {
-               ret << "        case 0: " << TOKEND() << " = " << TOKSTART() << "; ";
-               GOTO( ret, redFsm->errState->id, inFinish );
-               ret << "\n";
-       }
-
        for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
                ret << "        case " << lma->lmId << ":\n";
index bd556b1..1f68925 100644 (file)
@@ -61,7 +61,7 @@ void RubyCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish )
        out << INDENT_U() << "begin"
                << INDENT_S() <<     CS() << " = " << gotoDest
                << INDENT_S() <<     "_again.call " << CTRL_FLOW()
-               << INDENT_D() << "end";
+               << INDENT_D() << "end ";
 }
 
 void RubyCodeGen::GOTO_EXPR( ostream &out, InlineItem *ilItem, bool inFinish )
@@ -71,7 +71,7 @@ void RubyCodeGen::GOTO_EXPR( ostream &out, InlineItem *ilItem, bool inFinish )
        INLINE_LIST( out, ilItem->children, 0, inFinish );
        out << ")"
                << INDENT_S() <<    "_again.call " << CTRL_FLOW()
-               << INDENT_D() << "end";
+               << INDENT_D() << "end ";
 }
 
 void RubyCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish )
@@ -81,7 +81,7 @@ void RubyCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish
                << INDENT_S() <<   TOP() << "+= 1" 
                << INDENT_S() <<   CS() << " = " << callDest 
                << INDENT_S() <<   "_again.call " << CTRL_FLOW() 
-               << INDENT_D() << "end";
+               << INDENT_D() << "end ";
 }
 
 void RubyCodeGen::CALL_EXPR(ostream &out, InlineItem *ilItem, int targState, bool inFinish )
@@ -93,7 +93,7 @@ void RubyCodeGen::CALL_EXPR(ostream &out, InlineItem *ilItem, int targState, boo
        INLINE_LIST( out, ilItem->children, targState, inFinish );
        out << ")" 
                << INDENT_S() <<   "_again.call " << CTRL_FLOW() 
-               << INDENT_D() << "end";
+               << INDENT_D() << "end ";
 }
 
 void RubyCodeGen::RET( ostream &out, bool inFinish )
@@ -102,7 +102,7 @@ void RubyCodeGen::RET( ostream &out, bool inFinish )
                << INDENT_S() <<   TOP() << " -= 1" 
                << INDENT_S() <<   CS() << " = " << STACK() << "[" << TOP() << "]" 
                << INDENT_S() <<   "_again.call " << CTRL_FLOW() 
-               << INDENT_D() << "end";
+               << INDENT_D() << "end ";
 }
 
 void RubyCodeGen::BREAK( ostream &out, int targState )
@@ -1411,14 +1411,6 @@ void RubyCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
        ret << 
                "       case " << ACT() << "\n";
 
-       /* If the switch handles error then we also forced the error state. It
-        * will exist. */
-       if ( item->handlesError ) {
-               ret << "        when 0: " << TOKEND() << " = " << TOKSTART() << "; ";
-               GOTO( ret, redFsm->errState->id, inFinish );
-               ret << "\n";
-       }
-
        for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
                ret << "        when " << lma->lmId << ":\n";
diff --git a/test/scan1.rl b/test/scan1.rl
new file mode 100644 (file)
index 0000000..5b32e89
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * @LANG: indep
+ */
+ptr tokstart;
+ptr tokend;
+int act;
+int token;
+%%
+%%{
+       machine scanner;
+
+       # Warning: changing the patterns or the input string will affect the
+       # coverage of the scanner action types.
+       main := |*
+               'a' => { 
+                       prints "on last     ";
+                       if ( p+1 == tokend )
+                               prints "yes";
+                       prints "\n";
+               };
+
+               'b'+ => {
+                       prints "on next     ";
+                       if ( p+1 == tokend )
+                               prints "yes";
+                       prints "\n";
+               };
+
+               'c1' 'dxxx'? => {
+                       prints "on lag      ";
+                       if ( p+1 == tokend )
+                               prints "yes";
+                       prints "\n";
+               };
+
+               'd1' => {
+                       prints "lm switch1  ";
+                       if ( p+1 == tokend )
+                               prints "yes";
+                       prints "\n";
+               };
+               'd2' => {
+                       prints "lm switch2  ";
+                       if ( p+1 == tokend )
+                               prints "yes";
+                       prints "\n";
+               };
+
+               [d0-9]+ '.';
+
+               '\n';
+       *|;
+}%%
+/* _____INPUT_____
+"abbc1d1d2\n"
+_____INPUT_____ */
+/* _____OUTPUT_____
+on last     yes
+on next     yes
+on lag      yes
+lm switch1  yes
+lm switch2  yes
+ACCEPT
+_____OUTPUT_____ */