wagon_parser/parser/
term.rs1use 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#[derive(PartialEq, Debug, Eq, Hash, Clone)]
27#[new_unspanned]
28pub struct Term {
35 pub left: SpannableNode<Factor>,
37 pub cont: Option<TermP>
39}
40
41#[derive(PartialEq, Debug, Eq, Hash, Clone)]
42#[cfg_attr(test, new_unspanned)]
43pub struct TermP {
48 pub op: Op2,
50 pub right: SpannableNode<Factor>,
52 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)]
119pub enum Op2 {
124 Mul,
126 Div,
128 Floor,
130 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}