Merge pull request #153 from rtfeldman/parser-fixes

Fix parsing tags that have multiple arguments
This commit is contained in:
Richard Feldman 2020-01-18 18:59:42 -05:00 committed by GitHub
commit d0c02af6ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 12 deletions

View File

@ -44,10 +44,7 @@ macro_rules! tag_union {
pub fn term<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>> {
one_of!(
// The `*` type variable, e.g. in (List *) Wildcard,
map!(loc!(char('*')), |loc_val: Located<()>| {
loc_val.map(|_| TypeAnnotation::Wildcard)
}),
loc_wildcard(),
loc_parenthetical_type(min_indent),
loc!(record_type(min_indent)),
loc!(tag_union!(min_indent)),
@ -56,6 +53,24 @@ pub fn term<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>>
)
}
/// The `*` type variable, e.g. in (List *) Wildcard,
fn loc_wildcard<'a>() -> impl Parser<'a, Located<TypeAnnotation<'a>>> {
map!(loc!(char('*')), |loc_val: Located<()>| {
loc_val.map(|_| TypeAnnotation::Wildcard)
})
}
pub fn loc_applied_arg<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>> {
one_of!(
loc_wildcard(),
loc_parenthetical_type(min_indent),
loc!(record_type(min_indent)),
loc!(tag_union!(min_indent)),
loc!(parse_concrete_type),
loc!(parse_type_variable)
)
}
#[inline(always)]
fn loc_parenthetical_type<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>> {
between!(
@ -77,7 +92,7 @@ fn tag_type<'a>(min_indent: u16) -> impl Parser<'a, Tag<'a>> {
// Optionally parse space-separated arguments for the constructor,
// e.g. `ok err` in `Result ok err`
zero_or_more!(space1_before(
move |arena, state| term(min_indent).parse(arena, state),
move |arena, state| loc_applied_arg(min_indent).parse(arena, state),
min_indent,
))
),
@ -129,7 +144,7 @@ fn applied_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>> {
// Optionally parse space-separated arguments for the constructor,
// e.g. `Str Float` in `Map Str Float`
zero_or_more!(space1_before(
move |arena, state| term(min_indent).parse(arena, state),
move |arena, state| loc_applied_arg(min_indent).parse(arena, state),
min_indent,
))
),

View File

@ -1373,24 +1373,25 @@ mod test_parse {
name: Located::new(0, 0, 8, 13, "@True"),
args: &[],
};
let tag2arg = Located::new(0, 0, 24, 29, TypeAnnotation::Apply(&[], "Thing", &[]));
let tag2args = bumpalo::vec![in &arena; tag2arg];
let tag2arg1 = Located::new(0, 0, 24, 27, TypeAnnotation::Apply(&[], "Two", &[]));
let tag2arg2 = Located::new(0, 0, 28, 34, TypeAnnotation::Apply(&[], "Things", &[]));
let tag2args = bumpalo::vec![in &arena; tag2arg1, tag2arg2];
let tag2 = Tag::Private {
name: Located::new(0, 0, 15, 23, "@Perhaps"),
args: tag2args.into_bump_slice(),
};
let tags = bumpalo::vec![in &arena;
Located::new(0, 0, 8, 13, tag1),
Located::new(0, 0, 15, 29, tag2)
Located::new(0, 0, 15, 34, tag2)
];
let loc_wildcard = Located::new(0, 0, 31, 32, TypeAnnotation::Wildcard);
let loc_wildcard = Located::new(0, 0, 36, 37, TypeAnnotation::Wildcard);
let applied_ann = TypeAnnotation::TagUnion {
tags: tags.into_bump_slice(),
ext: Some(arena.alloc(loc_wildcard)),
};
let signature = Def::Annotation(
Located::new(0, 0, 0, 3, Identifier("foo")),
Located::new(0, 0, 6, 32, applied_ann),
Located::new(0, 0, 6, 37, applied_ann),
);
let def = Def::Body(
arena.alloc(Located::new(1, 1, 0, 3, Identifier("foo"))),
@ -1408,7 +1409,7 @@ mod test_parse {
assert_parses_to(
indoc!(
r#"
foo : [ @True, @Perhaps Thing ]*
foo : [ @True, @Perhaps Two Things ]*
foo = True
42