wagon_parser/parser/
comp.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 super::helpers::TokenMapper;
9
10use wagon_lexer::math::Math;
11
12use super::sum::Sum;
13use wagon_macros::TokenMapper;
14
15use quote::{ToTokens, quote};
16
17use wagon_macros::new_unspanned;
18
19#[derive(PartialEq, Debug, Eq, Hash, Clone)]
20#[new_unspanned]
21/// A comparison between two [`Sum`]s.
22///
23/// If `comp == None`, then this is just a `Sum`.
24///
25/// # Grammar
26/// `Comparison -> [Sum] ([CompOp] [Sum])?;`
27pub struct Comparison {
28    /// The left-hand side of the comparison
29	pub sum: SpannableNode<Sum>,
30    /// The optional operator and right-hand side.
31	pub comp: Option<Comp>
32}
33
34#[derive(PartialEq, Debug, Eq, Hash, Clone)]
35#[cfg_attr(test, new_unspanned)]
36/// The operator and right-hand side of a comparison.
37pub struct Comp {
38    /// The operator.
39	pub op: CompOp,
40    /// The right-hand side.
41	pub right: SpannableNode<Sum>
42}
43
44#[derive(TokenMapper, PartialEq, Debug, Eq, Hash, Clone)]
45/// All possible comparison operators.
46///
47/// # Grammar
48/// `CompOp -> "<" | "<=" | ">" | ">=" | "==" | "!=" | "in";`
49pub enum CompOp {
50    /// `==`
51	Eq,
52    /// `!=` 
53	Neq,
54    /// `<=`
55	Lte,
56    /// `<`
57	Lt,
58    /// `>=`
59	Gte,
60    /// `>`
61	Gt,
62    /// `in`
63	In
64}
65
66impl Parse for Comparison {
67
68    fn parse(lexer: &mut LexerBridge) -> ParseResult<Self> where Self: Sized {
69        Ok(Self { sum: SpannableNode::parse(lexer)?, comp: Comp::parse_option(lexer)? })
70    }
71
72}
73
74impl ParseOption for Comp {
75
76    fn parse_option(lexer: &mut LexerBridge) -> ParseResult<Option<Self>> where Self: Sized {
77        if let Some(op) = CompOp::token_to_enum(lexer.peek_result()?) {
78        	lexer.next();
79        	Ok(Some(Self { op, right: SpannableNode::parse(lexer)?}))
80        } else {
81        	Ok(None)
82        }
83    }
84}
85
86impl GetReqAttributes for Comparison {
87    fn get_req_attributes(&self) -> crate::firstpass::ReqAttributes {
88        let mut req = self.sum.get_req_attributes();
89        if let Some(cont) = &self.comp {
90            req.extend(cont.right.get_req_attributes());
91        }
92        req
93    }
94}
95
96impl RewriteToSynth for Comparison {
97    fn rewrite_to_synth(&mut self) -> crate::firstpass::ReqAttributes {
98        let mut req = self.sum.rewrite_to_synth();
99        if let Some(cont) = &mut self.comp {
100            req.extend(cont.right.rewrite_to_synth());
101        }
102        req
103    }
104}
105
106impl Display for Comparison {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        if let Some(c) = &self.comp {
109            write!(f, "{} {} {}", self.sum, c.op, c.right)
110        } else {
111            write!(f, "{}", self.sum)
112        }
113    }
114}
115
116impl Display for CompOp {
117    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118        match self {
119            Self::Eq => write!(f, "=="),
120            Self::Neq => write!(f, "!="),
121            Self::Lte => write!(f, "<="),
122            Self::Lt => write!(f, "<"),
123            Self::Gte => write!(f, ">="),
124            Self::Gt => write!(f, ">"),
125            Self::In => write!(f, "in"),
126        }
127    }
128}
129
130impl ToTokens for CompOp {
131    fn to_tokens(&self, tokens: &mut quote::__private::TokenStream) {
132        match self {
133            Self::Eq => tokens.extend(quote!(==)),
134            Self::Neq => tokens.extend(quote!(!=)),
135            Self::Lte => tokens.extend(quote!(<=)),
136            Self::Lt => tokens.extend(quote!(<)),
137            Self::Gte => tokens.extend(quote!(>=)),
138            Self::Gt => tokens.extend(quote!(>)),
139            Self::In => unimplemented!("Should be a special case!"),
140        };
141    }
142}