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.

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