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

52 行
1.6 KiB

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