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.

120 lines
2.3 KiB

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