Much improved version with proper handling for tokens, actions and so on
authorNick Downing <downing.nick@gmail.com>
Thu, 5 Jul 2018 23:07:02 +0000 (09:07 +1000)
committerNick Downing <downing.nick@gmail.com>
Thu, 5 Jul 2018 23:07:02 +0000 (09:07 +1000)
ast.py
bison_lr1dfa.py
skel/skel.y
skel/y.tab.c.patch

diff --git a/ast.py b/ast.py
index babcd76..1b9a054 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -1777,13 +1777,13 @@ class PYACC(element.Element):
                 )
               else:
                 assert False
-            elif isinstance(i, PYACC.Section2.Rules.RHS.Action):
+            elif isinstance(self[i], PYACC.Section2.Rules.RHS.Action):
               assert i == len(self) - 1
-              assert isinstance(self[i][0], PYACC.Text)
-              pyacc.actions_text.append(self[i][0])
+              assert isinstance(self[i][0], PYACC.BracedCode)
+              pyacc.actions_braced_code.append(self[i][0])
               break
           else:
-            pyacc.actions_text.append('')
+            pyacc.actions_braced_code.append(PYACC.BracedCode())
 
           character_set = pyacc.nonterminal_symbols[lhs_symbol].character_set
           character = len(pyacc.grammar)
@@ -1905,7 +1905,7 @@ class PYACC(element.Element):
     ):
       pass
 
-  # GENERATE ELEMENT(list(ref) prologue_text, set(int) characters_used, list(ref) terminal_symbols, list(ref) nonterminal_symbols, ref grammar, list(ref) actions_text) BEGIN
+  # GENERATE ELEMENT(list(ref) prologue_text, set(int) characters_used, list(ref) terminal_symbols, list(ref) nonterminal_symbols, ref grammar, list(ref) actions_braced_code) BEGIN
   def __init__(
     self,
     tag = 'PYACC',
@@ -1917,7 +1917,7 @@ class PYACC(element.Element):
     terminal_symbols = [],
     nonterminal_symbols = [],
     grammar = None,
-    actions_text = []
+    actions_braced_code = []
   ):
     element.Element.__init__(
       self,
@@ -1939,10 +1939,10 @@ class PYACC(element.Element):
     self.terminal_symbols = terminal_symbols
     self.nonterminal_symbols = nonterminal_symbols
     self.grammar = grammar
-    self.actions_text = (
-      [element.deserialize_str(i) for i in actions_text.split()]
-    if isinstance(actions_text, str) else
-      actions_text
+    self.actions_braced_code = (
+      [element.deserialize_str(i) for i in actions_braced_code.split()]
+    if isinstance(actions_braced_code, str) else
+      actions_braced_code
     )
   def serialize(self, ref_list, indent = 0):
     element.Element.serialize(self, ref_list, indent)
@@ -1964,8 +1964,8 @@ class PYACC(element.Element):
     )
     self.set('grammar', element.serialize_ref(self.grammar, ref_list))
     self.set(
-      'actions_text',
-      ' '.join([element.serialize_str(i) for i in self.actions_text])
+      'actions_braced_code',
+      ' '.join([element.serialize_str(i) for i in self.actions_braced_code])
     )
   def deserialize(self, ref_list):
     element.Element.deserialize(self, ref_list)
@@ -1988,9 +1988,9 @@ class PYACC(element.Element):
       for i in self.get('nonterminal_symbols', '').split()
     ]
     self.grammar = element.deserialize_ref(self.get('grammar', '-1'), ref_list)
-    self.actions_text = [
+    self.actions_braced_code = [
       element.deserialize_str(i)
-      for i in self.get('actions_text', '').split()
+      for i in self.get('actions_braced_code', '').split()
     ]
   def copy(self, factory = None):
     result = element.Element.copy(
@@ -2002,7 +2002,7 @@ class PYACC(element.Element):
     result.terminal_symbols = self.terminal_symbols
     result.nonterminal_symbols = self.nonterminal_symbols
     result.grammar = self.grammar
-    result.actions_text = self.actions_text
+    result.actions_braced_code = self.actions_braced_code
     return result
   def repr_serialize(self, params):
     element.Element.repr_serialize(self, params)
@@ -2034,10 +2034,10 @@ class PYACC(element.Element):
       params.append(
         'grammar = {0:s}'.format(repr(self.grammar))
       )
-    if len(self.actions_text):
+    if len(self.actions_braced_code):
       params.append(
-        'actions_text = [{0:s}]'.format(
-          ', '.join([repr(i) for i in self.actions_text])
+        'actions_braced_code = [{0:s}]'.format(
+          ', '.join([repr(i) for i in self.actions_braced_code])
         )
       )
   def __repr__(self):
@@ -2051,8 +2051,7 @@ class PYACC(element.Element):
     self.characters_used = set()
     self.terminal_symbols = [
       PYACC.Symbol(name = '$end', character_set = [0x100, 0x101]),
-      PYACC.Symbol(name = 'error', character_set = [0x101, 0x102]),
-      PYACC.Symbol(name = '$undefined', character_set = [0x102, 0x103])
+      PYACC.Symbol(name = 'error', character_set = [0x101, 0x102])
     ]
     self.nonterminal_symbols = []
     self.grammar = regex.Grammar(
@@ -2064,11 +2063,11 @@ class PYACC(element.Element):
         )
       ]
     )
-    self.actions_text = []
+    self.actions_braced_code = []
 
     # variables that won't be serialized
     # note: in name_to_symbol, >= 0 is terminal, < 0 is ~nonterminal
-    # (we do not bother storing the '$end' and '$undefined' entries)
+    # (we do not bother storing the '$end' entry, it can't be looked up)
     name_to_symbol = {'error': 1}
 
     # perform the semantic analysis pass
index 61fb89e..58b0b78 100644 (file)
@@ -8,7 +8,6 @@ class BisonLR1DFA:
     self,
     lr1dfa,
     n_terminals,
-    undefined_terminal,
     translate_terminals,
     n_nonterminals,
     translate_nonterminals
@@ -32,8 +31,6 @@ class BisonLR1DFA:
       ],
       0
     )
-    print(self.translate)
-    print(self.rule_data)
 
     # unpack tables into numpy arrays so we can manipulate them efficiently
     # note: the goto table is transposed with respect to the action table,
@@ -90,8 +87,6 @@ class BisonLR1DFA:
     action_table[mask] = -action_table[mask]
     assert numpy.all(goto_table != 0)
     goto_table[goto_table == -1] = 0
-    print(action_table)
-    print(goto_table)
 
     # find out which column the transition to each state occurs in, this
     # must be unique and is called the "accessing symbol" for the state
@@ -107,9 +102,8 @@ class BisonLR1DFA:
       )[numpy.newaxis, numpy.newaxis, :],
       0
     )
-    self.accessing_symbols = numpy.full(
+    self.accessing_symbols = numpy.zeros(
       (len(lr1dfa.states),),
-      undefined_terminal,
       numpy.int16
     )
     for i in range(1, len(lr1dfa.states)):
@@ -120,7 +114,6 @@ class BisonLR1DFA:
         self.accessing_symbols[i] = accessing_symbol[0]
       else:
         assert False
-    #print(self.accessing_symbols)
 
     # default_action is yydefact, default_goto is yydefgoto
     # find default reduce (most common negative value per action_table row)
@@ -254,7 +247,6 @@ class BisonLR1DFA:
     # n_productions == self.rule_data.shape[0]
     # n_nonterminals == self.goto_pointer.shape[0]
     self.n_terminals = n_terminals
-    self.undefined_terminal = undefined_terminal
 
 def generate(pyacc, skel_file, out_file):
   # generate the tables using an expanded character set, consisting of:
@@ -269,13 +261,11 @@ def generate(pyacc, skel_file, out_file):
   # than the internal way as only the set of lr1dfa.productions[] indices)
 
   # generate translate table for character literals and terminal symbols
-  n_terminals = 0
+  n_terminals = 1 # room for "$undefined"
   translate_terminals = numpy.zeros(
     (lr1dfa.n_terminals,),
     numpy.int16
   )
-  undefined_terminal = len(pyacc.characters_used) + 2
-  translate_terminals[:0x100] = undefined_terminal
   for i in sorted(pyacc.characters_used):
     translate_terminals[i] = n_terminals
     n_terminals += 1
@@ -307,7 +297,6 @@ def generate(pyacc, skel_file, out_file):
   bison_lr1dfa = BisonLR1DFA(
     lr1dfa,
     n_terminals,
-    undefined_terminal,
     translate_terminals,
     n_nonterminals,
     translate_nonterminals
@@ -325,6 +314,38 @@ def generate(pyacc, skel_file, out_file):
               ''.join([element.get_text(i, 0) for i in pyacc.prologue_text])
             )
           )
+        elif line == '/* GENERATE TOKENSEQUAL */\n':
+          fout.write(
+            '''/* GENERATE TOKENSEQUAL BEGIN */{0:s}
+/* GENERATE TOKENSEQUAL END*/
+'''.format(
+              ','.join(
+                [
+                  '\n    {0:s} = {1:d}'.format(
+                    pyacc.terminal_symbols[i].name,
+                    0x100 + i
+                  )
+                  for i in range(2, len(pyacc.terminal_symbols))
+                ]
+              )
+            )
+          )
+        elif line == '/* GENERATE TOKENS */\n':
+          fout.write(
+            '''/* GENERATE TOKENS BEGIN */
+{0:s}/* GENERATE TOKENS END*/
+'''.format(
+              ''.join(
+                [
+                  '#define {0:s} {1:d}\n'.format(
+                    pyacc.terminal_symbols[i].name,
+                    0x100 + i
+                  )
+                  for i in range(2, len(pyacc.terminal_symbols))
+                ]
+              )
+            )
+          )
         elif line == '/* GENERATE SECTION1SECOND */\n':
           fout.write(
             '''/* GENERATE SECTION1SECOND BEGIN */
@@ -343,7 +364,16 @@ def generate(pyacc, skel_file, out_file):
           # yytname (textual terminal/nonterminal name) wraps 70 columns
           x = 72
           yytname_lines = []
-          for i in ( 
+          for i in (
+            ['"$undefined"'] +
+            [
+              '"\'{0:s}\'"'.format(
+                chr(i)
+              if i >= 0x20 else
+                '\\x{0:02x}'.format(i)
+              )
+              for i in sorted(pyacc.characters_used)
+            ] +
             ['"{0:s}"'.format(i.name) for i in pyacc.terminal_symbols] +
             ['"{0:s}"'.format(i.name) for i in pyacc.nonterminal_symbols] +
             ['YY_NULLPTR']
@@ -382,22 +412,22 @@ def generate(pyacc, skel_file, out_file):
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
-#define YYUNDEFTOK {6:d}
-#define YYMAXUTOK {7:d}
+#define YYUNDEFTOK 0
+#define YYMAXUTOK {6:d}
 
-#define YYTRANSLATE(YYX)                                                \
+#define YYTRANSLATE(YYX)                                                \\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
    as returned by yylex, without out-of-bounds checking.  */
 static const yytype_uint16 yytranslate[] =
-{{{8:s}
+{{{7:s}
 }};
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
-{{{9:s}
+{{{8:s}
 }};
 #endif
 
@@ -405,7 +435,7 @@ static const yytype_uint16 yyrline[] =
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
-{{{10:s}
+{{{9:s}
 }};
 #endif
 
@@ -413,18 +443,18 @@ static const char *const yytname[] =
 /* YYTOKNUM[NUM] -- (External) token number corresponding to the
    (internal) symbol number NUM (which must be that of a token).  */
 static const yytype_uint16 yytoknum[] =
-{{{11:s}
+{{{10:s}
 }};
 # endif
 
-#define YYPACT_NINF {12:d}
+#define YYPACT_NINF {11:d}
 
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-1)))
+#define yypact_value_is_default(Yystate) \\
+  (!!((Yystate) == ({12:d})))
 
 #define YYTABLE_NINF -1
 
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(Yytable_value) \\
   0
 
   /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -490,8 +520,6 @@ static const yytype_uint16 yyr2[] =
               bison_lr1dfa.rule_data.shape[0],
               # YYNSTATES
               bison_lr1dfa.action_pointer.shape[0],
-              # YYUNDEFTOK
-              bison_lr1dfa.undefined_terminal,
               # YYMAXUTOK
               bison_lr1dfa.translate.shape[0] - 1,
               # yytranslate
@@ -542,6 +570,8 @@ static const yytype_uint16 yyr2[] =
               ),
               # YYPACT_NINF
               -bison_lr1dfa.entry_base,
+              # yypact_value_is_default
+              -bison_lr1dfa.entry_base,
               # yypact
               ','.join(
                 [
@@ -683,16 +713,22 @@ static const yytype_uint16 yyr2[] =
             '''/* GENERATE SECTION2 BEGIN */
 {0:s}/* GENERATE SECTION2 END */
 '''.format(
-              ''.join(
+              '\n'.join(
                 [
-                  '''case {0:d}:
-YY_RULE_SETUP
-{1:s}  YY_BREAK
+                  '''  case {0:d}:
+    {1:s}
+    break;
 '''.format(
                     i,
-                    element.get_text(pyacc.actions_text[i], 0)
+                    ''.join(
+                      [
+                        element.get_text(j, 0)
+                        for j in pyacc.actions_braced_code[i]
+                      ]
+                    )
                   )
-                  for i in range(1, len(pyacc.actions_text))
+                  for i in range(1, len(pyacc.actions_braced_code))
+                  if len(pyacc.actions_braced_code[i])
                 ]
               )
             )
index 4d4edcc..ba84706 100644 (file)
@@ -1,3 +1,4 @@
+%token TOKEN
 %start start
 %%
-start: ;
+start: { /* do something */ } | start TOKEN { /* do something else */ };
index e53c13c..97c971d 100644 (file)
@@ -1,5 +1,5 @@
---- y.tab.c.orig       2018-07-02 11:50:12.830973575 +1000
-+++ y.tab.c    2018-07-02 19:21:26.303835927 +1000
+--- y.tab.c.orig       2018-07-06 07:51:34.462479398 +1000
++++ y.tab.c    2018-07-06 09:03:46.066520012 +1000
 @@ -63,7 +63,7 @@
  
  /* Copy the first part of user declarations.  */
@@ -9,37 +9,51 @@
  
  # ifndef YY_NULLPTR
  #  if defined __cplusplus && 201103L <= __cplusplus
-@@ -107,7 +107,7 @@
+@@ -95,11 +95,11 @@
+ # define YYTOKENTYPE
+   enum yytokentype
+   {
+-    TOKEN = 258
++/* GENERATE TOKENSEQUAL */
+   };
+ #endif
+ /* Tokens.  */
+-#define TOKEN 258
++/* GENERATE TOKENS */
+ /* Value type.  */
+ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+@@ -117,7 +117,7 @@
  
  /* Copy the second part of user declarations.  */
  
--#line 111 "y.tab.c" /* yacc.c:358  */
+-#line 121 "y.tab.c" /* yacc.c:358  */
 +/* GENERATE SECTION1SECOND */
  
  #ifdef short
  # undef short
-@@ -346,155 +346,7 @@
+@@ -356,156 +356,8 @@
  # endif
  #endif /* !YYCOPY_NEEDED */
  
 -/* YYFINAL -- State number of the termination state.  */
 -#define YYFINAL  2
 -/* YYLAST -- Last index in YYTABLE.  */
--#define YYLAST   0
+-#define YYLAST   3
 -
 -/* YYNTOKENS -- Number of terminals.  */
--#define YYNTOKENS  3
+-#define YYNTOKENS  4
 -/* YYNNTS -- Number of nonterminals.  */
 -#define YYNNTS  2
 -/* YYNRULES -- Number of rules.  */
--#define YYNRULES  2
+-#define YYNRULES  3
 -/* YYNSTATES -- Number of states.  */
--#define YYNSTATES  3
+-#define YYNSTATES  4
 -
 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
 -   by yylex, with out-of-bounds checking.  */
 -#define YYUNDEFTOK  2
--#define YYMAXUTOK   257
+-#define YYMAXUTOK   258
 -
 -#define YYTRANSLATE(YYX)                                                \
 -  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 -       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 -       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 -       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
--       2,     2,     2,     2,     2,     2,     1,     2
+-       2,     2,     2,     2,     2,     2,     1,     2,     3
 -};
 -
 -#if YYDEBUG
 -  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 -static const yytype_uint8 yyrline[] =
 -{
--       0,     3,     3
+-       0,     4,     4,     4
 -};
 -#endif
 -
 -   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 -static const char *const yytname[] =
 -{
--  "$end", "error", "$undefined", "$accept", "start", YY_NULLPTR
+-  "$end", "error", "$undefined", "TOKEN", "$accept", "start", YY_NULLPTR
 -};
 -#endif
 -
 -   (internal) symbol number NUM (which must be that of a token).  */
 -static const yytype_uint16 yytoknum[] =
 -{
--       0,   256,   257
+-       0,   256,   257,   258
 -};
 -# endif
 -
 -     STATE-NUM.  */
 -static const yytype_int8 yypact[] =
 -{
--      -1,     0,    -1
+-      -1,     0,    -1,    -1
 -};
 -
 -  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
 -     means the default is an error.  */
 -static const yytype_uint8 yydefact[] =
 -{
--       2,     0,     1
+-       2,     0,     1,     3
 -};
 -
 -  /* YYPGOTO[NTERM-NUM].  */
 -     number is the opposite.  If YYTABLE_NINF, syntax error.  */
 -static const yytype_uint8 yytable[] =
 -{
--       2
+-       2,     0,     0,     3
 -};
 -
--static const yytype_uint8 yycheck[] =
+-static const yytype_int8 yycheck[] =
 -{
--       0
+-       0,    -1,    -1,     3
 -};
 -
 -  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
 -     symbol of state STATE-NUM.  */
 -static const yytype_uint8 yystos[] =
 -{
--       0,     4,     0
+-       0,     5,     0,     3
 -};
 -
 -  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 -static const yytype_uint8 yyr1[] =
 -{
--       0,     3,     4
+-       0,     4,     5,     5
 -};
 -
 -  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
 -static const yytype_uint8 yyr2[] =
 -{
--       0,     2,     0
+-       0,     2,     0,     2
 -};
 -
+-
 +/* GENERATE TABLES */
++ 
  #define yyerrok         (yyerrstatus = 0)
  #define yyclearin       (yychar = YYEMPTY)
-@@ -1169,8 +1021,7 @@
+ #define YYEMPTY         (-2)
+@@ -1179,20 +1031,8 @@
    YY_REDUCE_PRINT (yyn);
    switch (yyn)
      {
--      
--#line 1174 "y.tab.c" /* yacc.c:1648  */
-+/* GENERATE SECTION2 */      
+-        case 2:
+-#line 4 "skel.y" /* yacc.c:1648  */
+-    { /* do something */ }
+-#line 1186 "y.tab.c" /* yacc.c:1648  */
+-    break;
+-
+-  case 3:
+-#line 4 "skel.y" /* yacc.c:1648  */
+-    { /* do something else */ }
+-#line 1192 "y.tab.c" /* yacc.c:1648  */
+-    break;
+-
++/* GENERATE SECTION2 */
+-#line 1196 "y.tab.c" /* yacc.c:1648  */
        default: break;
      }
    /* User semantic actions sometimes alter yychar, and that requires
-@@ -1398,3 +1249,5 @@
+@@ -1420,3 +1260,5 @@
  #endif
    return yyresult;
  }