diff --git a/compiler/parse/src/ast.rs b/compiler/parse/src/ast.rs index 91583fa2fd..d24ea05ad7 100644 --- a/compiler/parse/src/ast.rs +++ b/compiler/parse/src/ast.rs @@ -36,9 +36,14 @@ pub struct WhenBranch<'a> { #[derive(Clone, Debug, PartialEq)] pub struct AppHeader<'a> { + pub name: Loc>, + pub provides: Vec<'a, Loc>>, pub imports: Vec<'a, Loc>>, // Potential comments and newlines - these will typically all be empty. + pub after_interface: &'a [CommentOrNewline<'a>], + pub before_provides: &'a [CommentOrNewline<'a>], + pub after_provides: &'a [CommentOrNewline<'a>], pub before_imports: &'a [CommentOrNewline<'a>], pub after_imports: &'a [CommentOrNewline<'a>], } diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index 3a4067749b..6f9e151b71 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -127,9 +127,30 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>> { #[inline(always)] fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { - move |_, _| { - panic!("TODO parse app header"); - } + parser::map( + and!( + skip_first!(string("app"), and!(space1(1), loc!(module_name()))), + and!(provides(), imports()) + ), + |( + (after_interface, name), + ( + ((before_provides, after_provides), provides), + ((before_imports, after_imports), imports), + ), + )| { + AppHeader { + name, + provides, + imports, + after_interface, + before_provides, + after_provides, + before_imports, + after_imports, + } + }, + ) } #[inline(always)] @@ -137,6 +158,20 @@ pub fn module_defs<'a>() -> impl Parser<'a, Vec<'a, Located>>> { zero_or_more!(space0_around(loc(def(0)), 0)) } +#[inline(always)] +fn provides<'a>() -> impl Parser< + 'a, + ( + (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), + Vec<'a, Located>>, + ), +> { + and!( + and!(skip_second!(space1(1), string("provides")), space1(1)), + collection!(char('['), loc!(exposes_entry()), char(','), char(']'), 1) + ) +} + #[inline(always)] fn exposes<'a>() -> impl Parser< 'a,