wagon_parser/parser/
term.rs

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