forester_rs/tree/parser/
ast.rs

1pub 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    // decorators
26    Inverter,
27    ForceSuccess,
28    ForceFail,
29    Repeat,
30    Retry,
31    Timeout,
32    Delay,
33    // actions
34    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}