Allow for shorter app headers

This commit is contained in:
Richard Feldman 2020-11-18 23:55:57 -05:00
parent ecfdadb5e3
commit 1868051105
6 changed files with 57 additions and 22 deletions

View file

@ -76,13 +76,19 @@ pub struct InterfaceHeader<'a> {
pub after_imports: &'a [CommentOrNewline<'a>],
}
#[derive(Clone, Debug, PartialEq)]
pub enum To<'a> {
ExistingPackage(&'a str),
NewPackage(PackageOrPath<'a>),
}
#[derive(Clone, Debug, PartialEq)]
pub struct AppHeader<'a> {
pub name: Loc<StrLiteral<'a>>,
pub packages: Vec<'a, Loc<PackageEntry<'a>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
pub to: Loc<&'a str>,
pub to: Loc<To<'a>>,
// Potential comments and newlines - these will typically all be empty.
pub after_app_keyword: &'a [CommentOrNewline<'a>],
@ -256,7 +262,7 @@ pub fn package_entry<'a>() -> impl Parser<'a, PackageEntry<'a>> {
}
}
fn package_or_path<'a>() -> impl Parser<'a, PackageOrPath<'a>> {
pub fn package_or_path<'a>() -> impl Parser<'a, PackageOrPath<'a>> {
map!(
either!(
string_literal::parse(),

View file

@ -2,13 +2,14 @@ use crate::ast::{Attempting, CommentOrNewline, Def, Module};
use crate::blankspace::{space0, space0_around, space0_before, space1};
use crate::expr::def;
use crate::header::{
package_entry, AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName,
PackageEntry, PackageName, PlatformHeader, TypedIdent,
package_entry, package_or_path, AppHeader, Effects, ExposesEntry, ImportsEntry,
InterfaceHeader, ModuleName, PackageEntry, PackageName, PackageOrPath, PlatformHeader, To,
TypedIdent,
};
use crate::ident::{lowercase_ident, unqualified_ident, uppercase_ident};
use crate::parser::{
self, ascii_char, ascii_string, loc, optional, peek_utf8_char, peek_utf8_char_at, unexpected,
unexpected_eof, ParseResult, Parser, State,
unexpected_eof, Either, ParseResult, Parser, State,
};
use crate::string_literal;
use crate::type_annotation;
@ -293,7 +294,7 @@ pub fn module_defs<'a>() -> impl Parser<'a, Vec<'a, Located<Def<'a>>>> {
struct ProvidesTo<'a> {
entries: Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
to: Located<&'a str>,
to: Located<To<'a>>,
before_provides_keyword: &'a [CommentOrNewline<'a>],
after_provides_keyword: &'a [CommentOrNewline<'a>],
@ -316,14 +317,30 @@ fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>> {
),
and!(
space1(1),
skip_first!(ascii_string("to"), and!(space1(1), loc!(lowercase_ident())))
skip_first!(
ascii_string("to"),
and!(
space1(1),
loc!(either!(lowercase_ident(), package_or_path()))
)
)
)
)
),
|(
(before_provides_keyword, after_provides_keyword),
(entries, (before_to_keyword, (after_to_keyword, to))),
(entries, (before_to_keyword, (after_to_keyword, loc_to))),
)| {
let loc_to: Located<Either<&'a str, PackageOrPath<'a>>> = loc_to;
let to_val = match loc_to.value {
Either::First(pkg) => To::ExistingPackage(pkg),
Either::Second(pkg) => To::NewPackage(pkg),
};
let to = Located {
value: to_val,
region: loc_to.region,
};
ProvidesTo {
entries,
to,