@@ -118,7 +118,7 @@ class XEarley: | |||
class XEarley_CompleteLex(XEarley): | |||
def __init__(self, *args, **kw): | |||
super(self).__init__(*args, complete_lex=True, **kw) | |||
XEarley.__init__(self, *args, complete_lex=True, **kw) | |||
@@ -9,17 +9,15 @@ The Earley parser outputs an SPPF-tree as per that document. The SPPF tree forma | |||
is better documented here: | |||
http://www.bramvandersanden.com/post/2014/06/shared-packed-parse-forest/ | |||
""" | |||
# Author: Erez Shinan (2017) | |||
# Email : erezshin@gmail.com | |||
from collections import deque, defaultdict | |||
from ..visitors import Transformer_InPlace, v_args | |||
from ..exceptions import ParseError, UnexpectedToken | |||
from .grammar_analysis import GrammarAnalyzer | |||
from ..grammar import NonTerminal | |||
from .earley_common import Column, Item | |||
from .earley_forest import ForestToTreeVisitor, ForestSumVisitor, SymbolNode | |||
from collections import deque, defaultdict | |||
from .earley_forest import ForestToTreeVisitor, ForestSumVisitor, SymbolNode, ForestToAmbiguousTreeVisitor | |||
class Parser: | |||
def __init__(self, parser_conf, term_matcher, resolve_ambiguity=True, forest_sum_visitor = ForestSumVisitor): | |||
@@ -199,7 +197,7 @@ class Parser: | |||
## If we're not resolving ambiguity, we just return the root of the SPPF tree to the caller. | |||
# This means the caller can work directly with the SPPF tree. | |||
if not self.resolve_ambiguity: | |||
return solutions[0] | |||
return ForestToAmbiguousTreeVisitor(solutions[0], self.callbacks).go() | |||
# ... otherwise, disambiguate and convert the SPPF to an AST, removing any ambiguities | |||
# according to the rules. | |||
@@ -20,12 +20,10 @@ from collections import defaultdict, deque | |||
from ..exceptions import ParseError, UnexpectedCharacters | |||
from ..lexer import Token | |||
from ..tree import Tree | |||
from .grammar_analysis import GrammarAnalyzer | |||
from ..grammar import NonTerminal, Terminal | |||
from .earley import ApplyCallbacks | |||
from .earley_common import Column, Item | |||
from .earley_forest import ForestToTreeVisitor, ForestSumVisitor, SymbolNode | |||
from .earley_forest import ForestToTreeVisitor, ForestSumVisitor, SymbolNode, ForestToAmbiguousTreeVisitor | |||
class Parser: | |||
@@ -267,8 +265,9 @@ class Parser: | |||
## If we're not resolving ambiguity, we just return the root of the SPPF tree to the caller. | |||
# This means the caller can work directly with the SPPF tree. | |||
if not self.resolve_ambiguity: | |||
return solutions[0] | |||
return ForestToAmbiguousTreeVisitor(solutions[0], self.callbacks).go() | |||
# ... otherwise, disambiguate and convert the SPPF to an AST, removing any ambiguities | |||
# according to the rules. | |||
return ForestToTreeVisitor(solutions[0], self.forest_sum_visitor, self.callbacks).go() | |||
@@ -25,6 +25,7 @@ from .test_parser import ( | |||
# TestFullEarleyScanless, | |||
TestFullEarleyDynamic, | |||
TestFullEarleyDynamic_complete, | |||
TestParsers, | |||
) | |||
@@ -21,7 +21,6 @@ from lark.lark import Lark | |||
from lark.exceptions import GrammarError, ParseError, UnexpectedToken, UnexpectedInput | |||
from lark.tree import Tree | |||
from lark.visitors import Transformer | |||
from lark.parsers.earley_forest import ForestToAmbiguousTreeVisitor | |||
from lark.parsers.earley import ApplyCallbacks | |||
__path__ = os.path.dirname(__file__) | |||
@@ -156,6 +155,8 @@ class TestParsers(unittest.TestCase): | |||
def _make_full_earley_test(LEXER): | |||
def _Lark(grammar, **kwargs): | |||
return Lark(grammar, lexer=LEXER, parser='earley', propagate_positions=True, **kwargs) | |||
class _TestFullEarley(unittest.TestCase): | |||
def test_anon(self): | |||
# Fails an Earley implementation without special handling for empty rules, | |||
@@ -238,8 +239,7 @@ def _make_full_earley_test(LEXER): | |||
""" | |||
parser = Lark(grammar, parser='earley', lexer=LEXER, ambiguity='explicit') | |||
root_symbol = parser.parse('ab') | |||
ambig_tree = ForestToAmbiguousTreeVisitor(root_symbol, parser.parser.parser.callbacks).go() | |||
ambig_tree = parser.parse('ab') | |||
# print(ambig_tree.pretty()) | |||
self.assertEqual( ambig_tree.data, '_ambig') | |||
self.assertEqual( len(ambig_tree.children), 2) | |||
@@ -254,8 +254,7 @@ def _make_full_earley_test(LEXER): | |||
""" | |||
l = Lark(grammar, parser='earley', ambiguity='explicit', lexer=LEXER) | |||
root_symbol = l.parse('cde') | |||
ambig_tree = ForestToAmbiguousTreeVisitor(root_symbol, l.parser.parser.callbacks).go() | |||
ambig_tree = l.parse('cde') | |||
# print(ambig_tree.pretty()) | |||
# tree = ApplyCallbacks(l.parser.parser.postprocess).transform(ambig_tree) | |||
@@ -301,8 +300,7 @@ def _make_full_earley_test(LEXER): | |||
%ignore WS | |||
""" | |||
parser = Lark(grammar, ambiguity='explicit', lexer=LEXER) | |||
root_symbol = parser.parse('fruit flies like bananas') | |||
tree = ForestToAmbiguousTreeVisitor(root_symbol, parser.parser.parser.callbacks).go() | |||
tree = parser.parse('fruit flies like bananas') | |||
# tree = ApplyCallbacks(parser.parser.parser.postprocess).transform(ambig_tree) | |||
expected = Tree('_ambig', [ | |||
@@ -335,10 +333,9 @@ def _make_full_earley_test(LEXER): | |||
""" | |||
text = """cat""" | |||
parser = Lark(grammar, start='start', ambiguity='explicit') | |||
root_symbol = parser.parse(text) | |||
ambig_tree = ForestToAmbiguousTreeVisitor(root_symbol).go() | |||
tree = ApplyCallbacks(parser.parser.parser.postprocess).transform(ambig_tree) | |||
parser = _Lark(grammar, start='start', ambiguity='explicit') | |||
tree = parser.parse(text) | |||
print(tree.pretty()) | |||
self.assertEqual(tree.data, '_ambig') | |||
combinations = {tuple(str(s) for s in t.children) for t in tree.children} | |||
@@ -1303,7 +1300,7 @@ _TO_TEST = [ | |||
for _LEXER, _PARSER in _TO_TEST: | |||
_make_parser_test(_LEXER, _PARSER) | |||
for _LEXER in ('dynamic',): | |||
for _LEXER in ('dynamic', 'dynamic_complete'): | |||
_make_full_earley_test(_LEXER) | |||
if __name__ == '__main__': | |||