cas_parser/parser/ast/
paren.rs1use 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#[derive(Debug, Clone, PartialEq)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub struct Paren {
19 pub expr: Box<Expr>,
21
22 pub span: Range<usize>,
24}
25
26impl Paren {
27 pub fn span(&self) -> Range<usize> {
29 self.span.clone()
30 }
31
32 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 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 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}