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.

116 lines
2.2 KiB

  1. """
  2. This example demonstrates how to transform a parse-tree into an AST using `lark.ast_utils`.
  3. create_transformer() collects every subclass of `Ast` subclass from the module,
  4. and creates a Lark transformer that builds the AST with no extra code.
  5. This example only works with Python 3.
  6. """
  7. import sys
  8. from typing import List
  9. from dataclasses import dataclass
  10. from lark import Lark, ast_utils, Transformer, v_args
  11. this_module = sys.modules[__name__]
  12. #
  13. # Define AST
  14. #
  15. class _Ast(ast_utils.Ast):
  16. # This will be skipped by create_transformer(), because it starts with an underscore
  17. pass
  18. class _Statement(_Ast):
  19. # This will be skipped by create_transformer(), because it starts with an underscore
  20. pass
  21. @dataclass
  22. class Value(_Ast):
  23. value: object
  24. @dataclass
  25. class Name(_Ast):
  26. name: str
  27. @dataclass
  28. class CodeBlock(_Ast, ast_utils.AsList):
  29. # Corresponds to code_block in the grammar
  30. statements: List[_Statement]
  31. @dataclass
  32. class If(_Statement):
  33. cond: Value
  34. then: CodeBlock
  35. @dataclass
  36. class SetVar(_Statement):
  37. # Corresponds to set_var in the grammar
  38. name: str
  39. value: Value
  40. @dataclass
  41. class Print(_Statement):
  42. value: Value
  43. class ToAst(Transformer):
  44. # Define extra transformation functions, for rules that don't correspond to an AST class.
  45. def STRING(self, s):
  46. # Remove quotation marks
  47. return s[1:-1]
  48. def DEC_NUMBER(self, n):
  49. return int(n)
  50. @v_args(inline=True)
  51. def start(self, x):
  52. return x
  53. #
  54. # Define Parser
  55. #
  56. parser = Lark("""
  57. start: code_block
  58. code_block: statement+
  59. ?statement: if | set_var | print
  60. if: "if" value "{" code_block "}"
  61. set_var: NAME "=" value ";"
  62. print: "print" value ";"
  63. value: name | STRING | DEC_NUMBER
  64. name: NAME
  65. %import python (NAME, STRING, DEC_NUMBER)
  66. %import common.WS
  67. %ignore WS
  68. """,
  69. parser="lalr",
  70. )
  71. transformer = ast_utils.create_transformer(this_module, ToAst())
  72. def parse(text):
  73. tree = parser.parse(text)
  74. return transformer.transform(tree)
  75. #
  76. # Test
  77. #
  78. if __name__ == '__main__':
  79. print(parse("""
  80. a = 1;
  81. if a {
  82. print "a is 1";
  83. a = 2;
  84. }
  85. """))