tree-based source processing language
1use nom::{
2 branch::alt,
3 bytes::complete::{is_not, tag},
4 character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, one_of},
5 combinator::{map, opt, recognize, value},
6 error::ParseError,
7 multi::{fold_many0, many0, many0_count, many1, separated_list0, separated_list1},
8 sequence::{delimited, pair, preceded, terminated, tuple},
9 IResult, Parser,
10};
11// use tree_sitter::Query;
12
13use crate::ast::*;
14use crate::string::parse_string;
15
16fn ws<'a, F: 'a, O, E>(inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
17where
18 F: FnMut(&'a str) -> IResult<&'a str, O, E>,
19 E: ParseError<&'a str>,
20{
21 delimited(multispace0, inner, multispace0)
22}
23
24// TODO use this
25fn _parse_comment<'a>(i: &'a str) -> IResult<&'a str, ()> {
26 value((), pair(tag("//"), is_not("\n\r")))(i)
27}
28
29fn parse_unit<'a>(i: &'a str) -> IResult<&'a str, ()> {
30 let open = char('(');
31 let close = char(')');
32 let unit = tuple((open, close));
33 value((), unit)(i)
34}
35
36fn parse_bool(i: &str) -> IResult<&str, bool> {
37 let t = value(true, tag("true"));
38 let f = value(false, tag("false"));
39 alt((t, f)).parse(i)
40}
41
42fn parse_int<'a>(i: &'a str) -> IResult<&'a str, i128> {
43 map(recognize(many1(one_of("0123456789"))), |s: &str| {
44 s.parse::<i128>().unwrap()
45 })(i)
46}
47
48fn parse_name(i: &str) -> IResult<&str, &str> {
49 recognize(pair(
50 alt((alpha1, tag("_"))),
51 many0_count(alt((alphanumeric1, tag("_")))),
52 ))
53 .parse(i)
54}
55
56fn parse_ident(i: &str) -> IResult<&str, Identifier> {
57 map(parse_name, str::to_owned)(i)
58}
59
60fn parse_lit<'a>(i: &'a str) -> IResult<&'a str, Literal> {
61 alt((
62 map(parse_string, Literal::Str),
63 map(parse_int, Literal::Int),
64 map(parse_bool, Literal::Bool),
65 ))
66 .parse(i)
67}
68
69fn parse_cmp_op(i: &str) -> IResult<&str, CmpOp> {
70 alt((
71 value(CmpOp::Eq, tag("==")),
72 value(CmpOp::Neq, tag("!=")),
73 value(CmpOp::Gte, tag(">=")),
74 value(CmpOp::Lte, tag("<=")),
75 value(CmpOp::Gt, tag(">")),
76 value(CmpOp::Lt, tag("<")),
77 ))
78 .parse(i)
79}
80
81fn parse_assign_op(i: &str) -> IResult<&str, AssignOp> {
82 let parse_arith_op = alt((
83 value(ArithOp::Add, char('+')),
84 value(ArithOp::Sub, char('-')),
85 value(ArithOp::Mul, char('*')),
86 value(ArithOp::Div, char('/')),
87 value(ArithOp::Mod, char('%')),
88 ));
89 map(tuple((opt(parse_arith_op), char('='))), |(op, _)| {
90 AssignOp { op }
91 })(i)
92}
93
94fn parse_op<'a, E, T>(
95 op_str: &'static str,
96 op: T,
97) -> impl FnMut(&'a str) -> Result<(&'a str, T), nom::Err<E>>
98where
99 E: ParseError<&'a str>,
100 T: Copy,
101{
102 value(op, tag(op_str))
103}
104
105fn parse_binary<'a, P1, P2, P3, E>(
106 lhs: P1,
107 op: P2,
108 rhs: P3,
109) -> impl FnMut(&'a str) -> Result<(&'a str, Expr), nom::Err<E>>
110where
111 P1: Parser<&'a str, Expr, E>,
112 P2: Parser<&'a str, BinOp, E>,
113 P3: Parser<&'a str, Expr, E>,
114 E: ParseError<&'a str>,
115{
116 map(tuple((lhs, op, rhs)), |(l, o, r)| {
117 Expr::Bin(l.boxed(), o, r.boxed())
118 })
119}
120
121fn parse_assign<'a>(i: &'a str) -> IResult<&'a str, Expr> {
122 let op = map(parse_assign_op, BinOp::Assign);
123 let recursive = parse_binary(parse_atom, op, parse_assign);
124 let base = parse_union;
125 alt((recursive, base)).parse(i)
126}
127
128fn parse_union<'a>(i: &'a str) -> IResult<&'a str, Expr> {
129 let op = parse_op("||", BinOp::Logic(LogicOp::Or));
130 let recursive = parse_binary(parse_intersection, op, parse_union);
131 let base = parse_intersection;
132 alt((recursive, base)).parse(i)
133}
134
135fn parse_intersection<'a>(i: &'a str) -> IResult<&'a str, Expr> {
136 let op = parse_op("&&", BinOp::Logic(LogicOp::And));
137 let recursive = parse_binary(parse_negated, op, parse_intersection);
138 let base = parse_negated;
139 alt((recursive, base)).parse(i)
140}
141
142fn parse_negated<'a>(i: &'a str) -> IResult<&'a str, Expr> {
143 let op = parse_op("!", UnaryOp::Not);
144 let recursive = map(tuple((op, parse_rel)), |(op, expr)| {
145 Expr::Unary(expr.boxed(), op)
146 });
147 let base = parse_rel;
148 alt((recursive, base)).parse(i)
149}
150
151fn parse_rel<'a>(i: &'a str) -> IResult<&'a str, Expr> {
152 let op = map(parse_cmp_op, BinOp::Cmp);
153 let recursive = parse_binary(parse_sum, op, parse_rel);
154 let base = parse_sum;
155 alt((recursive, base)).parse(i)
156}
157
158fn parse_sum<'a>(i: &'a str) -> IResult<&'a str, Expr> {
159 let add = parse_op("+", BinOp::Arith(ArithOp::Add));
160 let sub = parse_op("-", BinOp::Arith(ArithOp::Sub));
161 let op = alt((add, sub));
162 let recursive = parse_binary(parse_mul, op, parse_sum);
163 let base = parse_mul;
164 alt((recursive, base)).parse(i)
165}
166
167fn parse_mul<'a>(i: &'a str) -> IResult<&'a str, Expr> {
168 let mul = parse_op("*", BinOp::Arith(ArithOp::Mul));
169 let div = parse_op("/", BinOp::Arith(ArithOp::Div));
170 let mod_ = parse_op("%", BinOp::Arith(ArithOp::Mod));
171 let op = alt((mul, div, mod_));
172 let recursive = parse_binary(parse_field_or_index, op, parse_mul);
173 let base = parse_field_or_index;
174 alt((recursive, base)).parse(i)
175}
176
177fn parse_field_or_index<'a>(i: &'a str) -> IResult<&'a str, Expr> {
178 enum FieldOrIndex {
179 Field(String),
180 Index(Expr),
181 }
182
183 let (i, base) = parse_atom(i)?;
184
185 let field = map(tuple((ws(char('.')), ws(parse_ident))), |(_, i)| {
186 FieldOrIndex::Field(i)
187 });
188 let index = map(
189 tuple((ws(char('[')), parse_expr, ws(char(']')))),
190 |(_, idx, _)| FieldOrIndex::Index(idx),
191 );
192
193 fold_many0(
194 alt((field, index)),
195 move || base.clone(),
196 move |acc, new| match new {
197 FieldOrIndex::Field(f) => Expr::FieldAccess(acc.boxed(), f),
198 FieldOrIndex::Index(idx) => Expr::Index(acc.boxed(), idx.boxed()),
199 },
200 )(i)
201}
202
203fn parse_list<'a>(i: &'a str) -> IResult<&'a str, List> {
204 let open = ws(char('['));
205 let items = separated_list0(char(','), parse_expr);
206 let close = ws(char(']'));
207 map(tuple((open, items, close)), |(_, items, _)| List { items }).parse(i)
208}
209
210fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> {
211 let inner = alt((
212 map(tag("node"), |_| Expr::Node),
213 map(parse_block, Expr::Block),
214 map(parse_if, Expr::If),
215 map(parse_call, Expr::Call),
216 map(parse_list, Expr::List),
217 map(parse_lit, Expr::Lit),
218 map(parse_ident, Expr::Ident),
219 map(parse_unit, |_| Expr::Unit),
220 ));
221 ws(inner).parse(i)
222}
223
224fn parse_call<'a>(i: &'a str) -> IResult<&'a str, Call> {
225 let ident = parse_ident;
226 let open = ws(char('('));
227 let args = separated_list0(char(','), parse_expr);
228 let close = ws(char(')'));
229 map(
230 tuple((ident, open, args, close)),
231 |(function, _, parameters, _)| Call {
232 function,
233 parameters,
234 },
235 )
236 .parse(i)
237}
238
239fn parse_block<'a>(i: &'a str) -> IResult<&'a str, Block> {
240 let open = ws(char('{'));
241 let statements = map(many0(parse_statement), |body| Block { body });
242 let close = ws(char('}'));
243 delimited(open, statements, close).parse(i)
244}
245
246fn parse_if<'a>(i: &'a str) -> IResult<&'a str, IfExpr> {
247 let if_ = delimited(multispace0, tag("if"), multispace1);
248
249 let open = char('(');
250 let condition = ws(parse_expr);
251 let close = terminated(char(')'), multispace0);
252
253 let then = parse_block;
254
255 let else_kw = ws(tag("else"));
256 let else_ = opt(preceded(else_kw, parse_block));
257
258 map(
259 tuple((if_, open, condition, close, then, else_)),
260 |(_, _, condition, _, then, else_)| IfExpr {
261 condition: condition.boxed(),
262 then,
263 else_: else_.unwrap_or_default(),
264 },
265 )(i)
266}
267
268fn parse_expr<'a>(i: &'a str) -> IResult<&'a str, Expr> {
269 parse_assign.parse(i)
270}
271
272fn parse_bare<'a>(i: &'a str) -> IResult<&'a str, Expr> {
273 parse_expr(i)
274}
275
276fn parse_type<'a>(i: &'a str) -> IResult<&'a str, Type> {
277 let int = value(Type::Integer, tag("int"));
278 let string = value(Type::String, tag("string"));
279 let bool_ = value(Type::Boolean, tag("bool"));
280 let list = value(Type::List, tag("list"));
281 alt((int, string, bool_, list)).parse(i)
282}
283
284fn parse_declaration<'a>(i: &'a str) -> IResult<&'a str, Declaration> {
285 let ty = parse_type;
286 let name = parse_ident;
287 let op = ws(char('='));
288 let init = opt(preceded(op, map(parse_expr, Expr::boxed)));
289 map(
290 tuple((ty, multispace0, name, init)),
291 |(ty, _, name, init)| Declaration { ty, name, init },
292 )(i)
293}
294
295fn parse_statement<'a>(i: &'a str) -> IResult<&'a str, Statement> {
296 let semicolon = ws(char(';'));
297 let inner = alt((
298 map(parse_declaration, Statement::Declaration),
299 map(parse_bare, Statement::Bare),
300 ));
301 terminated(inner, semicolon).parse(i)
302}
303
304// pub fn skip_query(mut i: &str) -> IResult<&str, ()> {
305// let mut paren_depth = 0;
306// let mut in_string = false;
307// let mut in_escape = false;
308// let mut in_comment = false;
309// loop {
310// let ch = i
311// .chars()
312// .next()
313// .ok_or(nom::Err::Error(nom::error::Error::new(
314// i,
315// nom::error::ErrorKind::Eof,
316// )))?;
317// if in_escape {
318// in_escape = false;
319// } else if in_string {
320// match ch {
321// '\\' => {
322// in_escape = true;
323// }
324// '"' | '\n' => {
325// in_string = false;
326// }
327// _ => {}
328// }
329// } else if in_comment {
330// if ch == '\n' {
331// in_comment = false;
332// }
333// } else {
334// match ch {
335// '"' => in_string = true,
336// '(' => paren_depth += 1,
337// ')' => {
338// if paren_depth > 0 {
339// paren_depth -= 1;
340// }
341// }
342// '{' => return Ok((i, ())),
343// ';' => in_comment = true,
344// _ => {}
345// }
346// }
347// i = &i[1..];
348// }
349// }
350
351// fn parse_query<'a>(
352// language: tree_sitter::Language,
353// ) -> impl FnMut(&'a str) -> IResult<&'a str, Query> {
354// return move |initial: &'a str| {
355// let query_start = 0;
356// let (skipped, _) = skip_query(initial)?;
357// let query_end = initial.len() - skipped.len();
358// let query_source = &initial[query_start..query_end].to_owned();
359//
360// let query = Query::new(language, &query_source).map_err(|mut _e| {
361// nom::Err::Error(nom::error::Error::new(initial, nom::error::ErrorKind::Fail))
362// })?;
363// Ok((skipped, query))
364// };
365// }
366
367fn parse_modifier<'a>(i: &str) -> IResult<&str, Modifier> {
368 let pre = value(Modifier::Enter, tag("enter"));
369 let post = value(Modifier::Leave, tag("leave"));
370 map(opt(alt((pre, post))), Option::unwrap_or_default)(i)
371}
372
373fn parse_pattern<'a>(i: &str) -> IResult<&str, Pattern> {
374 let begin = value(Pattern::Begin, ws(tag("BEGIN")));
375 let end = value(Pattern::End, ws(tag("END")));
376 ws(alt((begin, end, parse_tree_pattern))).parse(i)
377}
378
379// fn parse_node_pattern<'a>(i: &str) -> IResult<&str, Pattern> {
380// map(
381// tuple((parse_modifier, multispace0, parse_ident)),
382// |(modifier, _, kind)| Pattern::Node(NodePattern { modifier, kind }),
383// )
384// .parse(i)
385// }
386
387fn parse_tree_pattern<'a>(i: &str) -> IResult<&str, Pattern> {
388 let parse_matcher = alt((parse_tree_atom, parse_tree_list));
389 tuple((parse_modifier, multispace0, parse_matcher))
390 .map(|(modifier, _, matcher)| Pattern::Tree { modifier, matcher })
391 .parse(i)
392}
393
394fn parse_tree_atom<'a>(i: &str) -> IResult<&str, TreePattern> {
395 parse_ident.map(TreePattern::Atom).parse(i)
396}
397
398fn parse_tree_list<'a>(i: &str) -> IResult<&str, TreePattern> {
399 let open = terminated(char('('), multispace0);
400 let close = preceded(multispace0, char(')'));
401 let list = separated_list1(multispace1, alt((parse_tree_atom, parse_tree_list)));
402 tuple((open, list, close))
403 .map(|(_, list, _)| TreePattern::List(list))
404 .parse(i)
405}
406
407pub fn parse_stanza<'a>(i: &str) -> IResult<&str, Stanza> {
408 map(
409 tuple((parse_pattern, parse_block)),
410 |(pattern, statements)| Stanza {
411 pattern,
412 statements,
413 },
414 )(i)
415}
416
417pub fn parse_file(i: &str) -> IResult<&str, Vec<Stanza>> {
418 many0(parse_stanza).parse(i)
419}
420
421#[cfg(test)]
422mod test {
423 use super::*;
424
425 // test helpers
426 impl Expr {
427 pub fn int(int: i128) -> Expr {
428 Self::Lit(Literal::Int(int))
429 }
430
431 pub fn str(s: &str) -> Expr {
432 Self::Lit(Literal::Str(s.to_owned()))
433 }
434
435 pub const fn false_() -> Expr {
436 Self::Lit(Literal::Bool(false))
437 }
438
439 pub const fn true_() -> Expr {
440 Self::Lit(Literal::Bool(true))
441 }
442 }
443
444 #[test]
445 fn test_parse_unit() {
446 assert_eq!(parse_unit("()"), Ok(("", ())))
447 }
448
449 #[test]
450 fn test_parse_int() {
451 assert_eq!(parse_int("123456"), Ok(("", 123456)));
452 assert_eq!(parse_int("00123456"), Ok(("", 123456)));
453 }
454
455 #[test]
456 fn test_parse_bool() {
457 assert_eq!(parse_bool("true"), Ok(("", true)));
458 assert_eq!(parse_bool("false"), Ok(("", false)));
459 }
460
461 #[test]
462 fn test_parse_name() {
463 assert_eq!(parse_name("true"), Ok(("", "true")));
464 assert_eq!(parse_name("_abc"), Ok(("", "_abc")));
465 }
466
467 #[test]
468 fn test_parse_literal() {
469 assert_eq!(
470 parse_lit(r#""foobarbaz""#),
471 Ok(("", Literal::Str("foobarbaz".to_owned())))
472 );
473 assert_eq!(parse_lit("123"), Ok(("", Literal::Int(123))));
474 assert_eq!(parse_lit("true"), Ok(("", Literal::Bool(true))));
475 }
476
477 #[test]
478 fn test_parse_expr() {
479 assert_eq!(parse_expr(" () "), Ok(("", Expr::Unit)));
480 assert_eq!(parse_expr(" 55 "), Ok(("", Expr::int(55))));
481 assert_eq!(
482 parse_expr(" true || true "),
483 Ok((
484 "",
485 Expr::Bin(
486 Expr::true_().boxed(),
487 BinOp::Logic(LogicOp::Or),
488 Expr::true_().boxed()
489 )
490 ))
491 );
492 assert_eq!(
493 parse_expr("true || false && 5 == 5 "),
494 Ok((
495 "",
496 Expr::Bin(
497 Expr::true_().boxed(),
498 BinOp::Logic(LogicOp::Or),
499 Expr::Bin(
500 Expr::false_().boxed(),
501 BinOp::Logic(LogicOp::And),
502 Expr::Bin(
503 Expr::int(5).boxed(),
504 BinOp::Cmp(CmpOp::Eq),
505 Expr::int(5).boxed(),
506 )
507 .boxed()
508 )
509 .boxed()
510 )
511 ))
512 );
513 assert_eq!(
514 parse_expr(" foo ( 1, 2,3 , 1 == 1)"),
515 Ok((
516 "",
517 Expr::Call(Call {
518 function: "foo".to_owned(),
519 parameters: vec![
520 Expr::int(1),
521 Expr::int(2),
522 Expr::int(3),
523 Expr::Bin(
524 Expr::int(1).boxed(),
525 BinOp::Cmp(CmpOp::Eq),
526 Expr::int(1).boxed()
527 )
528 ],
529 })
530 ))
531 );
532 assert_eq!(
533 parse_expr("a = b"),
534 Ok((
535 "",
536 Expr::Bin(
537 Expr::Ident("a".to_owned()).boxed(),
538 BinOp::Assign(AssignOp { op: None }),
539 Expr::Ident("b".to_owned()).boxed(),
540 )
541 ))
542 );
543 assert_eq!(
544 parse_expr(" a += 4 + 5"),
545 Ok((
546 "",
547 Expr::Bin(
548 Expr::Ident("a".to_owned()).boxed(),
549 BinOp::Assign(AssignOp {
550 op: Some(ArithOp::Add)
551 }),
552 Expr::Bin(
553 Expr::int(4).boxed(),
554 BinOp::Arith(ArithOp::Add),
555 Expr::int(5).boxed(),
556 )
557 .boxed()
558 )
559 ))
560 );
561 assert_eq!(
562 parse_expr("a[0]"),
563 Ok((
564 "",
565 Expr::Index(Expr::Ident("a".to_owned()).boxed(), Expr::int(0).boxed())
566 ))
567 );
568 assert_eq!(
569 parse_expr("children(node)[0]"),
570 Ok((
571 "",
572 Expr::Index(
573 Expr::Call(Call {
574 function: "children".to_owned(),
575 parameters: vec![Expr::Node]
576 })
577 .boxed(),
578 Expr::int(0).boxed()
579 )
580 ))
581 );
582 }
583
584 #[test]
585 fn test_parse_statement() {
586 assert_eq!(
587 parse_statement("true;"),
588 Ok(("", Statement::Bare(Expr::true_())))
589 );
590 assert_eq!(
591 parse_statement("true ; "),
592 Ok(("", Statement::Bare(Expr::true_())))
593 );
594 assert_eq!(
595 parse_statement("int a ; "),
596 Ok((
597 "",
598 Statement::Declaration(Declaration {
599 ty: Type::Integer,
600 name: "a".to_owned(),
601 init: None
602 })
603 ))
604 );
605 assert_eq!(
606 parse_statement("int a =5 ; "),
607 Ok((
608 "",
609 Statement::Declaration(Declaration {
610 ty: Type::Integer,
611 name: "a".to_owned(),
612 init: Some(Expr::int(5).boxed())
613 })
614 ))
615 );
616 assert_eq!(
617 parse_statement(r#"list a =["a", "b", "c"]; "#),
618 Ok((
619 "",
620 Statement::Declaration(Declaration {
621 ty: Type::List,
622 name: "a".to_owned(),
623 init: Some(
624 Expr::List(List {
625 items: vec![Expr::str("a"), Expr::str("b"), Expr::str("c"),]
626 })
627 .boxed()
628 )
629 })
630 ))
631 );
632 }
633
634 #[test]
635 fn test_parse_block() {
636 assert_eq!(
637 parse_expr(
638 r#"
639 {
640 true;
641 1;
642 }
643 "#
644 ),
645 Ok((
646 "",
647 Expr::Block(Block {
648 body: vec![
649 Statement::Bare(Expr::true_()),
650 Statement::Bare(Expr::int(1)),
651 ]
652 })
653 ))
654 );
655 }
656
657 #[test]
658 fn test_parse_node() {
659 assert_eq!(parse_expr(r#" node "#), Ok(("", Expr::Node)));
660 assert_eq!(
661 parse_expr(r#" node.foo "#),
662 Ok(("", Expr::FieldAccess(Expr::Node.boxed(), "foo".to_owned())))
663 );
664 assert_eq!(
665 parse_expr(
666 r#" node
667 .foo
668 .bar"#
669 ),
670 Ok((
671 "",
672 Expr::FieldAccess(
673 Expr::FieldAccess(Expr::Node.boxed(), "foo".to_owned()).boxed(),
674 "bar".to_owned()
675 )
676 ))
677 );
678 }
679
680 #[test]
681 fn test_parse_if() {
682 assert_eq!(
683 parse_expr(
684 r#"
685 if (1 == true) {
686 5;
687 } else {
688 10;
689 }
690 "#
691 ),
692 Ok((
693 "",
694 Expr::If(IfExpr {
695 condition: Expr::Bin(
696 Expr::int(1).boxed(),
697 BinOp::Cmp(CmpOp::Eq),
698 Expr::true_().boxed()
699 )
700 .boxed(),
701 then: Block {
702 body: vec![Statement::Bare(Expr::int(5)),]
703 },
704 else_: Block {
705 body: vec![Statement::Bare(Expr::int(10)),]
706 }
707 })
708 ))
709 );
710 }
711
712 #[test]
713 fn test_parse_index() {
714 assert_eq!(
715 parse_expr(
716 r#"
717 a[0]
718 "#
719 ),
720 Ok((
721 "",
722 Expr::Index(Expr::Ident("a".to_owned()).boxed(), Expr::int(0).boxed()),
723 ))
724 );
725 assert_eq!(
726 parse_expr(r#"node.children[idx]"#),
727 Ok((
728 "",
729 Expr::Index(
730 Expr::FieldAccess(Expr::Node.boxed(), Identifier::from("children")).boxed(),
731 Expr::Ident("idx".to_owned()).boxed()
732 )
733 ))
734 );
735 assert_eq!(
736 parse_expr(r#"foo[i].bar[j]"#),
737 Ok((
738 "",
739 Expr::Index(
740 Expr::FieldAccess(
741 Expr::Index(
742 Expr::Ident("foo".to_owned()).boxed(),
743 Expr::Ident("i".to_owned()).boxed()
744 )
745 .boxed(),
746 "bar".to_owned()
747 )
748 .boxed(),
749 Expr::Ident("j".to_owned()).boxed()
750 ),
751 ))
752 );
753 }
754
755 // #[test]
756 // fn test_skip_query() {
757 // assert_eq!(
758 // skip_query(
759 // r#"(heading
760 // (paragraph) @foo) {}"#
761 // ),
762 // Ok(("{}", ()))
763 // );
764 // }
765
766 #[test]
767 fn test_parse_pattern() {
768 assert_eq!(
769 parse_pattern("enter function_definition"),
770 Ok((
771 "",
772 Pattern::Tree {
773 modifier: Modifier::Enter,
774 matcher: TreePattern::Atom("function_definition".to_owned()),
775 }
776 ))
777 );
778 assert_eq!(
779 parse_pattern("function_definition"),
780 Ok((
781 "",
782 Pattern::Tree {
783 modifier: Modifier::Enter,
784 matcher: TreePattern::Atom("function_definition".to_owned()),
785 }
786 ))
787 );
788 assert_eq!(
789 parse_pattern("leave function_definition"),
790 Ok((
791 "",
792 Pattern::Tree {
793 modifier: Modifier::Leave,
794 matcher: TreePattern::Atom("function_definition".to_owned()),
795 }
796 ))
797 );
798 }
799
800 // #[test]
801 // fn test_parse_stanza() {
802 // assert_eq!(
803 // parse_stanza("enter function_definition { true; }"),
804 // Ok((
805 // "",
806 // Stanza {
807 // pattern: Pattern::Node(NodePattern {
808 // modifier: Modifier::Enter,
809 // kind: "function_definition".to_owned()
810 // }),
811 // statements: Block {
812 // body: vec![Statement::Bare(Expr::true_())]
813 // }
814 // }
815 // ))
816 // );
817 // assert_eq!(
818 // parse_stanza("BEGIN { true; }"),
819 // Ok((
820 // "",
821 // Stanza {
822 // pattern: Pattern::Begin,
823 // statements: Block {
824 // body: vec![Statement::Bare(Expr::true_())]
825 // }
826 // }
827 // ))
828 // );
829 // assert_eq!(
830 // parse_block(
831 // " {
832 // true;
833 // }"
834 // ),
835 // Ok((
836 // "",
837 // Block {
838 // body: vec![Statement::Bare(Expr::true_())]
839 // }
840 // ))
841 // );
842 // }
843
844 #[test]
845 fn test_parse_if_statement_regression() {
846 assert_eq!(
847 parse_statement("if (true) { true; };"),
848 Ok((
849 "",
850 Statement::Bare(Expr::If(IfExpr {
851 condition: Expr::true_().boxed(),
852 then: Block {
853 body: vec![Statement::Bare(Expr::true_())]
854 },
855 else_: Block::default(),
856 }))
857 ))
858 );
859 assert_eq!(
860 parse_expr("if (true) { true; } else { true; }"),
861 Ok((
862 "",
863 Expr::If(IfExpr {
864 condition: Expr::true_().boxed(),
865 then: Block {
866 body: vec![Statement::Bare(Expr::true_())]
867 },
868 else_: Block {
869 body: vec![Statement::Bare(Expr::true_())]
870 },
871 })
872 ))
873 );
874 }
875 #[test]
876 fn test_parse_tree_pattern() {
877 assert_eq!(
878 parse_tree_pattern("enter foo"),
879 Ok((
880 "",
881 Pattern::Tree {
882 modifier: Modifier::Enter,
883 matcher: TreePattern::Atom("foo".to_owned())
884 }
885 ))
886 );
887 assert_eq!(
888 parse_tree_pattern("enter (foo)"),
889 Ok((
890 "",
891 Pattern::Tree {
892 modifier: Modifier::Enter,
893 matcher: TreePattern::List(vec![TreePattern::Atom("foo".to_owned())])
894 }
895 ))
896 );
897 assert_eq!(
898 parse_tree_pattern("leave (foo bar baz)"),
899 Ok((
900 "",
901 Pattern::Tree {
902 modifier: Modifier::Leave,
903 matcher: TreePattern::List(vec![
904 TreePattern::Atom("foo".to_owned()),
905 TreePattern::Atom("bar".to_owned()),
906 TreePattern::Atom("baz".to_owned()),
907 ])
908 }
909 ))
910 );
911 assert_eq!(
912 parse_tree_pattern("leave (foo (bar quux) baz)"),
913 Ok((
914 "",
915 Pattern::Tree {
916 modifier: Modifier::Leave,
917 matcher: TreePattern::List(vec![
918 TreePattern::Atom("foo".to_owned()),
919 TreePattern::List(vec![
920 TreePattern::Atom("bar".to_owned()),
921 TreePattern::Atom("quux".to_owned())
922 ]),
923 TreePattern::Atom("baz".to_owned()),
924 ])
925 }
926 ))
927 );
928 assert_eq!(
929 parse_tree_pattern("enter ( foo (bar quux ) baz)"),
930 Ok((
931 "",
932 Pattern::Tree {
933 modifier: Modifier::Enter,
934 matcher: TreePattern::List(vec![
935 TreePattern::Atom("foo".to_owned()),
936 TreePattern::List(vec![
937 TreePattern::Atom("bar".to_owned()),
938 TreePattern::Atom("quux".to_owned())
939 ]),
940 TreePattern::Atom("baz".to_owned()),
941 ])
942 }
943 ))
944 );
945 assert!(parse_tree_pattern("( )").is_err());
946 assert!(parse_tree_pattern("()").is_err());
947 }
948}