mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Parse hosted modules
This commit is contained in:
parent
8633cedf4d
commit
484ce2fbc9
5 changed files with 217 additions and 18 deletions
|
@ -1,6 +1,6 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use crate::header::{AppHeader, InterfaceHeader, PlatformHeader};
|
||||
use crate::header::{AppHeader, InterfaceHeader, PlatformHeader, HostedHeader};
|
||||
use crate::ident::Ident;
|
||||
use bumpalo::collections::{String, Vec};
|
||||
use bumpalo::Bump;
|
||||
|
@ -70,6 +70,7 @@ pub enum Module<'a> {
|
|||
Interface { header: InterfaceHeader<'a> },
|
||||
App { header: AppHeader<'a> },
|
||||
Platform { header: PlatformHeader<'a> },
|
||||
Hosted { header: HostedHeader<'a> },
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
|
|
@ -81,6 +81,27 @@ pub struct InterfaceHeader<'a> {
|
|||
pub after_imports: &'a [CommentOrNewline<'a>],
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct HostedHeader<'a> {
|
||||
pub name: Loc<ModuleName<'a>>,
|
||||
pub exposes: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||
pub imports: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
||||
pub generates: UppercaseIdent<'a>,
|
||||
pub generates_with: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||
|
||||
// Potential comments and newlines - these will typically all be empty.
|
||||
pub before_header: &'a [CommentOrNewline<'a>],
|
||||
pub after_hosted_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>],
|
||||
pub before_generates: &'a [CommentOrNewline<'a>],
|
||||
pub after_generates: &'a [CommentOrNewline<'a>],
|
||||
pub before_with: &'a [CommentOrNewline<'a>],
|
||||
pub after_with: &'a [CommentOrNewline<'a>],
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum To<'a> {
|
||||
ExistingPackage(&'a str),
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
use crate::ast::{Collection, CommentOrNewline, Def, Module, Spaced};
|
||||
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
||||
use crate::header::{
|
||||
package_entry, package_name, AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader,
|
||||
ModuleName, PackageEntry, PlatformHeader, PlatformRequires, To, TypedIdent,
|
||||
package_entry, package_name, AppHeader, Effects, ExposedName, HostedHeader, ImportsEntry,
|
||||
InterfaceHeader, ModuleName, PackageEntry, PlatformHeader, PlatformRequires, To, TypedIdent,
|
||||
};
|
||||
use crate::ident::{
|
||||
self, lowercase_ident, unqualified_ident, uppercase, uppercase_ident, UppercaseIdent,
|
||||
};
|
||||
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase_ident, UppercaseIdent};
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{
|
||||
backtrackable, optional, specialize, specialize_region, word1, EEffects, EExposes, EHeader,
|
||||
EImports, EPackages, EProvides, ERequires, ETypedIdent, Parser, SourceError, SyntaxError,
|
||||
backtrackable, optional, specialize, specialize_region, word1, EEffects, EExposes, EGenerates,
|
||||
EGeneratesWith, EHeader, EImports, EPackages, EProvides, ERequires, ETypedIdent, Parser,
|
||||
SourceError, SyntaxError,
|
||||
};
|
||||
use crate::state::State;
|
||||
use crate::string_literal;
|
||||
|
@ -58,6 +61,15 @@ fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||
and!(
|
||||
space0_e(0, EHeader::Space, EHeader::IndentStart),
|
||||
one_of![
|
||||
map!(
|
||||
skip_first!(keyword_e("interface", EHeader::Start), interface_header()),
|
||||
|mut header: InterfaceHeader<'a>| -> Clos<'a> {
|
||||
Box::new(|spaces| {
|
||||
header.before_header = spaces;
|
||||
Module::Interface { header }
|
||||
})
|
||||
}
|
||||
),
|
||||
map!(
|
||||
skip_first!(keyword_e("app", EHeader::Start), app_header()),
|
||||
|mut header: AppHeader<'a>| -> Clos<'a> {
|
||||
|
@ -77,11 +89,11 @@ fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||
}
|
||||
),
|
||||
map!(
|
||||
skip_first!(keyword_e("interface", EHeader::Start), interface_header()),
|
||||
|mut header: InterfaceHeader<'a>| -> Clos<'a> {
|
||||
skip_first!(keyword_e("hosted", EHeader::Start), hosted_header()),
|
||||
|mut header: HostedHeader<'a>| -> Clos<'a> {
|
||||
Box::new(|spaces| {
|
||||
header.before_header = spaces;
|
||||
Module::Interface { header }
|
||||
Module::Hosted { header }
|
||||
})
|
||||
}
|
||||
)
|
||||
|
@ -121,6 +133,46 @@ fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn hosted_header<'a>() -> impl Parser<'a, HostedHeader<'a>, EHeader<'a>> {
|
||||
|arena, state| {
|
||||
let min_indent = 1;
|
||||
|
||||
let (_, after_hosted_keyword, state) =
|
||||
space0_e(min_indent, EHeader::Space, EHeader::IndentStart).parse(arena, state)?;
|
||||
let (_, name, state) = loc!(module_name_help(EHeader::ModuleName)).parse(arena, state)?;
|
||||
|
||||
let (_, ((before_exposes, after_exposes), exposes), state) =
|
||||
specialize(EHeader::Exposes, exposes_values()).parse(arena, state)?;
|
||||
let (_, ((before_imports, after_imports), imports), state) =
|
||||
specialize(EHeader::Imports, imports()).parse(arena, state)?;
|
||||
let (_, ((before_generates, after_generates), generates), state) =
|
||||
specialize(EHeader::Generates, generates()).parse(arena, state)?;
|
||||
let (_, ((before_with, after_with), generates_with), state) =
|
||||
specialize(EHeader::GeneratesWith, generates_with()).parse(arena, state)?;
|
||||
|
||||
let header = HostedHeader {
|
||||
name,
|
||||
exposes,
|
||||
imports,
|
||||
generates,
|
||||
generates_with,
|
||||
before_header: &[] as &[_],
|
||||
after_hosted_keyword,
|
||||
before_exposes,
|
||||
after_exposes,
|
||||
before_imports,
|
||||
after_imports,
|
||||
before_generates,
|
||||
after_generates,
|
||||
before_with,
|
||||
after_with,
|
||||
};
|
||||
|
||||
Ok((MadeProgress, header, state))
|
||||
}
|
||||
}
|
||||
|
||||
fn chomp_module_name(buffer: &[u8]) -> Result<&str, Progress> {
|
||||
use encode_unicode::CharExt;
|
||||
|
||||
|
@ -678,6 +730,64 @@ fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> {
|
|||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn generates<'a>() -> impl Parser<
|
||||
'a,
|
||||
(
|
||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||
UppercaseIdent<'a>,
|
||||
),
|
||||
EGenerates,
|
||||
> {
|
||||
let min_indent = 1;
|
||||
|
||||
and!(
|
||||
spaces_around_keyword(
|
||||
min_indent,
|
||||
"generates",
|
||||
EGenerates::Generates,
|
||||
EGenerates::Space,
|
||||
EGenerates::IndentGenerates,
|
||||
EGenerates::IndentTypeStart
|
||||
),
|
||||
specialize(|(), pos| EGenerates::Identifier(pos), uppercase())
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn generates_with<'a>() -> impl Parser<
|
||||
'a,
|
||||
(
|
||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||
Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||
),
|
||||
EGeneratesWith,
|
||||
> {
|
||||
let min_indent = 1;
|
||||
|
||||
and!(
|
||||
spaces_around_keyword(
|
||||
min_indent,
|
||||
"with",
|
||||
EGeneratesWith::With,
|
||||
EGeneratesWith::Space,
|
||||
EGeneratesWith::IndentWith,
|
||||
EGeneratesWith::IndentListStart
|
||||
),
|
||||
collection_trailing_sep_e!(
|
||||
word1(b'[', EGeneratesWith::ListStart),
|
||||
exposes_entry(EGeneratesWith::Identifier),
|
||||
word1(b',', EGeneratesWith::ListEnd),
|
||||
word1(b']', EGeneratesWith::ListEnd),
|
||||
min_indent,
|
||||
EGeneratesWith::Open,
|
||||
EGeneratesWith::Space,
|
||||
EGeneratesWith::IndentListEnd,
|
||||
Spaced::SpaceBefore
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn imports<'a>() -> impl Parser<
|
||||
'a,
|
||||
|
|
|
@ -72,6 +72,8 @@ pub enum EHeader<'a> {
|
|||
Requires(ERequires<'a>, Position),
|
||||
Packages(EPackages<'a>, Position),
|
||||
Effects(EEffects<'a>, Position),
|
||||
Generates(EGenerates, Position),
|
||||
GeneratesWith(EGeneratesWith, Position),
|
||||
|
||||
Space(BadInputError, Position),
|
||||
Start(Position),
|
||||
|
@ -202,6 +204,38 @@ pub enum EImports {
|
|||
SetEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum EGenerates {
|
||||
Open(Position),
|
||||
Generates(Position),
|
||||
IndentGenerates(Position),
|
||||
Identifier(Position),
|
||||
Space(BadInputError, Position),
|
||||
IndentTypeStart(Position),
|
||||
IndentTypeEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum EGeneratesWith {
|
||||
Open(Position),
|
||||
With(Position),
|
||||
IndentWith(Position),
|
||||
IndentListStart(Position),
|
||||
IndentListEnd(Position),
|
||||
ListStart(Position),
|
||||
ListEnd(Position),
|
||||
Identifier(Position),
|
||||
ExposingDot(Position),
|
||||
ShorthandDot(Position),
|
||||
Shorthand(Position),
|
||||
ModuleName(Position),
|
||||
Space(BadInputError, Position),
|
||||
IndentSetStart(Position),
|
||||
IndentSetEnd(Position),
|
||||
SetStart(Position),
|
||||
SetEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BadInputError {
|
||||
HasTab,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue