text.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import os
  2. from lark import Lark
  3. from sccd.action_lang.parser import text as action_lang
  4. from sccd.statechart.static.tree import *
  5. from sccd.cd.globals import *
  6. _grammar_dir = os.path.dirname(__file__)
  7. with open(os.path.join(_grammar_dir, "statechart.g")) as file:
  8. _sc_grammar = action_lang.action_lang_grammar + file.read()
  9. # Lark transformer for parsetree-less parsing of expressions
  10. class StatechartTransformer(action_lang.ExpressionTransformer):
  11. def __init__(self):
  12. super().__init__()
  13. self.globals: Globals = None
  14. # override
  15. def duration_literal(self, node):
  16. val = int(node[0])
  17. suffix = node[1]
  18. unit = {
  19. "d": None, # 'd' stands for "duration", the non-unit for all zero-durations.
  20. # need this to parse zero-duration as a duration instead of int.
  21. "fs": FemtoSecond,
  22. "ps": PicoSecond,
  23. "ns": Nanosecond,
  24. "us": Microsecond,
  25. "ms": Millisecond,
  26. "s": Second,
  27. "m": Minute,
  28. "h": Hour
  29. }[suffix]
  30. d = SCDurationLiteral(duration(val, unit))
  31. self.globals.durations.append(d)
  32. return d
  33. # Event declaration parsing
  34. def event_decl_list(self, node):
  35. pos_events = []
  36. neg_events = []
  37. for n in node:
  38. if n.data == "pos":
  39. pos_events.append(n.children[0])
  40. elif n.data == "neg":
  41. neg_events.append(n.children[0])
  42. return (pos_events, neg_events)
  43. def event_decl(self, node):
  44. event_name = node[0].value
  45. event_id = self.globals.events.assign_id(event_name)
  46. return EventDecl(id=event_id, name=event_name, params_decl=node[1])
  47. # Global variables so we don't have to rebuild our parser every time
  48. # Obviously not thread-safe
  49. _transformer = StatechartTransformer()
  50. _parser = Lark(_sc_grammar, parser="lalr", start=["expr", "block", "event_decl_list", "state_ref", "semantic_choice"], transformer=_transformer)
  51. # Exported functions:
  52. def parse_expression(globals: Globals, text: str) -> Expression:
  53. _transformer.globals = globals
  54. return _parser.parse(text, start="expr")
  55. def parse_block(globals: Globals, text: str) -> Block:
  56. _transformer.globals = globals
  57. return _parser.parse(text, start="block")
  58. def parse_events_decl(globals: Globals, text: str) -> Tuple[List[EventDecl], List[EventDecl]]:
  59. _transformer.globals = globals
  60. return _parser.parse(text, start="event_decl_list")
  61. def parse_state_ref(text: str):
  62. return _parser.parse(text, start="state_ref")
  63. def parse_semantic_choice(text: str):
  64. return _parser.parse(text, start="semantic_choice")