wagon_parser/parser/
sum.rs

1use std::fmt::Display;
2use std::write;
3
4use crate::firstpass::{GetReqAttributes, RewriteToSynth};
5
6use super::{Parse, LexerBridge, ParseResult, ParseOption, Tokens, SpannableNode, ResultPeek};
7
8use wagon_lexer::math::Math;
9
10use super::term::Term;
11use super::helpers::TokenMapper;
12use wagon_macros::TokenMapper;
13use quote::{ToTokens, quote};
14
15use wagon_macros::new_unspanned;
16
17#[derive(PartialEq, Debug, Eq, Hash, Clone)]
18#[new_unspanned]
19/// A sum of any number of [`Term`]s.
20///
21/// If `cont == None`, then this is just a `Term`.
22///
23/// # Grammar
24/// <code>[Sum] -> [Term] [SumP]?;</code>
25pub struct Sum {
26    /// The left-hand [`Term`].
27	pub left: SpannableNode<Term>,
28    /// The optional continuation.
29	pub cont: Option<SumP>
30}
31
32#[derive(PartialEq, Debug, Eq, Hash, Clone)]
33#[new_unspanned]
34/// The operator, right-hand side and possible further continuation of this sum.
35///
36/// # Grammar
37/// <code>[SumP] -> [Op1] [Term] [SumP]?;</code>
38pub struct SumP {
39    /// The operator
40	pub op: Op1,
41    /// The right-hand [`Term`].
42	pub right: SpannableNode<Term>,
43    /// The optional rest of the sum
44	pub cont: Option<Box<SumP>>
45}
46
47impl Parse for Sum {
48
49	fn parse(lexer: &mut LexerBridge) -> ParseResult<Self> {
50		Ok(Self {
51			left: SpannableNode::parse(lexer)?,
52			cont: SumP::parse_option(lexer)?
53		})
54	}
55}
56
57impl ParseOption for SumP {
58
59	fn parse_option(lexer: &mut LexerBridge) -> ParseResult<Option<Self>> where Self: Sized {
60	    if let Some(op) = Op1::token_to_enum(lexer.peek_result()?) {
61	    	lexer.next();
62	    	Ok(Some(Self { op, right: SpannableNode::parse(lexer)?, cont: Self::parse_option(lexer)?.map(Box::new) }))
63	    } else {
64	    	Ok(None)
65	    }
66	}
67}
68
69impl GetReqAttributes for Sum {
70    fn get_req_attributes(&self) -> crate::firstpass::ReqAttributes {
71        let mut req = self.left.get_req_attributes();
72        if let Some(cont) = &self.cont {
73            req.extend(cont.get_req_attributes());
74        }
75        req
76    }
77}
78
79impl GetReqAttributes for SumP {
80    fn get_req_attributes(&self) -> crate::firstpass::ReqAttributes {
81        let mut req = self.right.get_req_attributes();
82        if let Some(cont) = &self.cont {
83            req.extend(cont.get_req_attributes());
84        }
85        req
86    }
87}
88
89impl RewriteToSynth for Sum {
90    fn rewrite_to_synth(&mut self) -> crate::firstpass::ReqAttributes {
91        let mut req = self.left.rewrite_to_synth();
92        if let Some(cont) = &mut self.cont {
93            req.extend(cont.rewrite_to_synth());
94        }
95        req
96    }
97}
98
99impl RewriteToSynth for SumP {
100    fn rewrite_to_synth(&mut self) -> crate::firstpass::ReqAttributes {
101        let mut req = self.right.rewrite_to_synth();
102        if let Some(cont) = &mut self.cont {
103            req.extend(cont.rewrite_to_synth());
104        }
105        req
106    }
107}
108
109#[derive(TokenMapper, PartialEq, Debug, Eq, Hash, Clone)]
110/// The sum operations
111///
112/// # Grammar
113/// <code>[Op1] -> "+" | "-";</code>
114pub enum Op1 {
115    /// `+`
116	Add,
117    /// `-`
118	Sub
119}
120
121impl Display for Sum {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        if let Some(c) = &self.cont {
124        	write!(f, "{} {}", self.left, c)
125        } else {
126        	write!(f, "{}", self.left)
127        }
128    }
129}
130
131impl Display for SumP {
132    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133        if let Some(c) = &self.cont {
134        	write!(f, "{} {} {}", self.op, self.right, c)
135        } else {
136        	write!(f, "{} {}", self.op, self.right)
137        }
138    }
139}
140
141impl Display for Op1 {
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        match self {
144            Self::Add => write!(f, "+"),
145            Self::Sub => write!(f, "-"),
146        }
147    }
148}
149
150impl ToTokens for Op1 {
151    fn to_tokens(&self, tokens: &mut quote::__private::TokenStream) {
152        match self {
153            Self::Add => tokens.extend(quote!(std::ops::Add::add)),
154            Self::Sub => tokens.extend(quote!(std::ops::Sub::sub)),
155        }
156    }
157}