cas_parser/parser/ast/
while_expr.rs1use crate::parser::{
2 ast::expr::Expr,
3 error::{kind, Error},
4 fmt::Latex,
5 garbage::Garbage,
6 keyword::{Then, While as WhileToken},
7 Parse,
8 Parser,
9};
10use std::{fmt, ops::Range};
11
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, PartialEq)]
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19pub struct While {
20 pub condition: Box<Expr>,
22
23 pub body: Box<Expr>,
25
26 pub span: Range<usize>,
28
29 pub while_span: Range<usize>,
31
32 pub then_span: Range<usize>,
34}
35
36impl While {
37 pub fn span(&self) -> Range<usize> {
39 self.span.clone()
40 }
41}
42
43impl<'source> Parse<'source> for While {
44 fn std_parse(
45 input: &mut Parser<'source>,
46 recoverable_errors: &mut Vec<Error>
47 ) -> Result<Self, Vec<Error>> {
48 let while_token = input.try_parse::<WhileToken>().forward_errors(recoverable_errors)?;
49 let condition = input.try_parse().forward_errors(recoverable_errors)?;
50 let (then_token, body) = 'then: {
51 let then_token = match input.try_parse::<Then>().forward_errors(recoverable_errors) {
52 Ok(token) => token,
53 Err(_) => {
54 recoverable_errors.push(Error::new(
56 vec![while_token.span.clone(), input.span()],
57 kind::MissingIfKeyword {
58 keyword: "then",
59 },
60 ));
61 break 'then Garbage::garbage();
62 },
63 };
64 input.try_parse_with_state::<_, Expr>(|state| {
65 state.allow_loop_control = true;
66 })
67 .forward_errors(recoverable_errors)
68 .map(|expr| (then_token, expr))
69 .unwrap_or_else(|_| {
70 recoverable_errors.push(Error::new(
71 vec![while_token.span.clone(), input.span()],
72 kind::MissingIfBranch {
73 keyword: "then",
74 },
75 ));
76 Garbage::garbage()
77 })
78 };
79 let span = while_token.span.start..body.span().end;
80
81 Ok(Self {
82 condition: Box::new(condition),
83 body: Box::new(body),
84 span,
85 while_span: while_token.span,
86 then_span: then_token.span,
87 })
88 }
89}
90
91impl std::fmt::Display for While {
92 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
93 write!(f, "while {} then {}", self.condition, self.body)
94 }
95}
96
97impl Latex for While {
98 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
99 write!(f, "\\text{{while }}")?;
100 self.condition.fmt_latex(f)?;
101 write!(f, "\\text{{ then }}")?;
102 self.body.fmt_latex(f)?;
103 Ok(())
104 }
105}