Use UppercaseIdent over PlatformRigids

This commit is contained in:
Richard Feldman 2022-01-23 11:09:29 -05:00
parent 620e3f2913
commit c1c0ffb25f
10 changed files with 157 additions and 51 deletions

View file

@ -1,6 +1,6 @@
use crate::ast::{Collection, CommentOrNewline, Spaced, StrLiteral, TypeAnnotation};
use crate::blankspace::space0_e;
use crate::ident::lowercase_ident;
use crate::ident::{lowercase_ident, UppercaseIdent};
use crate::parser::Progress::*;
use crate::parser::{specialize, word1, EPackageEntry, EPackageName, Parser};
use crate::state::State;
@ -126,15 +126,9 @@ pub struct PackageHeader<'a> {
pub after_imports: &'a [CommentOrNewline<'a>],
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PlatformRigid<'a> {
pub rigid: &'a str,
pub alias: &'a str,
}
#[derive(Clone, Debug, PartialEq)]
pub struct PlatformRequires<'a> {
pub rigids: Collection<'a, Loc<Spaced<'a, PlatformRigid<'a>>>>,
pub rigids: Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>,
pub signature: Loc<Spaced<'a, TypedIdent<'a>>>,
}

View file

@ -5,6 +5,23 @@ use bumpalo::collections::vec::Vec;
use bumpalo::Bump;
use roc_region::all::Position;
/// A global tag, for example. Must start with an uppercase letter
/// and then contain only letters and numbers afterwards - no dots allowed!
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct UppercaseIdent<'a>(&'a str);
impl<'a> From<&'a str> for UppercaseIdent<'a> {
fn from(string: &'a str) -> Self {
UppercaseIdent(string)
}
}
impl<'a> From<UppercaseIdent<'a>> for &'a str {
fn from(ident: UppercaseIdent<'a>) -> Self {
ident.0
}
}
/// The parser accepts all of these in any position where any one of them could
/// appear. This way, canonicalization can give more helpful error messages like
/// "you can't redefine this tag!" if you wrote `Foo = ...` or
@ -91,6 +108,21 @@ pub fn tag_name<'a>() -> impl Parser<'a, &'a str, ()> {
}
}
/// This could be:
///
/// * A module name
/// * A type name
/// * A global tag
pub fn uppercase<'a>() -> impl Parser<'a, UppercaseIdent<'a>, ()> {
move |_, state: State<'a>| match chomp_uppercase_part(state.bytes()) {
Err(progress) => Err((progress, (), state)),
Ok(ident) => {
let width = ident.len();
Ok((MadeProgress, ident.into(), state.advance(width)))
}
}
}
/// This could be:
///
/// * A module name

View file

@ -2,13 +2,13 @@ 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, PlatformRigid, To, TypedIdent,
ModuleName, PackageEntry, PlatformHeader, PlatformRequires, To, TypedIdent,
};
use crate::ident::{lowercase_ident, unqualified_ident, uppercase_ident};
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase_ident, UppercaseIdent};
use crate::parser::Progress::{self, *};
use crate::parser::{
backtrackable, specialize, specialize_region, word1, word2, EEffects, EExposes, EHeader,
EImports, EPackages, EProvides, ERequires, ETypedIdent, Parser, SourceError, SyntaxError,
backtrackable, specialize, specialize_region, word1, EEffects, EExposes, EHeader, EImports,
EPackages, EProvides, ERequires, ETypedIdent, Parser, SourceError, SyntaxError,
};
use crate::state::State;
use crate::string_literal;
@ -439,10 +439,13 @@ fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a
#[inline(always)]
fn requires_rigids<'a>(
min_indent: u32,
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, PlatformRigid<'a>>>>, ERequires<'a>> {
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>, ERequires<'a>> {
collection_trailing_sep_e!(
word1(b'{', ERequires::ListStart),
specialize(|_, pos| ERequires::Rigid(pos), loc!(requires_rigid())),
specialize(
|_, pos| ERequires::Rigid(pos),
loc!(map!(ident::uppercase(), Spaced::Item))
),
word1(b',', ERequires::ListEnd),
word1(b'}', ERequires::ListEnd),
min_indent,
@ -453,17 +456,6 @@ fn requires_rigids<'a>(
)
}
#[inline(always)]
fn requires_rigid<'a>() -> impl Parser<'a, Spaced<'a, PlatformRigid<'a>>, ()> {
map!(
and!(
lowercase_ident(),
skip_first!(word2(b'=', b'>', |_| ()), uppercase_ident())
),
|(rigid, alias)| Spaced::Item(PlatformRigid { rigid, alias })
)
}
#[inline(always)]
fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>, ERequires<'a>> {
skip_first!(