cas_parser/parser/ast/
for_expr.rs1use cas_error::Error;
2use crate::parser::{
3 ast::{
4 expr::Expr,
5 literal::LitSym,
6 range::Range as RangeExpr,
7 },
8 fmt::Latex,
9 keyword::{In as InToken, For as ForToken},
10 Parse,
11 Parser,
12};
13use std::{fmt, ops::Range};
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22pub struct For {
23 pub variable: LitSym,
25
26 pub range: RangeExpr,
28
29 pub body: Box<Expr>,
31
32 pub span: Range<usize>,
34}
35
36impl For {
37 pub fn span(&self) -> Range<usize> {
39 self.span.clone()
40 }
41}
42
43impl<'source> Parse<'source> for For {
44 fn std_parse(
45 input: &mut Parser<'source>,
46 recoverable_errors: &mut Vec<Error>
47 ) -> Result<Self, Vec<Error>> {
48 let for_token = input.try_parse::<ForToken>().forward_errors(recoverable_errors)?;
49 let variable = input.try_parse::<LitSym>().forward_errors(recoverable_errors)?;
50 input.try_parse::<InToken>().forward_errors(recoverable_errors)?;
51 let range = input.try_parse::<RangeExpr>().forward_errors(recoverable_errors)?;
52 let body = input.try_parse_with_state::<_, Expr>(|state| {
53 state.allow_then = true;
54 state.allow_loop_control = true;
55 }).forward_errors(recoverable_errors)?;
56 let span = for_token.span.start..body.span().end;
57
58 Ok(Self {
59 variable,
60 range,
61 body: Box::new(body),
62 span,
63 })
64 }
65}
66
67impl std::fmt::Display for For {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 write!(f, "for {} in {} {}", self.variable, self.range, self.body)
70 }
71}
72
73impl Latex for For {
74 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
75 write!(
76 f,
77 "\\forall {} \\in {} \\text{{ do }} {}",
78 self.variable,
79 self.range,
80 self.body
81 )
82 }
83}