1use crate::{parse::*, parser::*, syntax::*};
5
6impl Parse for RangeFirst {
7 fn parse(pair: Pair) -> ParseResult<Self> {
8 Ok(Self(Box::new(
9 pair.find(Rule::expression)
10 .or(pair
11 .find(Rule::integer_literal)
12 .map(|i| Expression::Literal(Literal::Integer(i))))
13 .expect("Expression"),
14 )))
15 }
16}
17
18impl Parse for RangeLast {
19 fn parse(pair: Pair) -> ParseResult<Self> {
20 Ok(Self(Box::new(
21 pair.find(Rule::expression)
22 .or(pair
23 .find(Rule::integer_literal)
24 .map(|i| Expression::Literal(Literal::Integer(i))))
25 .expect("Expression"),
26 )))
27 }
28}
29
30impl Parse for RangeExpression {
31 fn parse(pair: Pair) -> ParseResult<Self> {
32 Ok(Self {
33 first: pair.find(Rule::range_start).expect("Range start"),
34 last: pair.find(Rule::range_end).expect("Range end"),
35 src_ref: pair.src_ref(),
36 })
37 }
38}
39
40impl Parse for ListExpression {
41 fn parse(pair: Pair) -> ParseResult<Self> {
42 pair.inner()
43 .filter_map(|pair| match pair.as_rule() {
44 Rule::expression => Some(Expression::parse(pair)),
45 _ => None,
46 })
47 .collect::<Result<Vec<_>, _>>()
48 }
49}
50
51impl Parse for ArrayExpression {
52 fn parse(pair: Pair) -> ParseResult<Self> {
53 Ok(Self {
54 inner: pair
55 .find(Rule::range_expression)
56 .map(ArrayExpressionInner::Range)
57 .or(pair
58 .find(Rule::list_expression)
59 .map(ArrayExpressionInner::List))
60 .unwrap_or_default(),
61 unit: pair.find(Rule::unit).unwrap_or_default(),
62 src_ref: pair.clone().into(),
63 })
64 }
65}
66
67impl Parse for Marker {
68 fn parse(pair: Pair) -> ParseResult<Self> {
69 Parser::ensure_rule(&pair, Rule::marker);
70 Ok(Self {
71 id: Identifier::parse(pair.inner().next().expect(INTERNAL_PARSE_ERROR))?,
72 src_ref: pair.src_ref(),
73 })
74 }
75}
76
77lazy_static::lazy_static! {
78 static ref PRATT_PARSER: pest::pratt_parser::PrattParser<Rule> = {
80 use pest::pratt_parser::{Assoc, Op,PrattParser};
81 use Assoc::*;
82 use Rule::*;
83
84 PrattParser::new()
86 .op(Op::infix(or, Left) | Op::infix(and, Left))
88 .op(Op::infix(equal, Left) | Op::infix(not_equal, Left))
89 .op(Op::infix(greater_than, Left) | Op::infix(less_than, Left))
90 .op(Op::infix(less_equal, Left) | Op::infix(greater_equal, Left))
91 .op(Op::infix(add, Left) | Op::infix(subtract, Left))
92 .op(Op::infix(multiply, Left) | Op::infix(divide, Left))
93 .op(Op::infix(r#union, Left) | Op::infix(intersect, Left))
94 .op(Op::infix(power_xor, Left))
95 .op(Op::infix(near, Left))
96 .op(Op::prefix(unary_minus))
97 .op(Op::prefix(unary_plus))
98 .op(Op::prefix(unary_not))
99 .op(Op::postfix(method_call))
100 .op(Op::postfix(array_element_access))
101 .op(Op::postfix(tuple_element_access))
102 .op(Op::postfix(attribute_access))
103 };
104}
105
106impl Expression {
107 pub fn literal_from_str(s: &str) -> ParseResult<Self> {
109 use std::str::FromStr;
110 if s.len() > 1 && s.starts_with('"') && s.ends_with('"') {
111 Ok(Self::FormatString(FormatString::from_str(s)?))
112 } else {
113 Ok(Self::Literal(Literal::from_str(s)?))
114 }
115 }
116}
117
118impl Parse for Expression {
119 fn parse(pair: Pair) -> ParseResult<Self> {
120 Parser::ensure_rule(&pair, Rule::expression);
121
122 PRATT_PARSER
123 .map_primary(|primary| {
124 match (
125 Pair::new(primary.clone(), pair.source_hash()),
126 primary.as_rule(),
127 ) {
128 (primary, Rule::literal) => Ok(Self::Literal(Literal::parse(primary)?)),
129 (primary, Rule::expression) => Ok(Self::parse(primary)?),
130 (primary, Rule::array_expression) => {
131 Ok(Self::ArrayExpression(ArrayExpression::parse(primary)?))
132 }
133 (primary, Rule::tuple_expression) => {
134 Ok(Self::TupleExpression(TupleExpression::parse(primary)?))
135 }
136 (primary, Rule::format_string) => {
137 Ok(Self::FormatString(FormatString::parse(primary)?))
138 }
139 (primary, Rule::body) => Ok(Self::Body(Body::parse(primary)?)),
140 (primary, Rule::call) => Ok(Self::Call(Call::parse(primary)?)),
141 (primary, Rule::qualified_name) => {
142 Ok(Self::QualifiedName(QualifiedName::parse(primary)?))
143 }
144 (primary, Rule::marker) => Ok(Self::Marker(Marker::parse(primary)?)),
145 rule => unreachable!(
146 "Expression::parse expected atom, found {:?} {:?}",
147 rule,
148 pair.as_span().as_str()
149 ),
150 }
151 })
152 .map_infix(|lhs, op, rhs| {
153 let op = match op.as_rule() {
154 Rule::add => "+",
155 Rule::subtract => "-",
156 Rule::multiply => "*",
157 Rule::divide => "/",
158 Rule::r#union => "|",
159 Rule::intersect => "&",
160 Rule::power_xor => "^",
161 Rule::greater_than => ">",
162 Rule::less_than => "<",
163 Rule::less_equal => "≤",
164 Rule::greater_equal => "≥",
165 Rule::equal => "==",
166 Rule::near => "~",
167 Rule::not_equal => "!=",
168 Rule::and => "&",
169 Rule::or => "|",
170
171 rule => unreachable!(
172 "Expression::parse expected infix operation, found {:?}",
173 rule
174 ),
175 };
176 Ok(Self::BinaryOp {
177 lhs: Box::new(lhs?),
178 op: op.into(),
179 rhs: Box::new(rhs?),
180 src_ref: pair.clone().into(),
181 })
182 })
183 .map_prefix(|op, rhs| {
184 let op = match op.as_rule() {
185 Rule::unary_minus => '-',
186 Rule::unary_plus => '+',
187 Rule::unary_not => '!',
188 _ => unreachable!(),
189 };
190
191 Ok(Self::UnaryOp {
192 op: op.into(),
193 rhs: Box::new(rhs?),
194 src_ref: pair.clone().into(),
195 })
196 })
197 .map_postfix(|lhs, op| {
198 match (Pair::new(op.clone(), pair.source_hash()), op.as_rule()) {
199 (op, Rule::array_element_access) => Ok(Self::ArrayElementAccess(
200 Box::new(lhs?),
201 Box::new(Self::parse(op)?),
202 pair.clone().into(),
203 )),
204 (op, Rule::attribute_access) => {
205 let op = op.inner().next().expect(INTERNAL_PARSE_ERROR);
206 Ok(Self::AttributeAccess(
207 Box::new(lhs?),
208 Identifier::parse(op)?,
209 pair.clone().into(),
210 ))
211 }
212 (op, Rule::tuple_element_access) => {
213 let op = op.inner().next().expect(INTERNAL_PARSE_ERROR);
214 match op.as_rule() {
215 Rule::identifier => Ok(Self::PropertyAccess(
216 Box::new(lhs?),
217 Identifier::parse(op)?,
218 pair.clone().into(),
219 )),
220 rule => unreachable!("Expected identifier or int, found {:?}", rule),
221 }
222 }
223 (op, Rule::method_call) => Ok(Self::MethodCall(
224 Box::new(lhs?),
225 MethodCall::parse(op)?,
226 pair.clone().into(),
227 )),
228 rule => {
229 unreachable!("Expr::parse expected postfix operation, found {:?}", rule)
230 }
231 }
232 })
233 .parse(
234 pair.pest_pair()
235 .clone()
236 .into_inner()
237 .filter(|pair| pair.as_rule() != Rule::COMMENT), )
239 }
240}
241
242impl Parse for TupleExpression {
243 fn parse(pair: Pair) -> ParseResult<Self> {
244 Ok(TupleExpression {
245 args: crate::find_rule!(pair, argument_list)?,
246 src_ref: pair.clone().into(),
247 })
248 }
249}
250
251#[macro_export]
253macro_rules! tuple_expression {
254 ($code:literal) => {{
255 $crate::parse!(
256 TupleExpression,
257 $crate::parser::Rule::tuple_expression,
258 $code
259 )
260 }};
261}