mech_syntax/
state_machines.rs

1#[macro_use]
2use crate::*;
3use nom::{
4  multi::separated_list0,
5  sequence::tuple as nom_tuple,
6};
7
8// #### State Machines
9
10// guard_operator := "|" | "│" | "├" | "└" ;
11pub fn guard_operator(input: ParseString) -> ParseResult<()> {
12  let (input, _) = whitespace0(input)?;
13  let (input, _) = alt((tag("|"),tag("│"),tag("├"),tag("└")))(input)?;
14  let (input, _) = whitespace0(input)?;
15  Ok((input, ()))
16}
17
18// fsm_implementation := "#", identifier, "(", list0(",", identifier), ")", transition_operator, pattern, whitespace*, fsm_arm+, "." ;
19pub fn fsm_implementation(input: ParseString) -> ParseResult<FsmImplementation> {
20  let (input, _) = hashtag(input)?;
21  let (input, name) = identifier(input)?;
22  let (input, _) = left_parenthesis(input)?;
23  let (input, input_vars) = separated_list0(list_separator, identifier)(input)?;
24  let (input, _) = right_parenthesis(input)?;
25  let (input, _) = transition_operator(input)?;
26  let (input, start) = pattern(input)?;
27  let (input, _) = whitespace0(input)?;
28  let (input, arms) = many1(fsm_arm)(input)?;
29  let (input, _) = period(input)?;
30  Ok((input, FsmImplementation{name,input: input_vars,start,arms}))
31}
32
33// fsm_arm := comment*, (fsm_transition | fsm_guard_arm), whitespace* ;
34pub fn fsm_arm(input: ParseString) -> ParseResult<FsmArm> {
35  let (input, _) = many0(comment)(input)?;
36  let (input, arm) = alt((fsm_guard_arm,fsm_transition))(input)?;
37  let (input, _) = whitespace0(input)?;
38  Ok((input, arm))
39}
40
41// fsm_guard_arm := comment*, pattern, fsm_guard+ ;
42pub fn fsm_guard_arm(input: ParseString) -> ParseResult<FsmArm> {
43  let (input, _) = many0(comment)(input)?;
44  let (input, start) = pattern(input)?;
45  let (input, grds) = many1(fsm_guard)(input)?;
46  Ok((input, FsmArm::Guard(start, grds)))
47}
48
49// fsm_guard := guard_operator, pattern, (fsm_statement_transition | fsm_state_transition | fsm_output | fsm_async_transition | fsm_block_transition)+ ;
50pub fn fsm_guard(input: ParseString) -> ParseResult<Guard> {
51  let (input, _) = guard_operator(input)?;
52  let (input, cnd) = pattern(input)?;
53  let (input, trns) = many1(alt((
54    fsm_statement_transition,
55    fsm_state_transition,
56    fsm_output,
57    fsm_async_transition,
58    fsm_block_transition)))(input)?;
59  Ok((input, Guard{condition: cnd, transitions: trns}))
60}
61
62// fsm_transition := comment*, pattern, (fsm_statement_transition | fsm_state_transition | fsm_output | fsm_async_transition | fsm_block_transition)+ ;
63pub fn fsm_transition(input: ParseString) -> ParseResult<FsmArm> {
64  let (input, _) = many0(comment)(input)?;
65  let (input, start) = pattern(input)?;
66  let (input, trns) = many1(alt((
67    fsm_state_transition,
68    fsm_output,
69    fsm_async_transition,
70    fsm_statement_transition,
71    fsm_block_transition)))(input)?;
72  Ok((input, FsmArm::Transition(start, trns)))
73}
74
75// fsm_state_transition := transition_operator, pattern ;
76pub fn fsm_state_transition(input: ParseString) -> ParseResult<Transition> {
77  let (input, _) = transition_operator(input)?;
78  let (input, ptrn) = pattern(input)?;
79  Ok((input, Transition::Next(ptrn)))
80}
81
82// fsm_async_transition := async_transition_operator, pattern ;
83pub fn fsm_async_transition(input: ParseString) -> ParseResult<Transition> {
84  let (input, _) = async_transition_operator(input)?;
85  let (input, ptrn) = pattern(input)?;
86  Ok((input, Transition::Async(ptrn)))
87}
88
89// fsm_statement_transition := transition_operator, statement ;
90pub fn fsm_statement_transition(input: ParseString) -> ParseResult<Transition> {
91  let (input, _) = transition_operator(input)?;
92  let (input, stmnt) = statement(input)?;
93  Ok((input, Transition::Statement(stmnt)))
94}
95
96// fsm_block_transition := transition_operator, left_brace, mech_code+, right_brace ;
97pub fn fsm_block_transition(input: ParseString) -> ParseResult<Transition> {
98  let (input, _) = transition_operator(input)?;
99  let (input, _) = left_brace(input)?;
100  let (input, code) = mech_code(input)?;
101  let (input, _) = right_brace(input)?;
102  Ok((input, Transition::CodeBlock(code)))
103}
104
105
106// fsm_output := output_operator, pattern ;
107pub fn fsm_output(input: ParseString) -> ParseResult<Transition> {
108  let (input, _) = output_operator(input)?;
109  let ((input, ptrn)) = pattern(input)?;
110  Ok((input, Transition::Output(ptrn)))
111}
112
113// fsm_specification := "#", identifier, "(", list0(",", var), ")", output_operator?, kind_annotation?, define_operator, fsm_state_definition+, "." ;
114pub fn fsm_specification(input: ParseString) -> ParseResult<FsmSpecification> {
115  let (input, _) = hashtag(input)?;
116  let (input, name) = identifier(input)?;
117  let (input, _) = left_parenthesis(input)?;
118  let (input, input_vars) = separated_list0(list_separator, var)(input)?;
119  let (input, _) = right_parenthesis(input)?;
120  let (input, _) = opt(output_operator)(input)?;
121  let (input, output) = opt(kind_annotation)(input)?;
122  let (input, _) = define_operator(input)?;
123  let (input, states) = many1(fsm_state_definition)(input)?;
124  let (input, _) = period(input)?;
125  Ok((input, FsmSpecification{name,input: input_vars, output, states}))
126}
127
128// pattern := pattern_tuple_struct | wildcard | formula ;
129pub fn pattern(input: ParseString) -> ParseResult<Pattern> {
130  match pattern_tuple_struct(input.clone()) {
131    Ok((input, tpl)) => {return Ok((input, Pattern::TupleStruct(tpl)))},
132    _ => ()
133  }
134  match wildcard(input.clone()) {
135    Ok((input, _)) => {return Ok((input, Pattern::Wildcard))},
136    _ => ()
137  }
138  match pattern_tuple(input.clone()) {
139    Ok((input, tpl)) => {return Ok((input, Pattern::Tuple(tpl)))},
140    _ => ()
141  }
142  match expression(input.clone()) {
143    Ok((input, expr)) => {return Ok((input, Pattern::Expression(expr)))},
144    Err(err) => {return Err(err)},
145  }
146}
147
148// wildcard := "*" ;
149pub fn wildcard(input: ParseString) -> ParseResult<Pattern> {
150  let ((input, _)) = asterisk(input)?;
151  Ok((input, Pattern::Wildcard))
152}
153
154// pattern_tuple_struct := grave, identifier, "(", list1(",", pattern), ")" ;
155pub fn pattern_tuple_struct(input: ParseString) -> ParseResult<PatternTupleStruct> {
156  let (input, _) = grave(input)?;
157  let (input, id) = identifier(input)?;
158  let (input, _) = left_parenthesis(input)?;
159  let (input, patterns) = separated_list1(list_separator, pattern)(input)?;
160  let (input, _) = right_parenthesis(input)?;
161  Ok((input, PatternTupleStruct{name: id, patterns}))
162}
163
164// pattern-tuple := "(", [pattern, ","], ")" ;
165pub fn pattern_tuple(input: ParseString) -> ParseResult<PatternTuple> {
166  let (input, _) = left_parenthesis(input)?;
167  let (input, patterns) = separated_list1(list_separator, pattern)(input)?;
168  let (input, _) = right_parenthesis(input)?;
169  Ok((input, PatternTuple(patterns)))
170}
171
172// fsm_state_definition := guard_operator, grave, identifier, fsm_state_definition_variables? ;
173pub fn fsm_state_definition(input: ParseString) -> ParseResult<StateDefinition> {
174  let (input, _) = guard_operator(input)?;
175  let (input, _) = whitespace0(input)?;
176  let (input, _) = grave(input)?;
177  let (input, name) = identifier(input)?;
178  let (input, vars) = opt(fsm_state_definition_variables)(input)?;
179  Ok((input, StateDefinition{name,state_variables: vars}))
180}
181
182// fsm_state_definition_variables := "(", list0(list_separator, var), ")" ;
183pub fn fsm_state_definition_variables(input: ParseString) -> ParseResult<Vec<Var>> {
184  let (input, _) = left_parenthesis(input)?;
185  let (input, names) = separated_list1(list_separator, var)(input)?;
186  let (input, _) = right_parenthesis(input)?;
187  Ok((input, names))
188}
189
190// fsm_pipe := fsm_instance, (fsm_state_transition | fsm_async_transition | fsm_output)* ;
191pub fn fsm_pipe(input: ParseString) -> ParseResult<FsmPipe> {
192  let (input, start) = fsm_instance(input)?;
193  let (input, trns) = many0(alt((fsm_state_transition,fsm_async_transition,fsm_output)))(input)?;
194  Ok((input, FsmPipe{start, transitions: trns}))
195}
196
197// fsm_declare := fsm, define_operator, fsm_pipe ;
198pub fn fsm_declare(input: ParseString) -> ParseResult<FsmDeclare> {
199  let (input, fsm) = fsm(input)?;
200  let (input, _) = define_operator(input)?;
201  let (input, pipe) = fsm_pipe(input)?;
202  Ok((input, FsmDeclare{fsm,pipe}))
203}
204  
205// fsm := "#", identifier, argument_list?, kind_annotation? ;
206pub fn fsm(input: ParseString) -> ParseResult<Fsm> {
207  let ((input, _)) = hashtag(input)?;
208  let ((input, name)) = identifier(input)?;
209  let ((input, args)) = opt(argument_list)(input)?;
210  let ((input, kind)) = opt(kind_annotation)(input)?;
211  Ok((input, Fsm{ name, args, kind }))
212}
213
214// fsm_instance := "#", identifier, fsm_args? ;
215pub fn fsm_instance(input: ParseString) -> ParseResult<FsmInstance> {
216  let ((input, _)) = hashtag(input)?;
217  let (input, name) = identifier(input)?;
218  let (input, args) = opt(fsm_args)(input)?;
219  Ok((input, FsmInstance{name,args} ))
220}
221
222// fsm_args := "(", list0(list_separator, (call_arg_with_binding | call_arg)), ")" ;
223pub fn fsm_args(input: ParseString) -> ParseResult<Vec<(Option<Identifier>,Expression)>> {
224  let (input, _) = left_parenthesis(input)?;
225  let (input, args) = separated_list0(list_separator, alt((call_arg_with_binding,call_arg)))(input)?;
226  let (input, _) = right_parenthesis(input)?;
227  Ok((input, args))
228}