Browse Source

Implement embedded in-place transformers. See #378.

As discussed in issue #378, when an embedded transformer (that is, one
passed to the Lark class using the transformer argument), is an
inplace transformer (either a subclass of Transformer_InPlace, or with
the @v_args(tree=True) decorator), the in-place transformer was not
working correctly and in-fact Lark used it like a normal non-in-place
transformer, expecting it to return the transformed value.
tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.7.2
Mostafa Razavi 5 years ago
parent
commit
e5868415eb
2 changed files with 38 additions and 1 deletions
  1. +12
    -0
      lark/parse_tree_builder.py
  2. +26
    -1
      tests/test_parser.py

+ 12
- 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,15 @@ 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)
func(tree)
return 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 +241,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)



+ 26
- 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,31 @@ class TestParsers(unittest.TestCase):
r = g.parse("xx")
self.assertEqual( r.children, ["<c>"] )

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

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

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

for t in [T1(), T2(), T3()]:
g = Lark("""start: a
a : "x"
""", parser='lalr', transformer=t)
r = g.parse("x")
first, = r.children
self.assertEqual(first.children, ["tested"])

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


Loading…
Cancel
Save