This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

55 rader
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