Implement %option caseless, also accept and ignore other options used in scan.l
authorNick Downing <downing.nick@gmail.com>
Mon, 23 Jul 2018 05:40:06 +0000 (15:40 +1000)
committerNick Downing <downing.nick@gmail.com>
Mon, 23 Jul 2018 08:10:12 +0000 (18:10 +1000)
ast.py
regex.py

diff --git a/ast.py b/ast.py
index e7b2c35..9dfcea6 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -389,6 +389,70 @@ class PLex(element.Element):
           return 'ast.PLex.Section1.Options.BoolOption({0:s})'.format(', '.join(params))
         # GENERATE END
 
+      class Caseless(BoolOption):
+        # GENERATE ELEMENT() BEGIN
+        def __init__(
+          self,
+          tag = 'PLex_Section1_Options_Caseless',
+          attrib = {},
+          text = '',
+          children = [],
+          value = False
+        ):
+          PLex.Section1.Options.BoolOption.__init__(
+            self,
+            tag,
+            attrib,
+            text,
+            children,
+            value
+          )
+        def copy(self, factory = None):
+          result = PLex.Section1.Options.BoolOption.copy(
+            self,
+            Caseless if factory is None else factory
+          )
+          return result
+        def __repr__(self):
+          params = []
+          self.repr_serialize(params)
+          return 'ast.PLex.Section1.Options.Caseless({0:s})'.format(', '.join(params))
+        # GENERATE END
+        def post_process(self, section):
+          section.caseless = self.value
+
+      class Default(BoolOption):
+        # GENERATE ELEMENT() BEGIN
+        def __init__(
+          self,
+          tag = 'PLex_Section1_Options_Default',
+          attrib = {},
+          text = '',
+          children = [],
+          value = False
+        ):
+          PLex.Section1.Options.BoolOption.__init__(
+            self,
+            tag,
+            attrib,
+            text,
+            children,
+            value
+          )
+        def copy(self, factory = None):
+          result = PLex.Section1.Options.BoolOption.copy(
+            self,
+            Default if factory is None else factory
+          )
+          return result
+        def __repr__(self):
+          params = []
+          self.repr_serialize(params)
+          return 'ast.PLex.Section1.Options.Default({0:s})'.format(', '.join(params))
+        # GENERATE END
+        def post_process(self, section):
+          section.default = self.value
+
       class ECS(BoolOption):
         # GENERATE ELEMENT() BEGIN
         def __init__(
@@ -485,6 +549,71 @@ class PLex(element.Element):
         def post_process(self, section):
           section.reject = self.value
 
+      class Stack(BoolOption):
+        # GENERATE ELEMENT() BEGIN
+        def __init__(
+          self,
+          tag = 'PLex_Section1_Options_Stack',
+          attrib = {},
+          text = '',
+          children = [],
+          value = False
+        ):
+          PLex.Section1.Options.BoolOption.__init__(
+            self,
+            tag,
+            attrib,
+            text,
+            children,
+            value
+          )
+        def copy(self, factory = None):
+          result = PLex.Section1.Options.BoolOption.copy(
+            self,
+            Stack if factory is None else factory
+          )
+          return result
+        def __repr__(self):
+          params = []
+          self.repr_serialize(params)
+          return 'ast.PLex.Section1.Options.Stack({0:s})'.format(', '.join(params))
+        # GENERATE END
+        def post_process(self, section):
+          section.stack = self.value
+
+      class StdInit(BoolOption):
+        # GENERATE ELEMENT() BEGIN
+        def __init__(
+          self,
+          tag = 'PLex_Section1_Options_StdInit',
+          attrib = {},
+          text = '',
+          children = [],
+          value = False
+        ):
+          PLex.Section1.Options.BoolOption.__init__(
+            self,
+            tag,
+            attrib,
+            text,
+            children,
+            value
+          )
+        def copy(self, factory = None):
+          result = PLex.Section1.Options.BoolOption.copy(
+            self,
+            StdInit if factory is None else factory
+          )
+          return result
+        def __repr__(self):
+          params = []
+          self.repr_serialize(params)
+          return 'ast.PLex.Section1.Options.StdInit({0:s})'.format(', '.join(params))
+        # GENERATE END
+        def post_process(self, section):
+          section.std_init = self.value
+
+
       class YYMore(BoolOption):
         # GENERATE ELEMENT() BEGIN
         def __init__(
@@ -517,6 +646,38 @@ class PLex(element.Element):
         def post_process(self, section):
           section.yymore = self.value
 
+      class YYTopState(BoolOption):
+        # GENERATE ELEMENT() BEGIN
+        def __init__(
+          self,
+          tag = 'PLex_Section1_Options_YYTopState',
+          attrib = {},
+          text = '',
+          children = [],
+          value = False
+        ):
+          PLex.Section1.Options.BoolOption.__init__(
+            self,
+            tag,
+            attrib,
+            text,
+            children,
+            value
+          )
+        def copy(self, factory = None):
+          result = PLex.Section1.Options.BoolOption.copy(
+            self,
+            YYTopState if factory is None else factory
+          )
+          return result
+        def __repr__(self):
+          params = []
+          self.repr_serialize(params)
+          return 'ast.PLex.Section1.Options.YYTopState({0:s})'.format(', '.join(params))
+        # GENERATE END
+        def post_process(self, section):
+          section.yy_top_state = self.value
+
       class YYWrap(BoolOption):
         # GENERATE ELEMENT() BEGIN
         def __init__(
@@ -659,7 +820,7 @@ class PLex(element.Element):
             )
           )
 
-    # GENERATE ELEMENT(bool ecs, bool meta_ecs, bool reject, bool yymore, bool yywrap) BEGIN
+    # GENERATE ELEMENT(bool caseless, bool default, bool ecs, bool meta_ecs, bool reject, bool stack, bool std_init, bool yymore, bool yy_top_state, bool yywrap) BEGIN
     def __init__(
       self,
       tag = 'PLex_Section1',
@@ -667,10 +828,15 @@ class PLex(element.Element):
       text = '',
       children = [],
       code_blocks_text = [],
+      caseless = False,
+      default = False,
       ecs = False,
       meta_ecs = False,
       reject = False,
+      stack = False,
+      std_init = False,
       yymore = False,
+      yy_top_state = False,
       yywrap = False
     ):
       PLex.Section1Or2.__init__(
@@ -681,6 +847,16 @@ class PLex(element.Element):
         children,
         code_blocks_text
       )
+      self.caseless = (
+        element.deserialize_bool(caseless)
+      if isinstance(caseless, str) else
+        caseless
+      )
+      self.default = (
+        element.deserialize_bool(default)
+      if isinstance(default, str) else
+        default
+      )
       self.ecs = (
         element.deserialize_bool(ecs)
       if isinstance(ecs, str) else
@@ -696,11 +872,26 @@ class PLex(element.Element):
       if isinstance(reject, str) else
         reject
       )
+      self.stack = (
+        element.deserialize_bool(stack)
+      if isinstance(stack, str) else
+        stack
+      )
+      self.std_init = (
+        element.deserialize_bool(std_init)
+      if isinstance(std_init, str) else
+        std_init
+      )
       self.yymore = (
         element.deserialize_bool(yymore)
       if isinstance(yymore, str) else
         yymore
       )
+      self.yy_top_state = (
+        element.deserialize_bool(yy_top_state)
+      if isinstance(yy_top_state, str) else
+        yy_top_state
+      )
       self.yywrap = (
         element.deserialize_bool(yywrap)
       if isinstance(yywrap, str) else
@@ -708,31 +899,54 @@ class PLex(element.Element):
       )
     def serialize(self, ref_list):
       PLex.Section1Or2.serialize(self, ref_list)
+      self.set('caseless', element.serialize_bool(self.caseless))
+      self.set('default', element.serialize_bool(self.default))
       self.set('ecs', element.serialize_bool(self.ecs))
       self.set('meta_ecs', element.serialize_bool(self.meta_ecs))
       self.set('reject', element.serialize_bool(self.reject))
+      self.set('stack', element.serialize_bool(self.stack))
+      self.set('std_init', element.serialize_bool(self.std_init))
       self.set('yymore', element.serialize_bool(self.yymore))
+      self.set('yy_top_state', element.serialize_bool(self.yy_top_state))
       self.set('yywrap', element.serialize_bool(self.yywrap))
     def deserialize(self, ref_list):
       PLex.Section1Or2.deserialize(self, ref_list)
+      self.caseless = element.deserialize_bool(self.get('caseless', 'false'))
+      self.default = element.deserialize_bool(self.get('default', 'false'))
       self.ecs = element.deserialize_bool(self.get('ecs', 'false'))
       self.meta_ecs = element.deserialize_bool(self.get('meta_ecs', 'false'))
       self.reject = element.deserialize_bool(self.get('reject', 'false'))
+      self.stack = element.deserialize_bool(self.get('stack', 'false'))
+      self.std_init = element.deserialize_bool(self.get('std_init', 'false'))
       self.yymore = element.deserialize_bool(self.get('yymore', 'false'))
+      self.yy_top_state = element.deserialize_bool(self.get('yy_top_state', 'false'))
       self.yywrap = element.deserialize_bool(self.get('yywrap', 'false'))
     def copy(self, factory = None):
       result = PLex.Section1Or2.copy(
         self,
         Section1 if factory is None else factory
       )
+      result.caseless = self.caseless
+      result.default = self.default
       result.ecs = self.ecs
       result.meta_ecs = self.meta_ecs
       result.reject = self.reject
+      result.stack = self.stack
+      result.std_init = self.std_init
       result.yymore = self.yymore
+      result.yy_top_state = self.yy_top_state
       result.yywrap = self.yywrap
       return result
     def repr_serialize(self, params):
       PLex.Section1Or2.repr_serialize(self, params)
+      if self.caseless != False:
+        params.append(
+          'caseless = {0:s}'.format(repr(self.caseless))
+        )
+      if self.default != False:
+        params.append(
+          'default = {0:s}'.format(repr(self.default))
+        )
       if self.ecs != False:
         params.append(
           'ecs = {0:s}'.format(repr(self.ecs))
@@ -745,10 +959,22 @@ class PLex(element.Element):
         params.append(
           'reject = {0:s}'.format(repr(self.reject))
         )
+      if self.stack != False:
+        params.append(
+          'stack = {0:s}'.format(repr(self.stack))
+        )
+      if self.std_init != False:
+        params.append(
+          'std_init = {0:s}'.format(repr(self.std_init))
+        )
       if self.yymore != False:
         params.append(
           'yymore = {0:s}'.format(repr(self.yymore))
         )
+      if self.yy_top_state != False:
+        params.append(
+          'yy_top_state = {0:s}'.format(repr(self.yy_top_state))
+        )
       if self.yywrap != False:
         params.append(
           'yywrap = {0:s}'.format(repr(self.yywrap))
@@ -766,10 +992,15 @@ class PLex(element.Element):
       inclusive_start_conditions,
       parent_start_conditions
     ):
+      self.caseless = False
+      self.default = True
       self.ecs = False
       self.meta_ecs = False
       self.reject = True
+      self.stack = True
+      self.std_init = True
       self.yymore = True
+      self.yy_top_state = True
       self.yywrap = True
       PLex.Section1Or2.post_process(
         self,
@@ -1018,8 +1249,12 @@ class PLex(element.Element):
             if not self[1].bol:
               plex.start_conditions[i].rules.append(self[1])
             plex.start_conditions[i].bol_rules.append(self[1])
-          self[1][0].post_process() # regex
-          self[1][1].post_process() # trailing context regex
+          self[1][0].post_process(
+            caseless = plex[0].caseless
+          ) # regex
+          self[1][1].post_process(
+            caseless = plex[0].caseless
+          ) # trailing context regex
           self[1].action = len(plex.actions_text)
           plex.actions_text.append(self[2][0] if len(self) > 2 else PLex.Text()) # fix this later
         else:
@@ -1282,7 +1517,7 @@ class PLex(element.Element):
                     children = [
                       k[1]
                     ],
-                    group_index = k.action
+                    index = k.action
                   )
                 ]
               )
@@ -1307,10 +1542,10 @@ class PLex(element.Element):
                       character_set = [0, 0x100]
                     ),
                     regex.RegexGroup(
-                      group_index = self.default_action,
                       children = [
                         regex.RegexEmpty()
-                      ]
+                      ],
+                      index = self.default_action
                     )
                   ]
                 )
@@ -1334,10 +1569,15 @@ tag_to_class = {
   'PLex_Section1_Options': PLex.Section1.Options,
   'PLex_Section1_Options_Option': PLex.Section1.Options.Option,
   'PLex_Section1_Options_BoolOption': PLex.Section1.Options.BoolOption,
+  'PLex_Section1_Options_Caseless': PLex.Section1.Options.Caseless,
+  'PLex_Section1_Options_Default': PLex.Section1.Options.Default,
   'PLex_Section1_Options_ECS': PLex.Section1.Options.ECS,
   'PLex_Section1_Options_MetaECS': PLex.Section1.Options.MetaECS,
   'PLex_Section1_Options_Reject': PLex.Section1.Options.Reject,
+  'PLex_Section1_Options_Stack': PLex.Section1.Options.Stack,
+  'PLex_Section1_Options_StdInit': PLex.Section1.Options.StdInit,
   'PLex_Section1_Options_YYMore': PLex.Section1.Options.YYMore,
+  'PLex_Section1_Options_YYTopState': PLex.Section1.Options.YYTopState,
   'PLex_Section1_Options_YYWrap': PLex.Section1.Options.YYWrap,
   'PLex_Section1_StartConditions': PLex.Section1.StartConditions,
   'PLex_Section2': PLex.Section2,
index 0193035..ac6b158 100644 (file)
--- a/regex.py
+++ b/regex.py
@@ -32,24 +32,17 @@ class Regex(element.Element):
     self.repr_serialize(params)
     return 'regex.Regex({0:s})'.format(', '.join(params))
   # GENERATE END
-  def post_process(self, group_index = 0): #, rule_name_to_character_set = None):
+  def post_process(self, group_index = 0, caseless = False):
     for i in self:
-      group_index = i.post_process(group_index) #, rule_name_to_character_set)
+      group_index = i.post_process(group_index, caseless)
     return group_index
-  def to_groups(self, groups):
+  def add_to_groups(self, groups):
     for i in self:
-      i.to_groups(groups)
+      i.add_to_groups(groups)
   def to_nfa_state(self, _nfa, next_state):
     raise NotImplementedException
   def add_to_nfa(self, _nfa):
     _nfa.start_state.append(self.to_nfa_state(_nfa, 0))
-  #def to_lr1_symbols(self, n_terminals, symbols, lookaheads, group_bounds):
-  #  group_count = 0
-  #  for i in self:
-  #    group_count += (
-  #      i.to_lr1_symbols(n_terminals, symbols, lookaheads, group_bounds)
-  #    )
-  #  return group_count # count of groups or ungrouped characters
 
 class RegexNone(Regex):
   # GENERATE ELEMENT() BEGIN
@@ -165,31 +158,66 @@ class RegexCharacter(Regex):
     self.repr_serialize(params)
     return 'regex.RegexCharacter({0:s})'.format(', '.join(params))
   # GENERATE END
+  def post_process(self, group_index = 0, caseless = False):
+    group_index = Regex.post_process(self, group_index, caseless)
+    if caseless:
+      temp = bisect_set.bisect_set_and(
+        self.character_set,
+        [0x41, 0x5b, 0x61, 0x7b]
+      )
+      self.character_set = bisect_set.bisect_set_or(
+        self.character_set,
+        [i ^ 0x20 for i in temp if i >= 0x60] +
+        [i ^ 0x20 for i in temp if i < 0x60]
+      )
+    return group_index
   def to_nfa_state(self, _nfa, next_state):
     new_state = len(_nfa.states)
     _nfa.states.append((nfa.NFA.STATE_CHARACTER, self.character_set, next_state))
     return new_state
-  #def to_lr1_symbols(self, n_terminals, symbols, lookaheads, group_bounds):
-  #  terminal_set = []
-  #  nonterminal_set = []
-  #  i = 0
-  #  while i < len(self.character_set):
-  #    [j, k] = self.character_set[i:i + 2]
-  #    if k > n_terminals:
-  #      if j < n_terminals:
-  #        terminal_set.extend([j, n_terminals])
-  #        nonterminal_set.extend([0, k - n_terminals])
-  #        i += 2
-  #      while i < len(self.character_set):
-  #        [j, k] = self.character_set[i:i + 2]
-  #        nonterminal_set.extend([j - n_terminals, k - n_terminals])
-  #        i += 2
-  #      break
-  #    terminal_set.extend([j, k])
-  #    i += 2
-  #  symbols.append((terminal_set, nonterminal_set))
-  #  lookaheads.append(([], False)) # initial_set, can_be_empty
-  #  return 1 # count of groups or ungrouped characters
+
+class RegexCharacterLiteral(RegexCharacter):
+  # GENERATE ELEMENT() BEGIN
+  def __init__(
+    self,
+    tag = 'RegexCharacterLiteral',
+    attrib = {},
+    text = '',
+    children = [],
+    character_set = []
+  ):
+    RegexCharacter.__init__(
+      self,
+      tag,
+      attrib,
+      text,
+      children,
+      character_set
+    )
+  def copy(self, factory = None):
+    result = RegexCharacter.copy(
+      self,
+      RegexCharacterLiteral if factory is None else factory
+    )
+    return result
+  def __repr__(self):
+    params = []
+    self.repr_serialize(params)
+    return 'regex.RegexCharacterLiteral({0:s})'.format(', '.join(params))
+  # GENERATE END
+  def post_process(self, group_index = 1, caseless = False):
+    group_index = RegexCharacter.post_process(self, group_index, False)
+    if caseless:
+      temp = bisect_set.bisect_set_and(
+        self.character_set,
+        [0x41, 0x5b, 0x61, 0x7b]
+      )
+      self.character_set = bisect_set.bisect_set_or(
+        self.character_set,
+        [i ^ 0x20 for i in temp if i >= 0x60] +
+        [i ^ 0x20 for i in temp if i < 0x60]
+      )
+    return group_index
 
 class RegexCharacterRange(RegexCharacter):
   # GENERATE ELEMENT() BEGIN
@@ -220,9 +248,19 @@ class RegexCharacterRange(RegexCharacter):
     self.repr_serialize(params)
     return 'regex.RegexCharacterRange({0:s})'.format(', '.join(params))
   # GENERATE END
-  def post_process(self, group_index = 0): #, rule_name_to_character_set = None):
-    group_index = RegexCharacter.post_process(self, group_index) #, rule_name_to_character_set)
+  def post_process(self, group_index = 0, caseless = False):
+    group_index = RegexCharacter.post_process(self, group_index, False)
     self.character_set = [self[0].character_set[0], self[1].character_set[-1]]
+    if caseless:
+      temp = bisect_set.bisect_set_and(
+        self.character_set,
+        [0x41, 0x5b, 0x61, 0x7b]
+      )
+      self.character_set = bisect_set.bisect_set_or(
+        self.character_set,
+        [i ^ 0x20 for i in temp if i >= 0x60] +
+        [i ^ 0x20 for i in temp if i < 0x60]
+      )
     return group_index
 
 class RegexCharacterOr(RegexCharacter):
@@ -254,8 +292,8 @@ class RegexCharacterOr(RegexCharacter):
     self.repr_serialize(params)
     return 'regex.RegexCharacterOr({0:s})'.format(', '.join(params))
   # GENERATE END
-  def post_process(self, group_index = 0): #, rule_name_to_character_set = None):
-    group_index = RegexCharacter.post_process(self, group_index) #, rule_name_to_character_set)
+  def post_process(self, group_index = 0, caseless = False):
+    group_index = RegexCharacter.post_process(self, group_index, caseless)
     self.character_set = bisect_set.bisect_set_or(self[0].character_set, self[1].character_set)
     return group_index
 
@@ -288,8 +326,8 @@ class RegexCharacterAnd(RegexCharacter):
     self.repr_serialize(params)
     return 'regex.RegexCharacterAnd({0:s})'.format(', '.join(params))
   # GENERATE END
-  def post_process(self, group_index = 0): #, rule_name_to_character_set = None):
-    group_index = RegexCharacter.post_process(self, group_index) #, rule_name_to_character_set)
+  def post_process(self, group_index = 0, caseless = False):
+    group_index = RegexCharacter.post_process(self, group_index, caseless)
     self.character_set = bisect_set.bisect_set_and(self[0].character_set, self[1].character_set)
     return group_index
 
@@ -322,60 +360,11 @@ class RegexCharacterNot(RegexCharacter):
     self.repr_serialize(params)
     return 'regex.RegexCharacterNot({0:s})'.format(', '.join(params))
   # GENERATE END
-  def post_process(self, group_index = 0): #, rule_name_to_character_set = None):
-    group_index = RegexCharacter.post_process(self, group_index) #, rule_name_to_character_set)
+  def post_process(self, group_index = 0, caseless = False):
+    group_index = RegexCharacter.post_process(self, group_index, caseless)
     self.character_set = bisect_set.bisect_set_not(self[0].character_set)
     return group_index
 
-#class RegexCharacterRule(RegexCharacter):
-#  # GENERATE ELEMENT(str rule_name) BEGIN
-#  def __init__(
-#    self,
-#    tag = 'RegexCharacterRule',
-#    attrib = {},
-#    text = '',
-#    children = [],
-#    character_set = [],
-#    rule_name = ''
-#  ):
-#    RegexCharacter.__init__(
-#      self,
-#      tag,
-#      attrib,
-#      text,
-#      children,
-#      character_set
-#    )
-#    self.rule_name = rule_name
-#  def serialize(self, ref_list, indent = 0):
-#    RegexCharacter.serialize(self, ref_list, indent)
-#    self.set('rule_name', element.serialize_str(self.rule_name))
-#  def deserialize(self, ref_list):
-#    RegexCharacter.deserialize(self, ref_list)
-#    self.rule_name = element.deserialize_str(self.get('rule_name', ''))
-#  def copy(self, factory = None):
-#    result = RegexCharacter.copy(
-#      self,
-#      RegexCharacterRule if factory is None else factory
-#    )
-#    result.rule_name = self.rule_name
-#    return result
-#  def repr_serialize(self, params):
-#    RegexCharacter.repr_serialize(self, params)
-#    if self.rule_name != '':
-#      params.append(
-#        'rule_name = {0:s}'.format(repr(self.rule_name))
-#      )
-#  def __repr__(self):
-#    params = []
-#    self.repr_serialize(params)
-#    return 'regex.RegexCharacterRule({0:s})'.format(', '.join(params))
-#  # GENERATE END
-#  def post_process(self, group_index = 0, rule_name_to_character_set = None):
-#    if rule_name_to_character_set is not None:
-#      self.character_set = rule_name_to_character_set[self.rule_name]
-#    return RegexCharacter.post_process(self, group_index, rule_name_to_character_set)
-
 class RegexOr(Regex):
   # GENERATE ELEMENT() BEGIN
   def __init__(
@@ -561,7 +550,7 @@ class RegexRepeat(Regex):
     self.repr_serialize(params)
     return 'regex.RegexRepeat({0:s})'.format(', '.join(params))
   # GENERATE END
-  def post_process(self, group_index = 0): #, rule_name_to_character_set = None):
+  def post_process(self, group_index = 0, caseless = False):
     # total hack which will be done in a Python action in future
     if len(self) >= 2:
       assert self[1].tag == 'Number'
@@ -573,7 +562,7 @@ class RegexRepeat(Regex):
         self.count1 = self.count0
       del self[1:]
     # end total hack
-    return Regex.post_process(self, group_index) #, rule_name_to_character_set)
+    return Regex.post_process(self, group_index, caseless)
   def to_nfa_state(self, _nfa, next_state):
     count0 = self.count0
     count1 = self.count1
@@ -660,16 +649,16 @@ class RegexGroup(Regex):
       return 'regex.RegexGroup.Attribute({0:s})'.format(', '.join(params))
     # GENERATE END
 
-  # GENERATE ELEMENT(int group_index, str group_name, list(ref) group_attributes) BEGIN
+  # GENERATE ELEMENT(int index, str name, list(ref) attributes) BEGIN
   def __init__(
     self,
     tag = 'RegexGroup',
     attrib = {},
     text = '',
     children = [],
-    group_index = -1,
-    group_name = '',
-    group_attributes = []
+    index = -1,
+    name = '',
+    attributes = []
   ):
     Regex.__init__(
       self,
@@ -678,52 +667,52 @@ class RegexGroup(Regex):
       text,
       children
     )
-    self.group_index = (
-      element.deserialize_int(group_index)
-    if isinstance(group_index, str) else
-      group_index
+    self.index = (
+      element.deserialize_int(index)
+    if isinstance(index, str) else
+      index
     )
-    self.group_name = group_name
-    self.group_attributes = group_attributes
+    self.name = name
+    self.attributes = attributes
   def serialize(self, ref_list):
     Regex.serialize(self, ref_list)
-    self.set('group_index', element.serialize_int(self.group_index))
-    self.set('group_name', element.serialize_str(self.group_name))
+    self.set('index', element.serialize_int(self.index))
+    self.set('name', element.serialize_str(self.name))
     self.set(
-      'group_attributes',
-      ' '.join([element.serialize_ref(i, ref_list) for i in self.group_attributes])
+      'attributes',
+      ' '.join([element.serialize_ref(i, ref_list) for i in self.attributes])
     )
   def deserialize(self, ref_list):
     Regex.deserialize(self, ref_list)
-    self.group_index = element.deserialize_int(self.get('group_index', '-1'))
-    self.group_name = element.deserialize_str(self.get('group_name', ''))
-    self.group_attributes = [
+    self.index = element.deserialize_int(self.get('index', '-1'))
+    self.name = element.deserialize_str(self.get('name', ''))
+    self.attributes = [
       element.deserialize_ref(i, ref_list)
-      for i in self.get('group_attributes', '').split()
+      for i in self.get('attributes', '').split()
     ]
   def copy(self, factory = None):
     result = Regex.copy(
       self,
       RegexGroup if factory is None else factory
     )
-    result.group_index = self.group_index
-    result.group_name = self.group_name
-    result.group_attributes = self.group_attributes
+    result.index = self.index
+    result.name = self.name
+    result.attributes = self.attributes
     return result
   def repr_serialize(self, params):
     Regex.repr_serialize(self, params)
-    if self.group_index != -1:
+    if self.index != -1:
       params.append(
-        'group_index = {0:s}'.format(repr(self.group_index))
+        'index = {0:s}'.format(repr(self.index))
       )
-    if self.group_name != '':
+    if self.name != '':
       params.append(
-        'group_name = {0:s}'.format(repr(self.group_name))
+        'name = {0:s}'.format(repr(self.name))
       )
-    if len(self.group_attributes):
+    if len(self.attributes):
       params.append(
-        'group_attributes = [{0:s}]'.format(
-          ', '.join([repr(i) for i in self.group_attributes])
+        'attributes = [{0:s}]'.format(
+          ', '.join([repr(i) for i in self.attributes])
         )
       )
   def __repr__(self):
@@ -731,49 +720,31 @@ class RegexGroup(Regex):
     self.repr_serialize(params)
     return 'regex.RegexGroup({0:s})'.format(', '.join(params))
   # GENERATE END
-  def post_process(self, group_index = 0): #, rule_name_to_character_set = None):
+  def post_process(self, group_index = 0, caseless = False):
     # total hack which will be done in a Python action in future
     if len(self) >= 2:
       assert self[0].tag == 'GroupName'
-      self.group_name = self[0].text[1:-1]
+      self.name = self[0].text[1:-1]
       del self[:1]
     # end total hack
-    self.group_index = group_index
+    self.index = group_index
     group_index += 1
-    return Regex.post_process(self, group_index) #, rule_name_to_character_set)
-  def to_groups(self, groups):
-    assert len(groups) == self.group_index
+    return Regex.post_process(self, group_index, caseless)
+  def add_to_groups(self, groups):
+    assert len(groups) == self.index
     groups.append(
-      (self.group_name, {i.name: i.value for i in self.group_attributes})
+      (self.name, {i.name: i.value for i in self.attributes})
     )
-    return Regex.to_groups(self, groups)
+    return Regex.add_to_groups(self, groups)
   def to_nfa_state(self, _nfa, next_state):
     mark_state = len(_nfa.states)
-    _nfa.states.append((nfa.NFA.STATE_MARK, self.group_index * 2 + 1, next_state))
+    _nfa.states.append((nfa.NFA.STATE_MARK, self.index * 2 + 1, next_state))
     child_state = self[0].to_nfa_state(_nfa, mark_state)
     if child_state == -1:
       return -1
     new_state = len(_nfa.states)
-    _nfa.states.append((nfa.NFA.STATE_MARK, self.group_index * 2, child_state))
+    _nfa.states.append((nfa.NFA.STATE_MARK, self.index * 2, child_state))
     return new_state
-  #def to_lr1_symbols(self, n_terminals, symbols, lookaheads, group_bounds):
-  #  group_start = len(symbols)
-  #  assert self.group_index == len(group_bounds)
-  #  group_bounds.append(None)
-  #  group_count = Regex.to_lr1_symbols(
-  #    self,
-  #    n_terminals,
-  #    symbols,
-  #    lookaheads,
-  #    group_bounds
-  #  )
-  #  group_bounds[self.group_index] = (
-  #    group_start,
-  #    group_count,
-  #    self.group_name,
-  #    {i.name: i.value for i in self.group_attributes}
-  #  )
-  #  return 1 # count of groups or ungrouped characters
 
 # GENERATE FACTORY(element.Element) BEGIN
 tag_to_class = {
@@ -781,6 +752,7 @@ tag_to_class = {
   'RegexNone': RegexNone,
   'RegexEmpty': RegexEmpty,
   'RegexCharacter': RegexCharacter,
+  'RegexCharacterLiteral': RegexCharacterLiteral,
   'RegexCharacterRange': RegexCharacterRange,
   'RegexCharacterOr': RegexCharacterOr,
   'RegexCharacterAnd': RegexCharacterAnd,
@@ -796,260 +768,261 @@ def factory(tag, attrib = {}, *args, **kwargs):
   return tag_to_class.get(tag, element.Element)(tag, attrib, *args, **kwargs)
 # GENERATE END
 
-if __name__ == '__main__':
-  import sys
-  import xml.etree.ElementTree
-
-  regex = RegexAnd(children = [RegexRepeat(children = [RegexCharacterNot(
-children = [RegexCharacter()], character_set = [0, 256])]), RegexGroup(children = [
-RegexOr(children = [RegexOr(children = [RegexOr(children = [RegexGroup(children
-= [RegexRepeat(children = [RegexCharacter(character_set = [9, 14, 32, 33])],
-one_or_more = True)], group_index = 1, group_name = 'Whitespace'), RegexGroup(
-children = [RegexRepeat(children = [RegexCharacter(character_set = [48, 58])],
-one_or_more = True)], group_index = 2, group_name = 'Number')]), RegexGroup(
-children = [RegexSequence(children = [RegexSequence(children = [RegexSequence(
-children = [RegexEmpty(), RegexCharacter(character_set = [102, 103])]),
-RegexCharacter(character_set = [111, 112])]), RegexCharacter(character_set = [114, 115])]
-)], group_index = 3, group_name = 'For')]), RegexGroup(children = [
-RegexSequence(children = [RegexCharacter(character_set = [65, 91, 95, 96, 97, 123]),
-RegexRepeat(children = [RegexCharacter(character_set = [48, 58, 65, 91, 95, 96, 97,
-123])])])], group_index = 4, group_name = 'Identifier')])], group_index = 0)])
-  #sys.stdout.write(
-  #  wrap_repr(
-  #    '  regex = {0:s}'.format(repr(regex).replace('regex.', '')),
-  #    79
-  #  )
-  #)
-
-  _nfa = regex.to_nfa()
-  #sys.stdout.write(
-  #  wrap_repr(
-  #    '  _nfa = {0:s}'.format(repr(_nfa).replace('regex.', '')),
-  #    79
-  #  )
-  #)
-
-  text = '     id   99id id99 for forex  '
-  i = 0
-  while i < len(text):
-    print('text "{0:s}"'.format(text[i:i + 72].replace('\n', '$')))
-    thread = _nfa.match_text(text, i)
-    if thread is None:
-      print('no match')
-      break
-    i = thread[0] # end position of overall match
-    group_start = [-1 for j in range(len(_nfa.groups))]
-    group_end = [-1 for j in range(len(_nfa.groups))]
-    while thread is not None:
-      pos, mark, thread = thread
-      group = mark >> 1
-      if (mark & 1) == 0:
-        group_start[group] = pos
-        print(
-          'group {0:d} name "{1:s}" text "{2:s}"'.format(
-             group,
-             _nfa.groups[group][0],
-             text[group_start[group]:group_end[group]].replace('\n', '$')
-          )
-        )
-      else:
-        group_end[group] = pos
-
-  dfa = _nfa.to_dfa()
-  #sys.stdout.write(
-  #  wrap_repr(
-  #    '  dfa = {0:s}'.format(repr(dfa).replace('regex.', '')),
-  #    79
-  #  )
-  #)
-
-  text = '     id   99id id99 for forex  '
-  i = 0
-  while i < len(text):
-    print('text "{0:s}"'.format(text[i:i + 72].replace('\n', '$')))
-    thread = dfa.match_text(text, i)
-    if thread is None:
-      print('no match')
-      break
-    i = thread[0] # end position of overall match
-    group_start = [-1 for j in range(len(dfa.groups))]
-    group_end = [-1 for j in range(len(dfa.groups))]
-    while thread is not None:
-      pos, mark, thread = thread
-      group = mark >> 1
-      if (mark & 1) == 0:
-        group_start[group] = pos
-        print(
-          'group {0:d} name "{1:s}" text "{2:s}"'.format(
-             group,
-             dfa.groups[group][0],
-             text[group_start[group]:group_end[group]].replace('\n', '$')
-          )
-        )
-      else:
-        group_end[group] = pos
-
-  grammar = Grammar(children = [Grammar.Production(children = [RegexSequence(
-children = [RegexSequence(children = [RegexEmpty(), RegexCharacterRule(character_set
-= [288, 295], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [
-259, 262], rule_name = 'expr0')])], nonterminal = 0), Grammar.Production(
-children = [RegexSequence(children = [RegexEmpty(), RegexCharacterRule(character_set
-= [262, 265], rule_name = 'expr1')])], nonterminal = 1), Grammar.Production(
-children = [RegexSequence(children = [RegexEmpty(), RegexGroup(children = [
-RegexSequence(children = [RegexSequence(children = [RegexSequence(children = [
-RegexSequence(children = [RegexEmpty(), RegexCharacterRule(character_set = [259, 262
-], rule_name = 'expr0')]), RegexCharacter(character_set = [43, 44])]),
-RegexCharacterRule(character_set = [288, 295], rule_name = 'whitespace_opt')]),
-RegexCharacterRule(character_set = [262, 265], rule_name = 'expr1')])], group_index
-= 0, group_name = 'Add')])], nonterminal = 2), Grammar.Production(children = [
-RegexSequence(children = [RegexEmpty(), RegexGroup(children = [RegexSequence(
-children = [RegexSequence(children = [RegexSequence(children = [RegexSequence(
-children = [RegexEmpty(), RegexCharacterRule(character_set = [259, 262], rule_name =
-'expr0')]), RegexCharacter(character_set = [45, 46])]), RegexCharacterRule(character_set
-= [288, 295], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [
-262, 265], rule_name = 'expr1')])], group_index = 0, group_name = 'Subtract')])
-], nonterminal = 3), Grammar.Production(children = [RegexSequence(children = [
-RegexEmpty(), RegexCharacterRule(character_set = [265, 268], rule_name = 'expr2')])
-], nonterminal = 4), Grammar.Production(children = [RegexSequence(children = [
-RegexEmpty(), RegexGroup(children = [RegexSequence(children = [RegexSequence(
-children = [RegexSequence(children = [RegexSequence(children = [RegexEmpty(),
-RegexCharacterRule(character_set = [262, 265], rule_name = 'expr1')]),
-RegexCharacter(character_set = [42, 43])]), RegexCharacterRule(character_set = [288, 295
-], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [265, 268],
-rule_name = 'expr2')])], group_index = 0, group_name = 'Multiply')])],
-nonterminal = 5), Grammar.Production(children = [RegexSequence(children = [
-RegexEmpty(), RegexGroup(children = [RegexSequence(children = [RegexSequence(
-children = [RegexSequence(children = [RegexSequence(children = [RegexEmpty(),
-RegexCharacterRule(character_set = [262, 265], rule_name = 'expr1')]),
-RegexCharacter(character_set = [47, 48])]), RegexCharacterRule(character_set = [288, 295
-], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [265, 268],
-rule_name = 'expr2')])], group_index = 0, group_name = 'Divide')])],
-nonterminal = 6), Grammar.Production(children = [RegexSequence(children = [
-RegexSequence(children = [RegexEmpty(), RegexGroup(children = [RegexSequence(
-children = [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name =
-'number')])], group_index = 0, group_name = 'Number')]), RegexCharacterRule(
-character_set = [288, 295], rule_name = 'whitespace_opt')])], nonterminal = 7),
-Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
-RegexGroup(children = [RegexSequence(children = [RegexSequence(children = [
-RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [45, 46])]),
-RegexCharacterRule(character_set = [288, 295], rule_name = 'whitespace_opt')]),
-RegexCharacterRule(character_set = [265, 268], rule_name = 'expr2')])], group_index
-= 0, group_name = 'Negate')])], nonterminal = 8), Grammar.Production(children =
-[RegexSequence(children = [RegexSequence(children = [RegexSequence(children = [
-RegexSequence(children = [RegexSequence(children = [RegexEmpty(),
-RegexCharacter(character_set = [40, 41])]), RegexCharacterRule(character_set = [288, 295
-], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [259, 262],
-rule_name = 'expr0')]), RegexCharacter(character_set = [41, 42])]),
-RegexCharacterRule(character_set = [288, 295], rule_name = 'whitespace_opt')])],
-nonterminal = 9), Grammar.Production(children = [RegexSequence(children = [
-RegexEmpty(), RegexCharacter(character_set = [48, 49])])], nonterminal = 10),
-Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
-RegexCharacter(character_set = [49, 50])])], nonterminal = 11), Grammar.Production(
-children = [RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [
-50, 51])])], nonterminal = 12), Grammar.Production(children = [RegexSequence(
-children = [RegexEmpty(), RegexCharacter(character_set = [51, 52])])], nonterminal =
-13), Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
-RegexCharacter(character_set = [52, 53])])], nonterminal = 14), Grammar.Production(
-children = [RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [
-53, 54])])], nonterminal = 15), Grammar.Production(children = [RegexSequence(
-children = [RegexEmpty(), RegexCharacter(character_set = [54, 55])])], nonterminal =
-16), Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
-RegexCharacter(character_set = [55, 56])])], nonterminal = 17), Grammar.Production(
-children = [RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [
-56, 57])])], nonterminal = 18), Grammar.Production(children = [RegexSequence(
-children = [RegexEmpty(), RegexCharacter(character_set = [57, 58])])], nonterminal =
-19), Grammar.Production(children = [RegexSequence(children = [RegexSequence(
-children = [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name =
-'number')]), RegexCharacter(character_set = [48, 49])])], nonterminal = 20),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [49, 50])])], nonterminal = 21),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [50, 51])])], nonterminal = 22),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [51, 52])])], nonterminal = 23),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [52, 53])])], nonterminal = 24),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [53, 54])])], nonterminal = 25),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [54, 55])])], nonterminal = 26),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [55, 56])])], nonterminal = 27),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [56, 57])])], nonterminal = 28),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
-)]), RegexCharacter(character_set = [57, 58])])], nonterminal = 29),
-Grammar.Production(children = [RegexEmpty()], nonterminal = 30),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
-'whitespace_opt')]), RegexCharacter(character_set = [9, 10])])], nonterminal = 31),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
-'whitespace_opt')]), RegexCharacter(character_set = [10, 11])])], nonterminal = 32),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
-'whitespace_opt')]), RegexCharacter(character_set = [11, 12])])], nonterminal = 33),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
-'whitespace_opt')]), RegexCharacter(character_set = [12, 13])])], nonterminal = 34),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
-'whitespace_opt')]), RegexCharacter(character_set = [13, 14])])], nonterminal = 35),
-Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
-= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
-'whitespace_opt')]), RegexCharacter(character_set = [32, 33])])], nonterminal = 36)
-], n_terminals = 258)
-  #sys.stdout.write(
-  #  wrap_repr(
-  #    '  grammar = {0:s}'.format(repr(grammar).replace('regex.', '')),
-  #    79
-  #  )
-  #)
-
-  lr1 = grammar.to_lr1()
-  #sys.stdout.write(
-  #  wrap_repr(
-  #    '  lr1 = {0:s}'.format(repr(lr1).replace('regex.', '')),
-  #    79
-  #  )
-  #)
-
-  lr1.parse_text('(13 + 5 * 6) * 2', 0)
-  root = element.Element('root', text = '(13 + 5 * 6) * 2')
-  lr1.parse_yychunk(root, 0, 0, element.Element, iter([]))
-  xml.etree.ElementTree.dump(root)
-
-  clr1 = lr1.to_clr1()
-  #sys.stdout.write(
-  #  wrap_repr(
-  #    '  clr1 = {0:s}'.format(repr(clr1).replace('regex.', '')),
-  #    79
-  #  )
-  #)
-
-  clr1.parse_text('(13 + 5 * 6) * 2', 0)
-  root = element.Element('root', text = '(13 + 5 * 6) * 2')
-  clr1.parse_yychunk(root, 0, 0, element.Element, iter([]))
-  xml.etree.ElementTree.dump(root)
-
-  lalr1 = lr1.to_lalr1()
-  #sys.stdout.write(
-  #  wrap_repr(
-  #    '  lalr1 = {0:s}'.format(repr(lalr1).replace('regex.', '')),
-  #    79
-  #  )
-  #)
-
-  lalr1.parse_text('(13 + 5 * 6) * 2', 0)
-  root = element.Element('root', text = '(13 + 5 * 6) * 2')
-  lalr1.parse_yychunk(root, 0, 0, element.Element, iter([]))
-  xml.etree.ElementTree.dump(root)
+# some of this should be moved into grammar.py:
+#if __name__ == '__main__':
+#  import sys
+#  import xml.etree.ElementTree
+#
+#  regex = RegexAnd(children = [RegexRepeat(children = [RegexCharacterNot(
+#children = [RegexCharacter()], character_set = [0, 256])]), RegexGroup(children = [
+#RegexOr(children = [RegexOr(children = [RegexOr(children = [RegexGroup(children
+#= [RegexRepeat(children = [RegexCharacter(character_set = [9, 14, 32, 33])],
+#one_or_more = True)], group_index = 1, group_name = 'Whitespace'), RegexGroup(
+#children = [RegexRepeat(children = [RegexCharacter(character_set = [48, 58])],
+#one_or_more = True)], group_index = 2, group_name = 'Number')]), RegexGroup(
+#children = [RegexSequence(children = [RegexSequence(children = [RegexSequence(
+#children = [RegexEmpty(), RegexCharacter(character_set = [102, 103])]),
+#RegexCharacter(character_set = [111, 112])]), RegexCharacter(character_set = [114, 115])]
+#)], group_index = 3, group_name = 'For')]), RegexGroup(children = [
+#RegexSequence(children = [RegexCharacter(character_set = [65, 91, 95, 96, 97, 123]),
+#RegexRepeat(children = [RegexCharacter(character_set = [48, 58, 65, 91, 95, 96, 97,
+#123])])])], group_index = 4, group_name = 'Identifier')])], group_index = 0)])
+#  #sys.stdout.write(
+#  #  wrap_repr(
+#  #    '  regex = {0:s}'.format(repr(regex).replace('regex.', '')),
+#  #    79
+#  #  )
+#  #)
+#
+#  _nfa = regex.to_nfa()
+#  #sys.stdout.write(
+#  #  wrap_repr(
+#  #    '  _nfa = {0:s}'.format(repr(_nfa).replace('regex.', '')),
+#  #    79
+#  #  )
+#  #)
+#
+#  text = '    id   99id id99 for forex  '
+#  i = 0
+#  while i < len(text):
+#    print('text "{0:s}"'.format(text[i:i + 72].replace('\n', '$')))
+#    thread = _nfa.match_text(text, i)
+#    if thread is None:
+#      print('no match')
+#      break
+#    i = thread[0] # end position of overall match
+#    group_start = [-1 for j in range(len(_nfa.groups))]
+#    group_end = [-1 for j in range(len(_nfa.groups))]
+#    while thread is not None:
+#      pos, mark, thread = thread
+#      group = mark >> 1
+#      if (mark & 1) == 0:
+#        group_start[group] = pos
+#        print(
+#          'group {0:d} name "{1:s}" text "{2:s}"'.format(
+#             group,
+#             _nfa.groups[group][0],
+#             text[group_start[group]:group_end[group]].replace('\n', '$')
+#          )
+#        )
+#      else:
+#        group_end[group] = pos
+#
+#  dfa = _nfa.to_dfa()
+#  #sys.stdout.write(
+#  #  wrap_repr(
+#  #    '  dfa = {0:s}'.format(repr(dfa).replace('regex.', '')),
+#  #    79
+#  #  )
+#  #)
+#
+#  text = '    id   99id id99 for forex  '
+#  i = 0
+#  while i < len(text):
+#    print('text "{0:s}"'.format(text[i:i + 72].replace('\n', '$')))
+#    thread = dfa.match_text(text, i)
+#    if thread is None:
+#      print('no match')
+#      break
+#    i = thread[0] # end position of overall match
+#    group_start = [-1 for j in range(len(dfa.groups))]
+#    group_end = [-1 for j in range(len(dfa.groups))]
+#    while thread is not None:
+#      pos, mark, thread = thread
+#      group = mark >> 1
+#      if (mark & 1) == 0:
+#        group_start[group] = pos
+#        print(
+#          'group {0:d} name "{1:s}" text "{2:s}"'.format(
+#             group,
+#             dfa.groups[group][0],
+#             text[group_start[group]:group_end[group]].replace('\n', '$')
+#          )
+#        )
+#      else:
+#        group_end[group] = pos
+#
+#  grammar = Grammar(children = [Grammar.Production(children = [RegexSequence(
+#children = [RegexSequence(children = [RegexEmpty(), RegexCharacterRule(character_set
+#= [288, 295], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [
+#259, 262], rule_name = 'expr0')])], nonterminal = 0), Grammar.Production(
+#children = [RegexSequence(children = [RegexEmpty(), RegexCharacterRule(character_set
+#= [262, 265], rule_name = 'expr1')])], nonterminal = 1), Grammar.Production(
+#children = [RegexSequence(children = [RegexEmpty(), RegexGroup(children = [
+#RegexSequence(children = [RegexSequence(children = [RegexSequence(children = [
+#RegexSequence(children = [RegexEmpty(), RegexCharacterRule(character_set = [259, 262
+#], rule_name = 'expr0')]), RegexCharacter(character_set = [43, 44])]),
+#RegexCharacterRule(character_set = [288, 295], rule_name = 'whitespace_opt')]),
+#RegexCharacterRule(character_set = [262, 265], rule_name = 'expr1')])], group_index
+#= 0, group_name = 'Add')])], nonterminal = 2), Grammar.Production(children = [
+#RegexSequence(children = [RegexEmpty(), RegexGroup(children = [RegexSequence(
+#children = [RegexSequence(children = [RegexSequence(children = [RegexSequence(
+#children = [RegexEmpty(), RegexCharacterRule(character_set = [259, 262], rule_name =
+#'expr0')]), RegexCharacter(character_set = [45, 46])]), RegexCharacterRule(character_set
+#= [288, 295], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [
+#262, 265], rule_name = 'expr1')])], group_index = 0, group_name = 'Subtract')])
+#], nonterminal = 3), Grammar.Production(children = [RegexSequence(children = [
+#RegexEmpty(), RegexCharacterRule(character_set = [265, 268], rule_name = 'expr2')])
+#], nonterminal = 4), Grammar.Production(children = [RegexSequence(children = [
+#RegexEmpty(), RegexGroup(children = [RegexSequence(children = [RegexSequence(
+#children = [RegexSequence(children = [RegexSequence(children = [RegexEmpty(),
+#RegexCharacterRule(character_set = [262, 265], rule_name = 'expr1')]),
+#RegexCharacter(character_set = [42, 43])]), RegexCharacterRule(character_set = [288, 295
+#], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [265, 268],
+#rule_name = 'expr2')])], group_index = 0, group_name = 'Multiply')])],
+#nonterminal = 5), Grammar.Production(children = [RegexSequence(children = [
+#RegexEmpty(), RegexGroup(children = [RegexSequence(children = [RegexSequence(
+#children = [RegexSequence(children = [RegexSequence(children = [RegexEmpty(),
+#RegexCharacterRule(character_set = [262, 265], rule_name = 'expr1')]),
+#RegexCharacter(character_set = [47, 48])]), RegexCharacterRule(character_set = [288, 295
+#], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [265, 268],
+#rule_name = 'expr2')])], group_index = 0, group_name = 'Divide')])],
+#nonterminal = 6), Grammar.Production(children = [RegexSequence(children = [
+#RegexSequence(children = [RegexEmpty(), RegexGroup(children = [RegexSequence(
+#children = [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name =
+#'number')])], group_index = 0, group_name = 'Number')]), RegexCharacterRule(
+#character_set = [288, 295], rule_name = 'whitespace_opt')])], nonterminal = 7),
+#Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
+#RegexGroup(children = [RegexSequence(children = [RegexSequence(children = [
+#RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [45, 46])]),
+#RegexCharacterRule(character_set = [288, 295], rule_name = 'whitespace_opt')]),
+#RegexCharacterRule(character_set = [265, 268], rule_name = 'expr2')])], group_index
+#= 0, group_name = 'Negate')])], nonterminal = 8), Grammar.Production(children =
+#[RegexSequence(children = [RegexSequence(children = [RegexSequence(children = [
+#RegexSequence(children = [RegexSequence(children = [RegexEmpty(),
+#RegexCharacter(character_set = [40, 41])]), RegexCharacterRule(character_set = [288, 295
+#], rule_name = 'whitespace_opt')]), RegexCharacterRule(character_set = [259, 262],
+#rule_name = 'expr0')]), RegexCharacter(character_set = [41, 42])]),
+#RegexCharacterRule(character_set = [288, 295], rule_name = 'whitespace_opt')])],
+#nonterminal = 9), Grammar.Production(children = [RegexSequence(children = [
+#RegexEmpty(), RegexCharacter(character_set = [48, 49])])], nonterminal = 10),
+#Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
+#RegexCharacter(character_set = [49, 50])])], nonterminal = 11), Grammar.Production(
+#children = [RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [
+#50, 51])])], nonterminal = 12), Grammar.Production(children = [RegexSequence(
+#children = [RegexEmpty(), RegexCharacter(character_set = [51, 52])])], nonterminal =
+#13), Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
+#RegexCharacter(character_set = [52, 53])])], nonterminal = 14), Grammar.Production(
+#children = [RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [
+#53, 54])])], nonterminal = 15), Grammar.Production(children = [RegexSequence(
+#children = [RegexEmpty(), RegexCharacter(character_set = [54, 55])])], nonterminal =
+#16), Grammar.Production(children = [RegexSequence(children = [RegexEmpty(),
+#RegexCharacter(character_set = [55, 56])])], nonterminal = 17), Grammar.Production(
+#children = [RegexSequence(children = [RegexEmpty(), RegexCharacter(character_set = [
+#56, 57])])], nonterminal = 18), Grammar.Production(children = [RegexSequence(
+#children = [RegexEmpty(), RegexCharacter(character_set = [57, 58])])], nonterminal =
+#19), Grammar.Production(children = [RegexSequence(children = [RegexSequence(
+#children = [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name =
+#'number')]), RegexCharacter(character_set = [48, 49])])], nonterminal = 20),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [49, 50])])], nonterminal = 21),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [50, 51])])], nonterminal = 22),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [51, 52])])], nonterminal = 23),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [52, 53])])], nonterminal = 24),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [53, 54])])], nonterminal = 25),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [54, 55])])], nonterminal = 26),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [55, 56])])], nonterminal = 27),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [56, 57])])], nonterminal = 28),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [268, 288], rule_name = 'number'
+#)]), RegexCharacter(character_set = [57, 58])])], nonterminal = 29),
+#Grammar.Production(children = [RegexEmpty()], nonterminal = 30),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
+#'whitespace_opt')]), RegexCharacter(character_set = [9, 10])])], nonterminal = 31),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
+#'whitespace_opt')]), RegexCharacter(character_set = [10, 11])])], nonterminal = 32),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
+#'whitespace_opt')]), RegexCharacter(character_set = [11, 12])])], nonterminal = 33),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
+#'whitespace_opt')]), RegexCharacter(character_set = [12, 13])])], nonterminal = 34),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
+#'whitespace_opt')]), RegexCharacter(character_set = [13, 14])])], nonterminal = 35),
+#Grammar.Production(children = [RegexSequence(children = [RegexSequence(children
+#= [RegexEmpty(), RegexCharacterRule(character_set = [288, 295], rule_name =
+#'whitespace_opt')]), RegexCharacter(character_set = [32, 33])])], nonterminal = 36)
+#], n_terminals = 258)
+#  #sys.stdout.write(
+#  #  wrap_repr(
+#  #    '  grammar = {0:s}'.format(repr(grammar).replace('regex.', '')),
+#  #    79
+#  #  )
+#  #)
+#
+#  lr1 = grammar.to_lr1()
+#  #sys.stdout.write(
+#  #  wrap_repr(
+#  #    '  lr1 = {0:s}'.format(repr(lr1).replace('regex.', '')),
+#  #    79
+#  #  )
+#  #)
+#
+#  lr1.parse_text('(13 + 5 * 6) * 2', 0)
+#  root = element.Element('root', text = '(13 + 5 * 6) * 2')
+#  lr1.parse_yychunk(root, 0, 0, element.Element, iter([]))
+#  xml.etree.ElementTree.dump(root)
+#
+#  clr1 = lr1.to_clr1()
+#  #sys.stdout.write(
+#  #  wrap_repr(
+#  #    '  clr1 = {0:s}'.format(repr(clr1).replace('regex.', '')),
+#  #    79
+#  #  )
+#  #)
+#
+#  clr1.parse_text('(13 + 5 * 6) * 2', 0)
+#  root = element.Element('root', text = '(13 + 5 * 6) * 2')
+#  clr1.parse_yychunk(root, 0, 0, element.Element, iter([]))
+#  xml.etree.ElementTree.dump(root)
+#
+#  lalr1 = lr1.to_lalr1()
+#  #sys.stdout.write(
+#  #  wrap_repr(
+#  #    '  lalr1 = {0:s}'.format(repr(lalr1).replace('regex.', '')),
+#  #    79
+#  #  )
+#  #)
+#
+#  lalr1.parse_text('(13 + 5 * 6) * 2', 0)
+#  root = element.Element('root', text = '(13 + 5 * 6) * 2')
+#  lalr1.parse_yychunk(root, 0, 0, element.Element, iter([]))
+#  xml.etree.ElementTree.dump(root)