@@ -8,9 +8,9 @@ class LexerConf: | |||
self.callbacks = callbacks or {} | |||
class ParserConf: | |||
def __init__(self, rules, callback, start): | |||
def __init__(self, rules, callbacks, start): | |||
self.rules = rules | |||
self.callback = callback | |||
self.callbacks = callbacks | |||
self.start = start | |||
@@ -132,7 +132,7 @@ class Lark: | |||
raise NotImplementedError("Not available yet") | |||
assert not self.options.profile, "Feature temporarily disabled" | |||
self.profiler = Profiler() if self.options.profile else None | |||
# self.profiler = Profiler() if self.options.profile else None | |||
if self.options.lexer == 'auto': | |||
if self.options.parser == 'lalr': | |||
@@ -192,8 +192,6 @@ class Lark: | |||
elif lexer: | |||
self.lexer = self._build_lexer() | |||
if self.profiler: self.profiler.enter_section('outside_lark') | |||
if __init__.__doc__: | |||
__init__.__doc__ += "\nOPTIONS:" + LarkOptions.OPTIONS_DOC | |||
@@ -204,13 +202,9 @@ class Lark: | |||
self.parser_class = get_frontend(self.options.parser, self.options.lexer) | |||
self._parse_tree_builder = ParseTreeBuilder(self.rules, self.options.tree_class, self.options.propagate_positions, self.options.keep_all_tokens, self.options.parser!='lalr' and self.options.ambiguity=='explicit', self.options.maybe_placeholders) | |||
callback = self._parse_tree_builder.create_callback(self.options.transformer) | |||
if self.profiler: | |||
for f in dir(callback): | |||
if not (f.startswith('__') and f.endswith('__')): | |||
setattr(callback, f, self.profiler.make_wrapper('transformer', getattr(callback, f))) | |||
callbacks = self._parse_tree_builder.create_callback(self.options.transformer) | |||
parser_conf = ParserConf(self.rules, callback, self.options.start) | |||
parser_conf = ParserConf(self.rules, callbacks, self.options.start) | |||
return self.parser_class(self.lexer_conf, parser_conf, options=self.options) | |||
@@ -187,10 +187,6 @@ def maybe_create_ambiguous_expander(tree_class, expansion, keep_all_tokens): | |||
if to_expand: | |||
return partial(AmbiguousExpander, to_expand, tree_class) | |||
class Callback(object): | |||
pass | |||
def ptb_inline_args(func): | |||
@wraps(func) | |||
def f(children): | |||
@@ -207,8 +203,6 @@ class ParseTreeBuilder: | |||
self.rule_builders = list(self._init_builders(rules)) | |||
self.user_aliases = {} | |||
def _init_builders(self, rules): | |||
for rule in rules: | |||
options = rule.options | |||
@@ -226,12 +220,9 @@ class ParseTreeBuilder: | |||
def create_callback(self, transformer=None): | |||
callback = Callback() | |||
callbacks = {} | |||
i = 0 | |||
for rule, wrapper_chain in self.rule_builders: | |||
internal_callback_name = '_cb%d_%s' % (i, rule.origin) | |||
i += 1 | |||
user_callback_name = rule.alias or rule.origin.name | |||
try: | |||
@@ -243,16 +234,14 @@ class ParseTreeBuilder: | |||
except AttributeError: | |||
f = partial(self.tree_class, user_callback_name) | |||
self.user_aliases[rule] = rule.alias | |||
rule.alias = internal_callback_name | |||
for w in wrapper_chain: | |||
f = w(f) | |||
if hasattr(callback, internal_callback_name): | |||
if rule in callbacks: | |||
raise GrammarError("Rule '%s' already exists" % (rule,)) | |||
setattr(callback, internal_callback_name, f) | |||
return callback | |||
callbacks[rule] = f | |||
return callbacks | |||
###} |
@@ -123,10 +123,7 @@ class CYK(WithLexer): | |||
self._analysis = GrammarAnalyzer(parser_conf) | |||
self._parser = cyk.Parser(parser_conf.rules, parser_conf.start) | |||
self._postprocess = {} | |||
for rule in parser_conf.rules: | |||
a = rule.alias | |||
self._postprocess[a] = a if callable(a) else (a and getattr(parser_conf.callback, a)) | |||
self.callbacks = parser_conf.callbacks | |||
def parse(self, text): | |||
tokens = list(self.lex(text)) | |||
@@ -142,11 +139,7 @@ class CYK(WithLexer): | |||
return self._apply_callback(tree) | |||
def _apply_callback(self, tree): | |||
children = tree.children | |||
callback = self._postprocess[tree.rule.alias] | |||
assert callback, tree.rule.alias | |||
r = callback(children) | |||
return r | |||
return self.callbacks[tree.rule](tree.children) | |||
def get_frontend(parser, lexer): | |||
@@ -86,7 +86,7 @@ class Parser(object): | |||
def __init__(self, rules, start): | |||
super(Parser, self).__init__() | |||
self.orig_rules = {rule.alias: rule for rule in rules} | |||
self.orig_rules = {rule: rule for rule in rules} | |||
rules = [self._to_rule(rule) for rule in rules] | |||
self.grammar = to_cnf(Grammar(rules)) | |||
self.start = NT(start) | |||
@@ -98,7 +98,7 @@ class Parser(object): | |||
return Rule( | |||
lark_rule.origin, lark_rule.expansion, | |||
weight=lark_rule.options.priority if lark_rule.options and lark_rule.options.priority else 0, | |||
alias=lark_rule.alias) | |||
alias=lark_rule) | |||
def parse(self, tokenized): # pylint: disable=invalid-name | |||
"""Parses input, which is a list of tokens.""" | |||
@@ -27,7 +27,7 @@ class Parser: | |||
self.FIRST = analysis.FIRST | |||
self.NULLABLE = analysis.NULLABLE | |||
self.callbacks = {} | |||
self.callbacks = parser_conf.callbacks | |||
self.predictions = {} | |||
## These could be moved to the grammar analyzer. Pre-computing these is *much* faster than | |||
@@ -37,7 +37,6 @@ class Parser: | |||
self.forest_sum_visitor = None | |||
for rule in parser_conf.rules: | |||
self.callbacks[rule] = rule.alias if callable(rule.alias) else getattr(parser_conf.callback, rule.alias) | |||
self.predictions[rule.origin] = [x.rule for x in analysis.expand_rule(rule.origin)] | |||
## Detect if any rules have priorities set. If the user specified priority = "none" then | |||
@@ -271,7 +271,8 @@ class ForestToTreeVisitor(ForestVisitor): | |||
according to some priority mechanism. | |||
""" | |||
__slots__ = ['forest_sum_visitor', 'callbacks', 'output_stack'] | |||
def __init__(self, callbacks = None, forest_sum_visitor = None): | |||
def __init__(self, callbacks, forest_sum_visitor = None): | |||
assert callbacks | |||
self.forest_sum_visitor = forest_sum_visitor | |||
self.callbacks = callbacks | |||
@@ -13,8 +13,7 @@ class Parser: | |||
for r in parser_conf.rules), "LALR doesn't yet support prioritization" | |||
analysis = LALR_Analyzer(parser_conf, debug=debug) | |||
analysis.compute_lookahead() | |||
callbacks = {rule: getattr(parser_conf.callback, rule.alias or rule.origin, None) | |||
for rule in parser_conf.rules} | |||
callbacks = parser_conf.callbacks | |||
self._parse_table = analysis.parse_table | |||
self.parser_conf = parser_conf | |||
@@ -112,7 +112,8 @@ class Reconstructor: | |||
def _reconstruct(self, tree): | |||
# TODO: ambiguity? | |||
parser = earley.Parser(ParserConf(self.rules, None, tree.data), self._match, resolve_ambiguity=True) | |||
callbacks = {rule: rule.alias for rule in self.rules} # TODO pass callbacks through dict, instead of alias? | |||
parser = earley.Parser(ParserConf(self.rules, callbacks, tree.data), self._match, resolve_ambiguity=True) | |||
unreduced_tree = parser.parse(tree.children) # find a full derivation | |||
assert unreduced_tree.data == tree.data | |||
res = self.write_tokens.transform(unreduced_tree) | |||
@@ -186,8 +186,7 @@ class ParserAtoms: | |||
print('parse_table.end_state = %s' % self.parse_table.end_state) | |||
print('class Lark_StandAlone:') | |||
print(' def __init__(self, transformer=None, postlex=None):') | |||
print(' callback = parse_tree_builder.create_callback(transformer=transformer)') | |||
print(' callbacks = {rule: getattr(callback, rule.alias or rule.origin, None) for rule in RULES.values()}') | |||
print(' callbacks = parse_tree_builder.create_callback(transformer=transformer)') | |||
print(' self.parser = _Parser(parse_table, callbacks)') | |||
print(' self.postlex = postlex') | |||
print(' def parse(self, stream):') | |||
@@ -199,14 +198,13 @@ class ParserAtoms: | |||
class TreeBuilderAtoms: | |||
def __init__(self, lark): | |||
self.rules = lark.rules | |||
self.ptb = lark._parse_tree_builder | |||
def print_python(self): | |||
# print('class InlineTransformer: pass') | |||
print('RULES = {') | |||
for i, r in enumerate(self.rules): | |||
rule_ids[r] = i | |||
print(' %d: Rule(%r, [%s], alias=%r, options=%r),' % (i, r.origin, ', '.join(s.fullrepr for s in r.expansion), self.ptb.user_aliases[r], r.options )) | |||
print(' %d: Rule(%r, [%s], alias=%r, options=%r),' % (i, r.origin, ', '.join(s.fullrepr for s in r.expansion), r.alias, r.options )) | |||
print('}') | |||
print('parse_tree_builder = ParseTreeBuilder(RULES.values(), Tree)') | |||