Split out PYACC.Symbol into PYACC.Terminal and PYACC.Nonterminal with no precedence...
authorNick Downing <downing.nick@gmail.com>
Thu, 19 Jul 2018 00:18:26 +0000 (10:18 +1000)
committerNick Downing <downing.nick@gmail.com>
Thu, 19 Jul 2018 00:18:26 +0000 (10:18 +1000)
ast.py
bison_lr1dfa.py

diff --git a/ast.py b/ast.py
index 181f3ab..2423375 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -41,7 +41,7 @@ class Item(element.Element):
 class PYACC(element.Element):
   # internal classes
   class Symbol(element.Element):
-    # GENERATE ELEMENT(str name, list(int) character_set, int precedence) BEGIN
+    # GENERATE ELEMENT(str name, list(int) character_set) BEGIN
     def __init__(
       self,
       tag = 'PYACC_Symbol',
@@ -49,8 +49,7 @@ class PYACC(element.Element):
       text = '',
       children = [],
       name = '',
-      character_set = [],
-      precedence = -1
+      character_set = []
     ):
       element.Element.__init__(
         self,
@@ -65,11 +64,6 @@ class PYACC(element.Element):
       if isinstance(character_set, str) else
         character_set
       )
-      self.precedence = (
-        element.deserialize_int(precedence)
-      if isinstance(precedence, str) else
-        precedence
-      )
     def serialize(self, ref_list, indent = 0):
       element.Element.serialize(self, ref_list, indent)
       self.set('name', element.serialize_str(self.name))
@@ -77,7 +71,6 @@ class PYACC(element.Element):
         'character_set',
         ' '.join([element.serialize_int(i) for i in self.character_set])
       )
-      self.set('precedence', element.serialize_int(self.precedence))
     def deserialize(self, ref_list):
       element.Element.deserialize(self, ref_list)
       self.name = element.deserialize_str(self.get('name', ''))
@@ -85,7 +78,6 @@ class PYACC(element.Element):
         element.deserialize_int(i)
         for i in self.get('character_set', '').split()
       ]
-      self.precedence = element.deserialize_int(self.get('precedence', '-1'))
     def copy(self, factory = None):
       result = element.Element.copy(
         self,
@@ -93,7 +85,6 @@ class PYACC(element.Element):
       )
       result.name = self.name
       result.character_set = self.character_set
-      result.precedence = self.precedence
       return result
     def repr_serialize(self, params):
       element.Element.repr_serialize(self, params)
@@ -107,6 +98,53 @@ class PYACC(element.Element):
             ', '.join([repr(i) for i in self.character_set])
           )
         )
+    def __repr__(self):
+      params = []
+      self.repr_serialize(params)
+      return 'ast.PYACC.Symbol({0:s})'.format(', '.join(params))
+    # GENERATE END
+
+  class Terminal(Symbol):
+    # GENERATE ELEMENT(int precedence) BEGIN
+    def __init__(
+      self,
+      tag = 'PYACC_Terminal',
+      attrib = {},
+      text = '',
+      children = [],
+      name = '',
+      character_set = [],
+      precedence = -1
+    ):
+      PYACC.Symbol.__init__(
+        self,
+        tag,
+        attrib,
+        text,
+        children,
+        name,
+        character_set
+      )
+      self.precedence = (
+        element.deserialize_int(precedence)
+      if isinstance(precedence, str) else
+        precedence
+      )
+    def serialize(self, ref_list, indent = 0):
+      PYACC.Symbol.serialize(self, ref_list, indent)
+      self.set('precedence', element.serialize_int(self.precedence))
+    def deserialize(self, ref_list):
+      PYACC.Symbol.deserialize(self, ref_list)
+      self.precedence = element.deserialize_int(self.get('precedence', '-1'))
+    def copy(self, factory = None):
+      result = PYACC.Symbol.copy(
+        self,
+        Terminal if factory is None else factory
+      )
+      result.precedence = self.precedence
+      return result
+    def repr_serialize(self, params):
+      PYACC.Symbol.repr_serialize(self, params)
       if self.precedence != -1:
         params.append(
           'precedence = {0:s}'.format(repr(self.precedence))
@@ -114,7 +152,39 @@ class PYACC(element.Element):
     def __repr__(self):
       params = []
       self.repr_serialize(params)
-      return 'ast.PYACC.Symbol({0:s})'.format(', '.join(params))
+      return 'ast.PYACC.Terminal({0:s})'.format(', '.join(params))
+    # GENERATE END
+
+  class Nonterminal(Symbol):
+    # GENERATE ELEMENT() BEGIN
+    def __init__(
+      self,
+      tag = 'PYACC_Nonterminal',
+      attrib = {},
+      text = '',
+      children = [],
+      name = '',
+      character_set = []
+    ):
+      PYACC.Symbol.__init__(
+        self,
+        tag,
+        attrib,
+        text,
+        children,
+        name,
+        character_set
+      )
+    def copy(self, factory = None):
+      result = PYACC.Symbol.copy(
+        self,
+        Nonterminal if factory is None else factory
+      )
+      return result
+    def __repr__(self):
+      params = []
+      self.repr_serialize(params)
+      return 'ast.PYACC.Nonterminal({0:s})'.format(', '.join(params))
     # GENERATE END
 
   # syntax classes
@@ -560,11 +630,11 @@ class PYACC(element.Element):
         assert production.precedence_terminal == -1
         production.precedence_terminal = self[0].terminal
 
-    class Symbol(Item):
+    class SymbolRef(Item):
       # GENERATE ELEMENT(int symbol) BEGIN
       def __init__(
         self,
-        tag = 'PYACC_Production_Symbol',
+        tag = 'PYACC_Production_SymbolRef',
         attrib = {},
         text = '',
         children = [],
@@ -591,7 +661,7 @@ class PYACC(element.Element):
       def copy(self, factory = None):
         result = PYACC.Production.Item.copy(
           self,
-          Symbol if factory is None else factory
+          SymbolRef if factory is None else factory
         )
         result.symbol = self.symbol
         return result
@@ -604,7 +674,7 @@ class PYACC(element.Element):
       def __repr__(self):
         params = []
         self.repr_serialize(params)
-        return 'ast.PYACC.Production.Symbol({0:s})'.format(', '.join(params))
+        return 'ast.PYACC.Production.SymbolRef({0:s})'.format(', '.join(params))
       # GENERATE END
       def post_process(
         self,
@@ -621,20 +691,20 @@ class PYACC(element.Element):
             self.symbol = character_to_symbol[character]
             assert self.symbol >= 0
           else:
-            self.symbol = len(pyacc.terminal_symbols)
+            self.symbol = len(pyacc.terminals)
             character_to_symbol[character] = self.symbol
-            pyacc.terminal_symbols.append(
-              PYACC.Symbol(character_set = [character, character + 1])
+            pyacc.terminals.append(
+              PYACC.Terminal(character_set = [character, character + 1])
             )
         elif isinstance(self[0], PYACC.ID):
           name = element.get_text(self[0], 0)
           if name in name_to_symbol:
             self.symbol = name_to_symbol[name]
           else:
-            self.symbol = ~len(pyacc.nonterminal_symbols)
+            self.symbol = ~len(pyacc.nonterminals)
             name_to_symbol[name] = self.symbol
-            pyacc.nonterminal_symbols.append(
-              PYACC.Symbol(name = name, character_set = [])
+            pyacc.nonterminals.append(
+              PYACC.Nonterminal(name = name, character_set = [])
             )
         else:
           assert False
@@ -643,9 +713,9 @@ class PYACC(element.Element):
       def add_to_symbols(self, pyacc, last_action, symbols):
         assert last_action is None
         symbols.append(
-          (pyacc.terminal_symbols[self.symbol].character_set, [])
+          (pyacc.terminals[self.symbol].character_set, [])
         if self.symbol >= 0 else
-          ([], pyacc.nonterminal_symbols[~self.symbol].character_set)
+          ([], pyacc.nonterminals[~self.symbol].character_set)
         )
         return None
 
@@ -744,7 +814,7 @@ class PYACC(element.Element):
       if self.precedence_terminal == -1:
         self.precedence_terminal = self.last_terminal
 
-      character_set = pyacc.nonterminal_symbols[
+      character_set = pyacc.nonterminals[
         self.lhs_nonterminal
       ].character_set
       character = 1 + len(pyacc.productions)
@@ -773,7 +843,7 @@ class PYACC(element.Element):
       precedence = (
         -1
       if self.precedence_terminal == -1 else
-        pyacc.terminal_symbols[self.precedence_terminal].precedence
+        pyacc.terminals[self.precedence_terminal].precedence
       )
       if len(_lr1.precedences[3]) and _lr1.precedences[3][-1] == precedence:
         _lr1.precedences[2][-1] = len(_lr1.productions)
@@ -1119,10 +1189,10 @@ class PYACC(element.Element):
           self.terminal = character_to_symbol[character]
           assert self.terminal >= 0
         else:
-          self.terminal = len(pyacc.terminal_symbols)
+          self.terminal = len(pyacc.terminals)
           character_to_symbol[character] = self.terminal
-          pyacc.terminal_symbols.append(
-            PYACC.Symbol(character_set = [character, character + 1])
+          pyacc.terminals.append(
+            PYACC.Terminal(character_set = [character, character + 1])
           )
       elif isinstance(self[0], PYACC.ID):
         name = element.get_text(self[0], 0)
@@ -1130,21 +1200,21 @@ class PYACC(element.Element):
           self.terminal = name_to_symbol[name]
           assert self.terminal >= 0
         else:
-          self.terminal = len(pyacc.terminal_symbols)
+          self.terminal = len(pyacc.terminals)
           name_to_symbol[name] = self.terminal
-          pyacc.terminal_symbols.append(
-            PYACC.Symbol(name = name)
+          pyacc.terminals.append(
+            PYACC.Terminal(name = name)
           )
       else:
         assert False
       if self.user_token != -1:
-        assert len(pyacc.terminal_symbols[self.terminal].character_set) == 0
-        pyacc.terminal_symbols[self.terminal].character_set = (
+        assert len(pyacc.terminals[self.terminal].character_set) == 0
+        pyacc.terminals[self.terminal].character_set = (
           [self.user_token, self.user_token + 1]
         )
       if precedence != -1:
-        assert pyacc.terminal_symbols[self.terminal].precedence == -1
-        pyacc.terminal_symbols[self.terminal].precedence = precedence
+        assert pyacc.terminals[self.terminal].precedence == -1
+        pyacc.terminals[self.terminal].precedence = precedence
       return tag
 
   class NonterminalRef(TagOrSymbolRef):
@@ -1222,10 +1292,10 @@ class PYACC(element.Element):
           assert i < 0
           self.nonterminal = ~i
         else:
-          self.nonterminal = len(pyacc.nonterminal_symbols)
+          self.nonterminal = len(pyacc.nonterminals)
           name_to_symbol[name] = ~self.nonterminal
-          pyacc.nonterminal_symbols.append(
-            PYACC.Symbol(name = name, character_set = [])
+          pyacc.nonterminals.append(
+            PYACC.Nonterminal(name = name, character_set = [])
           )
       else:
         assert False
@@ -2432,7 +2502,7 @@ class PYACC(element.Element):
       return 'ast.PYACC.ValueReference({0:s})'.format(', '.join(params))
     # GENERATE END
 
-  # GENERATE ELEMENT(list(ref) prologue_text, list(ref) terminal_symbols, list(ref) nonterminal_symbols, list(ref) productions, int first_nonterminal, int start_nonterminal, list(int) associativities) BEGIN
+  # GENERATE ELEMENT(list(ref) prologue_text, list(ref) terminals, list(ref) nonterminals, list(ref) productions, int first_nonterminal, int start_nonterminal, list(int) associativities) BEGIN
   def __init__(
     self,
     tag = 'PYACC',
@@ -2440,8 +2510,8 @@ class PYACC(element.Element):
     text = '',
     children = [],
     prologue_text = [],
-    terminal_symbols = [],
-    nonterminal_symbols = [],
+    terminals = [],
+    nonterminals = [],
     productions = [],
     first_nonterminal = -1,
     start_nonterminal = -1,
@@ -2455,8 +2525,8 @@ class PYACC(element.Element):
       children
     )
     self.prologue_text = prologue_text
-    self.terminal_symbols = terminal_symbols
-    self.nonterminal_symbols = nonterminal_symbols
+    self.terminals = terminals
+    self.nonterminals = nonterminals
     self.productions = productions
     self.first_nonterminal = (
       element.deserialize_int(first_nonterminal)
@@ -2480,12 +2550,12 @@ class PYACC(element.Element):
       ' '.join([element.serialize_ref(i, ref_list) for i in self.prologue_text])
     )
     self.set(
-      'terminal_symbols',
-      ' '.join([element.serialize_ref(i, ref_list) for i in self.terminal_symbols])
+      'terminals',
+      ' '.join([element.serialize_ref(i, ref_list) for i in self.terminals])
     )
     self.set(
-      'nonterminal_symbols',
-      ' '.join([element.serialize_ref(i, ref_list) for i in self.nonterminal_symbols])
+      'nonterminals',
+      ' '.join([element.serialize_ref(i, ref_list) for i in self.nonterminals])
     )
     self.set(
       'productions',
@@ -2503,13 +2573,13 @@ class PYACC(element.Element):
       element.deserialize_ref(i, ref_list)
       for i in self.get('prologue_text', '').split()
     ]
-    self.terminal_symbols = [
+    self.terminals = [
       element.deserialize_ref(i, ref_list)
-      for i in self.get('terminal_symbols', '').split()
+      for i in self.get('terminals', '').split()
     ]
-    self.nonterminal_symbols = [
+    self.nonterminals = [
       element.deserialize_ref(i, ref_list)
-      for i in self.get('nonterminal_symbols', '').split()
+      for i in self.get('nonterminals', '').split()
     ]
     self.productions = [
       element.deserialize_ref(i, ref_list)
@@ -2527,8 +2597,8 @@ class PYACC(element.Element):
       PYACC if factory is None else factory
     )
     result.prologue_text = self.prologue_text
-    result.terminal_symbols = self.terminal_symbols
-    result.nonterminal_symbols = self.nonterminal_symbols
+    result.terminals = self.terminals
+    result.nonterminals = self.nonterminals
     result.productions = self.productions
     result.first_nonterminal = self.first_nonterminal
     result.start_nonterminal = self.start_nonterminal
@@ -2542,16 +2612,16 @@ class PYACC(element.Element):
           ', '.join([repr(i) for i in self.prologue_text])
         )
       )
-    if len(self.terminal_symbols):
+    if len(self.terminals):
       params.append(
-        'terminal_symbols = [{0:s}]'.format(
-          ', '.join([repr(i) for i in self.terminal_symbols])
+        'terminals = [{0:s}]'.format(
+          ', '.join([repr(i) for i in self.terminals])
         )
       )
-    if len(self.nonterminal_symbols):
+    if len(self.nonterminals):
       params.append(
-        'nonterminal_symbols = [{0:s}]'.format(
-          ', '.join([repr(i) for i in self.nonterminal_symbols])
+        'nonterminals = [{0:s}]'.format(
+          ', '.join([repr(i) for i in self.nonterminals])
         )
       )
     if len(self.productions):
@@ -2584,12 +2654,12 @@ class PYACC(element.Element):
     # variables that will be serialized
     self.prologue_text = []
     self.precedences = 0
-    self.terminal_symbols = [
-      PYACC.Symbol(name = '$eof', character_set = [0, 1]),
-      PYACC.Symbol(name = 'error'),
-      PYACC.Symbol(name = '$undefined')
+    self.terminals = [
+      PYACC.Terminal(name = '$eof', character_set = [0, 1]),
+      PYACC.Terminal(name = 'error'),
+      PYACC.Terminal(name = '$undefined')
     ]
-    self.nonterminal_symbols = []
+    self.nonterminals = []
     self.productions = []
 
     # variables that won't be serialized
@@ -2612,7 +2682,7 @@ class PYACC(element.Element):
 
     # fill in token numbers that are not characters or overridden by user
     token = 0x100
-    for i in self.terminal_symbols:
+    for i in self.terminals:
       if len(i.character_set) == 0:
         i.character_set = [token, token + 1]
         token += 1
@@ -2626,7 +2696,7 @@ class PYACC(element.Element):
           [
             (
               [],
-              self.nonterminal_symbols[self.start_nonterminal].character_set
+              self.nonterminals[self.start_nonterminal].character_set
             )
           ],
           # lookaheads (list of initial_set, can_be_empty)
@@ -2641,7 +2711,7 @@ class PYACC(element.Element):
       # associativities (indexed by *_prec value)
       self.associativities,
       # n_terminals
-      max([0] + [i.character_set[-1] for i in self.terminal_symbols]),
+      max([0] + [i.character_set[-1] for i in self.terminals]),
       # eof_terminal
       0
     )
@@ -2651,7 +2721,7 @@ class PYACC(element.Element):
     for character1, _, precedence in sorted(
       [
         k
-        for i in self.terminal_symbols
+        for i in self.terminals
         for j in range(0, len(i.character_set), 2)
         for k in [
           (i.character_set[j], True, -1),
@@ -2707,6 +2777,8 @@ tag_to_class = {
   'Item': Item,
   'PYACC': PYACC,
   'PYACC_Symbol': PYACC.Symbol,
+  'PYACC_Terminal': PYACC.Terminal,
+  'PYACC_Nonterminal': PYACC.Nonterminal,
   'PYACC_BracedCode': PYACC.BracedCode,
   'PYACC_BracedPredicate': PYACC.BracedPredicate,
   'PYACC_Char': PYACC.Char,
@@ -2720,7 +2792,7 @@ tag_to_class = {
   'PYACC_Production_Empty': PYACC.Production.Empty,
   'PYACC_Production_Merge': PYACC.Production.Merge,
   'PYACC_Production_Prec': PYACC.Production.Prec,
-  'PYACC_Production_Symbol': PYACC.Production.Symbol,
+  'PYACC_Production_SymbolRef': PYACC.Production.SymbolRef,
   'PYACC_Section': PYACC.Section,
   'PYACC_StackLocation': PYACC.StackLocation,
   'PYACC_StackReference': PYACC.StackReference,
index 8130764..a52c34e 100644 (file)
@@ -268,11 +268,11 @@ def generate(pyacc, skel_file, out_file):
     2, # '$undefined'
     numpy.int16
   )
-  for i in range(len(pyacc.terminal_symbols)):
-    for j in range(0, len(pyacc.terminal_symbols[i].character_set), 2):
+  for i in range(len(pyacc.terminals)):
+    for j in range(0, len(pyacc.terminals[i].character_set), 2):
       translate_terminals[
-        pyacc.terminal_symbols[i].character_set[j]:
-        pyacc.terminal_symbols[i].character_set[j + 1]
+        pyacc.terminals[i].character_set[j]:
+        pyacc.terminals[i].character_set[j + 1]
       ] = i
 
   # generate translate table for nonterminal symbols
@@ -282,19 +282,19 @@ def generate(pyacc, skel_file, out_file):
     (len(lr1dfa.productions) - 1,),
     numpy.int16
   )
-  for i in range(len(pyacc.nonterminal_symbols)):
-    for j in range(0, len(pyacc.nonterminal_symbols[i].character_set), 2):
+  for i in range(len(pyacc.nonterminals)):
+    for j in range(0, len(pyacc.nonterminals[i].character_set), 2):
       translate_nonterminals[
-        pyacc.nonterminal_symbols[i].character_set[j] - 1:
-        pyacc.nonterminal_symbols[i].character_set[j + 1] - 1
+        pyacc.nonterminals[i].character_set[j] - 1:
+        pyacc.nonterminals[i].character_set[j + 1] - 1
       ] = i
 
   # translate and compress the tables
   bison_lr1dfa = BisonLR1DFA(
     lr1dfa,
-    len(pyacc.terminal_symbols),
+    len(pyacc.terminals),
     translate_terminals,
-    len(pyacc.nonterminal_symbols),
+    len(pyacc.nonterminals),
     translate_nonterminals
   )
 
@@ -318,7 +318,7 @@ def generate(pyacc, skel_file, out_file):
               ','.join(
                 [
                   '\n    {0:s} = {1:d}'.format(i.name, i.character_set[0])
-                  for i in pyacc.terminal_symbols[3:]
+                  for i in pyacc.terminals[3:]
                   if len(i.name)
                 ]
               )
@@ -332,7 +332,7 @@ def generate(pyacc, skel_file, out_file):
               ''.join(
                 [
                   '#define {0:s} {1:d}\n'.format(i.name, i.character_set[0])
-                  for i in pyacc.terminal_symbols[3:]
+                  for i in pyacc.terminals[3:]
                   if len(i.name)
                 ]
               )
@@ -367,9 +367,9 @@ def generate(pyacc, skel_file, out_file):
                   '\\\\x{0:02x}'.format(i.character_set[0])
                 )
               )
-              for i in pyacc.terminal_symbols
+              for i in pyacc.terminals
             ] +
-            ['"{0:s}"'.format(i.name) for i in pyacc.nonterminal_symbols] +
+            ['"{0:s}"'.format(i.name) for i in pyacc.nonterminals] +
             ['YY_NULLPTR']
           ):
             if x + len(i) >= 70: