mist_parser/parser/common/
expr.rs1use crate::{
2 Rule,
3 ast::*,
4 ast_ensure, ast_expr,
5 error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map},
6};
7use pest::pratt_parser::PrattParser;
8use std::sync::OnceLock;
9
10impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
11 type Error = AstError<'a, Self>;
12
13 fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
14 let rule = pair.as_rule();
15 let inner = pair.clone().into_inner();
16
17 match rule {
18 Rule::expr => {
19 static PRATT_PARSER: OnceLock<PrattParser<Rule>> = OnceLock::new();
20 let pratt = PRATT_PARSER.get_or_init(|| {
21 use pest::pratt_parser::{Assoc::*, Op};
22
23 PrattParser::new().op(Op::infix(Rule::bin_op, Left))
24 });
25
26 pratt
27 .map_primary(|primary_pair| Expression::try_from(primary_pair))
28 .map_infix(|expr, op, rhs| {
29 ast_expr!(Expression::Binary {
30 lhs: expr.map(Box::new).get_map(Box::new),
31 op: Ok(op.as_str().to_string()) as AstResult<'_, String>,
32 rhs: rhs.map(Box::new).get_map(Box::new),
33 })
34 })
35 .parse(inner)
36 }
37
38 Rule::term => {
39 let mut prefix_pairs = Vec::new();
40 let mut primary_pair = None;
41 let mut postfix_pairs = Vec::new();
42
43 for p in inner {
44 match p.as_rule() {
45 Rule::prefix => prefix_pairs.push(p),
46 Rule::primary => primary_pair = Some(p),
47 Rule::postfix => postfix_pairs.push(p),
48 _ => {}
49 }
50 }
51
52 let prefixes = collect_recovered::<Prefix, Prefix>(prefix_pairs.into_iter());
53 let exp = Expression::try_from(
54 primary_pair.expect("Term must contain a primary expression"),
55 );
56 let postfixes = collect_recovered::<Postfix, Postfix>(postfix_pairs.into_iter());
57
58 if postfixes.len() > 0 || prefixes.len() > 0 {
59 ast_expr!(Expression::Fix {
60 initial: exp.map(Box::new),
61 prefixes: prefixes,
62 postfixes: postfixes,
63 })
64 } else {
65 ast_expr!(use exp?, prefixes, postfixes)
66 }
67 }
68
69 Rule::tuple => {
70 ast_expr!(Expression::Literal(
71 collect_recovered(pair.into_inner())
72 .map(Literal::Tuple)
73 .get_map(Literal::Tuple)
74 ))
75 }
76
77 Rule::primary => pair.into_inner().next().unwrap().try_into(),
78 Rule::static_path => ast_expr!(Expression::Path(pair.try_into())),
79 Rule::literal => ast_expr!(Expression::Literal(pair.try_into())),
80 Rule::expr_path => ast_expr!(Expression::Path(pair.try_into())),
81 Rule::statement | Rule::basic_stmt | Rule::control_flow => ast_expr!(
82 Expression::Statement(pair.try_into().get_map(Box::new).map(Box::new))
83 ),
84
85 _ => AstError::bug_unimplemented(pair),
86 }
87 }
88}
89
90impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Prefix {
91 type Error = AstError<'a, Self>;
92
93 fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
94 Ok(match pair.as_rule() {
95 Rule::prefix => Self::try_from(pair.into_inner().next().unwrap())?,
96 Rule::deref_px => Self::Deref,
97 Rule::mut_ref_px => Self::RefMut,
98 Rule::ref_px => Self::Ref,
99 Rule::new_px => Self::New(
100 pair.into_inner()
101 .next()
102 .map(|v| v.try_into().get())
103 .transpose()?,
104 ),
105 Rule::not_px => Self::Not,
106 Rule::neg_px => Self::Neg,
107
108 _ => return AstError::bug_unimplemented(pair),
109 })
110 }
111}
112
113impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Postfix {
114 type Error = AstError<'a, Self>;
115
116 fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
117 let rule = pair.as_rule();
118 let mut inner = pair.clone().into_inner();
119
120 match rule {
121 Rule::postfix => Postfix::try_from(inner.next().unwrap()),
122
123 Rule::field_px => {
124 ast_expr!(Postfix::FieldAccess(
125 inner.next().unwrap().try_into(),
126 inner.next().map(Generics::try_from).transpose()
127 ))
128 }
129
130 Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))),
131
132 Rule::struct_px => ast_expr!(Postfix::StructCall(collect_recovered_map(inner, |p| {
133 let mut pi = p.into_inner();
134 Ok((
135 Identifier::try_from(pi.next().unwrap())?,
136 Expression::try_from(pi.next().unwrap()).get()?,
137 ))
138 }))),
139
140 Rule::index_px => {
141 ast_expr!(Postfix::Index(Expression::try_from(inner.next().unwrap())))
142 }
143
144 Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())),
145
146 Rule::as_px => {
147 ast_expr!(Postfix::As(inner.next().unwrap().try_into()))
148 }
149
150 Rule::try_px => Ok(Postfix::Try),
151
152 Rule::increment => Ok(Postfix::Increment),
153 Rule::decrement => Ok(Postfix::Decrement),
154
155 _ => AstError::bug_unimplemented(pair),
156 }
157 }
158}
159
160impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for ExprPath {
161 type Error = AstError<'a, Self>;
162
163 fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
164 ast_ensure!(pair, Rule::expr_path => {
165 ast_expr!(ExprPath(collect_recovered(pair.into_inner())))
166 })
167 }
168}
169
170impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for ExprPathSegment {
171 type Error = AstError<'a, Self>;
172
173 fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
174 let mut inner = pair.clone().into_inner();
175
176 ast_ensure!(pair, Rule::expr_path_segment => {
177 ast_expr!(ExprPathSegment {
178 ident: Identifier::try_from(inner.next().unwrap()),
179 generics: inner.next().map(Generics::try_from).transpose(),
180 })
181 })
182 }
183}