cas_parser/parser/ast/
paren.rs

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