yyparse: only calculate yytoken on yychar change
authorDavid Mitchell <davem@iabyn.com>
Sun, 4 Dec 2016 08:10:27 +0000 (08:10 +0000)
committerDavid Mitchell <davem@iabyn.com>
Mon, 5 Dec 2016 11:54:03 +0000 (11:54 +0000)
yytoken is a translated (via lookup table) version of parser->yychar.
So we only need to recalculate it when yychar changes (usually by
assigning the result of yylex() to it). This means when multiple
reductions are done without shifting another token, we skip the extra
overhead each time.

perly.act
perly.c
perly.h
perly.tab
perly.y

index 20f89b7..73c44e5 100644 (file)
--- a/perly.act
+++ b/perly.act
@@ -54,7 +54,7 @@ case 2:
                          PL_eval_root = (ps[0].val.opval);
                          (yyval.ival) = 0;
                          yyunlex();
-                         parser->yychar = YYEOF;
+                         parser->yychar = yytoken = YYEOF;
                        }
 
     break;
@@ -74,7 +74,7 @@ case 2:
                          PL_eval_root = (ps[0].val.opval);
                          (yyval.ival) = 0;
                          yyunlex();
-                         parser->yychar = YYEOF;
+                         parser->yychar = yytoken = YYEOF;
                        }
 
     break;
@@ -94,7 +94,7 @@ case 2:
                          PL_eval_root = (ps[0].val.opval);
                          (yyval.ival) = 0;
                          yyunlex();
-                         parser->yychar = YYEOF;
+                         parser->yychar = yytoken = YYEOF;
                        }
 
     break;
@@ -1977,6 +1977,6 @@ case 2:
     
 
 /* Generated from:
- * 5646c76b3536061de3b69eb5df829f5643d09247aa0d249bf2d2e050594b3679 perly.y
+ * a8b5527eacb1205d15c8c01acb4a8f99b494e5b453ddd68a2a2e7fca4be3302a perly.y
  * 153cba5d215c1a083a0459c43f4d55c45fd0a7093c197d7247a456dcde21ea53 regen_perly.pl
  * ex: set ro: */
diff --git a/perly.c b/perly.c
index af44956..5d1519f 100644 (file)
--- a/perly.c
+++ b/perly.c
@@ -289,6 +289,8 @@ Perl_yyparse (pTHX_ int gramtype)
 
     /* initialise state for this parse */
     parser->yychar = gramtype;
+    yytoken = YYTRANSLATE(NATIVE_TO_UNI(parser->yychar));
+
     parser->yyerrstatus = 0;
     parser->yylen = 0;
     Newx(parser->stack, YYINITDEPTH, yy_stack_frame);
@@ -325,40 +327,44 @@ Perl_yyparse (pTHX_ int gramtype)
 
             parser->yylen = 0;
 
-        /* Do appropriate processing given the current state.  */
-        /* Read a lookahead token if we need one and don't already have one.  */
+            /* Do appropriate processing given the current state. Read a
+             * lookahead token if we need one and don't already have one.
+             * */
 
-            /* First try to decide what to do without reference to lookahead token.  */
+            /* First try to decide what to do without reference to
+             * lookahead token. */
 
             yyn = yypact[yystate];
             if (yyn == YYPACT_NINF)
                 goto yydefault;
 
-            /* Not known => get a lookahead token if don't already have one.  */
+            /* Not known => get a lookahead token if don't already have
+             * one.  YYCHAR is either YYEMPTY or YYEOF or a valid
+             * lookahead symbol. */
 
-            /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
             if (parser->yychar == YYEMPTY) {
                 YYDPRINTF ((Perl_debug_log, "Reading a token:\n"));
                 parser->yychar = yylex();
+                assert(parser->yychar >= 0);
+                if (parser->yychar == YYEOF)
+                    YYDPRINTF ((Perl_debug_log, "Now at end of input.\n"));
+                /* perly.tab is shipped based on an ASCII system, so need
+                 * to index it with characters translated to ASCII.
+                 * Although it's not designed for this purpose, we can use
+                 * NATIVE_TO_UNI here.  It returns its argument on ASCII
+                 * platforms, and on EBCDIC translates native to ascii in
+                 * the 0-255 range, leaving everything else unchanged.
+                 * This jibes with yylex() returning some bare characters
+                 * in that range, but all tokens it returns are either 0,
+                 * or above 255.  There could be a problem if NULs weren't
+                 * 0, or were ever returned as raw chars by yylex() */
+                yytoken = YYTRANSLATE(NATIVE_TO_UNI(parser->yychar));
             }
 
-            if (parser->yychar <= YYEOF) {
-                parser->yychar = yytoken = YYEOF;
-                YYDPRINTF ((Perl_debug_log, "Now at end of input.\n"));
-            }
-            else {
-                /* perly.tab is shipped based on an ASCII system, so need to index it
-                 * with characters translated to ASCII.  Although it's not designed for
-                 * this purpose, we can use NATIVE_TO_UNI here.  It returns its
-                 * argument on ASCII platforms, and on EBCDIC translates native to
-                 * ascii in the 0-255 range, leaving everything else unchanged.  This
-                 * jibes with yylex() returning some bare characters in that range, but
-                 * all tokens it returns are either 0, or above 255.  There could be a
-                 * problem if NULs weren't 0, or were ever returned as raw chars by
-                 * yylex() */
-                yytoken = YYTRANSLATE (NATIVE_TO_UNI(parser->yychar));
-                YYDSYMPRINTF ("Next token is", yytoken, &parser->yylval);
-            }
+            /* make sure no-ones changed yychar since the last call to yylex */
+            assert(yytoken == YYTRANSLATE(NATIVE_TO_UNI(parser->yychar)));
+            YYDSYMPRINTF("lookahead token is", yytoken, &parser->yylval);
+
 
             /* If the proper action on seeing token YYTOKEN is to reduce or to
              * detect an error, take that action.
diff --git a/perly.h b/perly.h
index 1f5d6d7..a7e9a43 100644 (file)
--- a/perly.h
+++ b/perly.h
@@ -7,11 +7,11 @@
 #define PERL_BISON_VERSION  30000
 
 #ifdef PERL_CORE
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.0.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -160,7 +160,7 @@ S_is_opval_token(int type) {
 #endif /* PERL_IN_TOKE_C */
 #endif /* PERL_CORE */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
+typedef union YYSTYPE YYSTYPE;
 union YYSTYPE
 {
 
@@ -171,8 +171,6 @@ union YYSTYPE
     GV *gvval;
 
 };
-
-typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
 #endif
@@ -183,6 +181,6 @@ int yyparse (void);
 
 
 /* Generated from:
- * 5646c76b3536061de3b69eb5df829f5643d09247aa0d249bf2d2e050594b3679 perly.y
+ * a8b5527eacb1205d15c8c01acb4a8f99b494e5b453ddd68a2a2e7fca4be3302a perly.y
  * 153cba5d215c1a083a0459c43f4d55c45fd0a7093c197d7247a456dcde21ea53 regen_perly.pl
  * ex: set ro: */
index 0d0b607..e4065de 100644 (file)
--- a/perly.tab
+++ b/perly.tab
@@ -1109,6 +1109,6 @@ static const toketypes yy_type_tab[] =
 };
 
 /* Generated from:
- * 5646c76b3536061de3b69eb5df829f5643d09247aa0d249bf2d2e050594b3679 perly.y
+ * a8b5527eacb1205d15c8c01acb4a8f99b494e5b453ddd68a2a2e7fca4be3302a perly.y
  * 153cba5d215c1a083a0459c43f4d55c45fd0a7093c197d7247a456dcde21ea53 regen_perly.pl
  * ex: set ro: */
diff --git a/perly.y b/perly.y
index 3440dcb..7d57dea 100644 (file)
--- a/perly.y
+++ b/perly.y
@@ -143,7 +143,7 @@ grammar     :       GRAMPROG
                          PL_eval_root = $3;
                          $$ = 0;
                          yyunlex();
-                         parser->yychar = YYEOF;
+                         parser->yychar = yytoken = YYEOF;
                        }
        |       GRAMBARESTMT
                        {
@@ -155,7 +155,7 @@ grammar     :       GRAMPROG
                          PL_eval_root = $3;
                          $$ = 0;
                          yyunlex();
-                         parser->yychar = YYEOF;
+                         parser->yychar = yytoken = YYEOF;
                        }
        |       GRAMFULLSTMT
                        {
@@ -167,7 +167,7 @@ grammar     :       GRAMPROG
                          PL_eval_root = $3;
                          $$ = 0;
                          yyunlex();
-                         parser->yychar = YYEOF;
+                         parser->yychar = yytoken = YYEOF;
                        }
        |       GRAMSTMTSEQ
                        {