Browse Source

Merge branch 'elektito-embedded-inplace-transformer'

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.7.2
Erez Shinan 6 years ago
parent
commit
80fd20facb
4 changed files with 59 additions and 3 deletions
  1. +11
    -0
      lark/parse_tree_builder.py
  2. +1
    -1
      lark/parser_frontends.py
  3. +1
    -1
      lark/visitors.py
  4. +46
    -1
      tests/test_parser.py

+ 11
- 0
lark/parse_tree_builder.py View File

@@ -2,6 +2,7 @@ from .exceptions import GrammarError
from .lexer import Token
from .tree import Tree
from .visitors import InlineTransformer # XXX Deprecated
from .visitors import Transformer_InPlace

###{standalone
from functools import partial, wraps
@@ -193,6 +194,14 @@ def ptb_inline_args(func):
return func(*children)
return f

def inplace_transformer(func):
@wraps(func)
def f(children):
# function name in a Transformer is a rule name.
tree = Tree(func.__name__, children)
return func(tree)
return f

class ParseTreeBuilder:
def __init__(self, rules, tree_class, propagate_positions=False, keep_all_tokens=False, ambiguous=False, maybe_placeholders=False):
self.tree_class = tree_class
@@ -231,6 +240,8 @@ class ParseTreeBuilder:
# XXX InlineTransformer is deprecated!
if getattr(f, 'inline', False) or isinstance(transformer, InlineTransformer):
f = ptb_inline_args(f)
elif hasattr(f, 'whole_tree') or isinstance(transformer, Transformer_InPlace):
f = inplace_transformer(f)
except AttributeError:
f = partial(self.tree_class, user_callback_name)



+ 1
- 1
lark/parser_frontends.py View File

@@ -107,7 +107,7 @@ class LALR_ContextualLexer(LALR_WithLexer):
###}

class LALR_CustomLexer(LALR_WithLexer):
def __init__(self, lexer_cls, lexer_conf, parser_conf, *, options=None):
def __init__(self, lexer_cls, lexer_conf, parser_conf, options=None):
self.lexer = lexer_cls(self.lexer_conf)
debug = options.debug if options else False
self.parser = LALR_Parser(parser_conf, debug=debug)


+ 1
- 1
lark/visitors.py View File

@@ -36,7 +36,7 @@ class Transformer:
return f(*children)
elif getattr(f, 'whole_tree', False):
if new_children is not None:
raise NotImplementedError("Doesn't work with the base Transformer class")
tree.children = new_children
return f(tree)
else:
return f(children)


+ 46
- 1
tests/test_parser.py View File

@@ -20,7 +20,7 @@ logging.basicConfig(level=logging.INFO)
from lark.lark import Lark
from lark.exceptions import GrammarError, ParseError, UnexpectedToken, UnexpectedInput, UnexpectedCharacters
from lark.tree import Tree
from lark.visitors import Transformer
from lark.visitors import Transformer, Transformer_InPlace, v_args
from lark.grammar import Rule
from lark.lexer import TerminalDef

@@ -150,6 +150,51 @@ class TestParsers(unittest.TestCase):
r = g.parse("xx")
self.assertEqual( r.children, ["<c>"] )

def test_embedded_transformer_inplace(self):
@v_args(tree=True)
class T1(Transformer_InPlace):
def a(self, tree):
assert isinstance(tree, Tree), tree
tree.children.append("tested")
return tree

def b(self, tree):
return Tree(tree.data, tree.children + ['tested2'])

@v_args(tree=True)
class T2(Transformer):
def a(self, tree):
assert isinstance(tree, Tree)
tree.children.append("tested")
return tree

def b(self, tree):
return Tree(tree.data, tree.children + ['tested2'])

class T3(Transformer):
@v_args(tree=True)
def a(self, tree):
assert isinstance(tree, Tree)
tree.children.append("tested")
return tree

@v_args(tree=True)
def b(self, tree):
return Tree(tree.data, tree.children + ['tested2'])

for t in [T1(), T2(), T3()]:
for internal in [False, True]:
g = Lark("""start: a b
a : "x"
b : "y"
""", parser='lalr', transformer=t if internal else None)
r = g.parse("xy")
if not internal:
r = t.transform(r)

a, b = r.children
self.assertEqual(a.children, ["tested"])
self.assertEqual(b.children, ["tested2"])

def test_alias(self):
Lark("""start: ["a"] "b" ["c"] "e" ["f"] ["g"] ["h"] "x" -> d """)


Loading…
Cancel
Save