cas_parser/parser/ast/
paren.rs

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