expression_parser.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import os
  2. from lark import Lark, Transformer
  3. from sccd.syntax.statement import *
  4. from sccd.model.globals import *
  5. from sccd.syntax.scope import *
  6. from sccd.syntax.tree import *
  7. _grammar_dir = os.path.join(os.path.dirname(__file__), "grammar")
  8. with open(os.path.join(_grammar_dir,"action_language.g")) as file:
  9. _action_lang_grammar = file.read()
  10. # Lark transformer for parsetree-less parsing of expressions
  11. class _ExpressionTransformer(Transformer):
  12. def __init__(self):
  13. super().__init__()
  14. self.globals: Globals = None
  15. # Expression and statement parsing
  16. array = Array
  17. block = Block
  18. def string(self, node):
  19. return StringLiteral(node[0][1:-1])
  20. def int(self, node):
  21. return IntLiteral(int(node[0].value))
  22. def func_call(self, node):
  23. return FunctionCall(node[0], node[1].children)
  24. def identifier(self, node):
  25. name = node[0].value
  26. return Identifier(name)
  27. def binary_expr(self, node):
  28. return BinaryExpression(node[0], node[1].value, node[2])
  29. def unary_expr(self, node):
  30. return UnaryExpression(node[0].value, node[1])
  31. def bool(self, node):
  32. return BoolLiteral({
  33. "True": True,
  34. "False": False,
  35. }[node[0].value])
  36. def group(self, node):
  37. return Group(node[0])
  38. def assignment(self, node):
  39. return Assignment(node[0], node[1].value, node[2])
  40. def duration_literal(self, node):
  41. return DurationLiteral(node[0])
  42. def duration(self, node):
  43. val = int(node[0])
  44. suffix = node[1]
  45. unit = {
  46. "d": None, # 'd' stands for "duration", the non-unit for all zero-durations.
  47. # need this to parse zero-duration as a duration instead of int.
  48. "fs": FemtoSecond,
  49. "ps": PicoSecond,
  50. "ns": Nanosecond,
  51. "us": Microsecond,
  52. "ms": Millisecond,
  53. "s": Second,
  54. "m": Minute,
  55. "h": Hour
  56. }[suffix]
  57. d = duration(val, unit)
  58. self.globals.durations.append(d)
  59. return d
  60. def expression_stmt(self, node):
  61. return ExpressionStatement(node[0])
  62. def return_stmt(self, node):
  63. return ReturnStatement(node[0])
  64. # Event declaration parsing
  65. def event_decl_list(self, node):
  66. pos_events = []
  67. neg_events = []
  68. for n in node:
  69. if n.data == "pos":
  70. pos_events.append(n.children[0])
  71. elif n.data == "neg":
  72. neg_events.append(n.children[0])
  73. return (pos_events, neg_events)
  74. def event_decl(self, node):
  75. event_name = node[0]
  76. event_id = self.globals.events.assign_id(event_name)
  77. return EventDecl(id=event_id, name=event_name, params=node[1])
  78. params_decl = list
  79. def param_decl(self, node):
  80. type = {
  81. "int": int,
  82. "str": str,
  83. "Duration": Duration
  84. }[node[1]]
  85. return Param(name=node[0].value, type=type)
  86. def func_decl(self, node):
  87. return (node[0], node[1])
  88. # Global variables so we don't have to rebuild our parser every time
  89. # Obviously not thread-safe
  90. _transformer = _ExpressionTransformer()
  91. _parser = Lark(_action_lang_grammar, parser="lalr", start=["expr", "block", "duration", "event_decl_list", "func_decl", "state_ref", "semantic_choice"], transformer=_transformer)
  92. # Exported functions:
  93. def parse_expression(globals: Globals, text: str) -> Expression:
  94. _transformer.globals = globals
  95. return _parser.parse(text, start="expr")
  96. def parse_duration(globals: Globals, text: str) -> Duration:
  97. _transformer.globals = globals
  98. return _parser.parse(text, start="duration")
  99. def parse_block(globals: Globals, text: str) -> Statement:
  100. _transformer.globals = globals
  101. return _parser.parse(text, start="block")
  102. def parse_events_decl(globals: Globals, text: str):
  103. _transformer.globals = globals
  104. return _parser.parse(text, start="event_decl_list")
  105. def parse_func_decl(text: str) -> Tuple[str, List[Param]]:
  106. return _parser.parse(text, start="func_decl")
  107. def parse_state_ref(text: str):
  108. return _parser.parse(text, start="state_ref")
  109. def parse_semantic_choice(choice: str):
  110. return _parser.parse(choice, start="semantic_choice")