@@ -250,6 +250,7 @@ class Lark(Serialize): | |||||
options['postlex'] = postlex | options['postlex'] = postlex | ||||
inst.options = LarkOptions.deserialize(options, memo) | inst.options = LarkOptions.deserialize(options, memo) | ||||
inst.rules = [Rule.deserialize(r, memo) for r in data['rules']] | inst.rules = [Rule.deserialize(r, memo) for r in data['rules']] | ||||
inst.source = '<deserialized>' | |||||
inst._prepare_callbacks() | inst._prepare_callbacks() | ||||
inst.parser = inst.parser_class.deserialize(data['parser'], memo, inst._callbacks, inst.options.postlex) | inst.parser = inst.parser_class.deserialize(data['parser'], memo, inst._callbacks, inst.options.postlex) | ||||
return inst | return inst | ||||
@@ -290,4 +291,4 @@ class Lark(Serialize): | |||||
"Parse the given text, according to the options provided. Returns a tree, unless specified otherwise." | "Parse the given text, according to the options provided. Returns a tree, unless specified otherwise." | ||||
return self.parser.parse(text) | return self.parser.parse(text) | ||||
###} | |||||
###} |
@@ -278,8 +278,8 @@ class TraditionalLexer(Lexer): | |||||
__serialize_namespace__ = TerminalDef, | __serialize_namespace__ = TerminalDef, | ||||
def _deserialize(self): | def _deserialize(self): | ||||
self.mres = build_mres(self.terminals) | |||||
self.callback = {} # TODO implement | |||||
self.user_callbacks = {} # TODO implement | |||||
self.build() | |||||
def __init__(self, terminals, ignore=(), user_callbacks={}): | def __init__(self, terminals, ignore=(), user_callbacks={}): | ||||
@@ -304,19 +304,21 @@ class TraditionalLexer(Lexer): | |||||
self.ignore_types = list(ignore) | self.ignore_types = list(ignore) | ||||
terminals.sort(key=lambda x:(-x.priority, -x.pattern.max_width, -len(x.pattern.value), x.name)) | terminals.sort(key=lambda x:(-x.priority, -x.pattern.max_width, -len(x.pattern.value), x.name)) | ||||
self.terminals = terminals | |||||
self.user_callbacks = user_callbacks | |||||
self.build() | |||||
terminals, self.callback = _create_unless(terminals) | |||||
def build(self): | |||||
terminals, self.callback = _create_unless(self.terminals) | |||||
assert all(self.callback.values()) | assert all(self.callback.values()) | ||||
for type_, f in user_callbacks.items(): | |||||
for type_, f in self.user_callbacks.items(): | |||||
if type_ in self.callback: | if type_ in self.callback: | ||||
# Already a callback there, probably UnlessCallback | # Already a callback there, probably UnlessCallback | ||||
self.callback[type_] = CallChain(self.callback[type_], f, lambda t: t.type == type_) | self.callback[type_] = CallChain(self.callback[type_], f, lambda t: t.type == type_) | ||||
else: | else: | ||||
self.callback[type_] = f | self.callback[type_] = f | ||||
self.terminals = terminals | |||||
self.mres = build_mres(terminals) | self.mres = build_mres(terminals) | ||||
@@ -364,4 +366,4 @@ class ContextualLexer(Lexer): | |||||
l.lexer = self.lexers[self.parser_state] | l.lexer = self.lexers[self.parser_state] | ||||
l.state = self.parser_state | l.state = self.parser_state | ||||
###} | |||||
###} |
@@ -18,16 +18,7 @@ def classify_bool(seq, pred): | |||||
return true_elems, false_elems | return true_elems, false_elems | ||||
def classify(seq, key=None, value=None): | |||||
d = {} | |||||
for item in seq: | |||||
k = key(item) if (key is not None) else item | |||||
v = value(item) if (value is not None) else item | |||||
if k in d: | |||||
d[k].append(v) | |||||
else: | |||||
d[k] = [v] | |||||
return d | |||||
def bfs(initial, expand): | def bfs(initial, expand): | ||||
open_q = deque(list(initial)) | open_q = deque(list(initial)) | ||||
@@ -58,6 +49,18 @@ def _serialize(value, memo): | |||||
return value | return value | ||||
###{standalone | ###{standalone | ||||
def classify(seq, key=None, value=None): | |||||
d = {} | |||||
for item in seq: | |||||
k = key(item) if (key is not None) else item | |||||
v = value(item) if (value is not None) else item | |||||
if k in d: | |||||
d[k].append(v) | |||||
else: | |||||
d[k] = [v] | |||||
return d | |||||
def _deserialize(data, namespace, memo): | def _deserialize(data, namespace, memo): | ||||
if isinstance(data, dict): | if isinstance(data, dict): | ||||
if '__type__' in data: # Object | if '__type__' in data: # Object | ||||
@@ -1451,7 +1451,8 @@ def _make_parser_test(LEXER, PARSER): | |||||
@unittest.skipIf(PARSER!='lalr', "Serialize currently only works for LALR parsers (though it should be easy to extend)") | @unittest.skipIf(PARSER!='lalr', "Serialize currently only works for LALR parsers (though it should be easy to extend)") | ||||
def test_serialize(self): | def test_serialize(self): | ||||
grammar = """ | grammar = """ | ||||
start: "A" b "C" | |||||
start: _ANY b "C" | |||||
_ANY: /./ | |||||
b: "B" | b: "B" | ||||
""" | """ | ||||
parser = _Lark(grammar) | parser = _Lark(grammar) | ||||