diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/lark/ast_utils.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/lark/ast_utils.py | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/lark/ast_utils.py b/.venv/lib/python3.12/site-packages/lark/ast_utils.py new file mode 100644 index 00000000..0c03d458 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/lark/ast_utils.py @@ -0,0 +1,55 @@ +""" + Module of utilities for transforming a lark.Tree into a custom Abstract Syntax Tree +""" + +import inspect, re + +from lark import Transformer, v_args + +class Ast(object): + """Abstract class + + Subclasses will be collected by `create_transformer()` + """ + pass + +class AsList(object): + """Abstract class + + Subclasses will be instanciated with the parse results as a single list, instead of as arguments. + """ + +class WithMeta(object): + """Abstract class + + Subclasses will be instanciated with 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 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. + CamelCase names will be converted into snake_case. Example: "CodeBlock" -> "code_block". + + Classes starting with an underscore (`_`) will be skipped. + + 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): + 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
\ No newline at end of file |