1use crate::{
8 aim::{ContextLike, WriterLike, Writer},
9 expressions::{
10 Additive, Closure, Coalesce, Collection, Conditional, Equality, Expression, ExpressionLike,
11 LogicalAnd, LogicalOr, Multiplicative, Postfix, Reference, Relational, Unary,
12 parse_collection, parse_expression, parse_reference,
13 },
14 literals::{Literal, parse_literal},
15 values::Value,
16};
17use anyhow::Result;
18use nom::{
19 IResult, Parser,
20 branch::alt,
21 character::complete::{char, multispace0},
22 combinator::map, sequence::delimited,
23};
24use std::{
25 fmt,
26 sync::Arc,
27};
28
29#[derive(Debug, Clone, PartialEq)]
36pub enum Primary {
37 Literal(Literal),
39 Reference(Arc<Reference>),
41 Parentheses(Expression),
43 Collection(Collection),
45
46 Postfix(Postfix),
48 Unary(Unary),
49 Multiplicative(Multiplicative),
50 Additive(Additive),
51 Relational(Relational),
52 Equality(Equality),
53 LogicalAnd(LogicalAnd),
54 LogicalOr(LogicalOr),
55 Coalesce(Coalesce),
56 Conditional(Conditional),
57 Closure(Closure),
58}
59
60impl Primary {
61 pub fn is_literal(&self) -> bool {
63 match self {
64 Primary::Literal(_) => true,
65 _ => false,
66 }
67 }
68
69 pub fn is_reference(&self) -> bool {
71 match self {
72 Primary::Reference(_) => true,
73 _ => false,
74 }
75 }
76
77 pub fn print(&self, writer: &mut Writer) {
79 match self {
80 Primary::Literal(literal) => literal.print(writer),
81 Primary::Reference(reference) => reference.print(writer),
82 Primary::Parentheses(expression) => {
83 writer.write_char('(');
84 expression.print(writer);
85 writer.write_char(')');
86 }
87 Primary::Collection(collection) => collection.print(writer),
88
89 Primary::Postfix(postfix) => postfix.print(writer),
90 Primary::Unary(unary) => unary.print(writer),
91 Primary::Multiplicative(multiplicative) => multiplicative.print(writer),
92 Primary::Additive(additive) => additive.print(writer),
93 Primary::Relational(relational) => relational.print(writer),
94 Primary::Equality(equality) => equality.print(writer),
95 Primary::LogicalAnd(logical_and) => logical_and.print(writer),
96 Primary::LogicalOr(logical_or) => logical_or.print(writer),
97 Primary::Coalesce(coalesce) => coalesce.print(writer),
98 Primary::Conditional(conditional) => conditional.print(writer),
99 Primary::Closure(closure) => closure.print(writer),
100 }
101 }
102}
103
104pub fn parse_primary(input: &str) -> IResult<&str, Primary> {
121 alt((
122 map(parse_literal, Primary::Literal),
123 map(parse_reference, Primary::Reference),
124 map(parse_collection, |collection| {
125 Primary::Collection(collection)
126 }),
127 map(parse_parentheses, |expression| {
128 Primary::Parentheses(expression)
129 }),
130 ))
131 .parse(input)
132}
133
134pub fn parse_parentheses(input: &str) -> IResult<&str, Expression> {
139 alt((
140 (
142 char('('),
143 multispace0,
144 char(')'),
145 ).map(|_| Expression::Empty),
146
147 delimited(
149 char('('),
150 delimited(multispace0, parse_expression, multispace0),
151 char(')'),
152 ),
153 )).parse(input)
154}
155
156impl ExpressionLike for Primary {
157 fn evaluate(&self, context: &mut dyn ContextLike) -> Result<Arc<Value>> {
159 match self {
160 Primary::Literal(literal) => {
161 if literal.is_empty() {
162 Ok(Value::empty())
163 } else {
164 Ok(Arc::new(Value::Literal(literal.clone())))
165 }
166 }
167 Primary::Reference(reference) => reference.evaluate(context),
168 Primary::Parentheses(expression) => expression.evaluate(context),
169 Primary::Collection(collection) => collection.evaluate(context),
170
171 Primary::Postfix(postfix) => postfix.evaluate(context),
172 Primary::Unary(unary) => unary.evaluate(context),
173 Primary::Multiplicative(multiplicative) => multiplicative.evaluate(context),
174 Primary::Additive(additive) => additive.evaluate(context),
175 Primary::Relational(relational) => relational.evaluate(context),
176 Primary::Equality(equality) => equality.evaluate(context),
177 Primary::LogicalAnd(logical_and) => logical_and.evaluate(context),
178 Primary::LogicalOr(logical_or) => logical_or.evaluate(context),
179 Primary::Coalesce(coalesce) => coalesce.evaluate(context),
180 Primary::Conditional(conditional) => conditional.evaluate(context),
181 Primary::Closure(closure) => closure.evaluate(context),
182 }
183 }
184
185 fn to_formula(&self) -> String {
187 let mut writer = Writer::formulizer();
188 self.print(&mut writer);
189 writer.finish()
190 }
191}
192
193impl WriterLike for Primary {
194 fn write(&self, writer: &mut Writer) {
195 self.print(writer);
196 }
197}
198
199impl fmt::Display for Primary {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 write!(f, "{}", self.to_stringized())
202 }
203}