@@ -15,7 +15,7 @@ from .common import is_terminal, GrammarError, LexerConf, ParserConf, PatternStr | |||||
from .grammar import RuleOptions, Rule | from .grammar import RuleOptions, Rule | ||||
from .tree import Tree, SlottedTree as ST | from .tree import Tree, SlottedTree as ST | ||||
from .transformers import Transformer, Transformer_Children, Transformer_ChildrenInline, Visitor | |||||
from .transformers import Transformer, ChildrenTransformer, inline_args, Visitor | |||||
__path__ = os.path.dirname(__file__) | __path__ = os.path.dirname(__file__) | ||||
IMPORT_PATHS = [os.path.join(__path__, 'grammars')] | IMPORT_PATHS = [os.path.join(__path__, 'grammars')] | ||||
@@ -131,7 +131,8 @@ RULES = { | |||||
} | } | ||||
class EBNF_to_BNF(Transformer_ChildrenInline): | |||||
@inline_args | |||||
class EBNF_to_BNF(ChildrenTransformer): | |||||
def __init__(self): | def __init__(self): | ||||
self.new_rules = [] | self.new_rules = [] | ||||
self.rules_by_expr = {} | self.rules_by_expr = {} | ||||
@@ -224,7 +225,7 @@ class SimplifyRule_Visitor(Visitor): | |||||
tree.children = list(set(tree.children)) | tree.children = list(set(tree.children)) | ||||
class RuleTreeToText(Transformer_Children): | |||||
class RuleTreeToText(ChildrenTransformer): | |||||
def expansions(self, x): | def expansions(self, x): | ||||
return x | return x | ||||
def expansion(self, symbols): | def expansion(self, symbols): | ||||
@@ -235,17 +236,13 @@ class RuleTreeToText(Transformer_Children): | |||||
return expansion, alias.value | return expansion, alias.value | ||||
class CanonizeTree(Transformer_ChildrenInline): | |||||
@inline_args | |||||
class CanonizeTree(ChildrenTransformer): | |||||
def maybe(self, expr): | def maybe(self, expr): | ||||
return ST('expr', [expr, Token('OP', '?', -1)]) | return ST('expr', [expr, Token('OP', '?', -1)]) | ||||
def tokenmods(self, *args): | |||||
if len(args) == 1: | |||||
return list(args) | |||||
tokenmods, value = args | |||||
return tokenmods + [value] | |||||
class ExtractAnonTokens(Transformer_ChildrenInline): | |||||
@inline_args | |||||
class ExtractAnonTokens(ChildrenTransformer): | |||||
"Create a unique list of anonymous tokens. Attempt to give meaningful names to them when we add them" | "Create a unique list of anonymous tokens. Attempt to give meaningful names to them when we add them" | ||||
def __init__(self, tokens): | def __init__(self, tokens): | ||||
@@ -349,7 +346,8 @@ def _literal_to_pattern(literal): | |||||
'REGEXP': PatternRE }[literal.type](s, flags) | 'REGEXP': PatternRE }[literal.type](s, flags) | ||||
class PrepareLiterals(Transformer_ChildrenInline): | |||||
@inline_args | |||||
class PrepareLiterals(ChildrenTransformer): | |||||
def literal(self, literal): | def literal(self, literal): | ||||
return ST('pattern', [_literal_to_pattern(literal)]) | return ST('pattern', [_literal_to_pattern(literal)]) | ||||
@@ -361,13 +359,14 @@ class PrepareLiterals(Transformer_ChildrenInline): | |||||
regexp = '[%s-%s]' % (start, end) | regexp = '[%s-%s]' % (start, end) | ||||
return ST('pattern', [PatternRE(regexp)]) | return ST('pattern', [PatternRE(regexp)]) | ||||
class SplitLiterals(Transformer_ChildrenInline): | |||||
@inline_args | |||||
class SplitLiterals(ChildrenTransformer): | |||||
def pattern(self, p): | def pattern(self, p): | ||||
if isinstance(p, PatternStr) and len(p.value)>1: | if isinstance(p, PatternStr) and len(p.value)>1: | ||||
return ST('expansion', [ST('pattern', [PatternStr(ch, flags=p.flags)]) for ch in p.value]) | return ST('expansion', [ST('pattern', [PatternStr(ch, flags=p.flags)]) for ch in p.value]) | ||||
return ST('pattern', [p]) | return ST('pattern', [p]) | ||||
class TokenTreeToPattern(Transformer_Children): | |||||
class TokenTreeToPattern(ChildrenTransformer): | |||||
def pattern(self, ps): | def pattern(self, ps): | ||||
p ,= ps | p ,= ps | ||||
return p | return p | ||||
@@ -15,7 +15,7 @@ | |||||
from ..common import ParseError, UnexpectedToken, is_terminal | from ..common import ParseError, UnexpectedToken, is_terminal | ||||
from ..tree import Tree | from ..tree import Tree | ||||
from ..transformers import InPlaceTransformer | |||||
from ..transformers import Transformer_InPlace | |||||
from .grammar_analysis import GrammarAnalyzer | from .grammar_analysis import GrammarAnalyzer | ||||
@@ -230,7 +230,7 @@ class Parser: | |||||
return ApplyCallbacks(self.postprocess).transform(tree) | return ApplyCallbacks(self.postprocess).transform(tree) | ||||
class ApplyCallbacks(InPlaceTransformer): | |||||
class ApplyCallbacks(Transformer_InPlace): | |||||
def __init__(self, postprocess): | def __init__(self, postprocess): | ||||
self.postprocess = postprocess | self.postprocess = postprocess | ||||
@@ -1,5 +1,7 @@ | |||||
import inspect | |||||
from functools import wraps | from functools import wraps | ||||
from . import utils | |||||
from .tree import Tree | from .tree import Tree | ||||
class Discard(Exception): | class Discard(Exception): | ||||
@@ -31,7 +33,7 @@ class Transformer(Base): | |||||
def __mul__(self, other): | def __mul__(self, other): | ||||
return TransformerChain(self, other) | return TransformerChain(self, other) | ||||
class Transformer_Children(Transformer): | |||||
class ChildrenTransformer(Transformer): | |||||
def _call_userfunc(self, tree): | def _call_userfunc(self, tree): | ||||
# Assumes tree is already transformed | # Assumes tree is already transformed | ||||
try: | try: | ||||
@@ -41,7 +43,7 @@ class Transformer_Children(Transformer): | |||||
else: | else: | ||||
return f(tree.children) | return f(tree.children) | ||||
class Transformer_ChildrenInline(Transformer): | |||||
class ChildrenInlineTransformer(Transformer): | |||||
def _call_userfunc(self, tree): | def _call_userfunc(self, tree): | ||||
# Assumes tree is already transformed | # Assumes tree is already transformed | ||||
try: | try: | ||||
@@ -64,58 +66,44 @@ class TransformerChain(object): | |||||
def __mul__(self, other): | def __mul__(self, other): | ||||
return TransformerChain(*self.transformers + (other,)) | return TransformerChain(*self.transformers + (other,)) | ||||
class Visitor(Base): | |||||
# def visit(self, tree): | |||||
# for child in tree.children: | |||||
# if isinstance(child, Tree): | |||||
# self.visit(child) | |||||
# f = getattr(self, tree.data, self.__default__) | |||||
# f(tree) | |||||
# return tree | |||||
class Transformer_InPlace(Transformer): | |||||
def _transform(self, tree): | |||||
return self._call_userfunc(tree) | |||||
def transform(self, tree): | |||||
for subtree in tree.iter_subtrees(): | |||||
subtree.children = list(self._transform_children(subtree.children)) | |||||
return self._transform(tree) | |||||
class Visitor(Base): | |||||
def visit(self, tree): | def visit(self, tree): | ||||
for subtree in tree.iter_subtrees(): | for subtree in tree.iter_subtrees(): | ||||
self._call_userfunc(subtree) | self._call_userfunc(subtree) | ||||
return tree | return tree | ||||
class InPlaceTransformer(Transformer): | |||||
# def _transform(self, tree): | |||||
# children = [] | |||||
# for c in tree.children: | |||||
# try: | |||||
# children.append(self._transform(c) if isinstance(c, Tree) else c) | |||||
# except Discard: | |||||
# pass | |||||
# tree.children = children | |||||
# return self._call_userfunc(tree) | |||||
class Transformer_InPlaceRecursive(Transformer): | |||||
def _transform(self, tree): | def _transform(self, tree): | ||||
tree.children = list(self._transform_children(tree.children)) | |||||
return self._call_userfunc(tree) | return self._call_userfunc(tree) | ||||
def transform(self, tree): | |||||
for subtree in tree.iter_subtrees(): | |||||
subtree.children = list(self._transform_children(subtree.children)) | |||||
return self._transform(tree) | |||||
class Visitor_Recursive(Base): | |||||
def visit(self, tree): | |||||
for child in tree.children: | |||||
if isinstance(child, Tree): | |||||
self.visit(child) | |||||
f = getattr(self, tree.data, self.__default__) | |||||
f(tree) | |||||
return tree | |||||
#### XXX PSEUDOCODE TODO | |||||
# def items(obj): | |||||
# if isinstance(obj, Transformer): | |||||
# def new_get_userfunc(self, name): | |||||
# uf = self._get_userfunc(name) | |||||
# def _f(tree): | |||||
# return uf(tree.children) | |||||
# return _f | |||||
# obj._get_userfunc = new_get_userfunc | |||||
# else: | |||||
# assert callable(obj) | |||||
# # apply decorator | |||||
# def _f(tree): | |||||
# return obj(tree.children) | |||||
# return _f | |||||
def inline_args(obj): | |||||
if inspect.isclass(obj) and issubclass(obj, ChildrenTransformer): | |||||
class _NewTransformer(ChildrenInlineTransformer, obj): | |||||
pass | |||||
return _NewTransformer | |||||
else: | |||||
return utils.inline_args(obj) | |||||
@@ -21,7 +21,7 @@ from lark.lark import Lark | |||||
from lark.common import GrammarError, ParseError, UnexpectedToken | from lark.common import GrammarError, ParseError, UnexpectedToken | ||||
from lark.lexer import LexError, UnexpectedInput | from lark.lexer import LexError, UnexpectedInput | ||||
from lark.tree import Tree | from lark.tree import Tree | ||||
from lark.transformers import Transformer_Children as Transformer | |||||
from lark.transformers import ChildrenTransformer as Transformer | |||||
# from lark.tree import Transformer | # from lark.tree import Transformer | ||||
__path__ = os.path.dirname(__file__) | __path__ = os.path.dirname(__file__) | ||||