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 discard;
|
||||||
mod int;
|
mod int;
|
||||||
mod list;
|
mod list;
|
||||||
|
mod pair;
|
||||||
mod tuple;
|
mod tuple;
|
||||||
mod var;
|
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::{
|
use crate::{
|
||||||
ast::UntypedPattern,
|
ast::UntypedPattern,
|
||||||
parser::{error::ParseError, token::Token},
|
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> {
|
pub fn parser() -> impl Parser<Token, UntypedPattern, Error = ParseError> {
|
||||||
recursive(|expression| {
|
recursive(|pattern| {
|
||||||
choice((
|
choice((
|
||||||
var(expression.clone()),
|
var(pattern.clone()),
|
||||||
constructor(expression.clone()),
|
pair(pattern.clone()),
|
||||||
|
constructor(pattern.clone()),
|
||||||
discard(),
|
discard(),
|
||||||
int(),
|
int(),
|
||||||
tuple(expression.clone()),
|
tuple(pattern.clone()),
|
||||||
list(expression),
|
list(pattern),
|
||||||
))
|
))
|
||||||
.then(
|
.then(
|
||||||
just(Token::As)
|
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