aiken_lang/parser/pattern/
mod.rs1use 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}