1#[macro_export]
2macro_rules! parse_unit_impl {
3 ($enum_name:ident {
4 $($string:literal -> $var:ident,)*
5 }) => {
6 #[cfg(feature = "parse")]
7 impl terl::ParseUnit<$crate::Token> for $enum_name {
8 type Target = $enum_name;
9
10 fn parse(p: &mut terl::Parser<$crate::Token>) -> terl::ParseResult<Self, $crate::Token> {
11 use std::collections::HashMap;
12 use terl::WithSpanExt;
13
14 thread_local! {
15 static MAP: HashMap<&'static str, $enum_name> = {
16 let mut map = HashMap::new();
17 $(
18 if let Some(previous) = map.get($string) {
19 panic!("conflicting: both `{}` and `{}` are `{}`",
20 $enum_name::$var, previous, $string
21 );
22 }
23 map.insert($string, $enum_name::$var);
24 )*
25 map
26 };
27 }
28
29 let Some(next) = p.peek() else {
31 let msg = format!("expect a `{}`, but there are no token left", stringify!($enum_name));
32 return p.unmatch(msg)
33 };
34
35
36 match MAP.with(|map| map.get(&**next).copied()) {
37 Some(item) => {
38 p.next();
40 Ok(item)
41 },
42 None => {
43 p.unmatch(
44 format!("{} matched non of {}", &**next , stringify!($enum_name)),
45 )
46 }
47 }
48 }
49 }
50 };
51}
52
53macro_rules! operators {
54 (
55 $(#[$metas:meta])*
56 $(
57 symbols $sub_class:ident {
58 $($string:literal -> $var:ident : $ass:ident $priority:expr),*
59 }
60 )*
61
62 ) => {
63 $(#[$metas])*
64 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
65 pub enum OperatorAssociativity {
66 Binary,
67 Unary,
68 None,
69 }
70
71 impl OperatorAssociativity {
72 pub fn cost(&self) -> usize {
73 match self {
74 Self::Binary => 2,
75 Self::Unary => 1,
76 Self::None => 0
77 }
78 }
79 }
80
81 $(#[$metas])*
82 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
83 pub enum OperatorTypes {
84 $($sub_class,)*
85 }
86
87 $crate::reverse_parse_keywords! {
88 $(#[$metas])*
89 keywords Operators {
90 $(
91 $($string -> $var,)*
92 )*
93 }
94 }
95
96 parse_unit_impl!{
97 Operators {
98 $(
99 $($string -> $var,)*
100 )*
101 }
102 }
103
104 impl Operators {
105 pub fn op_ty(&self) -> OperatorTypes {
106 match *self {
107 $(
108 $(Self::$var => OperatorTypes::$sub_class,)*
109 )*
110 }
111 }
112
113 pub fn associativity(&self) -> OperatorAssociativity {
114 match *self {
115 $(
116 $(Self::$var => OperatorAssociativity::$ass,)*
117 )*
118 }
119 }
120
121 pub fn cost(&self) -> usize {
122 self.associativity().cost()
123 }
124
125 pub fn priority(&self) -> usize {
129 match *self {
130 $(
131 $(Self::$var => $priority,)*
132 )*
133 }
134 }
135 }
136
137 pub mod sub_classes {
138 use super::*;
139
140 $crate::reverse_parse_keywords! {
141 $(
142 keywords $sub_class {
143 $($string -> $var,)*
144 }
145 )*
146 }
147
148
149
150 $(
151 impl From<$sub_class> for Operators {
152 fn from(value: $sub_class) -> Operators {
153 match value {
154 $($sub_class::$var => Operators::$var,)*
155 }
156 }
157 }
158
159 impl TryFrom<Operators> for $sub_class {
160 type Error = ();
161
162 fn try_from(value: Operators) -> Result<Self, Self::Error> {
163 match value {
164 $(Operators::$var => Ok(Self::$var),)*
165 _ => Err(())
166 }
167 }
168 }
169
170 impl $sub_class {
171 pub fn associativity(&self) -> OperatorAssociativity {
172 match self {
173 $(Self::$var => OperatorAssociativity::$ass,)*
174 }
175 }
176
177 pub fn priority(&self) -> usize {
178 match self {
179 $(Self::$var => $priority,)*
180 }
181 }
182 }
183
184 )*
185 }
186 };
187}
188
189operators! {
190 #[derive(serde::Serialize,serde::Deserialize)]
191 symbols AlgebraOperator {
192 "jia1" -> Add : Binary 6,
193 "jian3" -> Sub : Binary 6,
194 "cheng2" -> Mul : Binary 5,
195 "chu2" -> Div : Binary 5,
196 "mo2" -> Mod : Binary 5,
197 "mi4" -> Pow : Binary 4,
198 "dui4" -> Log : Binary 4
199 }
200 symbols CompareOperator {
201 "tong2" -> Eq : Binary 10,
202 "fei1tong2" -> Neq : Binary 10,
203 "da4" -> Gt : Binary 8,
204 "xiao3" -> Lt : Binary 8,
205 "da4deng3" -> Ge : Binary 8,
206 "xiao3deng3" -> Le : Binary 8
207 }
208 symbols LogicalOperator {
209 "yu3" -> And : Binary 14,
210 "huo4" -> Or : Binary 15,
211 "fei1" -> Not : Unary 3
212 }
213 symbols ArithmeticOperator {
214 "wei4yu3" -> Band : Binary 11,
215 "wei4huo4" -> Bor : Binary 13,
216 "wei4fei1" -> Bnot : Unary 3,
217 "wei4yi4huo4" -> Xor : Binary 12,
218 "zuo3yi2" -> Shl : Binary 7,
219 "you4yi2" -> Shr : Binary 7
220 }
221 symbols SpecialOperator {
222 "qu3zhi3" -> AddrOf : Unary 3,
223 "fang3zhi3" -> Deref : Unary 3,
224 "fang3su4" -> GetElement : Binary 2,
225 "zhuan3" -> Cast : Unary 2,
226 "chang2du4" -> SizeOf : Unary 3
227 }
228 symbols StructOperator {
229 "jie2" -> BracketL : None 0,
230 "he2" -> BracketR : None 0
231 }
232}