forester_rs/tree/parser/
ast.rs1pub mod arg;
2pub mod call;
3pub mod invocation;
4pub mod message;
5use crate::tree::parser::ast::invocation::Invocation;
6use crate::tree::project::{AliasName, TreeName};
7use arg::{Arguments, Params};
8use call::{Call, Calls};
9use serde::{Deserialize, Serialize};
10use strum_macros::Display;
11use strum_macros::EnumString;
12
13pub type Key = String;
14
15#[derive(Display, Debug, Clone, Copy, Eq, PartialEq, EnumString, Deserialize, Serialize)]
16#[strum(serialize_all = "snake_case")]
17pub enum TreeType {
18 Root,
19 Parallel,
20 Sequence,
21 MSequence,
22 RSequence,
23 Fallback,
24 RFallback,
25 Inverter,
27 ForceSuccess,
28 ForceFail,
29 Repeat,
30 Retry,
31 Timeout,
32 Delay,
33 Impl,
35 Cond,
36}
37
38impl TreeType {
39 pub fn is_decorator(&self) -> bool {
40 matches!(
41 self,
42 TreeType::Inverter
43 | TreeType::ForceSuccess
44 | TreeType::ForceFail
45 | TreeType::Repeat
46 | TreeType::Retry
47 | TreeType::Delay
48 | TreeType::Timeout
49 )
50 }
51 pub fn is_action(&self) -> bool {
52 matches!(self, TreeType::Impl | TreeType::Cond)
53 }
54}
55
56pub fn validate_lambda<'a, 'b>(
57 tpe: &'a TreeType,
58 args: &'a Arguments,
59 calls: &'a Calls,
60) -> Result<(), &'b str> {
61 match tpe {
62 TreeType::Impl | TreeType::Cond => {
63 Err("the types impl or cond should have declaration and get called by name")
64 }
65
66 _ if tpe.is_decorator() => {
67 if calls.elems.len() != 1 {
68 Err("any decorator should have only one child")
69 } else {
70 Ok(())
71 }
72 }
73
74 _ => {
75 if args.args.is_empty() {
76 Ok(())
77 } else {
78 Err("any lambda invocation should not have arguments")
79 }
80 }
81 }
82}
83
84#[derive(Clone, Debug, PartialEq)]
85pub struct Tree {
86 pub tpe: TreeType,
87 pub name: Key,
88 pub params: Params,
89 pub calls: Calls,
90}
91
92impl Tree {
93 pub fn root(name: &str, calls: Vec<Call>) -> Self {
94 Tree::new(
95 TreeType::Root,
96 name.to_string(),
97 Params::default(),
98 Calls::new(calls),
99 )
100 }
101}
102
103impl Tree {
104 pub fn is_root(&self) -> bool {
105 matches!(self.tpe, TreeType::Root)
106 }
107 pub fn new(tpe: TreeType, name: Key, params: Params, calls: Calls) -> Self {
108 Self {
109 tpe,
110 name,
111 params,
112 calls,
113 }
114 }
115 pub fn to_inv(&self) -> Invocation {
116 self.into()
117 }
118 pub fn to_inv_args(&self, args: Arguments) -> Invocation {
119 Invocation::new(self, args)
120 }
121}
122
123#[derive(Clone, Debug, PartialEq, Eq, Hash)]
124pub struct Import(pub String, pub Vec<ImportName>);
125
126#[derive(Clone, Debug, PartialEq, Hash, Eq)]
127pub enum ImportName {
128 Id(String),
129 Alias(TreeName, AliasName),
130 WholeFile,
131}
132
133impl ImportName {
134 pub fn id(v: &str) -> Self {
135 ImportName::Id(v.to_string())
136 }
137 pub fn alias(v: &str, alias: &str) -> Self {
138 ImportName::Alias(v.to_string(), alias.to_string())
139 }
140}
141
142impl Import {
143 pub fn f_name(&self) -> &str {
144 match self {
145 Import(n, _) => n,
146 }
147 }
148 pub fn file(f: &str) -> Self {
149 Import(f.to_string(), vec![ImportName::WholeFile])
150 }
151 pub fn names(f: &str, names: Vec<&str>) -> Self {
152 Import(
153 f.to_string(),
154 names.into_iter().map(ImportName::id).collect(),
155 )
156 }
157 pub fn names_mixed(f: &str, names: Vec<ImportName>) -> Self {
158 Import(f.to_string(), names)
159 }
160}
161
162#[derive(Clone, Debug, PartialEq)]
163pub enum FileEntity {
164 Tree(Tree),
165 Import(Import),
166}
167
168#[derive(Clone, Debug, PartialEq)]
169pub struct AstFile(pub Vec<FileEntity>);
170
171impl AstFile {
172 pub fn new(field0: Vec<FileEntity>) -> Self {
173 Self(field0)
174 }
175}