|
- from .grammar_analysis import is_terminal
-
- class Callback(object):
- pass
-
-
- def create_expand1_tree_builder_function(tree_builder):
- def f(children):
- if len(children) == 1:
- return children[0]
- else:
- return tree_builder(children)
- return f
-
- def create_rule_handler(expansion, usermethod):
- to_include = [(i, sym.startswith('_')) for i, sym in enumerate(expansion)
- if not (is_terminal(sym) and sym.startswith('_'))]
-
- def _build_ast(match):
- children = []
- for i, to_expand in to_include:
- if to_expand:
- children += match[i].children
- else:
- children.append(match[i])
-
- return usermethod(children)
- return _build_ast
-
-
- class ParseTreeBuilder:
- def __init__(self, tree_class):
- self.tree_class = tree_class
-
- def _create_tree_builder_function(self, name):
- tree_class = self.tree_class
- def f(children):
- return tree_class(name, children)
- return f
-
-
- def create_tree_builder(self, rules, transformer):
- callback = Callback()
- new_rules = []
- for origin, expansions in rules.items():
- expand1 = origin.startswith('?')
- _origin = origin.lstrip('?*')
-
- for expansion, alias in expansions:
- if alias and origin.startswith('_'):
- raise Exception("Rule %s is marked for expansion (it starts with an underscore) and isn't allowed to have aliases" % origin)
-
- if alias:
- alias = alias.lstrip('*')
- _alias = 'autoalias_%s_%s' % (_origin, '_'.join(expansion))
-
- try:
- f = transformer._get_func(alias or _origin)
- except AttributeError:
- if alias:
- f = self._create_tree_builder_function(alias)
- else:
- f = self._create_tree_builder_function(_origin)
- if expand1:
- f = create_expand1_tree_builder_function(f)
-
- alias_handler = create_rule_handler(expansion, f)
-
- assert not hasattr(callback, _alias)
- setattr(callback, _alias, alias_handler)
-
- new_rules.append(( _origin, expansion, _alias ))
-
- return new_rules, callback
-
|