1use nom::{
2 branch::alt,
3 bytes::complete::{is_not, tag},
4 character::complete::{
5 alpha1, alphanumeric1, char, multispace0, newline, none_of, one_of, space0,
6 },
7 combinator::{opt, recognize, value},
8 multi::{many0, many1, separated_list1},
9 sequence::{delimited, pair, preceded, terminated, tuple},
10 Finish, IResult,
11};
12
13use crate::{BlackboardValueOwned, PortType};
14
15#[derive(Debug, PartialEq)]
16pub struct NodeDef<'src> {
17 name: &'src str,
18 ports: Vec<PortDef<'src>>,
19}
20
21impl<'src> NodeDef<'src> {
22 pub fn new(name: &'src str) -> Self {
23 Self {
24 name,
25 ports: Vec::new(),
26 }
27 }
28
29 pub fn name(&self) -> &str {
30 self.name
31 }
32
33 pub fn ports(&self) -> &[PortDef<'src>] {
34 &self.ports
35 }
36}
37
38#[derive(Debug, PartialEq)]
39pub struct PortDef<'src> {
40 pub direction: PortType,
41 pub name: &'src str,
42 pub ty: Option<&'src str>,
43}
44
45fn identifier(input: &str) -> IResult<&str, &str> {
46 recognize(pair(
47 alt((alpha1, tag("_"))),
48 many0(alt((alphanumeric1, tag("_")))),
49 ))(input)
50}
51
52fn newlines(i: &str) -> IResult<&str, ()> {
53 delimited(space0, many1(one_of("\r\n")), space0)(i).map(|(rest, _)| (rest, ()))
54}
55
56fn port_def(i: &str) -> IResult<&str, PortDef> {
57 let (i, inout) = delimited(space0, alt((tag("in"), tag("out"), tag("inout"))), space0)(i)?;
58 let (i, name) = identifier(i)?;
59 let (i, ty) = opt(preceded(delimited(space0, char(':'), space0), identifier))(i)?;
60 let (i, _) = multispace0(i)?;
61 let direction = match inout {
62 "in" => PortType::Input,
63 "out" => PortType::Output,
64 "inout" => PortType::InOut,
65 _ => {
66 return Err(nom::Err::Failure(nom::error::Error::new(
67 i,
68 nom::error::ErrorKind::Verify,
69 )))
70 }
71 };
72 Ok((
73 i,
74 PortDef {
75 direction,
76 name,
77 ty,
78 },
79 ))
80}
81
82fn ports_def(i: &str) -> IResult<&str, Vec<PortDef>> {
83 let (i, _) = many0(newlines)(i)?;
84
85 let (i, v) = many0(delimited(space0, port_def, many0(pair(space0, newlines))))(i)?;
86
87 let (i, _) = many0(newlines)(i)?;
88
89 Ok((i, v))
90}
91
92fn open_paren(i: &str) -> IResult<&str, ()> {
93 value((), delimited(space0, char('('), space0))(i)
94}
95
96fn close_paren(i: &str) -> IResult<&str, ()> {
97 value((), delimited(space0, char(')'), space0))(i)
98}
99
100fn open_brace(i: &str) -> IResult<&str, ()> {
101 value((), delimited(space0, char('{'), space0))(i)
102}
103
104fn close_brace(i: &str) -> IResult<&str, ()> {
105 value((), delimited(space0, char('}'), space0))(i)
106}
107
108pub fn node_def(i: &str) -> IResult<&str, NodeDef> {
109 let (i, _) = delimited(multispace0, tag("node"), space0)(i)?;
110
111 let (i, name) = delimited(space0, alphanumeric1, space0)(i)?;
112
113 let (i, ports) = delimited(open_brace, ports_def, close_brace)(i)?;
114
115 Ok((i, NodeDef { name, ports }))
116}
117
118pub fn parse_nodes(i: &str) -> IResult<&str, Vec<NodeDef>> {
119 many0(node_def)(i)
120}
121
122#[derive(Debug, PartialEq, Eq)]
123pub struct TreeDef<'src> {
124 pub(crate) ty: &'src str,
125 pub(crate) port_maps: Vec<PortMap<'src>>,
126 pub(crate) children: Vec<TreeDef<'src>>,
127 pub(crate) vars: Vec<VarDef<'src>>,
128}
129
130impl<'src> TreeDef<'src> {
131 pub fn get_type(&self) -> &str {
132 self.ty
133 }
134
135 pub fn port_maps(&self) -> &[PortMap<'src>] {
136 &self.port_maps
137 }
138
139 pub fn children(&self) -> &[TreeDef<'src>] {
140 &self.children
141 }
142}
143
144#[derive(Debug, PartialEq, Eq)]
145pub struct VarDef<'src> {
146 pub(crate) name: &'src str,
147 pub(crate) init: Option<&'src str>,
148}
149
150#[derive(Debug, PartialEq, Eq)]
151pub struct VarAssign<'src> {
152 pub(crate) name: &'src str,
153 pub(crate) init: &'src str,
154}
155
156impl<'src> TreeDef<'src> {
157 #[allow(dead_code)]
158 fn new(ty: &'src str) -> Self {
159 Self {
160 ty,
161 port_maps: vec![],
162 children: vec![],
163 vars: vec![],
164 }
165 }
166
167 #[allow(dead_code)]
168 fn new_with_child(ty: &'src str, child: TreeDef<'src>) -> Self {
169 Self {
170 ty,
171 port_maps: vec![],
172 children: vec![child],
173 vars: vec![],
174 }
175 }
176
177 fn new_with_children(ty: &'src str, children: Vec<TreeDef<'src>>) -> Self {
178 Self {
179 ty,
180 port_maps: vec![],
181 children,
182 vars: vec![],
183 }
184 }
185
186 #[allow(dead_code)]
187 fn new_with_children_and_vars(
188 ty: &'src str,
189 children: Vec<TreeDef<'src>>,
190 vars: Vec<VarDef<'src>>,
191 ) -> Self {
192 Self {
193 ty,
194 port_maps: vec![],
195 children,
196 vars,
197 }
198 }
199
200 fn new_with_tree_elems(ty: &'src str, children: Vec<TreeElem<'src>>) -> Self {
201 Self::new_with_ports_and_tree_elems(ty, vec![], children)
202 }
203
204 #[allow(dead_code)]
205 fn new_with_ports(ty: &'src str, port_maps: Vec<PortMap<'src>>) -> Self {
206 Self::new_with_ports_and_tree_elems(ty, port_maps, vec![])
207 }
208
209 fn new_with_ports_and_tree_elems(
210 ty: &'src str,
211 port_maps: Vec<PortMap<'src>>,
212 children: Vec<TreeElem<'src>>,
213 ) -> Self {
214 fn new_set_bool(name: &str, init: String) -> TreeDef {
215 TreeDef::new_with_ports(
216 "SetBool",
217 vec![
218 PortMap {
219 node_port: "value",
220 blackboard_value: BlackboardValue::Literal(init),
221 ty: PortType::Input,
222 },
223 PortMap {
224 node_port: "output",
225 blackboard_value: BlackboardValue::Ref(name),
226 ty: PortType::Output,
227 },
228 ],
229 )
230 }
231
232 let (children, vars) = children.into_iter().fold((vec![], vec![]), |mut acc, cur| {
233 match cur {
234 TreeElem::Node(node) => acc.0.push(node),
235 TreeElem::Var(var) => {
236 if let Some(init) = var.init {
237 acc.0.push(new_set_bool(var.name, init.to_owned()));
238 }
239 acc.1.push(var);
240 }
241 TreeElem::VarAssign(var) => {
242 acc.0.push(new_set_bool(var.name, var.init.to_owned()));
243 }
244 }
245 acc
246 });
247
248 Self {
249 ty,
250 port_maps,
251 children,
252 vars,
253 }
254 }
255}
256
257#[derive(Debug, PartialEq, Eq)]
258pub enum BlackboardValue<'src> {
259 Literal(String),
261 Ref(&'src str),
262}
263
264impl<'src> BlackboardValue<'src> {
265 fn to_owned(&self) -> BlackboardValueOwned {
266 match self {
267 Self::Literal(s) => BlackboardValueOwned::Literal(s.clone()),
268 Self::Ref(s) => BlackboardValueOwned::Ref(s.to_string()),
269 }
270 }
271}
272
273#[derive(Debug, PartialEq, Eq)]
274pub struct PortMap<'src> {
275 pub(crate) ty: PortType,
276 pub(crate) node_port: &'src str,
277 pub(crate) blackboard_value: BlackboardValue<'src>,
278}
279
280impl<'src> PortMap<'src> {
281 pub fn get_type(&self) -> PortType {
282 self.ty
283 }
284
285 pub fn node_port(&self) -> &'src str {
286 self.node_port
287 }
288
289 pub fn blackboard_value(&self) -> &BlackboardValue<'src> {
290 &self.blackboard_value
291 }
292
293 pub fn to_owned(&self) -> PortMapOwned {
294 PortMapOwned {
295 ty: self.ty,
296 node_port: self.node_port.to_owned(),
297 blackboard_value: self.blackboard_value.to_owned(),
298 }
299 }
300}
301
302#[derive(Debug, PartialEq, Eq)]
303pub struct PortMapOwned {
304 pub(crate) ty: PortType,
305 pub(crate) node_port: String,
306 pub(crate) blackboard_value: BlackboardValueOwned,
307}
308
309impl PortMapOwned {
310 pub fn new(ty: PortType, node_port: String, blackboard_value: BlackboardValueOwned) -> Self {
311 Self {
312 ty,
313 node_port,
314 blackboard_value,
315 }
316 }
317}
318
319fn subtree_ports_def(i: &str) -> IResult<&str, Vec<PortDef>> {
320 let (i, ports) = delimited(
321 open_paren,
322 many0(delimited(space0, port_def, opt(char(',')))),
323 close_paren,
324 )(i)?;
325 Ok((i, ports))
326}
327
328#[derive(Debug, PartialEq)]
329pub struct TreeRootDef<'src> {
330 pub(crate) name: &'src str,
331 pub(crate) root: TreeDef<'src>,
332 pub(crate) ports: Vec<PortDef<'src>>,
333}
334
335impl<'src> TreeRootDef<'src> {
336 pub fn name(&self) -> &str {
337 self.name
338 }
339
340 pub fn root(&self) -> &TreeDef<'src> {
341 &self.root
342 }
343
344 pub fn ports(&self) -> &[PortDef<'src>] {
345 &self.ports
346 }
347}
348
349fn parse_tree(i: &str) -> IResult<&str, TreeRootDef> {
350 let (i, _) = delimited(multispace0, tag("tree"), space0)(i)?;
351
352 let (i, name) = delimited(space0, identifier, space0)(i)?;
353
354 let (i, ports) = opt(subtree_ports_def)(i)?;
355
356 let (i, _) = delimited(space0, tag("="), space0)(i)?;
357
358 let (i, root) = parse_conditional_expr(i)?;
359
360 Ok((
361 i,
362 TreeRootDef {
363 name,
364 root,
365 ports: ports.unwrap_or_default(),
366 },
367 ))
368}
369
370fn line_comment<T>(i: &str) -> IResult<&str, Option<T>> {
371 let (i, _) = tuple((space0, char('#'), opt(is_not("\n\r"))))(i)?;
372
373 Ok((i, None))
374}
375
376fn line_comment_tree_elem(i: &str) -> IResult<&str, Option<TreeElem>> {
377 line_comment::<TreeElem>(i)
378}
379
380fn some<I, R>(f: impl Fn(I) -> IResult<I, R>) -> impl Fn(I) -> IResult<I, Option<R>> {
381 move |i| {
382 let (i, res) = f(i)?;
383 Ok((i, Some(res)))
384 }
385}
386
387#[derive(Debug)]
388enum TreeElem<'src> {
389 Node(TreeDef<'src>),
390 Var(VarDef<'src>),
391 VarAssign(VarAssign<'src>),
392}
393
394fn tree_children(i: &str) -> IResult<&str, Vec<TreeElem>> {
395 let (i, _) = many0(newlines)(i)?;
396
397 let (i, v) = many0(delimited(
398 space0,
399 alt((
400 line_comment,
401 some(var_assign),
402 some(var_decl),
403 some(parse_condition_node),
404 some(parse_tree_elem),
405 )),
406 many0(newlines),
407 ))(i)?;
408
409 let (i, _) = many0(newlines)(i)?;
410
411 Ok((i, v.into_iter().flatten().collect()))
412}
413
414fn parse_tree_node(i: &str) -> IResult<&str, TreeDef> {
415 let (i, ty) = delimited(space0, identifier, space0)(i)?;
416
417 let (i, input_ports) = opt(delimited(open_paren, port_maps, close_paren))(i)?;
418
419 let (i, children) = opt(delimited(open_brace, tree_children, close_brace))(i)?;
420
421 let (i, _) = opt(line_comment_tree_elem)(i)?;
422
423 Ok((
424 i,
425 TreeDef::new_with_ports_and_tree_elems(
426 ty,
427 input_ports.unwrap_or(vec![]),
428 children.unwrap_or(vec![]),
429 ),
430 ))
431}
432
433fn parse_tree_elem(i: &str) -> IResult<&str, TreeElem> {
434 let (i, elem) = parse_conditional_expr(i)?;
435 Ok((i, TreeElem::Node(elem)))
436}
437
438fn parse_conditional_factor(i: &str) -> IResult<&str, TreeDef> {
439 let (i, excl) = opt(delimited(space0, char('!'), space0))(i)?;
440
441 if excl.is_some() {
442 let (i, res) = parse_conditional_factor(i)?;
443
444 Ok((i, TreeDef::new_with_child("Inverter", res)))
445 } else {
446 alt((
447 delimited(open_paren, parse_conditional_expr, close_paren),
448 parse_tree_node,
449 ))(i)
450 }
451}
452
453fn parse_conditional_and(i: &str) -> IResult<&str, TreeDef> {
454 let (i, children) = separated_list1(tag("&&"), parse_conditional_factor)(i)?;
455
456 if children.len() == 1 {
457 Ok((i, children.into_iter().next().unwrap()))
458 } else {
459 Ok((i, TreeDef::new_with_children("Sequence", children)))
460 }
461}
462
463fn parse_conditional_expr(i: &str) -> IResult<&str, TreeDef> {
464 let (i, children) = separated_list1(tag("||"), parse_conditional_and)(i)?;
465
466 if children.len() == 1 {
467 Ok((i, children.into_iter().next().unwrap()))
468 } else {
469 Ok((i, TreeDef::new_with_children("Fallback", children)))
470 }
471}
472
473fn parse_condition_node(i: &str) -> IResult<&str, TreeElem> {
474 let (i, _ty) = delimited(space0, tag("if"), space0)(i)?;
475
476 let (i, condition) = delimited(open_paren, parse_conditional_expr, close_paren)(i)?;
477
478 let (i, then_children) = delimited(open_brace, tree_children, close_brace)(i)?;
479
480 let (i, else_children) = opt(delimited(
481 pair(delimited(space0, tag("else"), space0), open_brace),
482 tree_children,
483 close_brace,
484 ))(i)?;
485
486 let mut children = vec![
487 condition,
488 TreeDef::new_with_tree_elems("Sequence", then_children),
489 ];
490
491 if let Some(else_children) = else_children {
492 children.push(TreeDef::new_with_tree_elems("Sequence", else_children));
493 }
494
495 Ok((
496 i,
497 TreeElem::Node(TreeDef::new_with_children("if", children)),
498 ))
499}
500
501fn var_decl(i: &str) -> IResult<&str, TreeElem> {
502 let (i, _var) = delimited(space0, tag("var"), space0)(i)?;
503
504 let (i, name) = delimited(space0, identifier, space0)(i)?;
505
506 let (i, init) = opt(delimited(
507 delimited(space0, char('='), space0),
508 alt((tag("true"), tag("false"))),
509 space0,
510 ))(i)?;
511
512 let (i, _) = opt(line_comment_tree_elem)(i)?;
513
514 Ok((i, TreeElem::Var(VarDef { name, init })))
515}
516
517fn var_assign(i: &str) -> IResult<&str, TreeElem> {
518 let (i, name) = delimited(space0, identifier, space0)(i)?;
519
520 let (i, _) = delimited(space0, char('='), space0)(i)?;
521
522 let (i, init) = delimited(space0, alt((tag("true"), tag("false"))), space0)(i)?;
523
524 let (i, _) = opt(line_comment_tree_elem)(i)?;
525
526 Ok((i, TreeElem::VarAssign(VarAssign { name, init })))
527}
528
529fn port_maps(i: &str) -> IResult<&str, Vec<PortMap>> {
530 many0(delimited(
531 multispace0,
532 port_map,
533 many0(pair(multispace0, char(','))),
534 ))(i)
535}
536
537fn port_map(i: &str) -> IResult<&str, PortMap> {
538 let (i, node_port) = delimited(space0, identifier, space0)(i)?;
539
540 let (i, inout) = delimited(space0, alt((tag("<->"), tag("<-"), tag("->"))), space0)(i)?;
541
542 let (i, blackboard_name) = delimited(space0, alt((bb_ref, str_literal)), space0)(i)?;
543
544 let ty = match inout {
545 "<-" => PortType::Input,
546 "->" => PortType::Output,
547 "<->" => PortType::InOut,
548 _ => {
549 return Err(nom::Err::Failure(nom::error::Error::new(
550 i,
551 nom::error::ErrorKind::Alt,
552 )))
553 }
554 };
555
556 if let BlackboardValue::Literal(_) = blackboard_name {
558 if !matches!(ty, PortType::Input) {
559 return Err(nom::Err::Failure(nom::error::Error::new(
560 i,
561 nom::error::ErrorKind::Verify,
562 )));
563 }
564 }
565
566 Ok((
567 i,
568 PortMap {
569 ty,
570 node_port,
571 blackboard_value: blackboard_name,
572 },
573 ))
574}
575
576fn bb_ref(i: &str) -> IResult<&str, BlackboardValue> {
577 let (i, s) = identifier(i)?;
578 Ok((i, BlackboardValue::Ref(s)))
579}
580
581fn str_literal(input: &str) -> IResult<&str, BlackboardValue> {
582 let (r, val) = delimited(
583 preceded(multispace0, char('\"')),
584 many0(none_of("\"")),
585 terminated(char('"'), multispace0),
586 )(input)?;
587 Ok((
588 r,
589 BlackboardValue::Literal(
590 val.iter()
591 .collect::<String>()
592 .replace("\\\\", "\\")
593 .replace("\\n", "\n"),
594 ),
595 ))
596}
597
598pub fn parse_file(i: &str) -> Result<(&str, TreeSource), nom::error::Error<&str>> {
599 source_text(i).finish()
600}
601
602fn source_text(i: &str) -> IResult<&str, TreeSource> {
603 enum NodeOrTree<'src> {
604 Node(NodeDef<'src>),
605 Tree(TreeRootDef<'src>),
606 }
607
608 let (i, stmts) = many0(alt((
609 delimited(multispace0, line_comment, newline),
610 some(|i| {
611 let (i, node) = node_def(i)?;
612 Ok((i, NodeOrTree::Node(node)))
613 }),
614 some(|i| {
615 let (i, tree) = parse_tree(i)?;
616 Ok((i, NodeOrTree::Tree(tree)))
617 }),
618 )))(i)?;
619
620 let (i, _) = multispace0(i)?;
622
623 let (node_defs, tree_defs) =
624 stmts
625 .into_iter()
626 .flatten()
627 .fold((vec![], vec![]), |mut acc, cur| {
628 match cur {
629 NodeOrTree::Node(node) => acc.0.push(node),
630 NodeOrTree::Tree(tree) => acc.1.push(tree),
631 }
632 acc
633 });
634
635 Ok((
636 i,
637 TreeSource {
638 node_defs,
639 tree_defs,
640 },
641 ))
642}
643
644#[derive(Debug, PartialEq)]
645pub struct TreeSource<'src> {
646 pub node_defs: Vec<NodeDef<'src>>,
647 pub tree_defs: Vec<TreeRootDef<'src>>,
648}
649
650#[cfg(test)]
651mod test;