Refactor: introduce trait SpaceProblem to remove a bunch of redundant args in ::Space errors

This commit is contained in:
Joshua Warner 2022-02-15 20:48:04 -08:00
parent 999287e958
commit f440d53e7b
7 changed files with 117 additions and 170 deletions

View file

@ -1,5 +1,6 @@
use crate::ast::CommentOrNewline;
use crate::ast::Spaceable;
use crate::parser::SpaceProblem;
use crate::parser::{self, and, backtrackable, BadInputError, Parser, Progress::*};
use crate::state::State;
use bumpalo::collections::vec::Vec;
@ -10,7 +11,6 @@ use roc_region::all::Position;
pub fn space0_around_ee<'a, P, S, E>(
parser: P,
min_indent: u32,
space_problem: fn(BadInputError, Position) -> E,
indent_before_problem: fn(Position) -> E,
indent_after_problem: fn(Position) -> E,
) -> impl Parser<'a, Loc<S>, E>
@ -19,15 +19,12 @@ where
S: 'a,
P: Parser<'a, Loc<S>, E>,
P: 'a,
E: 'a,
E: 'a + SpaceProblem,
{
parser::map_with_arena(
and(
space0_e(min_indent, space_problem, indent_before_problem),
and(
parser,
space0_e(min_indent, space_problem, indent_after_problem),
),
space0_e(min_indent, indent_before_problem),
and(parser, space0_e(min_indent, indent_after_problem)),
),
spaces_around_help,
)
@ -36,7 +33,6 @@ where
pub fn space0_before_optional_after<'a, P, S, E>(
parser: P,
min_indent: u32,
space_problem: fn(BadInputError, Position) -> E,
indent_before_problem: fn(Position) -> E,
indent_after_problem: fn(Position) -> E,
) -> impl Parser<'a, Loc<S>, E>
@ -45,15 +41,15 @@ where
S: 'a,
P: Parser<'a, Loc<S>, E>,
P: 'a,
E: 'a,
E: 'a + SpaceProblem,
{
parser::map_with_arena(
and(
space0_e(min_indent, space_problem, indent_before_problem),
space0_e(min_indent, indent_before_problem),
and(
parser,
one_of![
backtrackable(space0_e(min_indent, space_problem, indent_after_problem)),
backtrackable(space0_e(min_indent, indent_after_problem)),
succeed!(&[] as &[_]),
],
),
@ -101,7 +97,6 @@ where
pub fn space0_before_e<'a, P, S, E>(
parser: P,
min_indent: u32,
space_problem: fn(BadInputError, Position) -> E,
indent_problem: fn(Position) -> E,
) -> impl Parser<'a, Loc<S>, E>
where
@ -109,10 +104,10 @@ where
S: 'a,
P: Parser<'a, Loc<S>, E>,
P: 'a,
E: 'a,
E: 'a + SpaceProblem,
{
parser::map_with_arena(
and!(space0_e(min_indent, space_problem, indent_problem), parser),
and!(space0_e(min_indent, indent_problem), parser),
|arena: &'a Bump, (space_list, loc_expr): (&'a [CommentOrNewline<'a>], Loc<S>)| {
if space_list.is_empty() {
loc_expr
@ -128,7 +123,6 @@ where
pub fn space0_after_e<'a, P, S, E>(
parser: P,
min_indent: u32,
space_problem: fn(BadInputError, Position) -> E,
indent_problem: fn(Position) -> E,
) -> impl Parser<'a, Loc<S>, E>
where
@ -136,10 +130,10 @@ where
S: 'a,
P: Parser<'a, Loc<S>, E>,
P: 'a,
E: 'a,
E: 'a + SpaceProblem,
{
parser::map_with_arena(
and!(parser, space0_e(min_indent, space_problem, indent_problem)),
and!(parser, space0_e(min_indent, indent_problem)),
|arena: &'a Bump, (loc_expr, space_list): (Loc<S>, &'a [CommentOrNewline<'a>])| {
if space_list.is_empty() {
loc_expr
@ -170,23 +164,21 @@ where
pub fn space0_e<'a, E>(
min_indent: u32,
space_problem: fn(BadInputError, Position) -> E,
indent_problem: fn(Position) -> E,
) -> impl Parser<'a, &'a [CommentOrNewline<'a>], E>
where
E: 'a,
E: 'a + SpaceProblem,
{
spaces_help_help(min_indent, space_problem, indent_problem)
spaces_help_help(min_indent, indent_problem)
}
#[inline(always)]
fn spaces_help_help<'a, E>(
min_indent: u32,
space_problem: fn(BadInputError, Position) -> E,
indent_problem: fn(Position) -> E,
) -> impl Parser<'a, &'a [CommentOrNewline<'a>], E>
where
E: 'a,
E: 'a + SpaceProblem,
{
use SpaceState::*;
@ -195,7 +187,7 @@ where
match eat_spaces(state.clone(), false, comments_and_newlines) {
HasTab(state) => Err((
MadeProgress,
space_problem(BadInputError::HasTab, state.pos()),
E::space_problem(BadInputError::HasTab, state.pos()),
state,
)),
Good {

View file

@ -39,7 +39,6 @@ pub fn test_parse_expr<'a>(
space0_before_e(
move |a, s| parse_loc_expr(min_indent, a, s),
min_indent,
EExpr::Space,
EExpr::IndentStart,
),
expr_end()
@ -106,7 +105,6 @@ fn loc_expr_in_parens_help_help<'a>(
min_indent, arena, state
)),
min_indent,
EInParens::Space,
EInParens::IndentOpen,
EInParens::IndentEnd,
),
@ -340,7 +338,7 @@ fn parse_expr_operator_chain<'a>(
let initial = state.clone();
let end = state.pos();
match space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state) {
match space0_e(min_indent, EExpr::IndentEnd).parse(arena, state) {
Err((_, _, state)) => Ok((MadeProgress, expr.value, state)),
Ok((_, spaces_before_op, state)) => {
let expr_state = ExprState {
@ -781,7 +779,7 @@ fn parse_defs_end<'a>(
let min_indent = start_column;
let initial = state.clone();
let state = match space0_e(min_indent, EExpr::Space, EExpr::IndentStart).parse(arena, state) {
let state = match space0_e(min_indent, EExpr::IndentStart).parse(arena, state) {
Err((MadeProgress, _, s)) => {
return Err((MadeProgress, EExpr::DefMissingFinalExpr(s.pos()), s));
}
@ -798,7 +796,6 @@ fn parse_defs_end<'a>(
match space0_after_e(
crate::pattern::loc_pattern_help(min_indent),
min_indent,
EPattern::Space,
EPattern::IndentEnd,
)
.parse(arena, state.clone())
@ -815,7 +812,6 @@ fn parse_defs_end<'a>(
let parse_def_expr = space0_before_e(
move |a, s| parse_loc_expr(min_indent + 1, a, s),
min_indent,
EExpr::Space,
EExpr::IndentEnd,
);
@ -842,7 +838,6 @@ fn parse_defs_end<'a>(
let parse_def_expr = space0_before_e(
move |a, s| parse_loc_expr(min_indent + 1, a, s),
min_indent,
EExpr::Space,
EExpr::IndentEnd,
);
@ -864,7 +859,6 @@ fn parse_defs_end<'a>(
space0_before_e(
type_annotation::located_help(min_indent + 1, false),
min_indent + 1,
EType::TSpace,
EType::TIndentStart,
),
)
@ -902,7 +896,6 @@ fn parse_defs_expr<'a>(
let parse_final_expr = space0_before_e(
move |a, s| parse_loc_expr(min_indent, a, s),
min_indent,
EExpr::Space,
EExpr::IndentEnd,
);
@ -936,7 +929,7 @@ fn parse_expr_operator<'a>(
state: State<'a>,
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
let (_, spaces_after_operator, state) =
space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state)?;
space0_e(min_indent, EExpr::IndentEnd).parse(arena, state)?;
// a `-` is unary if it is preceded by a space and not followed by a space
@ -961,11 +954,10 @@ fn parse_expr_operator<'a>(
expr_state.initial = state.clone();
let (spaces, state) =
match space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state) {
Err((_, _, state)) => (&[] as &[_], state),
Ok((_, spaces, state)) => (spaces, state),
};
let (spaces, state) = match space0_e(min_indent, EExpr::IndentEnd).parse(arena, state) {
Err((_, _, state)) => (&[] as &[_], state),
Ok((_, spaces, state)) => (spaces, state),
};
expr_state.arguments.push(arena.alloc(arg));
expr_state.spaces_after = spaces;
@ -1054,7 +1046,6 @@ fn parse_expr_operator<'a>(
let parse_cont = space0_before_e(
move |a, s| parse_loc_expr(min_indent, a, s),
min_indent,
EExpr::Space,
EExpr::IndentEnd,
);
@ -1094,7 +1085,6 @@ fn parse_expr_operator<'a>(
space0_before_e(
type_annotation::located_help(indented_more, true),
min_indent,
EType::TSpace,
EType::TIndentStart,
),
)
@ -1123,7 +1113,6 @@ fn parse_expr_operator<'a>(
space0_before_e(
type_annotation::located_help(indented_more, false),
min_indent,
EType::TSpace,
EType::TIndentStart,
),
);
@ -1180,7 +1169,7 @@ fn parse_expr_operator<'a>(
.with_spaces_before(spaces_after_operator, new_expr.region);
}
match space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state) {
match space0_e(min_indent, EExpr::IndentEnd).parse(arena, state) {
Err((_, _, state)) => {
let args = std::mem::replace(&mut expr_state.arguments, Vec::new_in(arena));
@ -1243,7 +1232,7 @@ fn parse_expr_end<'a>(
}
expr_state.initial = state.clone();
match space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state) {
match space0_e(min_indent, EExpr::IndentEnd).parse(arena, state) {
Err((_, _, state)) => {
expr_state.arguments.push(arena.alloc(arg));
expr_state.end = new_end;
@ -1290,7 +1279,6 @@ fn parse_expr_end<'a>(
space0_around_ee(
crate::pattern::loc_pattern_help(min_indent),
min_indent,
EPattern::Space,
EPattern::Start,
EPattern::IndentEnd,
),
@ -1316,7 +1304,6 @@ fn parse_expr_end<'a>(
let parse_body = space0_before_e(
move |a, s| parse_loc_expr(min_indent + 1, a, s),
min_indent,
EExpr::Space,
EExpr::IndentEnd,
);
@ -1325,7 +1312,6 @@ fn parse_expr_end<'a>(
let parse_cont = space0_before_e(
move |a, s| parse_loc_expr(min_indent, a, s),
min_indent,
EExpr::Space,
EExpr::IndentEnd,
);
@ -1538,7 +1524,7 @@ pub fn defs<'a>(min_indent: u32) -> impl Parser<'a, Vec<'a, Loc<Def<'a>>>, EExpr
};
let (_, initial_space, state) =
space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state)?;
space0_e(min_indent, EExpr::IndentEnd).parse(arena, state)?;
let start_column = state.column();
@ -1550,7 +1536,7 @@ pub fn defs<'a>(min_indent: u32) -> impl Parser<'a, Vec<'a, Loc<Def<'a>>>, EExpr
let (_, def_state, state) = parse_defs_end(options, start_column, def_state, arena, state)?;
let (_, final_space, state) =
space0_e(start_column, EExpr::Space, EExpr::IndentEnd).parse(arena, state)?;
space0_e(start_column, EExpr::IndentEnd).parse(arena, state)?;
let mut output = Vec::with_capacity_in(def_state.defs.len(), arena);
@ -1601,7 +1587,6 @@ fn closure_help<'a>(
space0_around_ee(
specialize(ELambda::Pattern, loc_closure_param(min_indent)),
min_indent,
ELambda::Space,
ELambda::IndentArg,
ELambda::IndentArrow
),
@ -1616,7 +1601,6 @@ fn closure_help<'a>(
parse_loc_expr_with_options(min_indent, options, arena, state)
}),
min_indent,
ELambda::Space,
ELambda::IndentBody
)
)
@ -1649,7 +1633,6 @@ mod when {
parse_loc_expr_with_options(min_indent, options, arena, state)
}),
min_indent,
EWhen::Space,
EWhen::IndentCondition,
EWhen::IndentIs,
),
@ -1797,7 +1780,6 @@ mod when {
parse_loc_expr_with_options(min_indent + 1, options, arena, state)
}),
min_indent,
EWhen::Space,
EWhen::IndentIfGuard,
EWhen::IndentArrow,
)
@ -1814,13 +1796,11 @@ mod when {
) -> impl Parser<'a, Loc<Pattern<'a>>, EWhen<'a>> {
move |arena, state| {
let (_, spaces, state) =
backtrackable(space0_e(min_indent, EWhen::Space, EWhen::IndentPattern))
.parse(arena, state)?;
backtrackable(space0_e(min_indent, EWhen::IndentPattern)).parse(arena, state)?;
let (_, loc_pattern, state) = space0_after_e(
specialize(EWhen::Pattern, crate::pattern::loc_pattern_help(min_indent)),
min_indent,
EWhen::Space,
EWhen::IndentPattern,
)
.parse(arena, state)?;
@ -1847,7 +1827,7 @@ mod when {
let initial = state.clone();
// put no restrictions on the indent after the spaces; we'll check it manually
match space0_e(0, EWhen::Space, EWhen::IndentPattern).parse(arena, state) {
match space0_e(0, EWhen::IndentPattern).parse(arena, state) {
Err((MadeProgress, fail, _)) => Err((NoProgress, fail, initial)),
Err((NoProgress, fail, _)) => Err((NoProgress, fail, initial)),
Ok((_progress, spaces, state)) => {
@ -1914,7 +1894,6 @@ mod when {
indent, arena, state
)),
indent,
EWhen::Space,
EWhen::IndentBranch,
)
)
@ -1929,7 +1908,6 @@ fn if_branch<'a>(min_indent: u32) -> impl Parser<'a, (Loc<Expr<'a>>, Loc<Expr<'a
parse_loc_expr(min_indent, arena, state)
}),
min_indent,
EIf::Space,
EIf::IndentCondition,
EIf::IndentThenToken,
)
@ -1945,7 +1923,6 @@ fn if_branch<'a>(min_indent: u32) -> impl Parser<'a, (Loc<Expr<'a>>, Loc<Expr<'a
parse_loc_expr(min_indent, arena, state)
}),
min_indent,
EIf::Space,
EIf::IndentThenBranch,
EIf::IndentElseToken,
)
@ -1975,7 +1952,6 @@ fn expect_help<'a>(
parse_loc_expr_with_options(start_column + 1, options, arena, state)
}),
start_column + 1,
EExpect::Space,
EExpect::IndentCondition,
)
.parse(arena, state)
@ -1986,7 +1962,6 @@ fn expect_help<'a>(
space0_before_e(
move |a, s| parse_loc_expr(min_indent, a, s),
min_indent,
EExpr::Space,
EExpr::IndentEnd,
),
);
@ -2018,7 +1993,7 @@ fn if_expr_help<'a>(
// try to parse another `if`
// NOTE this drops spaces between the `else` and the `if`
let optional_if = and!(
backtrackable(space0_e(min_indent, EIf::Space, EIf::IndentIf)),
backtrackable(space0_e(min_indent, EIf::IndentIf)),
parser::keyword_e(keyword::IF, EIf::If)
);
@ -2036,7 +2011,6 @@ fn if_expr_help<'a>(
parse_loc_expr_with_options(min_indent, options, arena, state)
}),
min_indent,
EIf::Space,
EIf::IndentElseBranch,
)
.parse(arena, state_final_else)
@ -2133,7 +2107,6 @@ fn list_literal_help<'a>(min_indent: u32) -> impl Parser<'a, Expr<'a>, EList<'a>
word1(b']', EList::End),
min_indent,
EList::Open,
EList::Space,
EList::IndentEnd,
Expr::SpaceBefore
)
@ -2158,8 +2131,7 @@ fn record_field_help<'a>(
.parse(arena, state)?;
debug_assert_eq!(progress, MadeProgress);
let (_, spaces, state) =
space0_e(min_indent, ERecord::Space, ERecord::IndentColon).parse(arena, state)?;
let (_, spaces, state) = space0_e(min_indent, ERecord::IndentColon).parse(arena, state)?;
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
// (This is true in both literals and types.)
@ -2173,7 +2145,6 @@ fn record_field_help<'a>(
parse_loc_expr_no_multi_backpassing(min_indent, a, s)
}),
min_indent,
ERecord::Space,
ERecord::IndentEnd,
)
))
@ -2236,7 +2207,6 @@ fn record_help<'a>(
// (and not e.g. an `Expr::Access`) and extract its string.
loc!(record_updateable_identifier()),
min_indent,
ERecord::Space,
ERecord::IndentEnd,
ERecord::IndentAmpersand,
),
@ -2254,12 +2224,11 @@ fn record_help<'a>(
space0_around_ee(
loc!(record_field_help(min_indent)),
min_indent,
ERecord::Space,
ERecord::IndentEnd,
ERecord::IndentEnd
),
),
space0_e(min_indent, ERecord::Space, ERecord::IndentEnd)
space0_e(min_indent, ERecord::IndentEnd)
),
word1(b'}', ERecord::End)
)

View file

@ -255,11 +255,7 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
specialize(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()),
word1(b':', EPackageEntry::Colon)
),
space0_e(
min_indent,
EPackageEntry::Space,
EPackageEntry::IndentPackage
)
space0_e(min_indent, EPackageEntry::IndentPackage)
))
.parse(arena, state)?;

View file

@ -9,7 +9,7 @@ use crate::parser::Progress::{self, *};
use crate::parser::{
backtrackable, optional, specialize, specialize_region, word1, EExposes, EGenerates,
EGeneratesWith, EHeader, EImports, EPackages, EProvides, ERequires, ETypedIdent, Parser,
SourceError, SyntaxError,
SourceError, SpaceProblem, SyntaxError,
};
use crate::state::State;
use crate::string_literal;
@ -57,7 +57,7 @@ fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
map!(
and!(
space0_e(0, EHeader::Space, EHeader::IndentStart),
space0_e(0, EHeader::IndentStart),
one_of![
map!(
skip_first!(keyword_e("interface", EHeader::Start), interface_header()),
@ -107,7 +107,7 @@ fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
let min_indent = 1;
let (_, after_interface_keyword, state) =
space0_e(min_indent, EHeader::Space, EHeader::IndentStart).parse(arena, state)?;
space0_e(min_indent, EHeader::IndentStart).parse(arena, state)?;
let (_, name, state) = loc!(module_name_help(EHeader::ModuleName)).parse(arena, state)?;
let (_, ((before_exposes, after_exposes), exposes), state) =
@ -137,7 +137,7 @@ fn hosted_header<'a>() -> impl Parser<'a, HostedHeader<'a>, EHeader<'a>> {
let min_indent = 1;
let (_, after_hosted_keyword, state) =
space0_e(min_indent, EHeader::Space, EHeader::IndentStart).parse(arena, state)?;
space0_e(min_indent, EHeader::IndentStart).parse(arena, state)?;
let (_, name, state) = loc!(module_name_help(EHeader::ModuleName)).parse(arena, state)?;
let (_, ((before_exposes, after_exposes), exposes), state) =
@ -236,7 +236,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
let min_indent = 1;
let (_, after_app_keyword, state) =
space0_e(min_indent, EHeader::Space, EHeader::IndentStart).parse(arena, state)?;
space0_e(min_indent, EHeader::IndentStart).parse(arena, state)?;
let (_, name, state) = loc!(crate::parser::specialize(
EHeader::AppName,
string_literal::parse()
@ -303,7 +303,7 @@ fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> {
let min_indent = 1;
let (_, after_platform_keyword, state) =
space0_e(min_indent, EHeader::Space, EHeader::IndentStart).parse(arena, state)?;
space0_e(min_indent, EHeader::IndentStart).parse(arena, state)?;
let (_, name, state) =
loc!(specialize(EHeader::PlatformName, package_name())).parse(arena, state)?;
@ -380,7 +380,6 @@ fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>, EProvides<'a>> {
min_indent,
"to",
EProvides::To,
EProvides::Space,
EProvides::IndentTo,
EProvides::IndentListStart
),
@ -422,7 +421,6 @@ fn provides_without_to<'a>() -> impl Parser<
min_indent,
"provides",
EProvides::Provides,
EProvides::Space,
EProvides::IndentProvides,
EProvides::IndentListStart
),
@ -434,7 +432,6 @@ fn provides_without_to<'a>() -> impl Parser<
word1(b']', EProvides::ListEnd),
min_indent,
EProvides::Open,
EProvides::Space,
EProvides::IndentListEnd,
Spaced::SpaceBefore
),
@ -468,7 +465,6 @@ fn provides_types<'a>(
word1(b'}', EProvides::ListEnd),
min_indent,
EProvides::Open,
EProvides::Space,
EProvides::IndentListEnd,
Spaced::SpaceBefore
)
@ -518,7 +514,6 @@ fn requires<'a>() -> impl Parser<
min_indent,
"requires",
ERequires::Requires,
ERequires::Space,
ERequires::IndentRequires,
ERequires::IndentListStart
),
@ -530,10 +525,7 @@ fn requires<'a>() -> impl Parser<
fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a>> {
map!(
and!(
skip_second!(
requires_rigids(0),
space0_e(0, ERequires::Space, ERequires::ListStart)
),
skip_second!(requires_rigids(0), space0_e(0, ERequires::ListStart)),
requires_typed_ident()
),
|(rigids, signature)| { PlatformRequires { rigids, signature } }
@ -554,7 +546,6 @@ fn requires_rigids<'a>(
word1(b'}', ERequires::ListEnd),
min_indent,
ERequires::Open,
ERequires::Space,
ERequires::IndentListEnd,
Spaced::SpaceBefore
)
@ -568,7 +559,6 @@ fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>
space0_around_ee(
specialize(ERequires::TypedIdent, loc!(typed_ident()),),
0,
ERequires::Space,
ERequires::ListStart,
ERequires::ListEnd
),
@ -593,7 +583,6 @@ fn exposes_values<'a>() -> impl Parser<
min_indent,
"exposes",
EExposes::Exposes,
EExposes::Space,
EExposes::IndentExposes,
EExposes::IndentListStart
),
@ -604,7 +593,6 @@ fn exposes_values<'a>() -> impl Parser<
word1(b']', EExposes::ListEnd),
min_indent,
EExposes::Open,
EExposes::Space,
EExposes::IndentListEnd,
Spaced::SpaceBefore
)
@ -615,19 +603,18 @@ fn spaces_around_keyword<'a, E>(
min_indent: u32,
keyword: &'static str,
expectation: fn(Position) -> E,
space_problem: fn(crate::parser::BadInputError, Position) -> E,
indent_problem1: fn(Position) -> E,
indent_problem2: fn(Position) -> E,
) -> impl Parser<'a, (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), E>
where
E: 'a,
E: 'a + SpaceProblem,
{
and!(
skip_second!(
backtrackable(space0_e(min_indent, space_problem, indent_problem1)),
backtrackable(space0_e(min_indent, indent_problem1)),
crate::parser::keyword_e(keyword, expectation)
),
space0_e(min_indent, space_problem, indent_problem2)
space0_e(min_indent, indent_problem2)
)
}
@ -647,7 +634,6 @@ fn exposes_modules<'a>() -> impl Parser<
min_indent,
"exposes",
EExposes::Exposes,
EExposes::Space,
EExposes::IndentExposes,
EExposes::IndentListStart
),
@ -658,7 +644,6 @@ fn exposes_modules<'a>() -> impl Parser<
word1(b']', EExposes::ListEnd),
min_indent,
EExposes::Open,
EExposes::Space,
EExposes::IndentListEnd,
Spaced::SpaceBefore
)
@ -696,7 +681,6 @@ fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> {
min_indent,
"packages",
EPackages::Packages,
EPackages::Space,
EPackages::IndentPackages,
EPackages::IndentListStart
),
@ -707,7 +691,6 @@ fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> {
word1(b'}', EPackages::ListEnd),
min_indent,
EPackages::Open,
EPackages::Space,
EPackages::IndentListEnd,
Spaced::SpaceBefore
)
@ -741,7 +724,6 @@ fn generates<'a>() -> impl Parser<
min_indent,
"generates",
EGenerates::Generates,
EGenerates::Space,
EGenerates::IndentGenerates,
EGenerates::IndentTypeStart
),
@ -765,7 +747,6 @@ fn generates_with<'a>() -> impl Parser<
min_indent,
"with",
EGeneratesWith::With,
EGeneratesWith::Space,
EGeneratesWith::IndentWith,
EGeneratesWith::IndentListStart
),
@ -776,7 +757,6 @@ fn generates_with<'a>() -> impl Parser<
word1(b']', EGeneratesWith::ListEnd),
min_indent,
EGeneratesWith::Open,
EGeneratesWith::Space,
EGeneratesWith::IndentListEnd,
Spaced::SpaceBefore
)
@ -799,7 +779,6 @@ fn imports<'a>() -> impl Parser<
min_indent,
"imports",
EImports::Imports,
EImports::Space,
EImports::IndentImports,
EImports::IndentListStart
),
@ -810,7 +789,6 @@ fn imports<'a>() -> impl Parser<
word1(b']', EImports::ListEnd),
min_indent,
EImports::Open,
EImports::Space,
EImports::IndentListEnd,
Spaced::SpaceBefore
)
@ -831,7 +809,7 @@ fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<
|_, pos| ETypedIdent::Identifier(pos),
lowercase_ident()
)),
space0_e(min_indent, ETypedIdent::Space, ETypedIdent::IndentHasType)
space0_e(min_indent, ETypedIdent::IndentHasType)
),
skip_first!(
word1(b':', ETypedIdent::HasType),
@ -841,7 +819,6 @@ fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<
type_annotation::located_help(min_indent, true)
),
min_indent,
ETypedIdent::Space,
ETypedIdent::IndentType,
)
)
@ -899,7 +876,6 @@ fn imports_entry<'a>() -> impl Parser<'a, Spaced<'a, ImportsEntry<'a>>, EImports
word1(b'}', EImports::SetEnd),
min_indent,
EImports::Open,
EImports::Space,
EImports::IndentSetEnd,
Spaced::SpaceBefore
)

View file

@ -63,6 +63,50 @@ pub enum SyntaxError<'a> {
Space(BadInputError),
NotEndOfFile(Position),
}
pub trait SpaceProblem {
fn space_problem(e: BadInputError, pos: Position) -> Self;
}
macro_rules! impl_space_problem {
($($name:ident $(< $lt:tt >)?),*) => {
$(
impl $(< $lt >)? SpaceProblem for $name $(< $lt >)? {
fn space_problem(e: BadInputError, pos: Position) -> Self {
Self::Space(e, pos)
}
}
)*
};
}
impl_space_problem! {
EExpect<'a>,
EExposes,
EExpr<'a>,
EGenerates,
EGeneratesWith,
EHeader<'a>,
EIf<'a>,
EImports,
EInParens<'a>,
ELambda<'a>,
EList<'a>,
EPackageEntry<'a>,
EPackages<'a>,
EPattern<'a>,
EProvides<'a>,
ERecord<'a>,
ERequires<'a>,
EString<'a>,
EType<'a>,
ETypeInParens<'a>,
ETypeRecord<'a>,
ETypeTagUnion<'a>,
ETypedIdent<'a>,
EWhen<'a>,
PInParens<'a>,
PRecord<'a>
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EHeader<'a> {
@ -505,6 +549,8 @@ pub enum PInParens<'a> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EType<'a> {
Space(BadInputError, Position),
TRecord(ETypeRecord<'a>, Position),
TTagUnion(ETypeTagUnion<'a>, Position),
TInParens(ETypeInParens<'a>, Position),
@ -516,7 +562,6 @@ pub enum EType<'a> {
///
TStart(Position),
TEnd(Position),
TSpace(BadInputError, Position),
TFunctionArgument(Position),
///
TIndentStart(Position),
@ -1153,11 +1198,11 @@ macro_rules! collection {
#[macro_export]
macro_rules! collection_trailing_sep_e {
($opening_brace:expr, $elem:expr, $delimiter:expr, $closing_brace:expr, $min_indent:expr, $open_problem:expr, $space_problem:expr, $indent_problem:expr, $space_before:expr) => {
($opening_brace:expr, $elem:expr, $delimiter:expr, $closing_brace:expr, $min_indent:expr, $open_problem:expr, $indent_problem:expr, $space_before:expr) => {
skip_first!(
$opening_brace,
|arena, state| {
let (_, spaces, state) = space0_e($min_indent, $space_problem, $indent_problem)
let (_, spaces, state) = space0_e($min_indent, $indent_problem)
.parse(arena, state)?;
let (_, (mut parsed_elems, mut final_comments), state) =
@ -1167,12 +1212,11 @@ macro_rules! collection_trailing_sep_e {
$crate::blankspace::space0_before_optional_after(
$elem,
$min_indent,
$space_problem,
$indent_problem,
$indent_problem
)
),
$crate::blankspace::space0_e($min_indent, $space_problem, $indent_problem)
$crate::blankspace::space0_e($min_indent, $indent_problem)
).parse(arena, state)?;
let (_,_, state) =

View file

@ -75,8 +75,7 @@ fn loc_tag_pattern_arg<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>,
// If we encounter one, we're done parsing function args!
move |arena, state| {
let (_, spaces, state) =
backtrackable(space0_e(min_indent, EPattern::Space, EPattern::IndentStart))
.parse(arena, state)?;
backtrackable(space0_e(min_indent, EPattern::IndentStart)).parse(arena, state)?;
let (_, loc_pat, state) = loc_parse_tag_pattern_arg(min_indent, arena, state)?;
@ -123,7 +122,6 @@ fn loc_pattern_in_parens_help<'a>(
move |arena, state| specialize_ref(PInParens::Pattern, loc_pattern_help(min_indent))
.parse(arena, state),
min_indent,
PInParens::Space,
PInParens::IndentOpen,
PInParens::IndentEnd,
),
@ -321,7 +319,6 @@ fn record_pattern_help<'a>(min_indent: u32) -> impl Parser<'a, Pattern<'a>, PRec
word1(b'}', PRecord::End),
min_indent,
PRecord::Open,
PRecord::Space,
PRecord::IndentEnd,
Pattern::SpaceBefore
)
@ -347,8 +344,7 @@ fn record_pattern_field<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>
.parse(arena, state)?;
debug_assert_eq!(progress, MadeProgress);
let (_, spaces, state) =
space0_e(min_indent, PRecord::Space, PRecord::IndentEnd).parse(arena, state)?;
let (_, spaces, state) = space0_e(min_indent, PRecord::IndentEnd).parse(arena, state)?;
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
// (This is true in both literals and types.)
@ -362,7 +358,7 @@ fn record_pattern_field<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>
Some(First(_)) => {
let val_parser = specialize_ref(PRecord::Pattern, loc_pattern_help(min_indent));
let (_, loc_val, state) =
space0_before_e(val_parser, min_indent, PRecord::Space, PRecord::IndentColon)
space0_before_e(val_parser, min_indent, PRecord::IndentColon)
.parse(arena, state)?;
let Loc {
@ -392,7 +388,7 @@ fn record_pattern_field<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>
});
let (_, loc_val, state) =
space0_before_e(val_parser, min_indent, PRecord::Space, PRecord::IndentColon)
space0_before_e(val_parser, min_indent, PRecord::IndentColon)
.parse(arena, state)?;
let Loc {

View file

@ -28,7 +28,6 @@ fn tag_union_type<'a>(min_indent: u32) -> impl Parser<'a, TypeAnnotation<'a>, ET
word1(b']', ETypeTagUnion::End),
min_indent,
ETypeTagUnion::Open,
ETypeTagUnion::Space,
ETypeTagUnion::IndentEnd,
Tag::SpaceBefore
)
@ -87,16 +86,11 @@ fn check_type_alias(
fn parse_type_alias_after_as<'a>(min_indent: u32) -> impl Parser<'a, AliasHeader<'a>, EType<'a>> {
move |arena, state| {
space0_before_e(
term(min_indent),
min_indent,
EType::TSpace,
EType::TAsIndentStart,
)
.parse(arena, state)
.and_then(|(p, annot, state)| {
specialize(EType::TInlineAlias, check_type_alias(p, annot)).parse(arena, state)
})
space0_before_e(term(min_indent), min_indent, EType::TAsIndentStart)
.parse(arena, state)
.and_then(|(p, annot, state)| {
specialize(EType::TInlineAlias, check_type_alias(p, annot)).parse(arena, state)
})
}
}
@ -122,7 +116,7 @@ fn term<'a>(min_indent: u32) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'
map!(
and!(
skip_second!(
backtrackable(space0_e(min_indent, EType::TSpace, EType::TIndentEnd)),
backtrackable(space0_e(min_indent, EType::TIndentEnd)),
crate::parser::keyword_e(keyword::AS, EType::TEnd)
),
parse_type_alias_after_as(min_indent)
@ -170,7 +164,7 @@ fn loc_applied_arg<'a>(min_indent: u32) -> impl Parser<'a, Loc<TypeAnnotation<'a
map_with_arena!(
and!(
backtrackable(space0_e(min_indent, EType::TSpace, EType::TIndentStart)),
backtrackable(space0_e(min_indent, EType::TIndentStart)),
one_of!(
loc_wildcard(),
loc_inferred(),
@ -201,7 +195,6 @@ fn loc_type_in_parens<'a>(
move |arena, state| specialize_ref(ETypeInParens::Type, expression(min_indent, true))
.parse(arena, state),
min_indent,
ETypeInParens::Space,
ETypeInParens::IndentOpen,
ETypeInParens::IndentEnd,
),
@ -263,7 +256,7 @@ fn record_type_field<'a>(
debug_assert_eq!(progress, MadeProgress);
let (_, spaces, state) =
space0_e(min_indent, ETypeRecord::Space, ETypeRecord::IndentEnd).parse(arena, state)?;
space0_e(min_indent, ETypeRecord::IndentEnd).parse(arena, state)?;
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
// (This is true in both literals and types.)
@ -277,13 +270,9 @@ fn record_type_field<'a>(
match opt_loc_val {
Some(First(_)) => {
let (_, loc_val, state) = space0_before_e(
val_parser,
min_indent,
ETypeRecord::Space,
ETypeRecord::IndentColon,
)
.parse(arena, state)?;
let (_, loc_val, state) =
space0_before_e(val_parser, min_indent, ETypeRecord::IndentColon)
.parse(arena, state)?;
Ok((
MadeProgress,
@ -292,13 +281,9 @@ fn record_type_field<'a>(
))
}
Some(Second(_)) => {
let (_, loc_val, state) = space0_before_e(
val_parser,
min_indent,
ETypeRecord::Space,
ETypeRecord::IndentOptional,
)
.parse(arena, state)?;
let (_, loc_val, state) =
space0_before_e(val_parser, min_indent, ETypeRecord::IndentOptional)
.parse(arena, state)?;
Ok((
MadeProgress,
@ -336,7 +321,6 @@ fn record_type<'a>(min_indent: u32) -> impl Parser<'a, TypeAnnotation<'a>, EType
word1(b'}', ETypeRecord::End),
min_indent,
ETypeRecord::Open,
ETypeRecord::Space,
ETypeRecord::IndentEnd,
AssignedField::SpaceBefore
)
@ -389,13 +373,8 @@ fn expression<'a>(
is_trailing_comma_valid: bool,
) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> {
(move |arena, state: State<'a>| {
let (p1, first, state) = space0_before_e(
term(min_indent),
min_indent,
EType::TSpace,
EType::TIndentStart,
)
.parse(arena, state)?;
let (p1, first, state) = space0_before_e(term(min_indent), min_indent, EType::TIndentStart)
.parse(arena, state)?;
let result = and![
zero_or_more!(skip_first!(
@ -404,7 +383,6 @@ fn expression<'a>(
space0_around_ee(
term(min_indent),
min_indent,
EType::TSpace,
EType::TIndentStart,
EType::TIndentEnd
),
@ -419,7 +397,7 @@ fn expression<'a>(
// TODO this space0 is dropped, so newlines just before the function arrow when there
// is only one argument are not seen by the formatter. Can we do better?
skip_second!(
space0_e(min_indent, EType::TSpace, EType::TIndentStart),
space0_e(min_indent, EType::TIndentStart),
word2(b'-', b'>', EType::TStart)
)
.trace("type_annotation:expression:arrow")
@ -428,13 +406,9 @@ fn expression<'a>(
match result {
Ok((p2, (rest, _dropped_spaces), state)) => {
let (p3, return_type, state) = space0_before_e(
term(min_indent),
min_indent,
EType::TSpace,
EType::TIndentStart,
)
.parse(arena, state)?;
let (p3, return_type, state) =
space0_before_e(term(min_indent), min_indent, EType::TIndentStart)
.parse(arena, state)?;
// prepare arguments
let mut arguments = Vec::with_capacity_in(rest.len() + 1, arena);
@ -452,7 +426,7 @@ fn expression<'a>(
Err(err) => {
if !is_trailing_comma_valid {
let (_, comma, _) = optional(skip_first!(
space0_e(min_indent, EType::TSpace, EType::TIndentStart),
space0_e(min_indent, EType::TIndentStart),
word1(b',', EType::TStart)
))
.trace("check trailing comma")