]> granicus.if.org Git - re2c/commitdiff
Fixed bug #119: "-f with -b/-g generates incorrect dispatch on fill labels".
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 25 Aug 2015 10:33:29 +0000 (11:33 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 25 Aug 2015 10:33:29 +0000 (11:33 +0100)
Consider the following example 1.re:
    /*!re2c
        "" {}
    */
With -if, re2c would generate correct dispatch:
    $ re2c -if 1.re
    /* Generated by re2c 0.14.3 on Tue Aug 25 10:41:45 2015 */
            switch (YYGETSTATE()) {
            default: goto yy0;
            case 0: goto yyFillLabel0;
            }
    yy0:
            YYSETSTATE(0);
    yyFillLabel0:
            {}

With -bif all positive YYGETSTATE() values will lead to yyFillLabel0,
which is clearly an error: values that are greater than 0 should lead
to yy0:
    $ re2c -bif 1.re
    /* Generated by re2c 0.14.3 on Tue Aug 25 10:40:32 2015 */
            if (YYGETSTATE() < 0) {
                    goto yy0;
            } else {
                    goto yyFillLabel0;
            }
    yy0:
            YYSETSTATE(0);
    yyFillLabel0:
            {}

With -gif the error is different: all values greater than 0 now cause
undefined behaviour (access to memory not within array bounds):
    $ re2c -gif 1.re
    /* Generated by re2c 0.14.3 on Tue Aug 25 10:47:41 2015 */
    {
            static void *yystable[] = {
                    &&yyFillLabel0,
            };
            if (YYGETSTATE() < 0) {
                    goto yy0;
            }
            goto *yystable[YYGETSTATE()];
    yy0:
            YYSETSTATE(0);
    yyFillLabel0:
            {}
    }

The situation gets even more tricky with re2c:state:abort configuration.
Besides, YYGETSTATE() macro is called multiple times with -b and -g,
which is not so good. Additional checks with -g don't help gain performance
either.

Fix: always generate simple switch.

23 files changed:
re2c/src/codegen/output.cc
re2c/src/codegen/output.h
re2c/test/bug119.bif.c [new file with mode: 0644]
re2c/test/bug119.bif.re [new file with mode: 0644]
re2c/test/bug119.gif.c [new file with mode: 0644]
re2c/test/bug119.gif.re [new file with mode: 0644]
re2c/test/bug119.if.c [new file with mode: 0644]
re2c/test/bug119.if.re [new file with mode: 0644]
re2c/test/bug119_abort.bif.c [new file with mode: 0644]
re2c/test/bug119_abort.bif.re [new file with mode: 0644]
re2c/test/bug119_abort.gif.c [new file with mode: 0644]
re2c/test/bug119_abort.gif.re [new file with mode: 0644]
re2c/test/bug119_abort.if.c [new file with mode: 0644]
re2c/test/bug119_abort.if.re [new file with mode: 0644]
re2c/test/condition_08.cbif.c
re2c/test/condition_09.cbif.c
re2c/test/condition_09.cgif.c
re2c/test/condition_10.cgif.c
re2c/test/condition_12.cgif.c
re2c/test/condition_14.cbif.c
re2c/test/condition_14.cgif.c
re2c/test/push.fb.c
re2c/test/push.fg.c

index bd5b945a0a6cd66ece1a869fde36afcd507d5a86..a55a5c05fcb0a4e68052b365789952a23e57da24 100644 (file)
@@ -360,93 +360,23 @@ Output::~Output ()
        }
 }
 
-void output_state_goto_sub (std::ostream & o, uint32_t ind, uint32_t start_label, int cMin, int cMax)
-{
-       if (cMin == cMax)
-       {
-               if (cMin == -1)
-               {
-                       o << indent(ind) << "goto " << labelPrefix << start_label << ";\n";
-               }
-               else
-               {
-                       o << indent(ind) << "goto " << mapCodeName["yyFillLabel"] << cMin << ";\n";
-               }
-       }
-       else
-       {
-               int cMid = cMin + ((cMax - cMin + 1) / 2);
-
-               o << indent(ind) << "if (" << output_get_state() << " < " << cMid << ") {\n";
-               output_state_goto_sub (o, ind + 1, start_label, cMin, cMid - 1);
-               o << indent(ind) << "} else {\n";
-               output_state_goto_sub (o, ind + 1, start_label, cMid, cMax);
-               o << indent(ind) << "}\n";
-       }
-}
-
 void output_state_goto (std::ostream & o, uint32_t ind, uint32_t start_label)
 {
-       if (gFlag)
+       o << indent(ind) << "switch (" << output_get_state() << ") {\n";
+       if (bUseStateAbort)
        {
-               o << indent(ind++) << "static void *" << mapCodeName["yystable"] << "[" << "] = {\n";
-
-               for (size_t i=0; i<last_fill_index; ++i)
-               {
-                       o << indent(ind) << "&&" << mapCodeName["yyFillLabel"] << i << ",\n";
-               }
-
-               o << indent(--ind) << "};\n";
-               o << "\n";
-
-               o << indent(ind) << "if (" << output_get_state();
-               if (bUseStateAbort)
-               {
-                       o << " == -1) {\n";
-               }
-               else
-               {
-                       o << " < 0) {\n";
-               }
-               o << indent(++ind) << "goto " << labelPrefix << start_label << ";\n";
-               if (bUseStateAbort)
-               {
-                       o << indent(--ind) << "} else if (" << output_get_state() << " < -1) {\n";
-                       o << indent(++ind) << "abort();\n";
-               }
-               o << indent(--ind) << "}\n";
-
-               o << indent(ind) << "goto *" << mapCodeName["yystable"] << "[" << output_get_state() << "];\n";
-
+               o << indent(ind) << "default: abort();\n";
+               o << indent(ind) << "case -1: goto " << labelPrefix << start_label << ";\n";
        }
-       else if (bFlag)
+       else
        {
-               output_state_goto_sub (o, ind, start_label, -1, last_fill_index-1);
-               if (bUseStateAbort)
-               {
-                       o << indent(ind) << "abort();\n";
-               }
+               o << indent(ind) << "default: goto " << labelPrefix << start_label << ";\n";
        }
-       else
+       for (uint32_t i = 0; i < last_fill_index; ++i)
        {
-               o << indent(ind) << "switch (" << output_get_state() << ") {\n";
-               if (bUseStateAbort)
-               {
-                       o << indent(ind) << "default: abort();\n";
-                       o << indent(ind) << "case -1: goto " << labelPrefix << start_label << ";\n";
-               }
-               else
-               {
-                       o << indent(ind) << "default: goto " << labelPrefix << start_label << ";\n";
-               }
-
-               for (size_t i=0; i<last_fill_index; ++i)
-               {
-                       o << indent(ind) << "case " << i << ": goto " << mapCodeName["yyFillLabel"] << i << ";\n";
-               }
-
-               o << indent(ind) << "}\n";
+               o << indent(ind) << "case " << i << ": goto " << mapCodeName["yyFillLabel"] << i << ";\n";
        }
+       o << indent(ind) << "}\n";
        if (bUseStateNext)
        {
                o << mapCodeName["yyNext"] << ":\n";
index 4a26865c0aba67539d4e3faa8bd06415fc0fc7c0..22e871e03cca5ead21c313f6f3571c8f8d371ac1 100644 (file)
@@ -147,7 +147,6 @@ void output_yyaccept_init (std::ostream &, uint32_t, bool);
 void output_yymaxfill (std::ostream &, uint32_t);
 
 // helpers
-void output_state_goto_sub (std::ostream & o, uint32_t ind, uint32_t start_label, int cMin, int cMax);
 std::string output_get_state ();
 
 } // namespace re2c
diff --git a/re2c/test/bug119.bif.c b/re2c/test/bug119.bif.c
new file mode 100644 (file)
index 0000000..0368ee8
--- /dev/null
@@ -0,0 +1,14 @@
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+/* Generated by re2c */
+
+
+       switch (YYGETSTATE()) {
+       default: abort();
+       case -1: goto yy0;
+       case 0: goto yyFillLabel0;
+       }
+yy0:
+       YYSETSTATE(0);
+yyFillLabel0:
+       {}
+
diff --git a/re2c/test/bug119.bif.re b/re2c/test/bug119.bif.re
new file mode 100644 (file)
index 0000000..7128c89
--- /dev/null
@@ -0,0 +1,4 @@
+/*!re2c
+    re2c:state:abort = 1;
+    "" {}
+*/
diff --git a/re2c/test/bug119.gif.c b/re2c/test/bug119.gif.c
new file mode 100644 (file)
index 0000000..d537eac
--- /dev/null
@@ -0,0 +1,16 @@
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+/* Generated by re2c */
+
+{
+
+       switch (YYGETSTATE()) {
+       default: abort();
+       case -1: goto yy0;
+       case 0: goto yyFillLabel0;
+       }
+yy0:
+       YYSETSTATE(0);
+yyFillLabel0:
+       {}
+}
+
diff --git a/re2c/test/bug119.gif.re b/re2c/test/bug119.gif.re
new file mode 100644 (file)
index 0000000..7128c89
--- /dev/null
@@ -0,0 +1,4 @@
+/*!re2c
+    re2c:state:abort = 1;
+    "" {}
+*/
diff --git a/re2c/test/bug119.if.c b/re2c/test/bug119.if.c
new file mode 100644 (file)
index 0000000..0368ee8
--- /dev/null
@@ -0,0 +1,14 @@
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+/* Generated by re2c */
+
+
+       switch (YYGETSTATE()) {
+       default: abort();
+       case -1: goto yy0;
+       case 0: goto yyFillLabel0;
+       }
+yy0:
+       YYSETSTATE(0);
+yyFillLabel0:
+       {}
+
diff --git a/re2c/test/bug119.if.re b/re2c/test/bug119.if.re
new file mode 100644 (file)
index 0000000..7128c89
--- /dev/null
@@ -0,0 +1,4 @@
+/*!re2c
+    re2c:state:abort = 1;
+    "" {}
+*/
diff --git a/re2c/test/bug119_abort.bif.c b/re2c/test/bug119_abort.bif.c
new file mode 100644 (file)
index 0000000..0368ee8
--- /dev/null
@@ -0,0 +1,14 @@
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+/* Generated by re2c */
+
+
+       switch (YYGETSTATE()) {
+       default: abort();
+       case -1: goto yy0;
+       case 0: goto yyFillLabel0;
+       }
+yy0:
+       YYSETSTATE(0);
+yyFillLabel0:
+       {}
+
diff --git a/re2c/test/bug119_abort.bif.re b/re2c/test/bug119_abort.bif.re
new file mode 100644 (file)
index 0000000..7128c89
--- /dev/null
@@ -0,0 +1,4 @@
+/*!re2c
+    re2c:state:abort = 1;
+    "" {}
+*/
diff --git a/re2c/test/bug119_abort.gif.c b/re2c/test/bug119_abort.gif.c
new file mode 100644 (file)
index 0000000..d537eac
--- /dev/null
@@ -0,0 +1,16 @@
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+/* Generated by re2c */
+
+{
+
+       switch (YYGETSTATE()) {
+       default: abort();
+       case -1: goto yy0;
+       case 0: goto yyFillLabel0;
+       }
+yy0:
+       YYSETSTATE(0);
+yyFillLabel0:
+       {}
+}
+
diff --git a/re2c/test/bug119_abort.gif.re b/re2c/test/bug119_abort.gif.re
new file mode 100644 (file)
index 0000000..7128c89
--- /dev/null
@@ -0,0 +1,4 @@
+/*!re2c
+    re2c:state:abort = 1;
+    "" {}
+*/
diff --git a/re2c/test/bug119_abort.if.c b/re2c/test/bug119_abort.if.c
new file mode 100644 (file)
index 0000000..0368ee8
--- /dev/null
@@ -0,0 +1,14 @@
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+/* Generated by re2c */
+
+
+       switch (YYGETSTATE()) {
+       default: abort();
+       case -1: goto yy0;
+       case 0: goto yyFillLabel0;
+       }
+yy0:
+       YYSETSTATE(0);
+yyFillLabel0:
+       {}
+
diff --git a/re2c/test/bug119_abort.if.re b/re2c/test/bug119_abort.if.re
new file mode 100644 (file)
index 0000000..7128c89
--- /dev/null
@@ -0,0 +1,4 @@
+/*!re2c
+    re2c:state:abort = 1;
+    "" {}
+*/
index c658768b829b1cc406ee5465e279a686a099a329..38c493ccfb7949ddda0414ee830914b82c650e04 100644 (file)
@@ -73,22 +73,12 @@ void scan(Scanner *s)
                s->tok = s->cur;
 
 
-               if (s->state < 1) {
-                       if (s->state < 0) {
-                               goto yy0;
-                       } else {
-                               goto yyFillLabel0;
-                       }
-               } else {
-                       if (s->state < 2) {
-                               goto yyFillLabel1;
-                       } else {
-                               if (s->state < 3) {
-                                       goto yyFillLabel2;
-                               } else {
-                                       goto yyFillLabel3;
-                               }
-                       }
+               switch (s->state) {
+               default: goto yy0;
+               case 0: goto yyFillLabel0;
+               case 1: goto yyFillLabel1;
+               case 2: goto yyFillLabel2;
+               case 3: goto yyFillLabel3;
                }
 yy0:
                if (s->cond < 2) {
index eb5ada8026dc3dc4340d88c0d2525c2e06952f1b..d7a1058d1e042fdaa46f86ac137ca8f51078c65a 100644 (file)
@@ -78,22 +78,12 @@ void scan(Scanner *s)
 {
        s->tok = s->cur;
 
-       if (s->state < 1) {
-               if (s->state < 0) {
-                       goto yy0;
-               } else {
-                       goto yyFillLabel0;
-               }
-       } else {
-               if (s->state < 2) {
-                       goto yyFillLabel1;
-               } else {
-                       if (s->state < 3) {
-                               goto yyFillLabel2;
-                       } else {
-                               goto yyFillLabel3;
-                       }
-               }
+       switch (s->state) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
+       case 3: goto yyFillLabel3;
        }
        for(;;)
        {
index c601babd452962a75e85c3d2b7027ba5f260b32d..c383451d3819665606cd1e1e8fe8e098977697a9 100644 (file)
@@ -78,17 +78,13 @@ void scan(Scanner *s)
 {
        s->tok = s->cur;
 
-       static void *yystable[] = {
-               &&yyFillLabel0,
-               &&yyFillLabel1,
-               &&yyFillLabel2,
-               &&yyFillLabel3,
-       };
-
-       if (s->state < 0) {
-               goto yy0;
+       switch (s->state) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
+       case 3: goto yyFillLabel3;
        }
-       goto *yystable[s->state];
        for(;;)
        {
                s->tok = s->cur;
index 8f8c3ac70ad536be2286c71ed51ebbad53e12255..fdca2378dbd20922b161e8f8ef303e89be550642 100644 (file)
@@ -78,17 +78,13 @@ void scan(Scanner *s)
 {
        s->tok = s->cur;
 
-       static void *yystable[] = {
-               &&yyFillLabel0,
-               &&yyFillLabel1,
-               &&yyFillLabel2,
-               &&yyFillLabel3,
-       };
-
-       if (s->state < 0) {
-               goto yy0;
+       switch (s->state) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
+       case 3: goto yyFillLabel3;
        }
-       goto *yystable[s->state];
        for(;;)
        {
                s->tok = s->cur;
index d306ad42647970c5bf66f645424739e40702e8f8..6caad89522571c1bbf10f30ffcbdf74c5cc3867e 100644 (file)
@@ -78,17 +78,13 @@ void scan(Scanner *s)
 {
        s->tok = s->cur;
 
-       static void *yystable[] = {
-               &&yyFillLabel0,
-               &&yyFillLabel1,
-               &&yyFillLabel2,
-               &&yyFillLabel3,
-       };
-
-       if (s->state < 0) {
-               goto yy0;
+       switch (s->state) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
+       case 3: goto yyFillLabel3;
        }
-       goto *yystable[s->state];
        for(;;)
        {
                s->tok = s->cur;
index a67d75234a131444c589c801a261fde475a18b2b..1ed996733647ff661c1adf3bc4af617a26267665 100644 (file)
@@ -78,22 +78,12 @@ void scan(Scanner *s)
 {
        s->tok = s->cur;
 
-       if (s->state < 1) {
-               if (s->state < 0) {
-                       goto yy0;
-               } else {
-                       goto yyFillLabel0;
-               }
-       } else {
-               if (s->state < 2) {
-                       goto yyFillLabel1;
-               } else {
-                       if (s->state < 3) {
-                               goto yyFillLabel2;
-                       } else {
-                               goto yyFillLabel3;
-                       }
-               }
+       switch (s->state) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
+       case 3: goto yyFillLabel3;
        }
        for(;;)
        {
index 3506c071575cf74e20a89944c61325803193a9ad..05c62c972d568b3a473c64ec2ff5c553520a1d9a 100644 (file)
@@ -78,17 +78,13 @@ void scan(Scanner *s)
 {
        s->tok = s->cur;
 
-       static void *yystable[] = {
-               &&yyFillLabel0,
-               &&yyFillLabel1,
-               &&yyFillLabel2,
-               &&yyFillLabel3,
-       };
-
-       if (s->state < 0) {
-               goto yy0;
+       switch (s->state) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
+       case 3: goto yyFillLabel3;
        }
-       goto *yystable[s->state];
        for(;;)
        {
                s->tok = s->cur;
index 0d4e0ac7b46b1c7b90384b2c63f1673d5700e3ab..f1a4f47ab8286d92df9730e6ecc997f1d0c388f6 100644 (file)
@@ -267,18 +267,11 @@ public:
                  0,   0,   0,   0,   0,   0,   0,   0, 
                  0,   0,   0,   0,   0,   0,   0,   0, 
        };
-       if (YYGETSTATE() < 1) {
-               if (YYGETSTATE() < 0) {
-                       goto yy0;
-               } else {
-                       goto yyFillLabel0;
-               }
-       } else {
-               if (YYGETSTATE() < 2) {
-                       goto yyFillLabel1;
-               } else {
-                       goto yyFillLabel2;
-               }
+       switch (YYGETSTATE()) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
        }
 yy0:
        YYSETSTATE(0);
@@ -367,7 +360,7 @@ yyFillLabel0:
 yy3:
 #line 246 "push.fb.re"
        { SEND(kIdentifier);     }
-#line 370 "<stdout>"
+#line 363 "<stdout>"
 yy4:
        yych = *++YYCURSOR;
        if (yych == 'o') goto yy64;
@@ -405,62 +398,62 @@ yy12:
 yy13:
 #line 247 "push.fb.re"
        { SEND(kDecimalConstant);}
-#line 408 "<stdout>"
+#line 401 "<stdout>"
 yy14:
        ++YYCURSOR;
 #line 249 "push.fb.re"
        { SEND(kEqual);          }
-#line 413 "<stdout>"
+#line 406 "<stdout>"
 yy16:
        ++YYCURSOR;
 #line 250 "push.fb.re"
        { SEND(kLeftParen);      }
-#line 418 "<stdout>"
+#line 411 "<stdout>"
 yy18:
        ++YYCURSOR;
 #line 251 "push.fb.re"
        { SEND(kRightParen);     }
-#line 423 "<stdout>"
+#line 416 "<stdout>"
 yy20:
        ++YYCURSOR;
 #line 252 "push.fb.re"
        { SEND(kMinus);          }
-#line 428 "<stdout>"
+#line 421 "<stdout>"
 yy22:
        ++YYCURSOR;
 #line 253 "push.fb.re"
        { SEND(kPlus);           }
-#line 433 "<stdout>"
+#line 426 "<stdout>"
 yy24:
        ++YYCURSOR;
 #line 254 "push.fb.re"
        { SEND(kStar);           }
-#line 438 "<stdout>"
+#line 431 "<stdout>"
 yy26:
        ++YYCURSOR;
 #line 255 "push.fb.re"
        { SEND(kSlash);          }
-#line 443 "<stdout>"
+#line 436 "<stdout>"
 yy28:
        ++YYCURSOR;
 #line 257 "push.fb.re"
        { SKIP();                }
-#line 448 "<stdout>"
+#line 441 "<stdout>"
 yy30:
        ++YYCURSOR;
 #line 258 "push.fb.re"
        { SKIP();                }
-#line 453 "<stdout>"
+#line 446 "<stdout>"
 yy32:
        ++YYCURSOR;
 #line 259 "push.fb.re"
        { send(kEOF); return 1;  }
-#line 458 "<stdout>"
+#line 451 "<stdout>"
 yy34:
        ++YYCURSOR;
 #line 260 "push.fb.re"
        { SEND(kUnknown);        }
-#line 463 "<stdout>"
+#line 456 "<stdout>"
 yy36:
        ++YYCURSOR;
        YYSETSTATE(1);
@@ -498,7 +491,7 @@ yy40:
        }
 #line 245 "push.fb.re"
        { SEND(kReturn);         }
-#line 501 "<stdout>"
+#line 494 "<stdout>"
 yy46:
        yych = *++YYCURSOR;
        if (yych != 'i') goto yy39;
@@ -512,7 +505,7 @@ yy46:
        }
 #line 244 "push.fb.re"
        { SEND(kWhile);          }
-#line 515 "<stdout>"
+#line 508 "<stdout>"
 yy51:
        yych = *++YYCURSOR;
        if (yych != 'e') goto yy39;
@@ -526,7 +519,7 @@ yy51:
        }
 #line 243 "push.fb.re"
        { SEND(kBreak);          }
-#line 529 "<stdout>"
+#line 522 "<stdout>"
 yy56:
        yych = *++YYCURSOR;
        if (yych != 't') goto yy39;
@@ -538,7 +531,7 @@ yy56:
        }
 #line 242 "push.fb.re"
        { SEND(kGoto);           }
-#line 541 "<stdout>"
+#line 534 "<stdout>"
 yy60:
        yych = *++YYCURSOR;
        if (yych != 's') goto yy39;
@@ -550,7 +543,7 @@ yy60:
        }
 #line 241 "push.fb.re"
        { SEND(kElse);           }
-#line 553 "<stdout>"
+#line 546 "<stdout>"
 yy64:
        yych = *++YYCURSOR;
        if (yych != 'r') goto yy39;
@@ -560,7 +553,7 @@ yy64:
        }
 #line 240 "push.fb.re"
        { SEND(kFor);            }
-#line 563 "<stdout>"
+#line 556 "<stdout>"
 yy67:
        ++YYCURSOR;
        if (yybm[0+(yych = *YYCURSOR)] & 128) {
@@ -568,7 +561,7 @@ yy67:
        }
 #line 239 "push.fb.re"
        { SEND(kIf);             }
-#line 571 "<stdout>"
+#line 564 "<stdout>"
 }
 #line 261 "push.fb.re"
 
index b685c66e84556f2ae4f54521f36385b2e6d3f685..37fb0051c691f22b7615bdb195a098f92171be4c 100644 (file)
@@ -267,16 +267,12 @@ public:
                  0,   0,   0,   0,   0,   0,   0,   0, 
                  0,   0,   0,   0,   0,   0,   0,   0, 
        };
-       static void *yystable[] = {
-               &&yyFillLabel0,
-               &&yyFillLabel1,
-               &&yyFillLabel2,
-       };
-
-       if (YYGETSTATE() < 0) {
-               goto yy0;
+       switch (YYGETSTATE()) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
        }
-       goto *yystable[YYGETSTATE()];
 yy0:
        YYSETSTATE(0);
        if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
@@ -326,7 +322,7 @@ yy2:
 yy3:
 #line 246 "push.fg.re"
        { SEND(kIdentifier);     }
-#line 329 "<stdout>"
+#line 325 "<stdout>"
 yy4:
        yych = *++YYCURSOR;
        if (yych == 'o') goto yy64;
@@ -364,62 +360,62 @@ yy12:
 yy13:
 #line 247 "push.fg.re"
        { SEND(kDecimalConstant);}
-#line 367 "<stdout>"
+#line 363 "<stdout>"
 yy14:
        ++YYCURSOR;
 #line 249 "push.fg.re"
        { SEND(kEqual);          }
-#line 372 "<stdout>"
+#line 368 "<stdout>"
 yy16:
        ++YYCURSOR;
 #line 250 "push.fg.re"
        { SEND(kLeftParen);      }
-#line 377 "<stdout>"
+#line 373 "<stdout>"
 yy18:
        ++YYCURSOR;
 #line 251 "push.fg.re"
        { SEND(kRightParen);     }
-#line 382 "<stdout>"
+#line 378 "<stdout>"
 yy20:
        ++YYCURSOR;
 #line 252 "push.fg.re"
        { SEND(kMinus);          }
-#line 387 "<stdout>"
+#line 383 "<stdout>"
 yy22:
        ++YYCURSOR;
 #line 253 "push.fg.re"
        { SEND(kPlus);           }
-#line 392 "<stdout>"
+#line 388 "<stdout>"
 yy24:
        ++YYCURSOR;
 #line 254 "push.fg.re"
        { SEND(kStar);           }
-#line 397 "<stdout>"
+#line 393 "<stdout>"
 yy26:
        ++YYCURSOR;
 #line 255 "push.fg.re"
        { SEND(kSlash);          }
-#line 402 "<stdout>"
+#line 398 "<stdout>"
 yy28:
        ++YYCURSOR;
 #line 257 "push.fg.re"
        { SKIP();                }
-#line 407 "<stdout>"
+#line 403 "<stdout>"
 yy30:
        ++YYCURSOR;
 #line 258 "push.fg.re"
        { SKIP();                }
-#line 412 "<stdout>"
+#line 408 "<stdout>"
 yy32:
        ++YYCURSOR;
 #line 259 "push.fg.re"
        { send(kEOF); return 1;  }
-#line 417 "<stdout>"
+#line 413 "<stdout>"
 yy34:
        ++YYCURSOR;
 #line 260 "push.fg.re"
        { SEND(kUnknown);        }
-#line 422 "<stdout>"
+#line 418 "<stdout>"
 yy36:
        ++YYCURSOR;
        YYSETSTATE(1);
@@ -457,7 +453,7 @@ yy40:
        }
 #line 245 "push.fg.re"
        { SEND(kReturn);         }
-#line 460 "<stdout>"
+#line 456 "<stdout>"
 yy46:
        yych = *++YYCURSOR;
        if (yych != 'i') goto yy39;
@@ -471,7 +467,7 @@ yy46:
        }
 #line 244 "push.fg.re"
        { SEND(kWhile);          }
-#line 474 "<stdout>"
+#line 470 "<stdout>"
 yy51:
        yych = *++YYCURSOR;
        if (yych != 'e') goto yy39;
@@ -485,7 +481,7 @@ yy51:
        }
 #line 243 "push.fg.re"
        { SEND(kBreak);          }
-#line 488 "<stdout>"
+#line 484 "<stdout>"
 yy56:
        yych = *++YYCURSOR;
        if (yych != 't') goto yy39;
@@ -497,7 +493,7 @@ yy56:
        }
 #line 242 "push.fg.re"
        { SEND(kGoto);           }
-#line 500 "<stdout>"
+#line 496 "<stdout>"
 yy60:
        yych = *++YYCURSOR;
        if (yych != 's') goto yy39;
@@ -509,7 +505,7 @@ yy60:
        }
 #line 241 "push.fg.re"
        { SEND(kElse);           }
-#line 512 "<stdout>"
+#line 508 "<stdout>"
 yy64:
        yych = *++YYCURSOR;
        if (yych != 'r') goto yy39;
@@ -519,7 +515,7 @@ yy64:
        }
 #line 240 "push.fg.re"
        { SEND(kFor);            }
-#line 522 "<stdout>"
+#line 518 "<stdout>"
 yy67:
        ++YYCURSOR;
        if (yybm[0+(yych = *YYCURSOR)] & 128) {
@@ -527,7 +523,7 @@ yy67:
        }
 #line 239 "push.fg.re"
        { SEND(kIf);             }
-#line 530 "<stdout>"
+#line 526 "<stdout>"
 }
 #line 261 "push.fg.re"