12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- import os
- from lark import Lark
- from sccd.action_lang.parser import text as action_lang
- from sccd.statechart.static.tree import *
- from sccd.cd.globals import *
- _grammar_dir = os.path.dirname(__file__)
- with open(os.path.join(_grammar_dir, "statechart.g")) as file:
- _sc_grammar = action_lang.action_lang_grammar + file.read()
- # Lark transformer for parsetree-less parsing of expressions
- class StatechartTransformer(action_lang.ExpressionTransformer):
- def __init__(self):
- super().__init__()
- self.globals: Globals = None
- # override
- def duration_literal(self, node):
- d = SCDurationLiteral(node[0])
- self.globals.durations.append(d)
- return d
- # Event declaration parsing
- def event_decl_list(self, node):
- pos_events = []
- neg_events = []
- for n in node:
- if n.data == "pos":
- pos_events.append(n.children[0])
- elif n.data == "neg":
- neg_events.append(n.children[0])
- return (pos_events, neg_events)
- def event_decl(self, node):
- event_name = node[0].value
- event_id = self.globals.events.assign_id(event_name)
- return EventDecl(id=event_id, name=event_name, params_decl=node[1])
- # Global variables so we don't have to rebuild our parser every time
- # Obviously not thread-safe
- _transformer = StatechartTransformer()
- _parser = Lark(_sc_grammar, parser="lalr", start=["expr", "block", "event_decl_list", "state_ref", "semantic_choice"], transformer=_transformer)
- # Exported functions:
- def parse_expression(globals: Globals, text: str) -> Expression:
- _transformer.globals = globals
- return _parser.parse(text, start="expr")
- def parse_block(globals: Globals, text: str) -> Block:
- _transformer.globals = globals
- return _parser.parse(text, start="block")
- def parse_events_decl(globals: Globals, text: str) -> Tuple[List[EventDecl], List[EventDecl]]:
- _transformer.globals = globals
- return _parser.parse(text, start="event_decl_list")
- def parse_state_ref(text: str):
- return _parser.parse(text, start="state_ref")
- def parse_semantic_choice(text: str):
- return _parser.parse(text, start="semantic_choice")
|