Change how start conditions are represented in the syntax tree
authorNick Downing <downing.nick@gmail.com>
Sat, 30 Jun 2018 03:08:23 +0000 (13:08 +1000)
committerNick Downing <downing.nick@gmail.com>
Sat, 30 Jun 2018 03:08:23 +0000 (13:08 +1000)
ast.py
plex.py

diff --git a/ast.py b/ast.py
index 67a2931..4707cdb 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -353,11 +353,11 @@ class Options(Option):
     for i in self:
       i.process(options)
 
-class StartCondDecl(element.Element):
+class StartConditionDecl(element.Element):
   # GENERATE ELEMENT(bool exclusive) BEGIN
   def __init__(
     self,
-    tag = 'StartCondDecl',
+    tag = 'StartConditionDecl',
     attrib = {},
     text = '',
     children = [],
@@ -384,7 +384,7 @@ class StartCondDecl(element.Element):
   def copy(self, factory = None):
     result = element.Element.copy(
       self,
-      StartCondDecl if factory is None else factory
+      StartConditionDecl if factory is None else factory
     )
     result.exclusive = self.exclusive
     return result
@@ -397,7 +397,7 @@ class StartCondDecl(element.Element):
   def __repr__(self):
     params = []
     self.repr_serialize(params)
-    return 'ast.StartCondDecl({0:s})'.format(', '.join(params))
+    return 'ast.StartConditionDecl({0:s})'.format(', '.join(params))
   # GENERATE END
 
 class Section2(element.Element):
@@ -428,14 +428,15 @@ class Section2(element.Element):
     return 'ast.Section2({0:s})'.format(', '.join(params))
   # GENERATE END
 
-class StartCondNone(element.Element):
-  # GENERATE ELEMENT() BEGIN
+class StartConditionList(element.Element):
+  # GENERATE ELEMENT(bool wildcard) BEGIN
   def __init__(
     self,
-    tag = 'StartCondNone',
+    tag = 'StartConditionList',
     attrib = {},
     text = '',
-    children = []
+    children = [],
+    wildcard = False
   ):
     element.Element.__init__(
       self,
@@ -444,44 +445,34 @@ class StartCondNone(element.Element):
       text,
       children
     )
-  def copy(self, factory = None):
-    result = element.Element.copy(
-      self,
-      StartCondNone if factory is None else factory
-    )
-    return result
-  def __repr__(self):
-    params = []
-    self.repr_serialize(params)
-    return 'ast.StartCondNone({0:s})'.format(', '.join(params))
-  # GENERATE END
-
-class StartCond(element.Element):
-  # GENERATE ELEMENT() BEGIN
-  def __init__(
-    self,
-    tag = 'StartCond',
-    attrib = {},
-    text = '',
-    children = []
-  ):
-    element.Element.__init__(
-      self,
-      tag,
-      attrib,
-      text,
-      children
+    self.wildcard = (
+      element.deserialize_bool(wildcard)
+    if isinstance(wildcard, str) else
+      wildcard
     )
+  def serialize(self, ref_list, indent = 0):
+    element.Element.serialize(self, ref_list, indent)
+    self.set('wildcard', element.serialize_bool(self.wildcard))
+  def deserialize(self, ref_list):
+    element.Element.deserialize(self, ref_list)
+    self.wildcard = element.deserialize_bool(self.get('wildcard', 'false'))
   def copy(self, factory = None):
     result = element.Element.copy(
       self,
-      StartCond if factory is None else factory
+      StartConditionList if factory is None else factory
     )
+    result.wildcard = self.wildcard
     return result
+  def repr_serialize(self, params):
+    element.Element.repr_serialize(self, params)
+    if self.wildcard != False:
+      params.append(
+        'wildcard = {0:s}'.format(repr(self.wildcard))
+      )
   def __repr__(self):
     params = []
     self.repr_serialize(params)
-    return 'ast.StartCond({0:s})'.format(', '.join(params))
+    return 'ast.StartConditionList({0:s})'.format(', '.join(params))
   # GENERATE END
 
 class BOLRule(element.Element):
@@ -637,10 +628,9 @@ tag_to_class = {
   'Options_Reject': Options.Reject,
   'Options_YYMore': Options.YYMore,
   'Options_YYWrap': Options.YYWrap,
-  'StartCondDecl': StartCondDecl,
+  'StartConditionDecl': StartConditionDecl,
   'Section2': Section2,
-  'StartCondNone': StartCondNone,
-  'StartCond': StartCond,
+  'StartConditionList': StartConditionList,
   'BOLRule': BOLRule,
   'EOFRule': EOFRule,
   'Rule': Rule,
diff --git a/plex.py b/plex.py
index 516af75..f1d31d7 100755 (executable)
--- a/plex.py
+++ b/plex.py
@@ -281,7 +281,7 @@ options = Options()
 for i in section1:
   if isinstance(i, ast.Options):
     i.process(options)
-  elif isinstance(i, ast.StartCondDecl):
+  elif isinstance(i, ast.StartConditionDecl):
     for j in i:
       assert isinstance(j, ast.Name)
       name = element.get_text(j, 0)
@@ -297,17 +297,22 @@ start_condition_exprs = [
   regex.RegexNone()
   for i in range(len(start_conditions) * 2) # normal followed by BOL expr
 ]
+all_start_conditions = set(range(len(start_conditions)))
 for i in section2:
   if isinstance(i, ast.Rule):
-    if isinstance(i[0], ast.StartCondNone):
+    rule_start_condition_list = i[0]
+    assert isinstance(rule_start_condition_list, ast.StartConditionList)
+    default = False
+    if rule_start_condition_list.wildcard:
+      start_condition_set = all_start_conditions
+    elif len(rule_start_condition_list) == 0:
       default = True
-      rule_start_conditions = inclusive_start_conditions
+      start_condition_set = inclusive_start_conditions
     else:
-      default = False
-      rule_start_conditions = set()
-      for j in i[0]:
+      start_condition_set = set()
+      for j in rule_start_condition_list:
         assert isinstance(j, ast.Name)
-        rule_start_conditions.add(
+        start_condition_set.add(
           name_to_start_condition[element.get_text(j, 0)]
         )
     rule_expr = i[1]
@@ -317,7 +322,7 @@ for i in section2:
     assert isinstance(rule_action, ast.Action)
     if isinstance(rule_expr, ast.EOFRule):
       assert isinstance(rule_trailing_context, regex.RegexNone)
-      for j in rule_start_conditions:
+      for j in start_condition_set:
         if default and start_conditions[j].eof_action != 0:
           continue # rule applies to start conditions with no EOF rule yet
         assert start_conditions[j].eof_action == 0
@@ -341,7 +346,7 @@ for i in section2:
         ]
       )
       rule_expr.post_process(len(actions))
-      for j in rule_start_conditions:
+      for j in start_condition_set:
         for k in range(j * 2 + int(bol_rule), j * 2 + 2):
           start_condition_exprs[k] = regex.RegexOr(
             children = [