1use crate::common::TextLocation;
19use crate::mel::grammar::GrammarNode;
20use brooks_macros::{grammar_location, grammar_name};
21use regex::Regex;
22use std::{fmt::Debug, net::IpAddr, sync::Arc};
23
24#[grammar_name(mel)]
25#[grammar_location]
26#[derive(Debug, Clone)]
27pub struct Mel<A: Debug + Clone> {
28 pub testing: usize,
29 pub aug: A,
30}
31
32#[grammar_name(function_call_expr)]
33#[grammar_location]
34#[derive(Debug, Clone)]
35pub struct FunctionCall<A: Debug + Clone> {
36 pub callee: Expr<A>,
37 pub arguments: ArgumentList<A>,
38 pub aug: A,
39}
40
41#[grammar_name(identifier)]
42#[grammar_location]
43#[derive(Debug, Clone)]
44pub struct Identifier<A: Debug + Clone> {
45 pub identifier: String,
46 pub aug: A,
47}
48
49#[grammar_name(member_access)]
50#[derive(Debug, Clone)]
51pub enum MemberAccessOperator {
52 MemberAccess,
53}
54
55#[grammar_name(member_access_expr)]
56#[grammar_location]
57#[derive(Debug, Clone)]
58pub struct MemberAccessExpression<A: Debug + Clone> {
59 pub base: Expr<A>,
60 pub oper: MemberAccessOperator,
61 pub member: Identifier<A>,
62 pub aug: A,
63}
64
65#[grammar_name(argument)]
66#[grammar_location]
67#[derive(Debug, Clone)]
68pub struct Argument<A: Debug + Clone> {
69 pub expr: Expr<A>,
70 pub aug: A,
71}
72
73#[grammar_name(argument_list)]
74#[grammar_location]
75#[derive(Debug, Clone)]
76pub struct ArgumentList<A: Debug + Clone> {
77 pub arguments: Vec<Argument<A>>,
78 pub aug: A,
79}
80
81#[derive(Debug, Clone)]
82pub enum BinaryInfixOperator {
83 Logic(LogicOperator),
84 Comparison(ComparisonOperator),
85 Math(MathOperator),
86 Concat(StringConcatOperator),
87 MemberAccess(MemberAccessOperator),
88}
89
90#[grammar_name(eq, ne, lt, lte, gt, gte, regex_eq, ipmatch)]
91#[derive(Debug, Clone)]
92pub enum ComparisonOperator {
93 Eq,
94 Ne,
95 Lt,
96 Lte,
97 Gt,
98 Gte,
99 Re,
100 IP,
101}
102
103#[grammar_name(and, or)]
104#[derive(Debug, Clone)]
105pub enum LogicOperator {
106 And,
107 Or,
108}
109
110#[grammar_name(string_concat)]
111#[derive(Debug, Clone)]
112pub struct StringConcatOperator {}
113
114#[grammar_name(plus, minus, mul, div, modulo)]
115#[derive(Debug, Clone)]
116pub enum MathOperator {
117 Plus,
118 Minus,
119 Multiply,
120 Divide,
121 Modulo,
122}
123
124#[grammar_name(binary_expr)]
125#[grammar_location]
126#[derive(Debug, Clone)]
127pub struct BinaryExpr<A: Debug + Clone> {
128 pub left: Expr<A>,
129 pub op: BinaryInfixOperator,
130 pub right: Expr<A>,
131 pub aug: A,
132}
133
134#[grammar_name(ternary_question, ternary_colon)]
135#[derive(Debug, Clone)]
136pub enum TernaryOperator {
137 Question,
138 Colon,
139}
140
141#[grammar_name(ternary_expr)]
142#[grammar_location]
143#[derive(Debug, Clone)]
144pub struct TernaryExpr<A: Debug + Clone> {
145 pub condition: Expr<A>,
146 pub yes: Expr<A>,
147 pub no: Expr<A>,
148 pub aug: A,
149}
150
151#[grammar_name(expr)]
152#[derive(Debug, Clone)]
153pub enum Expr<A: Debug + Clone> {
154 FunctionCall(Arc<FunctionCall<A>>),
155 BinaryExpr(Arc<BinaryExpr<A>>),
156 TernaryExpr(Arc<TernaryExpr<A>>),
157 Identifier(Arc<Identifier<A>>),
158 ArgumentList(Arc<ArgumentList<A>>),
159 Argument(Arc<Argument<A>>),
160 Literal(Literal, TextLocation, A),
161 MemberAccess(Arc<MemberAccessExpression<A>>),
162}
163
164impl<A: Debug + Clone> Expr<A> {
165 pub fn location(&self) -> TextLocation {
166 match self {
167 Expr::FunctionCall(function_call) => function_call.location.clone(),
168 Expr::BinaryExpr(binary_expr) => binary_expr.location.clone(),
169 Expr::TernaryExpr(ternary_expr) => ternary_expr.location.clone(),
170 Expr::Identifier(identifier) => identifier.location.clone(),
171 Expr::ArgumentList(argument_list) => argument_list.location.clone(),
172 Expr::Argument(argument) => argument.location.clone(),
173 Expr::MemberAccess(member_access) => member_access.location.clone(),
174 Expr::Literal(_, location, _) => location.clone(),
175 }
176 }
177}
178
179#[grammar_name(literal)]
180#[derive(Debug, Clone)]
181pub enum Literal {
182 Boolean(BooleanLiteral),
183 Number(NumberLiteral),
184 String(StringLiteral),
185 Regex(RegexLiteral),
186 IPAddress(IPAddressLiteral),
187}
188
189#[grammar_name(boolean_literal)]
190#[derive(Debug, Clone, PartialEq)]
191pub enum BooleanLiteral {
192 True,
193 False,
194}
195
196#[derive(Debug, Clone)]
197#[grammar_name(number_literal)]
198pub struct NumberLiteral {
199 pub literal: usize,
200}
201
202#[derive(Debug, Clone)]
203#[grammar_name(string_literal)]
204pub struct StringLiteral {
205 pub literal: String,
206}
207
208#[derive(Debug, Clone)]
209#[grammar_name(regex_literal)]
210pub struct RegexLiteral {
211 pub literal: Regex,
212}
213
214#[derive(Debug, Clone)]
215#[grammar_name(ip_literal)]
216pub struct IPAddressLiteral {
217 pub literal: IpAddr,
218}
219
220pub type AstVisitorResult<T, E> = Result<T, E>;
221
222pub trait AstVisitor<T, A: Debug + Clone, E> {
223 fn visit_function_call(
224 &self,
225 ast: &FunctionCall<A>,
226 context: T,
227 driver: &AstVisitorDriver,
228 ) -> AstVisitorResult<T, E>;
229 fn visit_identifier(
230 &self,
231 ast: &Identifier<A>,
232 context: T,
233 driver: &AstVisitorDriver,
234 ) -> AstVisitorResult<T, E>;
235 fn visit_argument_list(
236 &self,
237 ast: &ArgumentList<A>,
238 context: T,
239 driver: &AstVisitorDriver,
240 ) -> AstVisitorResult<T, E>;
241 fn visit_argument(
242 &self,
243 ast: &Argument<A>,
244 context: T,
245 driver: &AstVisitorDriver,
246 ) -> AstVisitorResult<T, E>;
247 fn visit_member_access_expr(
248 &self,
249 ast: &MemberAccessExpression<A>,
250 context: T,
251 driver: &AstVisitorDriver,
252 ) -> AstVisitorResult<T, E>;
253 fn visit_binary_expr(
254 &self,
255 ast: &BinaryExpr<A>,
256 context: T,
257 driver: &AstVisitorDriver,
258 ) -> AstVisitorResult<T, E>;
259 fn visit_ternary_expr(
260 &self,
261 ast: &TernaryExpr<A>,
262 context: T,
263 driver: &AstVisitorDriver,
264 ) -> AstVisitorResult<T, E>;
265 fn visit_literal(
266 &self,
267 ast: (&Literal, &TextLocation, &A),
268 context: T,
269 driver: &AstVisitorDriver,
270 ) -> AstVisitorResult<T, E>;
271}
272
273pub struct AstVisitorDriver {}
274
275impl AstVisitorDriver {
276 #[allow(dead_code)]
277 pub fn visit<T, A: Debug + Clone, E>(
278 &self,
279 node: &Expr<A>,
280 visitor: &impl AstVisitor<T, A, E>,
281 context: T,
282 ) -> AstVisitorResult<T, E> {
283 match node {
284 Expr::Argument(argument) => visitor.visit_argument(argument, context, self),
285 Expr::ArgumentList(argument_list) => {
286 visitor.visit_argument_list(argument_list, context, self)
287 }
288 Expr::Identifier(identifier) => visitor.visit_identifier(identifier, context, self),
289 Expr::FunctionCall(function_call) => {
290 visitor.visit_function_call(function_call, context, self)
291 }
292 Expr::BinaryExpr(binary_expr) => visitor.visit_binary_expr(binary_expr, context, self),
293 Expr::MemberAccess(member_access_expr) => {
294 visitor.visit_member_access_expr(member_access_expr, context, self)
295 }
296 Expr::TernaryExpr(ternary_expr) => {
297 visitor.visit_ternary_expr(ternary_expr, context, self)
298 }
299 Expr::Literal(literal, location, aug) => {
300 visitor.visit_literal((literal, location, aug), context, self)
301 }
302 }
303 }
304}