Combine PYACC.TerminalRef and PYACC.NonterminalRef into PYACC.SymbolRef (relying...
authorNick Downing <downing.nick@gmail.com>
Sun, 29 Jul 2018 00:09:17 +0000 (10:09 +1000)
committerNick Downing <downing.nick@gmail.com>
Sun, 29 Jul 2018 01:43:55 +0000 (11:43 +1000)
ast.py
bootstrap_pyacc.py

diff --git a/ast.py b/ast.py
index f4a1b4f..e68f830 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -136,11 +136,10 @@ class PYACC(element.Element):
     # GENERATE END
 
   class Symbol(TagOrSymbol):
-    TYPE_NONE = -1
     TYPE_TERMINAL = 0
     TYPE_NONTERMINAL = 1
 
-    # GENERATE ELEMENT(int _type, int _tag, list(int) character_set, int precedence) BEGIN
+    # GENERATE ELEMENT(int _type, int _tag, int precedence, list(int) character_set) BEGIN
     def __init__(
       self,
       tag = 'PYACC_Symbol',
@@ -151,8 +150,8 @@ class PYACC(element.Element):
       code_props = [],
       _type = -1,
       _tag = -1,
-      character_set = [],
-      precedence = -1
+      precedence = -1,
+      character_set = []
     ):
       PYACC.TagOrSymbol.__init__(
         self,
@@ -173,34 +172,34 @@ class PYACC(element.Element):
       if isinstance(_tag, str) else
         _tag
       )
-      self.character_set = (
-        [element.deserialize_int(i) for i in character_set.split()]
-      if isinstance(character_set, str) else
-        character_set
-      )
       self.precedence = (
         element.deserialize_int(precedence)
       if isinstance(precedence, str) else
         precedence
       )
+      self.character_set = (
+        [element.deserialize_int(i) for i in character_set.split()]
+      if isinstance(character_set, str) else
+        character_set
+      )
     def serialize(self, ref_list):
       PYACC.TagOrSymbol.serialize(self, ref_list)
       self.set('_type', element.serialize_int(self._type))
       self.set('_tag', element.serialize_int(self._tag))
+      self.set('precedence', element.serialize_int(self.precedence))
       self.set(
         '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):
       PYACC.TagOrSymbol.deserialize(self, ref_list)
       self._type = element.deserialize_int(self.get('_type', '-1'))
       self._tag = element.deserialize_int(self.get('_tag', '-1'))
+      self.precedence = element.deserialize_int(self.get('precedence', '-1'))
       self.character_set = [
         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 = PYACC.TagOrSymbol.copy(
         self,
@@ -208,8 +207,8 @@ class PYACC(element.Element):
       )
       result._type = self._type
       result._tag = self._tag
-      result.character_set = self.character_set
       result.precedence = self.precedence
+      result.character_set = self.character_set
       return result
     def repr_serialize(self, params):
       PYACC.TagOrSymbol.repr_serialize(self, params)
@@ -221,16 +220,16 @@ class PYACC(element.Element):
         params.append(
           '_tag = {0:s}'.format(repr(self._tag))
         )
+      if self.precedence != -1:
+        params.append(
+          'precedence = {0:s}'.format(repr(self.precedence))
+        )
       if len(self.character_set):
         params.append(
           'character_set = [{0:s}]'.format(
             ', '.join([repr(i) for i in self.character_set])
           )
         )
-      if self.precedence != -1:
-        params.append(
-          'precedence = {0:s}'.format(repr(self.precedence))
-        )
     def __repr__(self):
       params = []
       self.repr_serialize(params)
@@ -645,6 +644,7 @@ class PYACC(element.Element):
           name_to_symbol,
           string_to_symbol,
           name_to_tag,
+          PYACC.Symbol.TYPE_TERMINAL, # _type
           -1, # _tag
           -1 # precedence
         )
@@ -1153,6 +1153,7 @@ class PYACC(element.Element):
             name_to_symbol,
             string_to_symbol,
             name_to_tag,
+            PYACC.Symbol.TYPE_NONTERMINAL, # _type
             _tag,
             -1 # precedence
           )
@@ -1221,6 +1222,7 @@ class PYACC(element.Element):
             name_to_symbol,
             string_to_symbol,
             name_to_tag,
+            PYACC.Symbol.TYPE_TERMINAL, # _type
             _tag,
             len(pyacc.associativities) # precedence
           )
@@ -1269,6 +1271,8 @@ class PYACC(element.Element):
           name_to_symbol,
           string_to_symbol,
           name_to_tag,
+          PYACC.Symbol.TYPE_NONTERMINAL, # _type
+          -1, # _tag
           -1 # precedence
         )
         pyacc.start_nonterminal = self[0].symbol
@@ -1318,6 +1322,7 @@ class PYACC(element.Element):
             name_to_symbol,
             string_to_symbol,
             name_to_tag,
+            PYACC.Symbol.TYPE_TERMINAL, # _type
             _tag,
             -1 # precedence
           )
@@ -1367,6 +1372,7 @@ class PYACC(element.Element):
             name_to_symbol,
             string_to_symbol,
             name_to_tag,
+            -1, # _type
             _tag,
             -1 # precedence
           )
@@ -2387,6 +2393,7 @@ class PYACC(element.Element):
           name_to_symbol,
           string_to_symbol,
           name_to_tag,
+          PYACC.Symbol.TYPE_NONTERMINAL, # _type
           -1, # _tag
           -1 # precedence
         )
@@ -2493,6 +2500,7 @@ class PYACC(element.Element):
       name_to_symbol,
       string_to_symbol,
       name_to_tag,
+      _type,
       _tag,
       precedence
     ):
@@ -2564,6 +2572,7 @@ class PYACC(element.Element):
       name_to_symbol,
       string_to_symbol,
       name_to_tag,
+      _type,
       _tag,
       precedence
     ):
@@ -2601,13 +2610,14 @@ class PYACC(element.Element):
       pyacc.tags[self._tag].code_props[_type] = code
 
   class SymbolRef(TagOrSymbolRef):
-    # GENERATE ELEMENT(int symbol) BEGIN
+    # GENERATE ELEMENT(int user_token, int symbol) BEGIN
     def __init__(
       self,
       tag = 'PYACC_SymbolRef',
       attrib = {},
       text = '',
       children = [],
+      user_token = -1,
       symbol = -1
     ):
       PYACC.TagOrSymbolRef.__init__(
@@ -2617,6 +2627,11 @@ class PYACC(element.Element):
         text,
         children
       )
+      self.user_token = (
+        element.deserialize_int(user_token)
+      if isinstance(user_token, str) else
+        user_token
+      )
       self.symbol = (
         element.deserialize_int(symbol)
       if isinstance(symbol, str) else
@@ -2624,19 +2639,26 @@ class PYACC(element.Element):
       )
     def serialize(self, ref_list):
       PYACC.TagOrSymbolRef.serialize(self, ref_list)
+      self.set('user_token', element.serialize_int(self.user_token))
       self.set('symbol', element.serialize_int(self.symbol))
     def deserialize(self, ref_list):
       PYACC.TagOrSymbolRef.deserialize(self, ref_list)
+      self.user_token = element.deserialize_int(self.get('user_token', '-1'))
       self.symbol = element.deserialize_int(self.get('symbol', '-1'))
     def copy(self, factory = None):
       result = PYACC.TagOrSymbolRef.copy(
         self,
         SymbolRef if factory is None else factory
       )
+      result.user_token = self.user_token
       result.symbol = self.symbol
       return result
     def repr_serialize(self, params):
       PYACC.TagOrSymbolRef.repr_serialize(self, params)
+      if self.user_token != -1:
+        params.append(
+          'user_token = {0:s}'.format(repr(self.user_token))
+        )
       if self.symbol != -1:
         params.append(
           'symbol = {0:s}'.format(repr(self.symbol))
@@ -2646,95 +2668,6 @@ class PYACC(element.Element):
       self.repr_serialize(params)
       return 'ast.PYACC.SymbolRef({0:s})'.format(', '.join(params))
     # GENERATE END
-    def set_code_props(
-      self,
-      pyacc,
-      section,
-      character_to_symbol,
-      name_to_symbol,
-      string_to_symbol,
-      name_to_tag,
-      _type,
-      code
-    ):
-      if isinstance(self[0], PYACC.Char):
-        character = ord(self[0][0].get_text())
-        assert character != 0 # would conflict with YYEOF
-        if character in character_to_symbol:
-          self.symbol = character_to_symbol[character]
-          assert (
-            pyacc.symbols[self.symbol]._type ==
-            PYACC.Symbol.TYPE_TERMINAL
-          )
-        else:
-          self.symbol = len(pyacc.symbols)
-          character_to_symbol[character] = self.symbol
-          pyacc.symbols.append(
-            PYACC.Symbol(
-              code_props = [None, None],
-              _type = PYACC.Symbol.TYPE_TERMINAL,
-              character_set = [character, character + 1]
-            )
-          )
-      elif isinstance(self[0], PYACC.ID):
-        name = self[0].get_text()
-        self.symbol = name_to_symbol[name] # must already exist
-      elif isinstance(self[0], PYACC.String):
-        string = self[0][0].get_text()
-        self.symbol = string_to_symbol[string] # must already exist
-      else:
-        assert False
-      assert pyacc.symbols[self.symbol].code_props[_type] is None
-      pyacc.symbols[self.symbol].code_props[_type] = code
-
-  class TerminalRef(SymbolRef):
-    # GENERATE ELEMENT(int user_token) BEGIN
-    def __init__(
-      self,
-      tag = 'PYACC_TerminalRef',
-      attrib = {},
-      text = '',
-      children = [],
-      symbol = -1,
-      user_token = -1
-    ):
-      PYACC.SymbolRef.__init__(
-        self,
-        tag,
-        attrib,
-        text,
-        children,
-        symbol
-      )
-      self.user_token = (
-        element.deserialize_int(user_token)
-      if isinstance(user_token, str) else
-        user_token
-      )
-    def serialize(self, ref_list):
-      PYACC.SymbolRef.serialize(self, ref_list)
-      self.set('user_token', element.serialize_int(self.user_token))
-    def deserialize(self, ref_list):
-      PYACC.SymbolRef.deserialize(self, ref_list)
-      self.user_token = element.deserialize_int(self.get('user_token', '-1'))
-    def copy(self, factory = None):
-      result = PYACC.SymbolRef.copy(
-        self,
-        TerminalRef if factory is None else factory
-      )
-      result.user_token = self.user_token
-      return result
-    def repr_serialize(self, params):
-      PYACC.SymbolRef.repr_serialize(self, params)
-      if self.user_token != -1:
-        params.append(
-          'user_token = {0:s}'.format(repr(self.user_token))
-        )
-    def __repr__(self):
-      params = []
-      self.repr_serialize(params)
-      return 'ast.PYACC.TerminalRef({0:s})'.format(', '.join(params))
-    # GENERATE END
     def post_process(
       self,
       pyacc,
@@ -2743,6 +2676,7 @@ class PYACC(element.Element):
       name_to_symbol,
       string_to_symbol,
       name_to_tag,
+      _type,
       _tag,
       precedence
     ):
@@ -2751,10 +2685,6 @@ class PYACC(element.Element):
         assert character != 0 # would conflict with YYEOF
         if character in character_to_symbol:
           self.symbol = character_to_symbol[character]
-          assert (
-            pyacc.symbols[self.symbol]._type ==
-            PYACC.Symbol.TYPE_TERMINAL
-          )
         else:
           self.symbol = len(pyacc.symbols)
           character_to_symbol[character] = self.symbol
@@ -2769,29 +2699,23 @@ class PYACC(element.Element):
         name = self[0].get_text()
         if name in name_to_symbol:
           self.symbol = name_to_symbol[name]
-          assert (
-            pyacc.symbols[self.symbol]._type ==
-            PYACC.Symbol.TYPE_TERMINAL
-          )
         else:
           self.symbol = len(pyacc.symbols)
           name_to_symbol[name] = self.symbol
           pyacc.symbols.append(
             PYACC.Symbol(
               name = name,
-              _type = PYACC.Symbol.TYPE_TERMINAL,
-              code_props = [None, None]
+              code_props = [None, None],
+              character_set = []
             )
           )
       elif isinstance(self[0], PYACC.String):
         string = self[0][0].get_text()
         self.symbol = string_to_symbol[string] # must already exist
-        assert (
-          pyacc.symbols[self.symbol]._type ==
-          PYACC.Symbol.TYPE_TERMINAL
-        )
       else:
         assert False
+
+      # insert information from the SymbolRef element
       if self.user_token != -1:
         assert len(pyacc.symbols[self.symbol].character_set) == 0
         pyacc.symbols[self.symbol].character_set = (
@@ -2801,63 +2725,23 @@ class PYACC(element.Element):
         string = self[1][0].get_text()
         assert string not in string_to_symbol
         string_to_symbol[string] = self.symbol
+
+      # insert information from the calling contexxt
+      if _type != -1:
+        if pyacc.symbols[self.symbol]._type == -1:
+          pyacc.symbols[self.symbol]._type = _type
+        else:
+          assert pyacc.symbols[self.symbol]._type == _type
       if _tag != -1:
         assert pyacc.symbols[self.symbol]._tag == -1
         pyacc.symbols[self.symbol]._tag = _tag
       if precedence != -1:
         assert pyacc.symbols[self.symbol].precedence == -1
         pyacc.symbols[self.symbol].precedence = precedence
+
       return _tag
 
-  class NonterminalRef(SymbolRef):
-    # GENERATE ELEMENT(int user_token) BEGIN
-    def __init__(
-      self,
-      tag = 'PYACC_NonterminalRef',
-      attrib = {},
-      text = '',
-      children = [],
-      symbol = -1,
-      user_token = -1
-    ):
-      PYACC.SymbolRef.__init__(
-        self,
-        tag,
-        attrib,
-        text,
-        children,
-        symbol
-      )
-      self.user_token = (
-        element.deserialize_int(user_token)
-      if isinstance(user_token, str) else
-        user_token
-      )
-    def serialize(self, ref_list):
-      PYACC.SymbolRef.serialize(self, ref_list)
-      self.set('user_token', element.serialize_int(self.user_token))
-    def deserialize(self, ref_list):
-      PYACC.SymbolRef.deserialize(self, ref_list)
-      self.user_token = element.deserialize_int(self.get('user_token', '-1'))
-    def copy(self, factory = None):
-      result = PYACC.SymbolRef.copy(
-        self,
-        NonterminalRef if factory is None else factory
-      )
-      result.user_token = self.user_token
-      return result
-    def repr_serialize(self, params):
-      PYACC.SymbolRef.repr_serialize(self, params)
-      if self.user_token != -1:
-        params.append(
-          'user_token = {0:s}'.format(repr(self.user_token))
-        )
-    def __repr__(self):
-      params = []
-      self.repr_serialize(params)
-      return 'ast.PYACC.NonterminalRef({0:s})'.format(', '.join(params))
-    # GENERATE END
-    def post_process(
+    def set_code_props(
       self,
       pyacc,
       section,
@@ -2865,47 +2749,38 @@ class PYACC(element.Element):
       name_to_symbol,
       string_to_symbol,
       name_to_tag,
-      _tag,
-      precedence
+      _type,
+      code
     ):
-      if isinstance(self[0], PYACC.ID):
-        name = self[0].get_text()
-        if name in name_to_symbol:
-          self.symbol = name_to_symbol[name]
+      if isinstance(self[0], PYACC.Char):
+        character = ord(self[0][0].get_text())
+        assert character != 0 # would conflict with YYEOF
+        if character in character_to_symbol:
+          self.symbol = character_to_symbol[character]
           assert (
             pyacc.symbols[self.symbol]._type ==
-            PYACC.Symbol.TYPE_NONTERMINAL
+            PYACC.Symbol.TYPE_TERMINAL
           )
         else:
           self.symbol = len(pyacc.symbols)
-          name_to_symbol[name] = self.symbol
+          character_to_symbol[character] = self.symbol
           pyacc.symbols.append(
             PYACC.Symbol(
-              name = name,
               code_props = [None, None],
-              _type = PYACC.Symbol.TYPE_NONTERMINAL,
-              character_set = []
+              _type = PYACC.Symbol.TYPE_TERMINAL,
+              character_set = [character, character + 1]
             )
           )
+      elif isinstance(self[0], PYACC.ID):
+        name = self[0].get_text()
+        self.symbol = name_to_symbol[name] # must already exist
       elif isinstance(self[0], PYACC.String):
         string = self[0][0].get_text()
         self.symbol = string_to_symbol[string] # must already exist
-        assert (
-          pyacc.symbols[self.symbol]._type ==
-          PYACC.Symbol.TYPE_NONTERMINAL
-        )
       else:
         assert False
-      assert self.user_token == -1
-      if len(self) >= 2:
-        string = self[1][0].get_text()
-        assert string not in string_to_symbol
-        string_to_symbol[string] = self.symbol
-      if _tag != -1:
-        assert pyacc.symbols[self.symbol]._tag == -1
-        pyacc.symbols[self.symbol]._tag = _tag
-      assert precedence == -1
-      return _tag
+      assert pyacc.symbols[self.symbol].code_props[_type] is None
+      pyacc.symbols[self.symbol].code_props[_type] = code
 
   class Text(element.Element):
     class Item(element.Element):
@@ -3793,8 +3668,6 @@ tag_to_class = {
   'PYACC_TagOrSymbolRef': PYACC.TagOrSymbolRef,
   'PYACC_TagRef': PYACC.TagRef,
   'PYACC_SymbolRef': PYACC.SymbolRef,
-  'PYACC_TerminalRef': PYACC.TerminalRef,
-  'PYACC_NonterminalRef': PYACC.NonterminalRef,
   'PYACC_Text': PYACC.Text,
   'PYACC_Text_Item': PYACC.Text.Item,
   'PYACC_Text_Escape': PYACC.Text.Escape,
index 4d4c87f..f0a7223 100755 (executable)
@@ -46,6 +46,6 @@ with open(in_file) as fin:
 #element.serialize(pyacc, 'a.xml', 'utf-8')
 #pyacc = element.deserialize('a.xml', ast.factory, 'utf-8')
 pyacc.post_process()
-#element.serialize(pyacc, 'b.xml', 'utf-8')
-#pyacc = element.deserialize('b.xml', ast.factory, 'utf-8')
+element.serialize(pyacc, 'b.xml', 'utf-8')
+pyacc = element.deserialize('b.xml', ast.factory, 'utf-8')
 bison_lr1dfa.generate(pyacc, skel_file, out_file, defines_file)