This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

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