aiken_lang/parser/pattern/
mod.rs

1use chumsky::prelude::*;
2
3mod bytearray;
4mod constructor;
5mod discard;
6mod int;
7mod list;
8mod pair;
9mod string;
10mod tuple;
11mod var;
12
13use crate::{
14    ast::UntypedPattern,
15    parser::{error::ParseError, token::Token},
16};
17pub use bytearray::parser as bytearray;
18pub use constructor::parser as constructor;
19pub use discard::parser as discard;
20pub use int::parser as int;
21pub use list::parser as list;
22pub use pair::parser as pair;
23pub use string::parser as string;
24pub use tuple::parser as tuple;
25pub use var::parser as var;
26
27pub fn parser() -> impl Parser<Token, UntypedPattern, Error = ParseError> {
28    recursive(|pattern| {
29        choice((
30            pair(pattern.clone()),
31            constructor(pattern.clone()),
32            var(pattern.clone()),
33            discard(),
34            int(),
35            bytearray(),
36            tuple(pattern.clone()),
37            list(pattern),
38            string(),
39        ))
40        .then(
41            just(Token::As)
42                .ignore_then(select! { Token::Name {name} => name})
43                .or_not(),
44        )
45        .map_with_span(|(pattern, opt_as), span| {
46            if let Some(name) = opt_as {
47                UntypedPattern::Assign {
48                    name,
49                    location: span,
50                    pattern: Box::new(pattern),
51                }
52            } else {
53                pattern
54            }
55        })
56    })
57}
58
59#[cfg(test)]
60mod tests {
61    use crate::assert_pattern;
62
63    #[test]
64    fn pattern_var() {
65        assert_pattern!("foo");
66    }
67
68    #[test]
69    fn pattern_discard_unnamed() {
70        assert_pattern!("_");
71    }
72
73    #[test]
74    fn pattern_discard_named() {
75        assert_pattern!("_foo");
76    }
77
78    #[test]
79    fn pattern_pair_discards() {
80        assert_pattern!("Pair(_, _)");
81    }
82
83    #[test]
84    fn pattern_pair_explicit_depth_1() {
85        assert_pattern!("Pair(14, True)");
86    }
87
88    #[test]
89    fn pattern_pair_explicit_depth_2() {
90        assert_pattern!("Pair([1,2,3], Pair((14, 42), _))");
91    }
92
93    #[test]
94    fn pattern_constructor_no_labels() {
95        assert_pattern!("Foo(a, b)");
96    }
97
98    #[test]
99    fn pattern_constructor_labels() {
100        assert_pattern!("Foo { a, b }");
101    }
102
103    #[test]
104    fn pattern_constructor_spread() {
105        assert_pattern!("Foo { a, .. }");
106    }
107
108    #[test]
109    fn pattern_constructor_pair_interleaved() {
110        assert_pattern!("Foo(a, Pair(1, 2))");
111    }
112
113    #[test]
114    fn pattern_list_spread() {
115        assert_pattern!("[head, ..]");
116    }
117}