cas_parser/parser/ast/
block.rs

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