cas_parser/parser/ast/
block.rs

1use cas_error::Error;
2use crate::parser::{
3    ast::stmt::Stmt,
4    error::UnclosedParenthesis,
5    fmt::Latex,
6    garbage::Garbage,
7    token::{CloseCurly, OpenCurly},
8    Parse,
9    Parser,
10};
11use std::{fmt, ops::Range};
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16/// A blocked expression. A [`Block`] can contain multiple expressions in the form of statements.
17/// The last statement in the block is the return value of the block.
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20pub struct Block {
21    /// The inner statements.
22    pub stmts: Vec<Stmt>,
23
24    /// The region of the source code that this [`Block`] was parsed from.
25    pub span: Range<usize>,
26}
27
28impl Block {
29    /// Returns the span of the [`Block`].
30    pub fn span(&self) -> Range<usize> {
31        self.span.clone()
32    }
33}
34
35impl<'source> Parse<'source> for Block {
36    fn std_parse(
37        input: &mut Parser<'source>,
38        recoverable_errors: &mut Vec<Error>
39    ) -> Result<Self, Vec<Error>> {
40        let open_curly = input.try_parse::<OpenCurly>().forward_errors(recoverable_errors)?;
41        let mut stmts = Vec::new();
42        while let Ok(stmt) = input.try_parse().forward_errors(recoverable_errors) {
43            stmts.push(stmt);
44        }
45        let close_curly = input.try_parse::<CloseCurly>()
46            .forward_errors(recoverable_errors)
47            .unwrap_or_else(|_| {
48                recoverable_errors.push(Error::new(
49                    vec![open_curly.span.clone()],
50                    UnclosedParenthesis { opening: true },
51                ));
52
53                // fake a close paren for recovery purposes
54                Garbage::garbage()
55            });
56        Ok(Self {
57            stmts,
58            span: open_curly.span.start..close_curly.span.end,
59        })
60    }
61}
62
63impl std::fmt::Display for Block {
64    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
65        write!(f, "{{")?;
66        for stmt in &self.stmts {
67            stmt.fmt(f)?;
68        }
69        write!(f, "}}")
70    }
71}
72
73impl Latex for Block {
74    fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
75        write!(f, "{{")?;
76        for stmt in &self.stmts {
77            stmt.fmt_latex(f)?;
78        }
79        write!(f, "}}")
80    }
81}