text.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import os
  2. from lark import Lark, Transformer
  3. from sccd.action_lang.static.statement import *
  4. _grammar_dir = os.path.dirname(__file__)
  5. with open(os.path.join(_grammar_dir,"action_lang.g")) as file:
  6. action_lang_grammar = file.read()
  7. # Lark transformer for generating a parse tree of our own types.
  8. class ExpressionTransformer(Transformer):
  9. array = Array
  10. block = Block
  11. def string_literal(self, node):
  12. return StringLiteral(node[0][1:-1])
  13. def int_literal(self, node):
  14. return IntLiteral(int(node[0].value))
  15. def float_literal(self, node):
  16. return FloatLiteral(float(node[0].value))
  17. def bool_literal(self, node):
  18. return BoolLiteral({
  19. "True": True,
  20. "False": False,
  21. }[node[0].value])
  22. def duration_literal(self, node):
  23. val = int(node[0])
  24. suffix = node[1]
  25. unit = {
  26. "d": None, # 'd' stands for "duration", the non-unit for all zero-durations.
  27. # need this to parse zero-duration as a duration instead of int.
  28. "fs": FemtoSecond,
  29. "ps": PicoSecond,
  30. "ns": Nanosecond,
  31. "us": Microsecond,
  32. "ms": Millisecond,
  33. "s": Second,
  34. "m": Minute,
  35. "h": Hour
  36. }[suffix]
  37. return DurationLiteral(duration(val, unit))
  38. def func_call(self, node):
  39. return FunctionCall(node[0], node[1].children)
  40. def macro_call(self, node):
  41. return MacroCall(node[0], node[1].children)
  42. def array_indexed(self, node):
  43. return ArrayIndexed(node[0], node[1])
  44. def identifier(self, node):
  45. name = node[0].value
  46. return Identifier(name)
  47. def binary_expr(self, node):
  48. return BinaryExpression(node[0], node[1].value, node[2])
  49. def unary_expr(self, node):
  50. return UnaryExpression(node[0].value, node[1])
  51. def group(self, node):
  52. return Group(node[0])
  53. def assignment(self, node):
  54. operator = node[1].value
  55. if operator == "=":
  56. return Assignment(node[0], node[2])
  57. else:
  58. # Increment, decrement etc. operators are just syntactic sugar
  59. bin_operator = {"+=": "+", "-=": "-", "*=": "*", "/=": "/", "//=": "//"}[operator]
  60. return Assignment(node[0], BinaryExpression(node[0], bin_operator, node[2]))
  61. def expression_stmt(self, node):
  62. return ExpressionStatement(node[0])
  63. def return_stmt(self, node):
  64. return ReturnStatement(node[0])
  65. def if_stmt(self, node):
  66. if len(node) == 2:
  67. return IfStatement(cond=node[0], if_body=node[1])
  68. else:
  69. return IfStatement(cond=node[0], if_body=node[1], else_body=node[2])
  70. def import_stmt(self, node):
  71. return ImportStatement(module_name=node[0])
  72. params_decl = list
  73. def param_decl(self, node):
  74. return ParamDecl(name=node[0].value, formal_type=node[1])
  75. def type_annot(self, node):
  76. return {
  77. "int": SCCDInt,
  78. "str": SCCDString,
  79. "float": SCCDFloat,
  80. "dur": SCCDDuration,
  81. }[node[0]]
  82. def func_type(self, node):
  83. if len(node) > 1:
  84. return SCCDFunction(param_types=node[0], return_type=node[1])
  85. else:
  86. return SCCDFunction(param_types=node[0])
  87. param_types = list
  88. def func_decl(self, node):
  89. return FunctionDeclaration(params_decl=node[0], body=node[1])
  90. # Global variables so we don't have to rebuild our parser every time
  91. # Obviously not thread-safe
  92. _transformer = ExpressionTransformer()
  93. _parser = Lark(action_lang_grammar, parser="lalr", start=["expr", "block"], transformer=_transformer)
  94. # Exported functions:
  95. def parse_expression(text: str) -> Expression:
  96. return _parser.parse(text, start="expr")
  97. def parse_block(text: str) -> Statement:
  98. return _parser.parse(text, start="block")