arrow_parser/
parse_expr.rs

1use super::ast::Expression;
2use super::ast::LiteralTemplatePart;
3use super::ast::Node;
4use super::error::SyntaxErrorType;
5use super::error::SyntaxResult;
6use super::lex::lex_template_string_continue;
7use super::operator::Associativity;
8use super::operator::ExprOperatorName;
9use super::parse::Parser;
10use super::parse_literal::normalise_literal_float;
11use super::parse_literal::normalise_literal_int;
12use super::parse_literal::normalise_literal_template_string_part;
13use super::parse_operator::BINARY_OPERATOR_MAPPING;
14use super::parse_operator::UNARY_OPERATOR_MAPPING;
15use super::token::TokenType;
16use crate::ast::Statement;
17use crate::symbol::ScopeType;
18use crate::token::TokenTypeSet;
19
20impl<'a> Parser<'a> {
21  pub fn parse_expr(&mut self, terminator: TokenType) -> SyntaxResult<Node<Expression>> {
22    self.parse_expr_until(TokenTypeSet::new(&[terminator]))
23  }
24
25  pub fn parse_expr_until(&mut self, terminators: TokenTypeSet) -> SyntaxResult<Node<Expression>> {
26    self.parse_expr_with_min_prec(1, terminators)
27  }
28
29  // Useful for callables, where scope starts at parameters, not block.
30  pub fn parse_expr_block_without_new_scope(&mut self) -> SyntaxResult<Node<Expression>> {
31    let loc_start = self.require(TokenType::BraceOpen)?.loc;
32    let mut statements = Vec::new();
33    let mut result = None;
34    loop {
35      let Node { loc, scope, stx } = self.parse_stmt(false)?;
36      match (self.peek()?.typ == TokenType::BraceClose, *stx) {
37        (true, Statement::Expression { expression }) => {
38          result = Some(expression);
39          break;
40        }
41        (_, stx) => {
42          statements.push(Node {
43            loc,
44            scope,
45            stx: Box::new(stx),
46          });
47        }
48      };
49      self.require(TokenType::Semicolon)?;
50      if self.peek()?.typ == TokenType::BraceClose {
51        break;
52      };
53    }
54    let loc_end = self.require(TokenType::BraceClose)?.loc;
55    Ok(self.new_expression(loc_start + loc_end, Expression::Block {
56      statements,
57      result,
58    }))
59  }
60
61  pub fn parse_expr_block(&mut self) -> SyntaxResult<Node<Expression>> {
62    let parent_scope = self.enter_new_scope(ScopeType::Block);
63    let res = self.parse_expr_block_without_new_scope()?;
64    self.return_to_scope(parent_scope);
65    Ok(res)
66  }
67
68  pub fn parse_expr_closure(&mut self) -> SyntaxResult<Node<Expression>> {
69    let parent_scope = self.enter_new_scope(ScopeType::Closure);
70    let (no_params, loc_start) = match self.consume_if(TokenType::BarBar)?.match_loc() {
71      Some(loc) => (true, loc),
72      None => (false, self.require(TokenType::Bar)?.loc),
73    };
74    let mut parameters = vec![];
75    if !no_params {
76      loop {
77        if self.peek()?.typ == TokenType::Bar {
78          break;
79        };
80        let (name_loc, name) = self.require_identifier_as_string()?;
81        if !self.scope.add_symbol(name.clone()) {
82          return Err(name_loc.error(SyntaxErrorType::RedeclaredVar, None));
83        };
84        parameters.push(name);
85        if self.peek()?.typ == TokenType::Bar {
86          break;
87        };
88        self.require(TokenType::Comma)?;
89      }
90      self.require(TokenType::Bar)?;
91    };
92    let body = self.parse_expr_block_without_new_scope()?;
93    let loc_end = body.loc;
94    let closure = self.new_expression(loc_start + loc_end, Expression::Closure {
95      parameters,
96      body,
97    });
98    self.return_to_scope(parent_scope);
99    Ok(closure)
100  }
101
102  pub fn parse_expr_if(&mut self) -> SyntaxResult<Node<Expression>> {
103    let loc_start = self.require(TokenType::KeywordIf)?.loc;
104    let condition = self.parse_expr(TokenType::BraceOpen)?;
105    let consequent = self.parse_expr_block()?;
106    let alternate = if self.consume_if(TokenType::KeywordElse)?.is_match() {
107      Some(if self.peek()?.typ == TokenType::KeywordIf {
108        self.parse_expr_if()?
109      } else {
110        self.parse_expr_block()?
111      })
112    } else {
113      None
114    };
115    Ok(self.new_expression(
116      loc_start + alternate.as_ref().map(|s| s.loc).unwrap_or(consequent.loc),
117      Expression::If {
118        condition,
119        consequent,
120        alternate,
121      },
122    ))
123  }
124
125  pub fn parse_expr_grouping(&mut self) -> SyntaxResult<Node<Expression>> {
126    self.require(TokenType::ParenthesisOpen)?;
127    let expr =
128      self.parse_expr_with_min_prec(1, TokenTypeSet::new(&[TokenType::ParenthesisClose]))?;
129    self.require(TokenType::ParenthesisClose)?;
130    Ok(expr)
131  }
132
133  pub fn parse_expr_literal_array(&mut self) -> SyntaxResult<Node<Expression>> {
134    let loc_start = self.require(TokenType::BracketOpen)?.loc;
135    let mut entries = vec![];
136    loop {
137      if self.peek()?.typ == TokenType::BracketClose {
138        break;
139      };
140      let value = self.parse_expr_until(TokenTypeSet::new(&[
141        TokenType::Comma,
142        TokenType::BracketClose,
143      ]))?;
144      entries.push(value);
145      if self.peek()?.typ == TokenType::BracketClose {
146        break;
147      };
148      self.require(TokenType::Comma)?;
149    }
150    let loc_end = self.require(TokenType::BracketClose)?.loc;
151    Ok(self.new_expression(loc_start + loc_end, Expression::LiteralArray { entries }))
152  }
153
154  pub fn parse_expr_literal_object(&mut self) -> SyntaxResult<Node<Expression>> {
155    let loc_start = self.require(TokenType::BraceOpen)?.loc;
156    let mut fields = vec![];
157    loop {
158      if self.peek()?.typ == TokenType::BraceClose {
159        break;
160      };
161      let (_, key) = self.require_identifier_as_string()?;
162      self.require(TokenType::Colon)?;
163      let value = self.parse_expr_until(TokenTypeSet::new(&[
164        TokenType::Comma,
165        TokenType::BraceClose,
166      ]))?;
167      fields.push((key, value));
168      if self.peek()?.typ == TokenType::BraceClose {
169        break;
170      };
171      self.require(TokenType::Comma)?;
172    }
173    let loc_end = self.require(TokenType::BraceClose)?.loc;
174    Ok(self.new_expression(loc_start + loc_end, Expression::LiteralObject { fields }))
175  }
176
177  fn parse_expr_operand(&mut self, terminators: TokenTypeSet) -> SyntaxResult<Node<Expression>> {
178    let cp = self.checkpoint();
179    let t = self.consume()?;
180    let operand = if let Some(&operator) = UNARY_OPERATOR_MAPPING.get(&t.typ) {
181      let next_min_prec =
182        operator.precedence + (operator.associativity == Associativity::Left) as u8;
183      let operand = self.parse_expr_with_min_prec(next_min_prec, terminators)?;
184      self.new_expression(t.loc + operand.loc, Expression::Unary {
185        operand,
186        operator: operator.name,
187      })
188    } else {
189      match t.typ {
190        TokenType::BraceOpen => {
191          self.restore_checkpoint(cp);
192          self.parse_expr_literal_object()?
193        }
194        TokenType::BracketOpen => {
195          self.restore_checkpoint(cp);
196          self.parse_expr_literal_array()?
197        }
198        TokenType::Bar | TokenType::BarBar => {
199          self.restore_checkpoint(cp);
200          self.parse_expr_closure()?
201        }
202        TokenType::Identifier => self.new_expression(t.loc, Expression::Var {
203          name: self.source_as_string(t.loc),
204        }),
205        TokenType::KeywordIf => {
206          self.restore_checkpoint(cp);
207          self.parse_expr_if()?
208        }
209        TokenType::LiteralFloat => self.new_expression(t.loc, Expression::LiteralFloat {
210          value: normalise_literal_float(self.source(t.loc))
211            .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
212        }),
213        TokenType::LiteralInt => self.new_expression(t.loc, Expression::LiteralInt {
214          value: normalise_literal_int(self.source(t.loc))
215            .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
216        }),
217        TokenType::LiteralNone => self.new_expression(t.loc, Expression::LiteralNone {}),
218        TokenType::LiteralTemplatePartString => {
219          let mut loc = t.loc;
220          let mut parts = vec![];
221          parts.push(LiteralTemplatePart::String(
222            normalise_literal_template_string_part(self.source(t.loc))
223              .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
224          ));
225          loop {
226            let substitution = self.parse_expr(TokenType::BraceClose)?;
227            self.require(TokenType::BraceClose)?;
228            parts.push(LiteralTemplatePart::Substitution(substitution));
229            let string = lex_template_string_continue(self.lexer_mut())?;
230            loc.extend(string.loc);
231            parts.push(LiteralTemplatePart::String(
232              normalise_literal_template_string_part(self.source(string.loc))
233                .ok_or_else(|| string.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
234            ));
235            if let TokenType::LiteralTemplatePartStringEnd = string.typ {
236              break;
237            };
238          }
239          self.new_expression(loc, Expression::LiteralTemplateExpr { parts })
240        }
241        TokenType::LiteralTemplatePartStringEnd => {
242          self.new_expression(t.loc, Expression::LiteralTemplateExpr {
243            parts: vec![LiteralTemplatePart::String(
244              normalise_literal_template_string_part(self.source(t.loc))
245                .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
246            )],
247          })
248        }
249        TokenType::LiteralTrue | TokenType::LiteralFalse => {
250          self.new_expression(t.loc, Expression::LiteralBoolean {
251            value: t.typ == TokenType::LiteralTrue,
252          })
253        }
254        TokenType::ParenthesisOpen => {
255          self.restore_checkpoint(cp);
256          self.parse_expr_grouping()?
257        }
258        _ => return Err(t.error(SyntaxErrorType::ExpectedSyntax("expression operand"))),
259      }
260    };
261    Ok(operand)
262  }
263
264  fn parse_expr_with_min_prec(
265    &mut self,
266    min_prec: u8,
267    terminators: TokenTypeSet,
268  ) -> SyntaxResult<Node<Expression>> {
269    let mut left = self.parse_expr_operand(terminators)?;
270
271    loop {
272      let cp = self.checkpoint();
273      let t = self.consume()?;
274
275      if terminators.contains(t.typ) {
276        self.restore_checkpoint(cp);
277        break;
278      };
279
280      let Some(operator) = BINARY_OPERATOR_MAPPING.get(&t.typ) else {
281        return Err(t.error(SyntaxErrorType::ExpectedSyntax("expression operator")));
282      };
283
284      if operator.precedence < min_prec {
285        self.restore_checkpoint(cp);
286        break;
287      };
288
289      let next_min_prec =
290        operator.precedence + (operator.associativity == Associativity::Left) as u8;
291
292      left = match operator.name {
293        ExprOperatorName::As => {
294          let (impl_name_loc, impl_name) = self.require_identifier_as_string()?;
295          self.new_expression(left.loc + impl_name_loc, Expression::Cast {
296            value: left,
297            typ: impl_name,
298          })
299        }
300        ExprOperatorName::Bind => {
301          let loc_start = left.loc;
302          let Expression::Var { name: impl_name } = left.stx.as_ref() else {
303            return Err(loc_start.error(SyntaxErrorType::BindingToNonImpl, None));
304          };
305          let (method_name_loc, method_name) = self.require_identifier_as_string()?;
306          let mut arguments = vec![];
307          let mut loc_end = method_name_loc;
308          if self.consume_if(TokenType::ParenthesisOpen)?.is_match() {
309            loop {
310              if self.peek()?.typ == TokenType::ParenthesisClose {
311                break;
312              };
313              let value = self.parse_expr_until(TokenTypeSet::new(&[
314                TokenType::Comma,
315                TokenType::ParenthesisClose,
316              ]))?;
317              arguments.push(value);
318              if !self.consume_if(TokenType::Comma)?.is_match() {
319                break;
320              };
321            }
322            loc_end = self.require(TokenType::ParenthesisClose)?.loc;
323          };
324          self.new_expression(loc_start + loc_end, Expression::BindMethod {
325            impl_: impl_name.clone(),
326            method: method_name,
327            arguments,
328          })
329        }
330        ExprOperatorName::Call | ExprOperatorName::OptionalCall => {
331          let mut arguments = vec![];
332          loop {
333            if self.peek()?.typ == TokenType::ParenthesisClose {
334              break;
335            };
336            let value = self.parse_expr_until(TokenTypeSet::new(&[
337              TokenType::Comma,
338              TokenType::ParenthesisClose,
339            ]))?;
340            arguments.push(value);
341            if !self.consume_if(TokenType::Comma)?.is_match() {
342              break;
343            };
344          }
345          let end = self.require(TokenType::ParenthesisClose)?;
346          let optional = match operator.name {
347            ExprOperatorName::OptionalCall => true,
348            _ => false,
349          };
350          self.new_expression(
351            left.loc + end.loc,
352            if let Expression::Field {
353              object,
354              field,
355              optional,
356            } = *left.stx
357            {
358              Expression::CallMethod {
359                object,
360                method: field,
361                arguments,
362                optional,
363              }
364            } else {
365              Expression::CallValue {
366                callee: left,
367                arguments,
368                optional,
369              }
370            },
371          )
372        }
373        ExprOperatorName::Index | ExprOperatorName::OptionalIndex => {
374          let index = self.parse_expr(TokenType::BracketClose)?;
375          let end = self.require(TokenType::BracketClose)?;
376          self.new_expression(left.loc + end.loc, Expression::Index {
377            object: left,
378            index,
379            optional: match operator.name {
380              ExprOperatorName::OptionalIndex => true,
381              _ => false,
382            },
383          })
384        }
385        ExprOperatorName::MemberAccess | ExprOperatorName::OptionalMemberAccess => {
386          let right_tok = self.consume()?;
387          let TokenType::Identifier = right_tok.typ else {
388            return Err(
389              right_tok.error(SyntaxErrorType::ExpectedSyntax("member access property")),
390            );
391          };
392          let right = right_tok.loc;
393          self.new_expression(left.loc + right, Expression::Field {
394            object: left,
395            field: self.source_as_string(right),
396            optional: match operator.name {
397              ExprOperatorName::OptionalMemberAccess => true,
398              _ => false,
399            },
400          })
401        }
402        _ => {
403          let right = self.parse_expr_with_min_prec(next_min_prec, terminators)?;
404          self.new_expression(left.loc + right.loc, Expression::Binary {
405            operator: operator.name,
406            left,
407            right,
408          })
409        }
410      };
411    }
412
413    Ok(left)
414  }
415}