use cas_error::Error;
use crate::parser::{
ast::expr::Expr,
error::UnclosedParenthesis,
fmt::Latex,
garbage::Garbage,
token::{CloseParen, OpenParen},
Parse,
Parser,
};
use std::{fmt, ops::Range};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Paren {
pub expr: Box<Expr>,
pub span: Range<usize>,
}
impl Paren {
pub fn span(&self) -> Range<usize> {
self.span.clone()
}
pub fn innermost(&self) -> &Expr {
let mut inner = &self.expr;
while let Expr::Paren(paren) = inner.as_ref() {
inner = &paren.expr;
}
inner
}
pub fn into_innermost(self) -> Expr {
let mut inner = self.expr;
while let Expr::Paren(paren) = *inner {
inner = paren.expr;
}
*inner
}
}
impl<'source> Parse<'source> for Paren {
fn std_parse(
input: &mut Parser<'source>,
recoverable_errors: &mut Vec<Error>
) -> Result<Self, Vec<Error>> {
let open_paren = input.try_parse::<OpenParen>().forward_errors(recoverable_errors)?;
let expr = input.try_parse().forward_errors(recoverable_errors)?;
let close_paren = input.try_parse::<CloseParen>()
.forward_errors(recoverable_errors)
.unwrap_or_else(|_| {
recoverable_errors.push(Error::new(
vec![open_paren.span.clone()],
UnclosedParenthesis { opening: true },
));
Garbage::garbage()
});
Ok(Self {
expr: Box::new(expr),
span: open_paren.span.start..close_paren.span.end,
})
}
}
impl std::fmt::Display for Paren {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "(")?;
self.expr.fmt(f)?;
write!(f, ")")
}
}
impl Latex for Paren {
fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\\left(")?;
self.expr.fmt_latex(f)?;
write!(f, "\\right)")
}
}