|
|
@@ -20,23 +20,16 @@ class AsList(object): |
|
|
|
""" |
|
|
|
|
|
|
|
class WithMeta(object): |
|
|
|
"""Abstract class |
|
|
|
|
|
|
|
Subclasses will be instanciated the Meta instance of the tree. (see ``v_args`` for more detail) |
|
|
|
""" |
|
|
|
pass |
|
|
|
|
|
|
|
def camel_to_snake(name): |
|
|
|
return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower() |
|
|
|
|
|
|
|
def _call(func, _data, children, _meta): |
|
|
|
return func(*children) |
|
|
|
def _call_with_meta(func, _data, children, meta): |
|
|
|
return func(meta, children) |
|
|
|
def _call_with_meta_inline(func, _data, children, meta): |
|
|
|
return func(meta, *children) |
|
|
|
|
|
|
|
inline = v_args(wrapper=_call) |
|
|
|
with_meta = v_args(wrapper=_call_with_meta) |
|
|
|
with_meta_inline = v_args(wrapper=_call_with_meta_inline) |
|
|
|
|
|
|
|
def create_transformer(ast_module, transformer=None): |
|
|
|
def create_transformer(ast_module, transformer=None, decorator_factory=v_args): |
|
|
|
"""Collects `Ast` subclasses from the given module, and creates a Lark transformer that builds the AST. |
|
|
|
|
|
|
|
For each class, we create a corresponding rule in the transformer, with a matching name. |
|
|
@@ -47,20 +40,16 @@ def create_transformer(ast_module, transformer=None): |
|
|
|
Parameters: |
|
|
|
ast_module: A Python module containing all the subclasses of ``ast_utils.Ast`` |
|
|
|
transformer (Optional[Transformer]): An initial transformer. Its attributes may be overwritten. |
|
|
|
decorator_factory (Callable): An optional callable accepting two booleans, inline, and meta, |
|
|
|
and returning a decorator for the methods of ``transformer``. (default: ``v_args``). |
|
|
|
""" |
|
|
|
t = transformer or Transformer() |
|
|
|
|
|
|
|
for name, obj in inspect.getmembers(ast_module): |
|
|
|
if not name.startswith('_') and inspect.isclass(obj): |
|
|
|
if issubclass(obj, Ast): |
|
|
|
if not issubclass(obj, AsList): |
|
|
|
if issubclass(obj, WithMeta): |
|
|
|
obj = with_meta_inline(obj).__get__(t) |
|
|
|
else: |
|
|
|
obj = inline(obj).__get__(t) |
|
|
|
elif issubclass(obj, WithMeta): |
|
|
|
obj = with_meta(obj).__get__(t) |
|
|
|
|
|
|
|
wrapper = decorator_factory(inline=not issubclass(obj, AsList), meta=issubclass(obj, WithMeta)) |
|
|
|
obj = wrapper(obj).__get__(t) |
|
|
|
setattr(t, camel_to_snake(name), obj) |
|
|
|
|
|
|
|
return t |