Split out PYACC.Section1Or2.Symbol into PYACC.TerminalRef, PYACC.NonterminalRef
authorNick Downing <downing.nick@gmail.com>
Wed, 18 Jul 2018 12:45:37 +0000 (22:45 +1000)
committerNick Downing <downing.nick@gmail.com>
Wed, 18 Jul 2018 13:12:28 +0000 (23:12 +1000)
ast.py

diff --git a/ast.py b/ast.py
index 9902f23..2571e13 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -375,6 +375,7 @@ class PYACC(element.Element):
       def post_process(
         self,
         pyacc,
+        section,
         production,
         character_to_symbol,
         name_to_symbol,
@@ -414,6 +415,7 @@ class PYACC(element.Element):
       def post_process(
         self,
         pyacc,
+        section,
         production,
         character_to_symbol,
         name_to_symbol,
@@ -557,39 +559,23 @@ class PYACC(element.Element):
       def post_process(
         self,
         pyacc,
+        section,
         production,
         character_to_symbol,
         name_to_symbol,
         last_terminal
       ):
-        # make this contain Section1Or2.Symbol eventually, duplicate for now
-        if isinstance(self[0], PYACC.Char):
-          character = ord(self[0].get_text())
-          assert character != 0 # would conflict with YYEOF
-          if character in character_to_symbol:
-            self.symbol = character_to_symbol[character]
-            assert self.symbol >= 0
-          else:
-            self.symbol = len(pyacc.terminal_symbols)
-            character_to_symbol[character] = self.symbol
-            pyacc.terminal_symbols.append(
-              PYACC.Symbol(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]
-            assert self.symbol >= 0
-          else:
-            self.symbol = len(pyacc.terminal_symbols)
-            name_to_symbol[name] = self.symbol
-            pyacc.terminal_symbols.append(
-              PYACC.Symbol(name = name)
-            )
-        else:
-          assert False
+        self[0].post_process(
+          pyacc,
+          section,
+          character_to_symbol,
+          name_to_symbol,
+          -1, # precedence
+          -1, # associativity
+          None # tag
+        )
         assert production.precedence_terminal == -1
-        production.precedence_terminal = self.symbol
+        production.precedence_terminal = self[0].terminal
         return last_terminal
 
     class Symbol(Item):
@@ -641,6 +627,7 @@ class PYACC(element.Element):
       def post_process(
         self,
         pyacc,
+        section,
         production,
         character_to_symbol,
         name_to_symbol,
@@ -742,6 +729,7 @@ class PYACC(element.Element):
     def post_process(
       self,
       pyacc,
+      section,
       lhs_nonterminal,
       character_to_symbol,
       name_to_symbol
@@ -753,6 +741,7 @@ class PYACC(element.Element):
       for i in self:
         last_terminal = i.post_process(
           pyacc,
+          section,
           self,
           character_to_symbol,
           name_to_symbol,
@@ -963,6 +952,295 @@ class PYACC(element.Element):
         ]
       )
 
+  class TagOrSymbolRef(element.Element):
+    # GENERATE ELEMENT() BEGIN
+    def __init__(
+      self,
+      tag = 'PYACC_TagOrSymbolRef',
+      attrib = {},
+      text = '',
+      children = []
+    ):
+      element.Element.__init__(
+        self,
+        tag,
+        attrib,
+        text,
+        children
+      )
+    def copy(self, factory = None):
+      result = element.Element.copy(
+        self,
+        TagOrSymbolRef if factory is None else factory
+      )
+      return result
+    def __repr__(self):
+      params = []
+      self.repr_serialize(params)
+      return 'ast.PYACC.TagOrSymbolRef({0:s})'.format(', '.join(params))
+    # GENERATE END
+    def post_process(
+      self,
+      pyacc,
+      section,
+      character_to_symbol,
+      name_to_symbol,
+      precedence,
+      associativity,
+      tag
+    ):
+      raise NotImplementedException
+
+  class Tag(TagOrSymbolRef):
+    # GENERATE ELEMENT(int type) BEGIN
+    def __init__(
+      self,
+      tag = 'PYACC_Tag',
+      attrib = {},
+      text = '',
+      children = [],
+      type = -1
+    ):
+      PYACC.TagOrSymbolRef.__init__(
+        self,
+        tag,
+        attrib,
+        text,
+        children
+      )
+      self.type = (
+        element.deserialize_int(type)
+      if isinstance(type, str) else
+        type
+      )
+    def serialize(self, ref_list, indent = 0):
+      PYACC.TagOrSymbolRef.serialize(self, ref_list, indent)
+      self.set('type', element.serialize_int(self.type))
+    def deserialize(self, ref_list):
+      PYACC.TagOrSymbolRef.deserialize(self, ref_list)
+      self.type = element.deserialize_int(self.get('type', '-1'))
+    def copy(self, factory = None):
+      result = PYACC.TagOrSymbolRef.copy(
+        self,
+        Tag if factory is None else factory
+      )
+      result.type = self.type
+      return result
+    def repr_serialize(self, params):
+      PYACC.TagOrSymbolRef.repr_serialize(self, params)
+      if self.type != -1:
+        params.append(
+          'type = {0:s}'.format(repr(self.type))
+        )
+    def __repr__(self):
+      params = []
+      self.repr_serialize(params)
+      return 'ast.PYACC.Tag({0:s})'.format(', '.join(params))
+    # GENERATE END
+    def post_process(
+      self,
+      pyacc,
+      section,
+      character_to_symbol,
+      name_to_symbol,
+      precedence,
+      associativity,
+      tag
+    ):
+      return self
+
+  class TerminalRef(TagOrSymbolRef):
+    # GENERATE ELEMENT(int terminal, int user_token) BEGIN
+    def __init__(
+      self,
+      tag = 'PYACC_TerminalRef',
+      attrib = {},
+      text = '',
+      children = [],
+      terminal = -1,
+      user_token = -1
+    ):
+      PYACC.TagOrSymbolRef.__init__(
+        self,
+        tag,
+        attrib,
+        text,
+        children
+      )
+      self.terminal = (
+        element.deserialize_int(terminal)
+      if isinstance(terminal, str) else
+        terminal
+      )
+      self.user_token = (
+        element.deserialize_int(user_token)
+      if isinstance(user_token, str) else
+        user_token
+      )
+    def serialize(self, ref_list, indent = 0):
+      PYACC.TagOrSymbolRef.serialize(self, ref_list, indent)
+      self.set('terminal', element.serialize_int(self.terminal))
+      self.set('user_token', element.serialize_int(self.user_token))
+    def deserialize(self, ref_list):
+      PYACC.TagOrSymbolRef.deserialize(self, ref_list)
+      self.terminal = element.deserialize_int(self.get('terminal', '-1'))
+      self.user_token = element.deserialize_int(self.get('user_token', '-1'))
+    def copy(self, factory = None):
+      result = PYACC.TagOrSymbolRef.copy(
+        self,
+        TerminalRef if factory is None else factory
+      )
+      result.terminal = self.terminal
+      result.user_token = self.user_token
+      return result
+    def repr_serialize(self, params):
+      PYACC.TagOrSymbolRef.repr_serialize(self, params)
+      if self.terminal != -1:
+        params.append(
+          'terminal = {0:s}'.format(repr(self.terminal))
+        )
+      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,
+      section,
+      character_to_symbol,
+      name_to_symbol,
+      precedence,
+      associativity,
+      tag
+    ):
+      if isinstance(self[0], PYACC.Char):
+        character = ord(self[0].get_text())
+        assert character != 0 # would conflict with YYEOF
+        if character in character_to_symbol:
+          self.terminal = character_to_symbol[character]
+          assert self.terminal >= 0
+        else:
+          self.terminal = len(pyacc.terminal_symbols)
+          character_to_symbol[character] = self.terminal
+          pyacc.terminal_symbols.append(
+            PYACC.Symbol(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.terminal = name_to_symbol[name]
+          assert self.terminal >= 0
+        else:
+          self.terminal = len(pyacc.terminal_symbols)
+          name_to_symbol[name] = self.terminal
+          pyacc.terminal_symbols.append(
+            PYACC.Symbol(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 = (
+          [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
+      if associativity != -1:
+        assert pyacc.terminal_symbols[self.terminal].associativity == -1
+        pyacc.terminal_symbols[self.terminal].associativity = associativity
+      return tag
+
+  class NonterminalRef(TagOrSymbolRef):
+    # GENERATE ELEMENT(int nonterminal, int user_token) BEGIN
+    def __init__(
+      self,
+      tag = 'PYACC_NonterminalRef',
+      attrib = {},
+      text = '',
+      children = [],
+      nonterminal = -1,
+      user_token = -1
+    ):
+      PYACC.TagOrSymbolRef.__init__(
+        self,
+        tag,
+        attrib,
+        text,
+        children
+      )
+      self.nonterminal = (
+        element.deserialize_int(nonterminal)
+      if isinstance(nonterminal, str) else
+        nonterminal
+      )
+      self.user_token = (
+        element.deserialize_int(user_token)
+      if isinstance(user_token, str) else
+        user_token
+      )
+    def serialize(self, ref_list, indent = 0):
+      PYACC.TagOrSymbolRef.serialize(self, ref_list, indent)
+      self.set('nonterminal', element.serialize_int(self.nonterminal))
+      self.set('user_token', element.serialize_int(self.user_token))
+    def deserialize(self, ref_list):
+      PYACC.TagOrSymbolRef.deserialize(self, ref_list)
+      self.nonterminal = element.deserialize_int(self.get('nonterminal', '-1'))
+      self.user_token = element.deserialize_int(self.get('user_token', '-1'))
+    def copy(self, factory = None):
+      result = PYACC.TagOrSymbolRef.copy(
+        self,
+        NonterminalRef if factory is None else factory
+      )
+      result.nonterminal = self.nonterminal
+      result.user_token = self.user_token
+      return result
+    def repr_serialize(self, params):
+      PYACC.TagOrSymbolRef.repr_serialize(self, params)
+      if self.nonterminal != -1:
+        params.append(
+          'nonterminal = {0:s}'.format(repr(self.nonterminal))
+        )
+      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(
+      self,
+      pyacc,
+      section,
+      character_to_symbol,
+      name_to_symbol,
+      precedence,
+      associativity,
+      tag
+    ):
+      if isinstance(self[0], PYACC.ID):
+        name = element.get_text(self[0], 0)
+        if name in name_to_symbol:
+          i = name_to_symbol[name]
+          assert i < 0
+          self.nonterminal = ~i
+        else:
+          self.nonterminal = len(pyacc.nonterminal_symbols)
+          name_to_symbol[name] = ~self.nonterminal
+          pyacc.nonterminal_symbols.append(
+            PYACC.Symbol(name = name, character_set = [])
+          )
+      else:
+        assert False
+      return tag
+
   class Text(element.Element):
     # GENERATE ELEMENT() BEGIN
     def __init__(
@@ -1162,7 +1440,6 @@ class PYACC(element.Element):
           section,
           character_to_symbol,
           name_to_symbol,
-          False, # is_nonterminal
           pyacc.precedences, # precedence
           self.type # associativity
         )
@@ -1207,234 +1484,10 @@ class PYACC(element.Element):
           section,
           character_to_symbol,
           name_to_symbol,
-          True, # is_nonterminal
           -1, # precedence
           -1 # associativity
         )
-        pyacc.start_nonterminal = ~self[0].symbol
-
-    class TagOrSymbol(element.Element):
-      # GENERATE ELEMENT() BEGIN
-      def __init__(
-        self,
-        tag = 'PYACC_Section1Or2_TagOrSymbol',
-        attrib = {},
-        text = '',
-        children = []
-      ):
-        element.Element.__init__(
-          self,
-          tag,
-          attrib,
-          text,
-          children
-        )
-      def copy(self, factory = None):
-        result = element.Element.copy(
-          self,
-          TagOrSymbol if factory is None else factory
-        )
-        return result
-      def __repr__(self):
-        params = []
-        self.repr_serialize(params)
-        return 'ast.PYACC.Section1Or2.TagOrSymbol({0:s})'.format(', '.join(params))
-      # GENERATE END
-      def post_process(
-        self,
-        pyacc,
-        section,
-        character_to_symbol,
-        name_to_symbol,
-        is_nonterminal,
-        precedence,
-        associativity,
-        tag
-      ):
-        raise NotImplementedException
-
-    class Tag(TagOrSymbol):
-      # GENERATE ELEMENT(int type) BEGIN
-      def __init__(
-        self,
-        tag = 'PYACC_Section1Or2_Tag',
-        attrib = {},
-        text = '',
-        children = [],
-        type = -1
-      ):
-        PYACC.Section1Or2.TagOrSymbol.__init__(
-          self,
-          tag,
-          attrib,
-          text,
-          children
-        )
-        self.type = (
-          element.deserialize_int(type)
-        if isinstance(type, str) else
-          type
-        )
-      def serialize(self, ref_list, indent = 0):
-        PYACC.Section1Or2.TagOrSymbol.serialize(self, ref_list, indent)
-        self.set('type', element.serialize_int(self.type))
-      def deserialize(self, ref_list):
-        PYACC.Section1Or2.TagOrSymbol.deserialize(self, ref_list)
-        self.type = element.deserialize_int(self.get('type', '-1'))
-      def copy(self, factory = None):
-        result = PYACC.Section1Or2.TagOrSymbol.copy(
-          self,
-          Tag if factory is None else factory
-        )
-        result.type = self.type
-        return result
-      def repr_serialize(self, params):
-        PYACC.Section1Or2.TagOrSymbol.repr_serialize(self, params)
-        if self.type != -1:
-          params.append(
-            'type = {0:s}'.format(repr(self.type))
-          )
-      def __repr__(self):
-        params = []
-        self.repr_serialize(params)
-        return 'ast.PYACC.Section1Or2.Tag({0:s})'.format(', '.join(params))
-      # GENERATE END
-      def post_process(
-        self,
-        pyacc,
-        section,
-        character_to_symbol,
-        name_to_symbol,
-        is_terminal,
-        precedence,
-        associativity,
-        tag
-      ):
-        return self
-
-    class Symbol(TagOrSymbol):
-      # GENERATE ELEMENT(int symbol, int token) BEGIN
-      def __init__(
-        self,
-        tag = 'PYACC_Section1Or2_Symbol',
-        attrib = {},
-        text = '',
-        children = [],
-        symbol = -1,
-        token = -1
-      ):
-        PYACC.Section1Or2.TagOrSymbol.__init__(
-          self,
-          tag,
-          attrib,
-          text,
-          children
-        )
-        self.symbol = (
-          element.deserialize_int(symbol)
-        if isinstance(symbol, str) else
-          symbol
-        )
-        self.token = (
-          element.deserialize_int(token)
-        if isinstance(token, str) else
-          token
-        )
-      def serialize(self, ref_list, indent = 0):
-        PYACC.Section1Or2.TagOrSymbol.serialize(self, ref_list, indent)
-        self.set('symbol', element.serialize_int(self.symbol))
-        self.set('token', element.serialize_int(self.token))
-      def deserialize(self, ref_list):
-        PYACC.Section1Or2.TagOrSymbol.deserialize(self, ref_list)
-        self.symbol = element.deserialize_int(self.get('symbol', '-1'))
-        self.token = element.deserialize_int(self.get('token', '-1'))
-      def copy(self, factory = None):
-        result = PYACC.Section1Or2.TagOrSymbol.copy(
-          self,
-          Symbol if factory is None else factory
-        )
-        result.symbol = self.symbol
-        result.token = self.token
-        return result
-      def repr_serialize(self, params):
-        PYACC.Section1Or2.TagOrSymbol.repr_serialize(self, params)
-        if self.symbol != -1:
-          params.append(
-            'symbol = {0:s}'.format(repr(self.symbol))
-          )
-        if self.token != -1:
-          params.append(
-            'token = {0:s}'.format(repr(self.token))
-          )
-      def __repr__(self):
-        params = []
-        self.repr_serialize(params)
-        return 'ast.PYACC.Section1Or2.Symbol({0:s})'.format(', '.join(params))
-      # GENERATE END
-      def post_process(
-        self,
-        pyacc,
-        section,
-        character_to_symbol,
-        name_to_symbol,
-        is_nonterminal,
-        precedence,
-        associativity,
-        tag
-      ):
-        if is_nonterminal:
-          if isinstance(self[0], PYACC.ID):
-            name = element.get_text(self[0], 0)
-            if name in name_to_symbol:
-              self.symbol = name_to_symbol[name]
-              assert self.symbol < 0
-            else:
-              self.symbol = ~len(pyacc.nonterminal_symbols)
-              name_to_symbol[name] = self.symbol
-              pyacc.nonterminal_symbols.append(
-                PYACC.Symbol(name = name, character_set = [])
-              )
-          else:
-            assert False
-          # in this case ignore token, precedence and associativity
-        else:
-          if isinstance(self[0], PYACC.Char):
-            character = ord(self[0].get_text())
-            assert character != 0 # would conflict with YYEOF
-            if character in character_to_symbol:
-              self.symbol = character_to_symbol[character]
-              assert self.symbol >= 0
-            else:
-              self.symbol = len(pyacc.terminal_symbols)
-              character_to_symbol[character] = self.symbol
-              pyacc.terminal_symbols.append(
-                PYACC.Symbol(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]
-              assert self.symbol >= 0
-            else:
-              self.symbol = len(pyacc.terminal_symbols)
-              name_to_symbol[name] = self.symbol
-              pyacc.terminal_symbols.append(
-                PYACC.Symbol(name = name)
-              )
-          else:
-            assert False
-          if self.token != -1:
-            assert len(pyacc.terminal_symbols[self.symbol].character_set) == 0
-            pyacc.terminal_symbols[self.symbol].character_set = (
-              [self.token, self.token + 1]
-            )
-          if precedence != -1:
-            assert pyacc.terminal_symbols[self.symbol].precedence == -1
-            pyacc.terminal_symbols[self.symbol].precedence = precedence
-          if associativity != -1:
-            assert pyacc.terminal_symbols[self.symbol].associativity == -1
-            pyacc.terminal_symbols[self.symbol].associativity = associativity
-        return tag
+        pyacc.start_nonterminal = self[0].nonterminal
 
     class TaggedSymbols(element.Element):
       # GENERATE ELEMENT() BEGIN
@@ -1469,7 +1522,6 @@ class PYACC(element.Element):
         section,
         character_to_symbol,
         name_to_symbol,
-        is_terminal,
         precedence,
         associativity
       ):
@@ -1480,7 +1532,6 @@ class PYACC(element.Element):
             section,
             character_to_symbol,
             name_to_symbol,
-            is_terminal,
             precedence,
             associativity,
             tag
@@ -1525,7 +1576,6 @@ class PYACC(element.Element):
           section,
           character_to_symbol,
           name_to_symbol,
-          False, # is_nonterminal
           -1, # precedence
           -1 # associativity
         )
@@ -2263,7 +2313,6 @@ class PYACC(element.Element):
           section,
           character_to_symbol,
           name_to_symbol,
-          True, # is_nonterminal
           -1, # precedence
           -1, # associativity
           None # tag
@@ -2271,7 +2320,8 @@ class PYACC(element.Element):
         for i in self[1:]:
           i.post_process(
             pyacc,
-            ~self[0].symbol,
+            section,
+            self[0].nonterminal,
             character_to_symbol,
             name_to_symbol
           )
@@ -2638,6 +2688,10 @@ tag_to_class = {
   'PYACC_StackLocation': PYACC.StackLocation,
   'PYACC_StackReference': PYACC.StackReference,
   'PYACC_String': PYACC.String,
+  'PYACC_TagOrSymbolRef': PYACC.TagOrSymbolRef,
+  'PYACC_Tag': PYACC.Tag,
+  'PYACC_TerminalRef': PYACC.TerminalRef,
+  'PYACC_NonterminalRef': PYACC.NonterminalRef,
   'PYACC_Text': PYACC.Text,
   'PYACC_Section1Or2': PYACC.Section1Or2,
   'PYACC_Section1Or2_Code': PYACC.Section1Or2.Code,
@@ -2646,9 +2700,6 @@ tag_to_class = {
   'PYACC_Section1Or2_NTerm': PYACC.Section1Or2.NTerm,
   'PYACC_Section1Or2_Precedence': PYACC.Section1Or2.Precedence,
   'PYACC_Section1Or2_Start': PYACC.Section1Or2.Start,
-  'PYACC_Section1Or2_TagOrSymbol': PYACC.Section1Or2.TagOrSymbol,
-  'PYACC_Section1Or2_Tag': PYACC.Section1Or2.Tag,
-  'PYACC_Section1Or2_Symbol': PYACC.Section1Or2.Symbol,
   'PYACC_Section1Or2_TaggedSymbols': PYACC.Section1Or2.TaggedSymbols,
   'PYACC_Section1Or2_Token': PYACC.Section1Or2.Token,
   'PYACC_Section1Or2_Type': PYACC.Section1Or2.Type,