lm_switch needs to set p from tokend when there is no user action.
authorthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Mon, 21 Apr 2008 17:55:02 +0000 (17:55 +0000)
committerthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Mon, 21 Apr 2008 17:55:02 +0000 (17:55 +0000)
git-svn-id: http://svn.complang.org/ragel/trunk@442 052ea7fc-9027-0410-9066-f65837a77df0

ragel/xmlcodegen.cpp
rlgen-cd/fsmcodegen.cpp
rlgen-csharp/fsmcodegen.cpp
rlgen-java/javacodegen.cpp
rlgen-ruby/ruby-codegen.cpp
test/scan4.rl [new file with mode: 0644]

index 046c2df..16bd833 100644 (file)
@@ -311,6 +311,11 @@ void XMLCodeGen::writeLmSwitch( InlineItem *item )
        LongestMatch *longestMatch = item->longestMatch;
        out << "<lm_switch>\n";
 
+       /* We can't put the <exec> here because we may need to handle the error
+        * case and in that case p should not be changed. Instead use a default
+        * label in the switch to adjust p when user actions are not set. An id of
+        * -1 indicates the default. */
+
        if ( longestMatch->lmSwitchHandlesError ) {
                /* If the switch handles error then we should have also forced the
                 * error state. */
@@ -321,17 +326,27 @@ void XMLCodeGen::writeLmSwitch( InlineItem *item )
                out << "</sub_action>\n";
        }
        
+       bool needDefault = false;
        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 );
-                       out << "</sub_action>\n";
+               if ( lmi->inLmSelect ) {
+                       if ( lmi->action == 0 )
+                               needDefault = true;
+                       else {
+                               /* 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 );
+                               out << "</sub_action>\n";
+                       }
                }
        }
 
+       if ( needDefault ) {
+               out << "        <sub_action id=\"-1\"><exec><get_tokend>"
+                               "</get_tokend></exec></sub_action>\n";
+       }
+
        out << "    </lm_switch>";
 }
 
index 9508120..2d4a14c 100644 (file)
@@ -333,9 +333,15 @@ void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
        ret << 
                "       switch( " << ACT() << " ) {\n";
 
+       bool haveDefault = false;
        for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
-               ret << "        case " << lma->lmId << ":\n";
+               if ( lma->lmId < 0 ) {
+                       ret << "        default:\n";
+                       haveDefault = true;
+               }
+               else
+                       ret << "        case " << lma->lmId << ":\n";
 
                /* Write the block and close it off. */
                ret << "        {";
@@ -344,9 +350,11 @@ void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
 
                ret << "        break;\n";
        }
-       /* Default required for D code. */
+
+       if ( hostLang->lang == HostLang::D && !haveDefault )
+               ret << "        default: break;";
+
        ret << 
-               "       default: break;\n"
                "       }\n"
                "\t";
 }
index 09398d8..dafb4bc 100644 (file)
@@ -357,7 +357,10 @@ void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
 
        for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
-               ret << "        case " << lma->lmId << ":\n";
+               if ( lma->lmId < 0 )
+                       ret << "        default:\n";
+               else
+                       ret << "        case " << lma->lmId << ":\n";
 
                /* Write the block and close it off. */
                ret << "        {";
@@ -366,9 +369,8 @@ void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
 
                ret << "        break;\n";
        }
-       /* Default required for D code. */
+
        ret << 
-               "       default: break;\n"
                "       }\n"
                "\t";
 }
index 0859e0c..fdd4899 100644 (file)
@@ -1496,7 +1496,10 @@ void JavaTabCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
 
        for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
-               ret << "        case " << lma->lmId << ":\n";
+               if ( lma->lmId < 0 )
+                       ret << "        default:\n";
+               else
+                       ret << "        case " << lma->lmId << ":\n";
 
                /* Write the block and close it off. */
                ret << "        {";
@@ -1505,9 +1508,8 @@ void JavaTabCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
 
                ret << "        break;\n";
        }
-       /* Default required for D code. */
+
        ret << 
-               "       default: break;\n"
                "       }\n"
                "\t";
 }
index 94c9568..c7e923c 100644 (file)
@@ -570,7 +570,11 @@ void RubyCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
 
        for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
-               ret << "        when " << lma->lmId << " then\n";
+               if ( lma->lmId < 0 )
+                       ret << "        else\n";
+               else
+                       ret << "        when " << lma->lmId << " then\n";
+
 
                /* Write the block and close it off. */
                ret << "        begin";
diff --git a/test/scan4.rl b/test/scan4.rl
new file mode 100644 (file)
index 0000000..12d4d4c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * @LANG: indep
+ */
+ptr ts;
+ptr te;
+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 "pat1\n";
+         };
+
+         [ab]+ . 'c' => {
+                 prints "pat2\n";
+         };
+
+         any;
+       *|;
+}%%
+/* _____INPUT_____
+"ba a"
+_____INPUT_____ */
+/* _____OUTPUT_____
+pat1
+pat1
+ACCEPT
+_____OUTPUT_____ */