소스 검색

More work

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.6.0
Erez Shinan 6 년 전
부모
커밋
4864a1cf4d
5개의 변경된 파일119개의 추가작업 그리고 50개의 파일을 삭제
  1. +2
    -2
      examples/calc.py
  2. +3
    -4
      lark/parsers/earley.py
  3. +6
    -6
      lark/parsers/resolve_ambig.py
  4. +55
    -37
      lark/visitors.py
  5. +53
    -1
      tests/test_trees.py

+ 2
- 2
examples/calc.py 파일 보기

@@ -2,7 +2,7 @@
# This example shows how to write a basic calculator with variables.
#

from lark import Lark, InlineTransformer
from lark import Lark, Transformer, children_args_inline

try:
input = raw_input # For Python2 compatibility
@@ -34,7 +34,7 @@ calc_grammar = """
%ignore WS_INLINE
"""

class CalculateTree(InlineTransformer):
class CalculateTree(SimpleTransformer):
from operator import add, sub, mul, truediv as div, neg
number = float



+ 3
- 4
lark/parsers/earley.py 파일 보기

@@ -21,11 +21,10 @@ from ..grammar import NonTerminal


class Derivation(Tree):
_hash = None

def __init__(self, rule, items=None):
Tree.__init__(self, 'drv', items or [])
self.rule = rule
self.meta.rule = rule
self._hash = None

def _pretty_label(self): # Nicer pretty for debugging the parser
return self.rule.origin if self.rule else self.data
@@ -236,4 +235,4 @@ class ApplyCallbacks(Transformer_InPlace):
self.postprocess = postprocess

def drv(self, tree):
return self.postprocess[tree.rule](tree.children)
return self.postprocess[tree.meta.rule](tree.children)

+ 6
- 6
lark/parsers/resolve_ambig.py 파일 보기

@@ -16,7 +16,7 @@ def _sum_priority(tree):

for n in tree.iter_subtrees():
try:
p += n.rule.options.priority or 0
p += n.meta.rule.options.priority or 0
except AttributeError:
pass

@@ -26,8 +26,8 @@ def _compare_priority(tree1, tree2):
tree1.iter_subtrees()

def _compare_drv(tree1, tree2):
rule1 = getattr(tree1, 'rule', None)
rule2 = getattr(tree2, 'rule', None)
rule1 = getattr(tree1.meta, 'rule', None)
rule2 = getattr(tree2.meta, 'rule', None)

if None == rule1 == rule2:
return compare(tree1, tree2)
@@ -45,7 +45,7 @@ def _compare_drv(tree1, tree2):
if c:
return c

c = _compare_rules(tree1.rule, tree2.rule)
c = _compare_rules(tree1.meta.rule, tree2.meta.rule)
if c:
return c

@@ -65,7 +65,7 @@ def _standard_resolve_ambig(tree):
best = max(tree.children, key=key_f)
assert best.data == 'drv'
tree.set('drv', best.children)
tree.rule = best.rule # needed for applying callbacks
tree.meta.rule = best.meta.rule # needed for applying callbacks

def standard_resolve_ambig(tree):
for ambig in tree.find_data('_ambig'):
@@ -93,7 +93,7 @@ def _antiscore_sum_resolve_ambig(tree):
best = min(tree.children, key=_antiscore_sum_drv)
assert best.data == 'drv'
tree.set('drv', best.children)
tree.rule = best.rule # needed for applying callbacks
tree.meta.rule = best.meta.rule # needed for applying callbacks

def antiscore_sum_resolve_ambig(tree):
for ambig in tree.find_data('_ambig'):


+ 55
- 37
lark/visitors.py 파일 보기

@@ -1,4 +1,4 @@
from inspect import isclass
from inspect import isclass, getmembers, getmro
from functools import wraps

from .utils import smart_decorator
@@ -16,6 +16,30 @@ class Base:
"Default operation on tree (for override)"
return tree

@classmethod
def _apply_decorator(cls, decorator):
mro = getmro(cls)
assert mro[0] is cls
libmembers = {name for _cls in mro[1:] for name, _ in getmembers(_cls)}
for name, value in getmembers(cls):
if name.startswith('_') or name in libmembers:
continue

setattr(cls, name, decorator(value))
return cls


class SimpleBase(Base):
def _call_userfunc(self, tree):
# Assumes tree is already transformed
try:
f = getattr(self, tree.data)
except AttributeError:
return self.__default__(tree)
else:
return f(tree.children)


class Transformer(Base):
def _transform_children(self, children):
for c in children:
@@ -35,6 +59,7 @@ class Transformer(Base):
return TransformerChain(self, other)



class TransformerChain(object):
def __init__(self, *transformers):
self.transformers = transformers
@@ -110,8 +135,22 @@ class Interpreter(object):



def _children_args__func(f):
@wraps(f)


def _apply_decorator(obj, decorator):
try:
_apply = obj._apply_decorator
except AttributeError:
return decorator(obj)
else:
return _apply(decorator)


def _children_args__func(func):
if getattr(func, '_children_args_decorated', False):
return func

@wraps(func)
def create_decorator(_f, with_self):
if with_self:
def f(self, tree):
@@ -119,55 +158,34 @@ def _children_args__func(f):
else:
def f(args):
return _f(tree.children)
f._children_args_decorated = True
return f

return smart_decorator(f, create_decorator)

def _children_args__class(cls):
def _call_userfunc(self, tree):
# Assumes tree is already transformed
try:
f = getattr(self, tree.data)
except AttributeError:
return self.__default__(tree)
else:
return f(tree.children)
cls._call_userfunc = _call_userfunc
return cls

return smart_decorator(func, create_decorator)

def children_args(obj):
decorator = _children_args__class if isclass(obj) and issubclass(obj, Base) else _children_args__func
return decorator(obj)
return _apply_decorator(obj, _children_args__func)



def _children_args_inline__func(f):
@wraps(f)
def _children_args_inline__func(func):
if getattr(func, '_children_args_decorated', False):
return func

@wraps(func)
def create_decorator(_f, with_self):
if with_self:
def f(self, tree):
return _f(self, *tree.children)
else:
def f(args):
def f(self, tree):
print ('##', _f, tree)
return _f(*tree.children)
f._children_args_decorated = True
return f

return smart_decorator(f, create_decorator)

return smart_decorator(func, create_decorator)

def _children_args_inline__class(cls):
def _call_userfunc(self, tree):
# Assumes tree is already transformed
try:
f = getattr(self, tree.data)
except AttributeError:
return self.__default__(tree)
else:
return f(*tree.children)
cls._call_userfunc = _call_userfunc
return cls

def children_args_inline(obj):
decorator = _children_args_inline__class if isclass(obj) and issubclass(obj, Base) else _children_args_inline__func
return decorator(obj)
return _apply_decorator(obj, _children_args_inline__func)

+ 53
- 1
tests/test_trees.py 파일 보기

@@ -6,7 +6,7 @@ import copy
import pickle

from lark.tree import Tree
from lark.visitors import Interpreter, visit_children_decor
from lark.visitors import Transformer, Interpreter, visit_children_decor, children_args_inline, children_args


class TestTrees(TestCase):
@@ -59,6 +59,58 @@ class TestTrees(TestCase):

self.assertEqual(Interp3().visit(t), list('BCd'))

def test_transformer(self):
t = Tree('add', [Tree('sub', [Tree('i', ['3']), Tree('f', ['1.1'])]), Tree('i', ['1'])])

class T(Transformer):
i = children_args_inline(int)
f = children_args_inline(float)

sub = lambda self, tree: tree.children[0] - tree.children[1]

def add(self, tree):
return sum(tree.children)


res = T().transform(t)
self.assertEqual(res, 2.9)

@children_args_inline
class T(Transformer):
i = int
f = float
sub = lambda self, a, b: a-b

def add(self, a, b):
return a + b


res = T().transform(t)
self.assertEqual(res, 2.9)


@children_args_inline
class T(Transformer):
i = int
f = float
from operator import sub, add

res = T().transform(t)
self.assertEqual(res, 2.9)


@children_args
class T(Transformer):
i = children_args_inline(int)
f = children_args_inline(float)

sub = lambda self, values: values[0] - values[1]

def add(self, values):
return sum(values)

res = T().transform(t)
self.assertEqual(res, 2.9)


if __name__ == '__main__':


불러오는 중...
취소
저장