Finish introducing new header keywords

This commit is contained in:
Richard Feldman 2020-11-16 23:34:45 -05:00
parent ab1be6e394
commit a78434fd48
6 changed files with 404 additions and 210 deletions

View file

@ -1,7 +1,6 @@
use crate::header::{ModuleName, PackageName};
use crate::header::{AppHeader, ImportsEntry, InterfaceHeader, PlatformHeader, TypedIdent};
use crate::ident::Ident;
use bumpalo::collections::String;
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_module::operator::{BinOp, CalledVia, UnaryOp};
use roc_region::all::{Loc, Region};
@ -13,20 +12,6 @@ pub enum Module<'a> {
Platform { header: PlatformHeader<'a> },
}
#[derive(Clone, Debug, PartialEq)]
pub struct InterfaceHeader<'a> {
pub name: Loc<ModuleName<'a>>,
pub exposes: Vec<'a, Loc<ExposesEntry<'a>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
// Potential comments and newlines - these will typically all be empty.
pub after_interface_keyword: &'a [CommentOrNewline<'a>],
pub before_exposes: &'a [CommentOrNewline<'a>],
pub after_exposes: &'a [CommentOrNewline<'a>],
pub before_imports: &'a [CommentOrNewline<'a>],
pub after_imports: &'a [CommentOrNewline<'a>],
}
#[derive(Clone, Debug, PartialEq)]
pub struct WhenBranch<'a> {
pub patterns: &'a [Loc<Pattern<'a>>],
@ -34,94 +19,6 @@ pub struct WhenBranch<'a> {
pub guard: Option<Loc<Expr<'a>>>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct AppHeader<'a> {
pub name: Loc<ModuleName<'a>>,
pub provides: Vec<'a, Loc<ExposesEntry<'a>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
// Potential comments and newlines - these will typically all be empty.
pub after_app_keyword: &'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>],
}
#[derive(Clone, Debug, PartialEq)]
pub struct PlatformHeader<'a> {
pub name: Loc<PackageName<'a>>,
pub provides: Vec<'a, Loc<ExposesEntry<'a>>>,
pub requires: Vec<'a, Loc<TypedIdent<'a>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
pub effects: Effects<'a>,
// Potential comments and newlines - these will typically all be empty.
pub after_platform_keyword: &'a [CommentOrNewline<'a>],
pub before_provides: &'a [CommentOrNewline<'a>],
pub after_provides: &'a [CommentOrNewline<'a>],
pub before_requires: &'a [CommentOrNewline<'a>],
pub after_requires: &'a [CommentOrNewline<'a>],
pub before_imports: &'a [CommentOrNewline<'a>],
pub after_imports: &'a [CommentOrNewline<'a>],
}
#[derive(Clone, Debug, PartialEq)]
pub struct Effects<'a> {
pub spaces_before_effects_keyword: &'a [CommentOrNewline<'a>],
pub spaces_after_effects_keyword: &'a [CommentOrNewline<'a>],
pub spaces_after_type_name: &'a [CommentOrNewline<'a>],
pub type_name: &'a str,
pub entries: Vec<'a, Loc<TypedIdent<'a>>>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum TypedIdent<'a> {
/// e.g.
///
/// printLine : Str -> Effect {}
Entry {
ident: Loc<&'a str>,
spaces_before_colon: &'a [CommentOrNewline<'a>],
ann: Loc<TypeAnnotation<'a>>,
},
// Spaces
SpaceBefore(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]),
}
#[derive(Clone, Debug, PartialEq)]
pub enum ExposesEntry<'a> {
/// e.g. `Task`
Ident(&'a str),
// Spaces
SpaceBefore(&'a ExposesEntry<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a ExposesEntry<'a>, &'a [CommentOrNewline<'a>]),
}
#[derive(Clone, Debug, PartialEq)]
pub enum ImportsEntry<'a> {
/// e.g. `Task` or `Task.{ Task, after }`
Module(ModuleName<'a>, Vec<'a, Loc<ExposesEntry<'a>>>),
// Spaces
SpaceBefore(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]),
}
impl<'a> ExposesEntry<'a> {
pub fn as_str(&'a self) -> &'a str {
use ExposesEntry::*;
match self {
Ident(string) => string,
SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => sub_entry.as_str(),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct WhenPattern<'a> {
pub pattern: Loc<Pattern<'a>>,
@ -633,15 +530,6 @@ impl<'a> Spaceable<'a> for TypeAnnotation<'a> {
}
}
impl<'a> Spaceable<'a> for ExposesEntry<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
ExposesEntry::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
ExposesEntry::SpaceAfter(self, spaces)
}
}
impl<'a> Spaceable<'a> for ImportsEntry<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
ImportsEntry::SpaceBefore(self, spaces)

View file

@ -1,15 +1,43 @@
use crate::ast::CommentOrNewline;
use crate::ast::{CommentOrNewline, Spaceable, StrLiteral, TypeAnnotation};
use crate::blankspace::space0;
use crate::ident::lowercase_ident;
use crate::module::package_name;
use crate::parser::{ascii_char, optional, Either, Parser};
use crate::string_literal;
use bumpalo::collections::Vec;
use inlinable_string::InlinableString;
use roc_region::all::Loc;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct PackageName<'a> {
pub account: &'a str,
pub pkg: &'a str,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum Version<'a> {
Exact(&'a str),
Range {
min: &'a str,
min_comparison: VersionComparison,
max: &'a str,
max_comparison: VersionComparison,
},
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum VersionComparison {
AllowsEqual,
DisallowsEqual,
}
#[derive(Clone, PartialEq, Debug)]
pub enum PackageOrPath<'a> {
Package(PackageName<'a>, Version<'a>),
Path(StrLiteral<'a>),
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct ModuleName<'a>(&'a str);
impl<'a> Into<&'a str> for ModuleName<'a> {
@ -34,15 +62,14 @@ impl<'a> ModuleName<'a> {
}
}
// TODO is this all duplicated from parse::ast?
#[derive(Clone, Debug, PartialEq)]
pub struct InterfaceHeader<'a> {
pub name: Loc<ModuleName<'a>>,
pub exposes: Vec<'a, Loc<Exposes<'a>>>,
pub imports: Vec<'a, (ModuleName<'a>, Vec<'a, Loc<Imports<'a>>>)>,
pub exposes: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
// Potential comments and newlines - these will typically all be empty.
pub after_interface: &'a [CommentOrNewline<'a>],
pub after_interface_keyword: &'a [CommentOrNewline<'a>],
pub before_exposes: &'a [CommentOrNewline<'a>],
pub after_exposes: &'a [CommentOrNewline<'a>],
pub before_imports: &'a [CommentOrNewline<'a>],
@ -51,29 +78,202 @@ pub struct InterfaceHeader<'a> {
#[derive(Clone, Debug, PartialEq)]
pub struct AppHeader<'a> {
pub imports: Vec<'a, (ModuleName<'a>, Loc<Imports<'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>,
// Potential comments and newlines - these will typically all be empty.
pub after_app_keyword: &'a [CommentOrNewline<'a>],
pub before_packages: &'a [CommentOrNewline<'a>],
pub after_packages: &'a [CommentOrNewline<'a>],
pub before_imports: &'a [CommentOrNewline<'a>],
pub after_imports: &'a [CommentOrNewline<'a>],
pub before_provides: &'a [CommentOrNewline<'a>],
pub after_provides: &'a [CommentOrNewline<'a>],
pub before_to: &'a [CommentOrNewline<'a>],
pub after_to: &'a [CommentOrNewline<'a>],
}
#[derive(Clone, Debug, PartialEq)]
pub struct PackageHeader<'a> {
pub name: Loc<PackageName<'a>>,
pub exposes: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
pub packages: Vec<'a, (Loc<&'a str>, Loc<PackageOrPath<'a>>)>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
// Potential comments and newlines - these will typically all be empty.
pub after_package_keyword: &'a [CommentOrNewline<'a>],
pub before_exposes: &'a [CommentOrNewline<'a>],
pub after_exposes: &'a [CommentOrNewline<'a>],
pub before_packages: &'a [CommentOrNewline<'a>],
pub after_packages: &'a [CommentOrNewline<'a>],
pub before_imports: &'a [CommentOrNewline<'a>],
pub after_imports: &'a [CommentOrNewline<'a>],
}
#[derive(Clone, Debug, PartialEq)]
pub enum Exposes<'a> {
/// e.g. `Task`
Ident(&'a str),
pub struct PlatformHeader<'a> {
pub name: Loc<PackageName<'a>>,
pub requires: Vec<'a, Loc<TypedIdent<'a>>>,
pub exposes: Vec<'a, Loc<ExposesEntry<'a, ModuleName<'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 effects: Effects<'a>,
// Spaces
SpaceBefore(&'a Exposes<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a Exposes<'a>, &'a [CommentOrNewline<'a>]),
// Potential comments and newlines - these will typically all be empty.
pub after_platform_keyword: &'a [CommentOrNewline<'a>],
pub before_requires: &'a [CommentOrNewline<'a>],
pub after_requires: &'a [CommentOrNewline<'a>],
pub before_exposes: &'a [CommentOrNewline<'a>],
pub after_exposes: &'a [CommentOrNewline<'a>],
pub before_packages: &'a [CommentOrNewline<'a>],
pub after_packages: &'a [CommentOrNewline<'a>],
pub before_imports: &'a [CommentOrNewline<'a>],
pub after_imports: &'a [CommentOrNewline<'a>],
pub before_provides: &'a [CommentOrNewline<'a>],
pub after_provides: &'a [CommentOrNewline<'a>],
}
#[derive(Clone, Debug, PartialEq)]
pub enum Imports<'a> {
/// e.g. `Task` or `Task.{ Task, after }`
Ident(&'a str, Vec<'a, &'a str>),
pub struct Effects<'a> {
pub spaces_before_effects_keyword: &'a [CommentOrNewline<'a>],
pub spaces_after_effects_keyword: &'a [CommentOrNewline<'a>],
pub spaces_after_type_name: &'a [CommentOrNewline<'a>],
pub type_name: &'a str,
pub entries: Vec<'a, Loc<TypedIdent<'a>>>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ExposesEntry<'a, T> {
/// e.g. `Task`
Exposed(T),
// Spaces
SpaceBefore(&'a Imports<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a Imports<'a>, &'a [CommentOrNewline<'a>]),
SpaceBefore(&'a ExposesEntry<'a, T>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a ExposesEntry<'a, T>, &'a [CommentOrNewline<'a>]),
}
impl<'a, T> Spaceable<'a> for ExposesEntry<'a, T> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
ExposesEntry::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
ExposesEntry::SpaceAfter(self, spaces)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum ImportsEntry<'a> {
/// e.g. `Task` or `Task.{ Task, after }`
Module(ModuleName<'a>, Vec<'a, Loc<ExposesEntry<'a, &'a str>>>),
/// e.g. `base.Task` or `base.Task.{ after }` or `base.{ Task.{ Task, after } }`
Package(&'a str, Vec<'a, Loc<&'a ImportsEntry<'a>>>),
// Spaces
SpaceBefore(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]),
}
impl<'a> ExposesEntry<'a, &'a str> {
pub fn as_str(&'a self) -> &'a str {
use ExposesEntry::*;
match self {
Exposed(string) => string,
SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => sub_entry.as_str(),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum TypedIdent<'a> {
/// e.g.
///
/// printLine : Str -> Effect {}
Entry {
ident: Loc<&'a str>,
spaces_before_colon: &'a [CommentOrNewline<'a>],
ann: Loc<TypeAnnotation<'a>>,
},
// Spaces
SpaceBefore(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]),
}
#[derive(Clone, Debug, PartialEq)]
pub enum PackageEntry<'a> {
Entry {
shorthand: &'a str,
spaces_after_shorthand: &'a [CommentOrNewline<'a>],
package_or_path: Loc<PackageOrPath<'a>>,
},
// Spaces
SpaceBefore(&'a PackageEntry<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a PackageEntry<'a>, &'a [CommentOrNewline<'a>]),
}
impl<'a> Spaceable<'a> for PackageEntry<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
PackageEntry::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
PackageEntry::SpaceAfter(self, spaces)
}
}
pub fn package_entry<'a>() -> impl Parser<'a, PackageEntry<'a>> {
move |arena, state| {
// You may optionally have a package shorthand,
// e.g. "uc" in `uc: roc/unicode 1.0.0`
//
// (Indirect dependencies don't have a shorthand.)
let (opt_shorthand, state) = optional(and!(
skip_second!(lowercase_ident(), ascii_char(b':')),
space0(1)
))
.parse(arena, state)?;
let (package_or_path, state) = loc!(package_or_path()).parse(arena, state)?;
let entry = match opt_shorthand {
Some((shorthand, spaces_after_shorthand)) => PackageEntry::Entry {
shorthand,
spaces_after_shorthand,
package_or_path,
},
None => PackageEntry::Entry {
shorthand: "",
spaces_after_shorthand: &[],
package_or_path,
},
};
Ok((entry, state))
}
}
fn package_or_path<'a>() -> impl Parser<'a, PackageOrPath<'a>> {
map!(
either!(
string_literal::parse(),
and!(
package_name(),
skip_first!(one_or_more!(ascii_char(b' ')), package_version())
)
),
|answer| {
match answer {
Either::First(str_literal) => PackageOrPath::Path(str_literal),
Either::Second((name, version)) => PackageOrPath::Package(name, version),
}
}
)
}
fn package_version<'a>() -> impl Parser<'a, Version<'a>> {
move |_, _| todo!("TODO parse package version")
}

View file

@ -1,15 +1,16 @@
use crate::ast::{
AppHeader, Attempting, CommentOrNewline, Def, Effects, ExposesEntry, ImportsEntry,
InterfaceHeader, Module, PlatformHeader, TypedIdent,
};
use crate::ast::{Attempting, CommentOrNewline, Def, Module};
use crate::blankspace::{space0, space0_around, space0_before, space1};
use crate::expr::def;
use crate::header::{ModuleName, PackageName};
use crate::header::{
package_entry, AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName,
PackageEntry, PackageName, PlatformHeader, 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,
};
use crate::string_literal;
use crate::type_annotation;
use bumpalo::collections::{String, Vec};
use bumpalo::Bump;
@ -44,7 +45,7 @@ pub fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>> {
ascii_string("interface"),
and!(space1(1), loc!(module_name()))
),
and!(exposes(), imports())
and!(exposes_values(), imports())
),
|(
(after_interface_keyword, name),
@ -176,25 +177,31 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>> {
fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> {
parser::map(
and!(
skip_first!(ascii_string("app"), and!(space1(1), loc!(module_name()))),
and!(provides(), imports())
skip_first!(
ascii_string("app"),
and!(space1(1), loc!(string_literal::parse()))
),
and!(packages(), and!(imports(), provides_to()))
),
|(
(after_app_keyword, name),
(
((before_provides, after_provides), provides),
((before_imports, after_imports), imports),
),
(packages, (((before_imports, after_imports), imports), provides)),
)| {
AppHeader {
name,
provides,
packages: packages.entries,
imports,
provides: provides.entries,
to: provides.to,
after_app_keyword,
before_provides,
after_provides,
before_packages: packages.before_packages_keyword,
after_packages: packages.after_packages_keyword,
before_imports,
after_imports,
before_provides: provides.before_provides_keyword,
after_provides: provides.after_provides_keyword,
before_to: provides.before_to_keyword,
after_to: provides.after_to_keyword,
}
},
)
@ -208,31 +215,49 @@ fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>> {
ascii_string("platform"),
and!(space1(1), loc!(package_name()))
),
and!(provides(), and!(requires(), and!(imports(), effects())))
and!(
and!(
and!(requires(), and!(exposes_modules(), packages())),
and!(imports(), provides_without_to())
),
effects()
)
),
|(
(after_platform_keyword, name),
(
((before_provides, after_provides), provides),
(
((before_requires, after_requires), requires),
(((before_imports, after_imports), imports), effects),
(
((before_requires, after_requires), requires),
(((before_exposes, after_exposes), exposes), packages),
),
(
((before_imports, after_imports), imports),
((before_provides, after_provides), provides),
),
),
effects,
),
)| {
PlatformHeader {
name,
provides,
requires,
exposes,
packages: packages.entries,
imports,
provides,
effects,
after_platform_keyword,
before_provides,
after_provides,
before_requires,
after_requires,
before_exposes,
after_exposes,
before_packages: packages.before_packages_keyword,
after_packages: packages.after_packages_keyword,
before_imports,
after_imports,
before_provides,
after_provides,
}
},
)
@ -243,39 +268,69 @@ pub fn module_defs<'a>() -> impl Parser<'a, Vec<'a, Located<Def<'a>>>> {
zero_or_more!(space0_around(loc(def(0)), 0))
}
struct ProvidesTo<'a> {
entries: Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
to: Located<&'a str>,
before_provides_keyword: &'a [CommentOrNewline<'a>],
after_provides_keyword: &'a [CommentOrNewline<'a>],
before_to_keyword: &'a [CommentOrNewline<'a>],
after_to_keyword: &'a [CommentOrNewline<'a>],
}
#[inline(always)]
fn provides<'a>() -> impl Parser<
fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>> {
map!(
and!(
and!(skip_second!(space1(1), ascii_string("provides")), space1(1)),
and!(
collection!(
ascii_char(b'['),
loc!(map!(unqualified_ident(), ExposesEntry::Exposed)),
ascii_char(b','),
ascii_char(b']'),
1
),
and!(
space1(1),
skip_first!(ascii_string("to"), and!(space1(1), loc!(lowercase_ident())))
)
)
),
|(
(before_provides_keyword, after_provides_keyword),
(entries, (before_to_keyword, (after_to_keyword, to))),
)| {
ProvidesTo {
entries,
to,
before_provides_keyword,
after_provides_keyword,
before_to_keyword,
after_to_keyword,
}
}
)
}
#[inline(always)]
fn provides_without_to<'a>() -> impl Parser<
'a,
(
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
Vec<'a, Located<ExposesEntry<'a>>>,
Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
),
> {
map!(
and!(
and!(skip_second!(space1(1), ascii_string("provides")), space1(1)),
collection!(
ascii_char(b'['),
loc!(exposes_entry()),
ascii_char(b','),
ascii_char(b']'),
1
)
)
,
|((before_provides_keyword, after_provides_keyword), provides_entries| {
Provides {
provides_entries,
to,
before_provides_keyword,
after_provides_keyword,
before_to_keyword,
after_to_keyword,
}
}
)
}
}
and!(
and!(skip_second!(space1(1), ascii_string("provides")), space1(1)),
collection!(
ascii_char(b'['),
loc!(map!(unqualified_ident(), ExposesEntry::Exposed)),
ascii_char(b','),
ascii_char(b']'),
1
)
)
}
#[inline(always)]
@ -299,18 +354,18 @@ fn requires<'a>() -> impl Parser<
}
#[inline(always)]
fn exposes<'a>() -> impl Parser<
fn exposes_values<'a>() -> impl Parser<
'a,
(
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
Vec<'a, Located<ExposesEntry<'a>>>,
Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
),
> {
and!(
and!(skip_second!(space1(1), ascii_string("exposes")), space1(1)),
collection!(
ascii_char(b'['),
loc!(exposes_entry()),
loc!(map!(unqualified_ident(), ExposesEntry::Exposed)),
ascii_char(b','),
ascii_char(b']'),
1
@ -318,6 +373,56 @@ fn exposes<'a>() -> impl Parser<
)
}
#[inline(always)]
fn exposes_modules<'a>() -> impl Parser<
'a,
(
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
Vec<'a, Located<ExposesEntry<'a, ModuleName<'a>>>>,
),
> {
and!(
and!(skip_second!(space1(1), ascii_string("exposes")), space1(1)),
collection!(
ascii_char(b'['),
loc!(map!(module_name(), ExposesEntry::Exposed)),
ascii_char(b','),
ascii_char(b']'),
1
)
)
}
struct Packages<'a> {
entries: Vec<'a, Located<PackageEntry<'a>>>,
before_packages_keyword: &'a [CommentOrNewline<'a>],
after_packages_keyword: &'a [CommentOrNewline<'a>],
}
#[inline(always)]
fn packages<'a>() -> impl Parser<'a, Packages<'a>> {
map!(
and!(
and!(skip_second!(space1(1), ascii_string("packages")), space1(1)),
collection!(
ascii_char(b'{'),
loc!(package_entry()),
ascii_char(b','),
ascii_char(b'}'),
1
)
),
|((before_packages_keyword, after_packages_keyword), entries)| {
Packages {
entries,
before_packages_keyword,
after_packages_keyword,
}
}
)
}
#[inline(always)]
fn imports<'a>() -> impl Parser<
'a,
@ -397,11 +502,6 @@ fn typed_ident<'a>() -> impl Parser<'a, TypedIdent<'a>> {
}
}
#[inline(always)]
fn exposes_entry<'a>() -> impl Parser<'a, ExposesEntry<'a>> {
map!(unqualified_ident(), ExposesEntry::Ident)
}
#[inline(always)]
fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> {
map_with_arena!(
@ -413,7 +513,7 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> {
ascii_char(b'.'),
collection!(
ascii_char(b'{'),
loc!(exposes_entry()),
loc!(map!(unqualified_ident(), ExposesEntry::Exposed)),
ascii_char(b','),
ascii_char(b'}'),
1
@ -423,7 +523,7 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> {
|arena,
(module_name, opt_values): (
ModuleName<'a>,
Option<Vec<'a, Located<ExposesEntry<'a>>>>
Option<Vec<'a, Located<ExposesEntry<'a, &'a str>>>>
)| {
let exposed_values = opt_values.unwrap_or_else(|| Vec::new_in(arena));

View file

@ -1037,7 +1037,11 @@ macro_rules! one_or_more {
}
}
}
Err((_, new_state)) => Err(unexpected_eof(0, new_state.attempting, new_state)),
Err((_, new_state)) => Err($crate::parser::unexpected_eof(
0,
new_state.attempting,
new_state,
)),
}
}
};
@ -1083,9 +1087,9 @@ macro_rules! either {
let original_attempting = state.attempting;
match $p1.parse(arena, state) {
Ok((output, state)) => Ok((Either::First(output), state)),
Ok((output, state)) => Ok(($crate::parser::Either::First(output), state)),
Err((_, state)) => match $p2.parse(arena, state) {
Ok((output, state)) => Ok((Either::Second(output), state)),
Ok((output, state)) => Ok(($crate::parser::Either::Second(output), state)),
Err((fail, state)) => Err((
Fail {
attempting: original_attempting,