cas_parser/parser/ast/
sum.rs1use cas_error::Error;
2use crate::parser::{
3 ast::{
4 expr::Expr,
5 literal::LitSym,
6 range::Range as RangeExpr,
7 },
8 fmt::Latex,
9 keyword::{In as InToken, Sum as SumToken},
10 Parse,
11 Parser,
12};
13use std::{fmt, ops::Range};
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33pub struct Sum {
34 pub variable: LitSym,
36
37 pub range: RangeExpr,
39
40 pub body: Box<Expr>,
42
43 pub span: Range<usize>,
45}
46
47impl Sum {
48 pub fn span(&self) -> Range<usize> {
50 self.span.clone()
51 }
52}
53
54impl<'source> Parse<'source> for Sum {
55 fn std_parse(
56 input: &mut Parser<'source>,
57 recoverable_errors: &mut Vec<Error>
58 ) -> Result<Self, Vec<Error>> {
59 let sum_token = input.try_parse::<SumToken>().forward_errors(recoverable_errors)?;
60 let variable = input.try_parse::<LitSym>().forward_errors(recoverable_errors)?;
61 input.try_parse::<InToken>().forward_errors(recoverable_errors)?;
62 let range = input.try_parse::<RangeExpr>().forward_errors(recoverable_errors)?;
63 let body = input.try_parse_with_state::<_, Expr>(|state| {
64 state.allow_of = true;
65 }).forward_errors(recoverable_errors)?;
66 let span = sum_token.span.start..body.span().end;
67
68 Ok(Self {
69 variable,
70 range,
71 body: Box::new(body),
72 span,
73 })
74 }
75}
76
77impl std::fmt::Display for Sum {
78 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79 write!(f, "sum {} in {} {}", self.variable, self.range, self.body)
80 }
81}
82
83impl Latex for Sum {
84 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 write!(
86 f,
87 "\\sum_{{{}={}}}^{{{}}} {}",
88 self.variable,
89 self.range.start,
90 self.range.end,
91 self.body,
92 )
93 }
94}