1#[cfg(test)]
2mod test {
3 use crate::{
4 ast::Parser,
5 expr::Expr,
6 op::BinOp,
7 token::{Token, Tokenizer},
8 };
9
10 #[test]
11 fn basic() {
12 let tokens = vec![
13 Token::At,
14 Token::Id("req".to_string()),
15 Token::Dot,
16 Token::Id("user".to_string()),
17 Token::Dot,
18 Token::Id("age".to_string()),
19 Token::Gt,
20 Token::Int(18),
21 ];
22 let expr = Expr::Bin(
23 Box::new(Expr::At(vec![
24 Box::new(Expr::Val("req".into())),
25 Box::new(Expr::Val("user".into())),
26 Box::new(Expr::Val("age".into())),
27 ])),
28 BinOp::Gt,
29 Box::new(Expr::Val(18.into())),
30 );
31 let parsed = Parser::new(&tokens).parse().unwrap();
32 assert_eq!(parsed, expr);
33 }
34
35 #[test]
36 fn paren() {
37 let r = r#"
38 (
39 true
40 ||
41 false
42 )
43 "#;
44
45 let ts = Tokenizer::new(r).unwrap();
46 let parsed = Parser::new(&ts).parse().unwrap();
47 let expected = Expr::Paren(Box::new(Expr::Or(
48 Box::new(Expr::Val(true.into())),
49 Box::new(Expr::Val(false.into())),
50 )));
51 assert_eq!(parsed, expected);
52 }
53
54 #[test]
55 fn complex() {
56 let r = r#"
57 (
58 @time != 0
59 ||
60 @col.pub == true
61 )
62 &&
63 @random > 0.5
64 "#;
65
66 let ts = Tokenizer::new(r).unwrap();
67 let parsed = Parser::new(&ts).parse().unwrap();
68 let expected = Expr::And(
69 Box::new(Expr::Paren(Box::new(Expr::Or(
70 Box::new(Expr::Bin(
71 Box::new(Expr::At(vec![Box::new(Expr::Val("time".into()))])),
72 BinOp::Ne,
73 Box::new(Expr::Val(0.into())),
74 )),
75 Box::new(Expr::Bin(
76 Box::new(Expr::At(vec![
77 Box::new(Expr::Val("col".into())),
78 Box::new(Expr::Val("pub".into())),
79 ])),
80 BinOp::Eq,
81 Box::new(Expr::Val(true.into())),
82 )),
83 )))),
84 Box::new(Expr::Bin(
85 Box::new(Expr::At(vec![Box::new(Expr::Val("random".into()))])),
86 BinOp::Gt,
87 Box::new(Expr::Val(0.5.into())),
88 )),
89 );
90 assert_eq!(parsed, expected);
91 }
92
93 #[test]
94 fn access_str_int_str() {
95 let r = "@list.0.name";
96
97 let ts = Tokenizer::new(r).unwrap();
98 let parsed = Parser::new(&ts).parse().unwrap();
99 let expected = Expr::At(vec![
100 Box::new(Expr::Val("list".into())),
101 Box::new(Expr::Val(0.into())),
102 Box::new(Expr::Val("name".into())),
103 ]);
104 assert_eq!(parsed, expected);
105 }
106
107 #[test]
108 fn access_first_int_paths() {
109 let r = "@1.2";
110
111 let t = Tokenizer::new(r).unwrap();
112 let parsed = Parser::new(&t).parse();
113 assert!(parsed.is_err());
114 }
115
116 #[test]
117 fn empty_list() {
118 let r = "[]";
119
120 let ts = Tokenizer::new(r).unwrap();
121 let parsed = Parser::new(&ts).parse().unwrap();
122 let expected = Expr::List(vec![]);
123 assert_eq!(parsed, expected);
124 }
125
126 #[test]
127 fn simple_list() {
128 let r = "[1, 2, 3]";
129
130 let ts = Tokenizer::new(r).unwrap();
131 let parsed = Parser::new(&ts).parse().unwrap();
132 let expected = Expr::List(vec![
133 Box::new(Expr::Val(1.into())),
134 Box::new(Expr::Val(2.into())),
135 Box::new(Expr::Val(3.into())),
136 ]);
137 assert_eq!(parsed, expected);
138 }
139
140 #[test]
141 fn mixed_list() {
142 let r = r#"[1, "hello", true]"#;
143
144 let ts = Tokenizer::new(r).unwrap();
145 let parsed = Parser::new(&ts).parse().unwrap();
146 let expected = Expr::List(vec![
147 Box::new(Expr::Val(1.into())),
148 Box::new(Expr::Val("hello".into())),
149 Box::new(Expr::Val(true.into())),
150 ]);
151 assert_eq!(parsed, expected);
152 }
153
154 #[test]
155 fn list_with_expressions() {
156 let r = "[1 + 2, 3 * 4]";
157
158 let ts = Tokenizer::new(r).unwrap();
159 let parsed = Parser::new(&ts).parse().unwrap();
160 let expected = Expr::List(vec![
161 Box::new(Expr::Bin(
162 Box::new(Expr::Val(1.into())),
163 BinOp::Add,
164 Box::new(Expr::Val(2.into())),
165 )),
166 Box::new(Expr::Bin(
167 Box::new(Expr::Val(3.into())),
168 BinOp::Mul,
169 Box::new(Expr::Val(4.into())),
170 )),
171 ]);
172 assert_eq!(parsed, expected);
173 }
174
175 #[test]
176 fn nested_list() {
177 let r = "[[1, 2], [3, 4]]";
178
179 let ts = Tokenizer::new(r).unwrap();
180 let parsed = Parser::new(&ts).parse().unwrap();
181 let expected = Expr::List(vec![
182 Box::new(Expr::List(vec![
183 Box::new(Expr::Val(1.into())),
184 Box::new(Expr::Val(2.into())),
185 ])),
186 Box::new(Expr::List(vec![
187 Box::new(Expr::Val(3.into())),
188 Box::new(Expr::Val(4.into())),
189 ])),
190 ]);
191 assert_eq!(parsed, expected);
192 }
193
194 #[test]
195 fn list_with_trailing_comma() {
196 let r = "[1, 2, 3,]";
197
198 let ts = Tokenizer::new(r).unwrap();
199 let parsed = Parser::new(&ts).parse().unwrap();
200 let expected = Expr::List(vec![
201 Box::new(Expr::Val(1.into())),
202 Box::new(Expr::Val(2.into())),
203 Box::new(Expr::Val(3.into())),
204 ]);
205 assert_eq!(parsed, expected);
206 }
207
208 #[test]
209 fn empty_map() {
210 let r = "{}";
211
212 let ts = Tokenizer::new(r).unwrap();
213 let parsed = Parser::new(&ts).parse().unwrap();
214 let expected = Expr::Map(vec![]);
215 assert_eq!(parsed, expected);
216 }
217
218 #[test]
219 fn simple_map() {
220 let r = r#"{"name": "Alice", "age": 30}"#;
221
222 let ts = Tokenizer::new(r).unwrap();
223 let parsed = Parser::new(&ts).parse().unwrap();
224 let expected = Expr::Map(vec![
225 (
226 Box::new(Expr::Val("name".into())),
227 Box::new(Expr::Val("Alice".into())),
228 ),
229 (
230 Box::new(Expr::Val("age".into())),
231 Box::new(Expr::Val(30.into())),
232 ),
233 ]);
234 assert_eq!(parsed, expected);
235 }
236
237 #[test]
238 fn map_with_expressions() {
239 let r = r#"{"sum": 1 + 2, "product": 3 * 4}"#;
240
241 let ts = Tokenizer::new(r).unwrap();
242 let parsed = Parser::new(&ts).parse().unwrap();
243 let expected = Expr::Map(vec![
244 (
245 Box::new(Expr::Val("sum".into())),
246 Box::new(Expr::Bin(
247 Box::new(Expr::Val(1.into())),
248 BinOp::Add,
249 Box::new(Expr::Val(2.into())),
250 )),
251 ),
252 (
253 Box::new(Expr::Val("product".into())),
254 Box::new(Expr::Bin(
255 Box::new(Expr::Val(3.into())),
256 BinOp::Mul,
257 Box::new(Expr::Val(4.into())),
258 )),
259 ),
260 ]);
261 assert_eq!(parsed, expected);
262 }
263
264 #[test]
265 fn map_with_different_key_types() {
266 let r = r#"{42: "number", true: "bool", "key": "string"}"#;
267
268 let ts = Tokenizer::new(r).unwrap();
269 let parsed = Parser::new(&ts).parse().unwrap();
270 let expected = Expr::Map(vec![
271 (
272 Box::new(Expr::Val(42.into())),
273 Box::new(Expr::Val("number".into())),
274 ),
275 (
276 Box::new(Expr::Val(true.into())),
277 Box::new(Expr::Val("bool".into())),
278 ),
279 (
280 Box::new(Expr::Val("key".into())),
281 Box::new(Expr::Val("string".into())),
282 ),
283 ]);
284 assert_eq!(parsed, expected);
285 }
286
287 #[test]
288 fn nested_map() {
289 let r = r#"{"user": {"name": "Alice", "age": 30}}"#;
290
291 let ts = Tokenizer::new(r).unwrap();
292 let parsed = Parser::new(&ts).parse().unwrap();
293 let expected = Expr::Map(vec![(
294 Box::new(Expr::Val("user".into())),
295 Box::new(Expr::Map(vec![
296 (
297 Box::new(Expr::Val("name".into())),
298 Box::new(Expr::Val("Alice".into())),
299 ),
300 (
301 Box::new(Expr::Val("age".into())),
302 Box::new(Expr::Val(30.into())),
303 ),
304 ])),
305 )]);
306 assert_eq!(parsed, expected);
307 }
308
309 #[test]
310 fn map_with_trailing_comma() {
311 let r = r#"{"a": 1, "b": 2,}"#;
312
313 let ts = Tokenizer::new(r).unwrap();
314 let parsed = Parser::new(&ts).parse().unwrap();
315 let expected = Expr::Map(vec![
316 (
317 Box::new(Expr::Val("a".into())),
318 Box::new(Expr::Val(1.into())),
319 ),
320 (
321 Box::new(Expr::Val("b".into())),
322 Box::new(Expr::Val(2.into())),
323 ),
324 ]);
325 assert_eq!(parsed, expected);
326 }
327
328 #[test]
329 fn mixed_structures() {
330 let r = r#"[{"name": "Alice", "scores": [90, 85]}, {"name": "Bob", "scores": [88, 92]}]"#;
331
332 let ts = Tokenizer::new(r).unwrap();
333 let parsed = Parser::new(&ts).parse().unwrap();
334 let expected = Expr::List(vec![
335 Box::new(Expr::Map(vec![
336 (
337 Box::new(Expr::Val("name".into())),
338 Box::new(Expr::Val("Alice".into())),
339 ),
340 (
341 Box::new(Expr::Val("scores".into())),
342 Box::new(Expr::List(vec![
343 Box::new(Expr::Val(90.into())),
344 Box::new(Expr::Val(85.into())),
345 ])),
346 ),
347 ])),
348 Box::new(Expr::Map(vec![
349 (
350 Box::new(Expr::Val("name".into())),
351 Box::new(Expr::Val("Bob".into())),
352 ),
353 (
354 Box::new(Expr::Val("scores".into())),
355 Box::new(Expr::List(vec![
356 Box::new(Expr::Val(88.into())),
357 Box::new(Expr::Val(92.into())),
358 ])),
359 ),
360 ])),
361 ]);
362 assert_eq!(parsed, expected);
363 }
364
365 #[test]
366 fn context_access_in_literals() {
367 let r = r#"[@user.name, @user.age]"#;
368
369 let ts = Tokenizer::new(r).unwrap();
370 let parsed = Parser::new(&ts).parse().unwrap();
371 let expected = Expr::List(vec![
372 Box::new(Expr::At(vec![
373 Box::new(Expr::Val("user".into())),
374 Box::new(Expr::Val("name".into())),
375 ])),
376 Box::new(Expr::At(vec![
377 Box::new(Expr::Val("user".into())),
378 Box::new(Expr::Val("age".into())),
379 ])),
380 ]);
381 assert_eq!(parsed, expected);
382 }
383
384 #[test]
385 fn invalid_list_syntax() {
386 let r = "[1, 2, 3";
388 let ts = Tokenizer::new(r).unwrap();
389 let parsed = Parser::new(&ts).parse();
390 assert!(parsed.is_err());
391
392 let r = "[1; 2; 3]";
394 let ts = Tokenizer::new(r).unwrap();
395 let parsed = Parser::new(&ts).parse();
396 assert!(parsed.is_err());
397 }
398
399 #[test]
400 fn invalid_map_syntax() {
401 let r = r#"{"key": "value""#;
403 let ts = Tokenizer::new(r).unwrap();
404 let parsed = Parser::new(&ts).parse();
405 assert!(parsed.is_err());
406
407 let r = r#"{"key" "value"}"#;
409 let ts = Tokenizer::new(r).unwrap();
410 let parsed = Parser::new(&ts).parse();
411 assert!(parsed.is_err());
412
413 let r = r#"{"key":}"#;
415 let ts = Tokenizer::new(r).unwrap();
416 let parsed = Parser::new(&ts).parse();
417 assert!(parsed.is_err());
418 }
419}