Skip to content

Commit

Permalink
Add parser for 'Pair' pattern
Browse files Browse the repository at this point in the history
  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.
  • Loading branch information
KtorZ authored and MicroProofs committed May 3, 2024
1 parent 8c1a0f1 commit c1aa795
Show file tree
Hide file tree
Showing 13 changed files with 374 additions and 10 deletions.
82 changes: 72 additions & 10 deletions crates/aiken-lang/src/parser/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,32 @@ mod constructor;
mod discard;
mod int;
mod list;
mod pair;
mod tuple;
mod 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;

use crate::{
ast::UntypedPattern,
parser::{error::ParseError, token::Token},
};

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)
Expand All @@ -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, ..]");
}
}
25 changes: 25 additions & 0 deletions crates/aiken-lang/src/parser/pattern/pair.rs
Original file line number Diff line number Diff line change
@@ -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,
})
}
Original file line number Diff line number Diff line change
@@ -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: (),
}
Original file line number Diff line number Diff line change
@@ -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: (),
}
Original file line number Diff line number Diff line change
@@ -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: (),
}
Original file line number Diff line number Diff line change
@@ -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: (),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
source: crates/aiken-lang/src/parser/pattern/mod.rs
description: "Code:\n\n_foo"
---
Discard {
name: "_foo",
location: 0..4,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
source: crates/aiken-lang/src/parser/pattern/mod.rs
description: "Code:\n\n_"
---
Discard {
name: "_",
location: 0..1,
}
Original file line number Diff line number Diff line change
@@ -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,
},
),
}
Original file line number Diff line number Diff line change
@@ -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,
},
}
Original file line number Diff line number Diff line change
@@ -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 comments on commit c1aa795

Please sign in to comment.