This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

60 行
2.0 KiB

  1. """
  2. Module of utilities for transforming a lark.Tree into a custom Abstract Syntax Tree
  3. """
  4. import inspect, re
  5. import types
  6. from typing import Optional, Callable
  7. from lark import Transformer, v_args
  8. class Ast:
  9. """Abstract class
  10. Subclasses will be collected by `create_transformer()`
  11. """
  12. pass
  13. class AsList:
  14. """Abstract class
  15. Subclasses will be instanciated with the parse results as a single list, instead of as arguments.
  16. """
  17. class WithMeta:
  18. """Abstract class
  19. Subclasses will be instanciated with the Meta instance of the tree. (see ``v_args`` for more detail)
  20. """
  21. pass
  22. def camel_to_snake(name):
  23. return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
  24. def create_transformer(ast_module: types.ModuleType,
  25. transformer: Optional[Transformer]=None,
  26. decorator_factory: Callable=v_args) -> Transformer:
  27. """Collects `Ast` subclasses from the given module, and creates a Lark transformer that builds the AST.
  28. For each class, we create a corresponding rule in the transformer, with a matching name.
  29. CamelCase names will be converted into snake_case. Example: "CodeBlock" -> "code_block".
  30. Classes starting with an underscore (`_`) will be skipped.
  31. Parameters:
  32. ast_module: A Python module containing all the subclasses of ``ast_utils.Ast``
  33. transformer (Optional[Transformer]): An initial transformer. Its attributes may be overwritten.
  34. decorator_factory (Callable): An optional callable accepting two booleans, inline, and meta,
  35. and returning a decorator for the methods of ``transformer``. (default: ``v_args``).
  36. """
  37. t = transformer or Transformer()
  38. for name, obj in inspect.getmembers(ast_module):
  39. if not name.startswith('_') and inspect.isclass(obj):
  40. if issubclass(obj, Ast):
  41. wrapper = decorator_factory(inline=not issubclass(obj, AsList), meta=issubclass(obj, WithMeta))
  42. obj = wrapper(obj).__get__(t)
  43. setattr(t, camel_to_snake(name), obj)
  44. return t