Add parser for 'Pair' pattern
And a few more tests along the way for others. Note that it is important here that we try to parse for a 'Pair' BEFORE we try to parse for a constructor pattern. Because the latter would swallow any Pair pattern.
This commit is contained in:
parent
91a7e77ab4
commit
5c59b816ea
|
@ -4,30 +4,32 @@ mod constructor;
|
|||
mod discard;
|
||||
mod int;
|
||||
mod list;
|
||||
mod pair;
|
||||
mod tuple;
|
||||
mod var;
|
||||
|
||||
pub use constructor::parser as constructor;
|
||||
pub use discard::parser as discard;
|
||||
pub use int::parser as int;
|
||||
pub use list::parser as list;
|
||||
pub use tuple::parser as tuple;
|
||||
pub use var::parser as var;
|
||||
|
||||
use crate::{
|
||||
ast::UntypedPattern,
|
||||
parser::{error::ParseError, token::Token},
|
||||
};
|
||||
pub use constructor::parser as constructor;
|
||||
pub use discard::parser as discard;
|
||||
pub use int::parser as int;
|
||||
pub use list::parser as list;
|
||||
pub use pair::parser as pair;
|
||||
pub use tuple::parser as tuple;
|
||||
pub use var::parser as var;
|
||||
|
||||
pub fn parser() -> impl Parser<Token, UntypedPattern, Error = ParseError> {
|
||||
recursive(|expression| {
|
||||
recursive(|pattern| {
|
||||
choice((
|
||||
var(expression.clone()),
|
||||
constructor(expression.clone()),
|
||||
var(pattern.clone()),
|
||||
pair(pattern.clone()),
|
||||
constructor(pattern.clone()),
|
||||
discard(),
|
||||
int(),
|
||||
tuple(expression.clone()),
|
||||
list(expression),
|
||||
tuple(pattern.clone()),
|
||||
list(pattern),
|
||||
))
|
||||
.then(
|
||||
just(Token::As)
|
||||
|
@ -47,3 +49,63 @@ pub fn parser() -> impl Parser<Token, UntypedPattern, Error = ParseError> {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::assert_pattern;
|
||||
|
||||
#[test]
|
||||
fn pattern_var() {
|
||||
assert_pattern!("foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_discard_unnamed() {
|
||||
assert_pattern!("_");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_discard_named() {
|
||||
assert_pattern!("_foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_pair_discards() {
|
||||
assert_pattern!("Pair(_, _)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_pair_explicit_depth_1() {
|
||||
assert_pattern!("Pair(14, True)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_pair_explicit_depth_2() {
|
||||
assert_pattern!("Pair([1,2,3], Pair((14, 42), _))");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_constructor_no_labels() {
|
||||
assert_pattern!("Foo(a, b)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_constructor_labels() {
|
||||
assert_pattern!("Foo { a, b }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_constructor_spread() {
|
||||
assert_pattern!("Foo { a, .. }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_constructor_pair_interleaved() {
|
||||
assert_pattern!("Foo(a, Pair(1, 2))");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_list_spread() {
|
||||
assert_pattern!("[head, ..]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
use crate::{
|
||||
ast::UntypedPattern,
|
||||
builtins::PAIR,
|
||||
parser::{error::ParseError, token::Token},
|
||||
};
|
||||
use chumsky::prelude::*;
|
||||
|
||||
pub fn parser(
|
||||
pattern: Recursive<'_, Token, UntypedPattern, ParseError>,
|
||||
) -> impl Parser<Token, UntypedPattern, Error = ParseError> + '_ {
|
||||
select! {Token::UpName { name } if name == PAIR => name}
|
||||
.ignore_then(choice((
|
||||
just(Token::LeftParen),
|
||||
just(Token::NewLineLeftParen),
|
||||
)))
|
||||
.then(pattern.clone())
|
||||
.then_ignore(just(Token::Comma))
|
||||
.then(pattern.clone())
|
||||
.then_ignore(just(Token::RightParen))
|
||||
.map_with_span(|((_name, fst), snd), location| UntypedPattern::Pair {
|
||||
fst: Box::new(fst),
|
||||
snd: Box::new(snd),
|
||||
location,
|
||||
})
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nFoo { a, b }"
|
||||
---
|
||||
Constructor {
|
||||
is_record: true,
|
||||
location: 0..12,
|
||||
name: "Foo",
|
||||
arguments: [
|
||||
CallArg {
|
||||
label: Some(
|
||||
"a",
|
||||
),
|
||||
location: 6..7,
|
||||
value: Var {
|
||||
location: 6..7,
|
||||
name: "a",
|
||||
},
|
||||
},
|
||||
CallArg {
|
||||
label: Some(
|
||||
"b",
|
||||
),
|
||||
location: 9..10,
|
||||
value: Var {
|
||||
location: 9..10,
|
||||
name: "b",
|
||||
},
|
||||
},
|
||||
],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nFoo(a, b)"
|
||||
---
|
||||
Constructor {
|
||||
is_record: false,
|
||||
location: 0..9,
|
||||
name: "Foo",
|
||||
arguments: [
|
||||
CallArg {
|
||||
label: None,
|
||||
location: 4..5,
|
||||
value: Var {
|
||||
location: 4..5,
|
||||
name: "a",
|
||||
},
|
||||
},
|
||||
CallArg {
|
||||
label: None,
|
||||
location: 7..8,
|
||||
value: Var {
|
||||
location: 7..8,
|
||||
name: "b",
|
||||
},
|
||||
},
|
||||
],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nFoo(a, Pair(1, 2))"
|
||||
---
|
||||
Constructor {
|
||||
is_record: false,
|
||||
location: 0..18,
|
||||
name: "Foo",
|
||||
arguments: [
|
||||
CallArg {
|
||||
label: None,
|
||||
location: 4..5,
|
||||
value: Var {
|
||||
location: 4..5,
|
||||
name: "a",
|
||||
},
|
||||
},
|
||||
CallArg {
|
||||
label: None,
|
||||
location: 7..17,
|
||||
value: Pair {
|
||||
location: 7..17,
|
||||
fst: Int {
|
||||
location: 12..13,
|
||||
value: "1",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
snd: Int {
|
||||
location: 15..16,
|
||||
value: "2",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nFoo { a, .. }"
|
||||
---
|
||||
Constructor {
|
||||
is_record: true,
|
||||
location: 0..13,
|
||||
name: "Foo",
|
||||
arguments: [
|
||||
CallArg {
|
||||
label: Some(
|
||||
"a",
|
||||
),
|
||||
location: 6..7,
|
||||
value: Var {
|
||||
location: 6..7,
|
||||
name: "a",
|
||||
},
|
||||
},
|
||||
],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: true,
|
||||
tipo: (),
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\n_foo"
|
||||
---
|
||||
Discard {
|
||||
name: "_foo",
|
||||
location: 0..4,
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\n_"
|
||||
---
|
||||
Discard {
|
||||
name: "_",
|
||||
location: 0..1,
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\n[head, ..]"
|
||||
---
|
||||
List {
|
||||
location: 0..10,
|
||||
elements: [
|
||||
Var {
|
||||
location: 1..5,
|
||||
name: "head",
|
||||
},
|
||||
],
|
||||
tail: Some(
|
||||
Discard {
|
||||
name: "_",
|
||||
location: 9..10,
|
||||
},
|
||||
),
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nPair(_, _)"
|
||||
---
|
||||
Pair {
|
||||
location: 0..10,
|
||||
fst: Discard {
|
||||
name: "_",
|
||||
location: 5..6,
|
||||
},
|
||||
snd: Discard {
|
||||
name: "_",
|
||||
location: 8..9,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nPair(14, True)"
|
||||
---
|
||||
Pair {
|
||||
location: 0..14,
|
||||
fst: Int {
|
||||
location: 5..7,
|
||||
value: "14",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
snd: Constructor {
|
||||
is_record: false,
|
||||
location: 9..13,
|
||||
name: "True",
|
||||
arguments: [],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
},
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nPair([1,2,3], Pair((14, 42), _))"
|
||||
---
|
||||
Pair {
|
||||
location: 0..32,
|
||||
fst: List {
|
||||
location: 5..12,
|
||||
elements: [
|
||||
Int {
|
||||
location: 6..7,
|
||||
value: "1",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
Int {
|
||||
location: 8..9,
|
||||
value: "2",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
Int {
|
||||
location: 10..11,
|
||||
value: "3",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
tail: None,
|
||||
},
|
||||
snd: Pair {
|
||||
location: 14..31,
|
||||
fst: Tuple {
|
||||
location: 19..27,
|
||||
elems: [
|
||||
Int {
|
||||
location: 20..22,
|
||||
value: "14",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
Int {
|
||||
location: 24..26,
|
||||
value: "42",
|
||||
base: Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
snd: Discard {
|
||||
name: "_",
|
||||
location: 29..30,
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/mod.rs
|
||||
description: "Code:\n\nfoo"
|
||||
---
|
||||
Var {
|
||||
location: 0..3,
|
||||
name: "foo",
|
||||
}
|
Loading…
Reference in New Issue