use cas_error::Error;
use crate::parser::{
ast::expr::Expr,
error::{OfOutsideSumProduct, ThenOutsideIfWhileFor},
fmt::Latex,
keyword::{Of as OfToken, Then as ThenToken},
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 Then {
pub expr: Box<Expr>,
pub span: Range<usize>,
pub then_span: Range<usize>,
}
impl Then {
pub fn span(&self) -> Range<usize> {
self.span.clone()
}
}
impl<'source> Parse<'source> for Then {
fn std_parse(
input: &mut Parser<'source>,
recoverable_errors: &mut Vec<Error>
) -> Result<Self, Vec<Error>> {
let then_token = input.try_parse::<ThenToken>().forward_errors(recoverable_errors)?;
if !input.state.allow_then {
recoverable_errors.push(Error::new(
vec![then_token.span.clone()],
ThenOutsideIfWhileFor,
));
}
let body = input.try_parse_with_state::<_, Expr>(|input| {
input.allow_then = false;
}).forward_errors(recoverable_errors)?;
let span = then_token.span.start..body.span().end;
Ok(Self {
expr: Box::new(body),
span,
then_span: then_token.span,
})
}
}
impl std::fmt::Display for Then {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "then {}", self.expr)
}
}
impl Latex for Then {
fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\\text{{ then }}")?;
self.expr.fmt_latex(f)?;
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Of {
pub expr: Box<Expr>,
pub span: Range<usize>,
pub of_span: Range<usize>,
}
impl Of {
pub fn span(&self) -> Range<usize> {
self.span.clone()
}
}
impl<'source> Parse<'source> for Of {
fn std_parse(
input: &mut Parser<'source>,
recoverable_errors: &mut Vec<Error>
) -> Result<Self, Vec<Error>> {
let of_token = input.try_parse::<OfToken>().forward_errors(recoverable_errors)?;
if !input.state.allow_of {
recoverable_errors.push(Error::new(
vec![of_token.span.clone()],
OfOutsideSumProduct,
));
}
let body = input.try_parse_with_state::<_, Expr>(|input| {
input.allow_of = false;
}).forward_errors(recoverable_errors)?;
let span = of_token.span.start..body.span().end;
Ok(Self {
expr: Box::new(body),
span,
of_span: of_token.span,
})
}
}
impl std::fmt::Display for Of {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "of {}", self.expr)
}
}
impl Latex for Of {
fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\\text{{ of }}")?;
self.expr.fmt_latex(f)?;
Ok(())
}
}