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 .lexer import Token
from .tree import Tree from .tree import Tree
from .visitors import InlineTransformer # XXX Deprecated from .visitors import InlineTransformer # XXX Deprecated
from .visitors import Transformer_InPlace


###{standalone ###{standalone
from functools import partial, wraps from functools import partial, wraps
@@ -193,6 +194,14 @@ def ptb_inline_args(func):
return func(*children) return func(*children)
return f 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: class ParseTreeBuilder:
def __init__(self, rules, tree_class, propagate_positions=False, keep_all_tokens=False, ambiguous=False, maybe_placeholders=False): def __init__(self, rules, tree_class, propagate_positions=False, keep_all_tokens=False, ambiguous=False, maybe_placeholders=False):
self.tree_class = tree_class self.tree_class = tree_class
@@ -231,6 +240,8 @@ class ParseTreeBuilder:
# XXX InlineTransformer is deprecated! # XXX InlineTransformer is deprecated!
if getattr(f, 'inline', False) or isinstance(transformer, InlineTransformer): if getattr(f, 'inline', False) or isinstance(transformer, InlineTransformer):
f = ptb_inline_args(f) f = ptb_inline_args(f)
elif hasattr(f, 'whole_tree') or isinstance(transformer, Transformer_InPlace):
f = inplace_transformer(f)
except AttributeError: except AttributeError:
f = partial(self.tree_class, user_callback_name) 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): 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) self.lexer = lexer_cls(self.lexer_conf)
debug = options.debug if options else False debug = options.debug if options else False
self.parser = LALR_Parser(parser_conf, debug=debug) self.parser = LALR_Parser(parser_conf, debug=debug)


+ 1
- 1
lark/visitors.py View File

@@ -36,7 +36,7 @@ class Transformer:
return f(*children) return f(*children)
elif getattr(f, 'whole_tree', False): elif getattr(f, 'whole_tree', False):
if new_children is not None: if new_children is not None:
raise NotImplementedError("Doesn't work with the base Transformer class")
tree.children = new_children
return f(tree) return f(tree)
else: else:
return f(children) 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.lark import Lark
from lark.exceptions import GrammarError, ParseError, UnexpectedToken, UnexpectedInput, UnexpectedCharacters from lark.exceptions import GrammarError, ParseError, UnexpectedToken, UnexpectedInput, UnexpectedCharacters
from lark.tree import Tree 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.grammar import Rule
from lark.lexer import TerminalDef from lark.lexer import TerminalDef


@@ -150,6 +150,51 @@ class TestParsers(unittest.TestCase):
r = g.parse("xx") r = g.parse("xx")
self.assertEqual( r.children, ["<c>"] ) 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): def test_alias(self):
Lark("""start: ["a"] "b" ["c"] "e" ["f"] ["g"] ["h"] "x" -> d """) Lark("""start: ["a"] "b" ["c"] "e" ["f"] ["g"] ["h"] "x" -> d """)


Loading…
Cancel
Save