cas_parser/parser/ast/
while_expr.rs

1use cas_error::Error;
2use crate::parser::{
3    ast::expr::Expr,
4    fmt::Latex,
5    keyword::While as WhileToken,
6    Parse,
7    Parser,
8};
9use std::{fmt, ops::Range};
10
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14/// A `while` loop expression, such as `while x < 10 then x += 1`. The loop body is executed
15/// repeatedly as long as the outer condition is true.
16#[derive(Debug, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub struct While {
19    /// The condition that must be true for the loop body to be executed.
20    pub condition: Box<Expr>,
21
22    /// The body of the loop.
23    pub body: Box<Expr>,
24
25    /// The region of the source code that this expression was parsed from.
26    pub span: Range<usize>,
27
28    /// The span of the `while` keyword.
29    pub while_span: Range<usize>,
30}
31
32impl While {
33    /// Returns the span of the `while` loop expression.
34    pub fn span(&self) -> Range<usize> {
35        self.span.clone()
36    }
37}
38
39impl<'source> Parse<'source> for While {
40    fn std_parse(
41        input: &mut Parser<'source>,
42        recoverable_errors: &mut Vec<Error>
43    ) -> Result<Self, Vec<Error>> {
44        let while_token = input.try_parse::<WhileToken>().forward_errors(recoverable_errors)?;
45        let condition = input.try_parse::<Expr>().forward_errors(recoverable_errors)?;
46        let then_body = input.try_parse_with_state::<_, Expr>(|state| {
47            state.allow_then = true;
48            state.allow_loop_control = true;
49        }).forward_errors(recoverable_errors)?;
50        let span = while_token.span.start..then_body.span().end;
51
52        Ok(Self {
53            condition: Box::new(condition),
54            body: Box::new(then_body),
55            span,
56            while_span: while_token.span,
57        })
58    }
59}
60
61impl std::fmt::Display for While {
62    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63        write!(f, "while {} {}", self.condition, self.body)
64    }
65}
66
67impl Latex for While {
68    fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
69        write!(f, "\\text{{while }}")?;
70        self.condition.fmt_latex(f)?;
71        self.body.fmt_latex(f)?;
72        Ok(())
73    }
74}