1use crate::{
6 aim::{ContextLike, Writer, WriterLike},
7 expressions::{
8 Branch, Closure, Conditional, ExpressionLike, Primary, Retry, parse_closure, parse_conditional
9 },
10 values::{Errata, Value},
11};
12use anyhow::Result;
13use nom::{
14 IResult, Parser,
15 character::complete::{char, multispace0},
16 multi::many1, sequence::preceded,
17};
18use std::{
19 fmt,
20 sync::Arc,
21};
22
23#[derive(Debug, Clone, PartialEq)]
30pub enum Expression {
31 Empty,
32 Errata(Errata),
33 Single(Conditional),
34 Array(Vec<Box<Conditional>>),
35 ArgumentList(Vec<Box<Closure>>),
36 Branch(Branch),
37 Retry(Retry),
38 Primary(Box<Primary>),
40}
41
42impl Expression {
43 pub fn convert(input: &str) -> Self {
44 match parse_expression(input) {
45 Ok((_, expression)) => expression,
46 Err(nom::Err::Incomplete(_)) => {
47 Errata::new_expression(
48 Arc::from("Incomplete Expression"),
49 Arc::from(input),
50 )
51 }
52 Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => {
53 Errata::new_expression_location(
54 Arc::from(format!("Syntax Error ({})", e)),
55 Arc::from(input),
56 Arc::from(e.input),
57 )
58 }
59 }
60 }
61 pub fn is_empty(&self) -> bool {
63 match self {
64 Expression::Empty => true,
65 _ => false,
66 }
67 }
68
69 pub fn is_error(&self) -> bool {
71 match self {
72 Expression::Errata(_) => true,
73 _ => false,
74 }
75 }
76
77 pub fn is_branch(&self) -> bool {
79 match self {
80 Expression::Branch(_) => true,
81 _ => false,
82 }
83 }
84
85 pub fn is_retry(&self) -> bool {
87 match self {
88 Expression::Retry(_) => true,
89 _ => false,
90 }
91 }
92
93 pub fn print(&self, writer: &mut Writer) {
95 match self {
96 Expression::Empty => {}
97 Expression::Errata(errata) => errata.print(writer),
98 Expression::Single(conditional) => conditional.print(writer),
99 Expression::Array(conditionals) => {
100 if let Some((first, rest)) = conditionals.split_first() {
101 first.print(writer);
102 for conditional in rest {
103 writer.write_str(", ");
104 conditional.print(writer);
105 }
106 }
107 }
108 Expression::ArgumentList(closures) => {
109 if let Some((first, rest)) = closures.split_first() {
110 first.print(writer);
111 for closure in rest {
112 writer.write_str(", ");
113 closure.print(writer);
114 }
115 }
116 }
117 Expression::Branch(branch) => branch.print(writer),
118 Expression::Retry(retry) => retry.print(writer),
119 Expression::Primary(primary) => primary.print(writer),
120 }
121 }
122}
123
124pub fn parse_argument_list(input: &str) -> IResult<&str, Expression> {
132 let input = input.trim();
133 if input.is_empty() {
135 return Ok((input, Expression::Empty));
136 }
137 let (input, closure) = parse_closure(input)?;
138 let mut array = vec![Box::new(closure)];
139 if let Ok((input, closure_list)) = many1(closure_array).parse(input) {
140 for closure in closure_list {
141 array.push(Box::new(closure));
142 }
143 let (input, _) = multispace0(input)?;
144 Ok((input, Expression::ArgumentList(array)))
145 } else {
146 let (input, _) = multispace0(input)?;
147 Ok((input, Expression::ArgumentList(array)))
148 }
149}
150
151pub fn parse_expression(input: &str) -> IResult<&str, Expression> {
159 let input = input.trim();
160 if input.is_empty() {
162 return Ok((input, Expression::Empty));
163 }
164 let (input, conditional) = parse_conditional(input)?;
165 if let Ok((input, conditional_list)) = many1(conditional_array).parse(input) {
166 let mut array = vec![Box::new(conditional)];
167 for conditional in conditional_list {
168 array.push(Box::new(conditional));
169 }
170 let (input, _) = multispace0(input)?;
171 Ok((input, Expression::Array(array)))
172 } else {
173 let expression = match conditional {
174 Conditional::Primary(primary) => Expression::Primary(primary),
175 _ => Expression::Single(conditional),
176 };
177 let (input, _) = multispace0(input)?;
178 Ok((input, expression))
179 }
180}
181
182fn closure_array(input: &str) -> IResult<&str, Closure> {
184 preceded(
185 (multispace0, char(','), multispace0),
186 parse_closure
187 ).parse(input)
188}
189
190fn conditional_array(input: &str) -> IResult<&str, Conditional> {
192 preceded(
193 (multispace0, char(','), multispace0),
194 parse_conditional
195 ).parse(input)
196}
197
198impl ExpressionLike for Expression {
199 fn evaluate(&self, context: &mut dyn ContextLike) -> Result<Arc<Value>> {
205 match self {
206 Expression::Empty => Ok(Value::empty()),
207 Expression::Errata(errata) => Ok(Arc::new(Value::Errata(errata.clone()))),
208 Expression::Single(conditional) => conditional.evaluate(context),
209 Expression::Array(array) => {
210 let mut value_array: Vec<Arc<Value>> = Vec::new();
211 for conditional in array {
212 let value = conditional.evaluate(context)?;
213 if value.is_error() {
214 return Ok(value);
215 }
216 value_array.push(value);
217 }
218 Ok(Arc::new(Value::Array(Arc::new(value_array))))
219 }
220 Expression::ArgumentList(array) => {
221 let mut value_array: Vec<Arc<Value>> = Vec::new();
222 for closure in array {
223 let value = closure.evaluate(context)?;
224 if value.is_error() {
225 return Ok(value);
226 }
227 value_array.push(value);
228 }
229 Ok(Arc::new(Value::Array(Arc::new(value_array))))
230 }
231 Expression::Branch(branch) => branch.evaluate(context),
232 Expression::Retry(retry) => retry.evaluate(context),
233 Expression::Primary(primary) => primary.evaluate(context),
234 }
235 }
236
237 fn to_formula(&self) -> String {
239 let mut writer = Writer::formulizer();
240 self.print(&mut writer);
241 writer.finish()
242 }
243}
244
245impl WriterLike for Expression {
246 fn write(&self, writer: &mut Writer) {
247 self.print(writer);
248 }
249}
250
251impl fmt::Display for Expression {
252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 write!(f, "{}", self.to_stringized())
254 }
255}