mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
if guard empty condition message
This commit is contained in:
parent
bcf87f5df6
commit
576b7974e8
6 changed files with 122 additions and 23 deletions
|
@ -2,8 +2,8 @@ use crate::ast::{
|
|||
AssignedField, Attempting, CommentOrNewline, Def, Expr, Pattern, Spaceable, TypeAnnotation,
|
||||
};
|
||||
use crate::blankspace::{
|
||||
line_comment, space0, space0_after, space0_around, space0_before, space0_before_e, space1,
|
||||
space1_around, space1_before, spaces_exactly,
|
||||
line_comment, space0, space0_after, space0_around, space0_around_e, space0_before,
|
||||
space0_before_e, space1, space1_around, space1_before, spaces_exactly,
|
||||
};
|
||||
use crate::ident::{global_tag_or_ident, ident, lowercase_ident, Ident};
|
||||
use crate::keyword;
|
||||
|
@ -11,10 +11,10 @@ use crate::number_literal::number_literal;
|
|||
use crate::parser::{
|
||||
self, allocated, and_then_with_indent_level, ascii_char, ascii_string, attempt, backtrackable,
|
||||
fail, map, newline_char, not, not_followed_by, optional, sep_by1, specialize, specialize_ref,
|
||||
then, unexpected, unexpected_eof, word2, EExpr, Either, ParseResult, Parser, State,
|
||||
then, unexpected, unexpected_eof, word1, word2, EExpr, Either, ParseResult, Parser, State,
|
||||
SyntaxError, When,
|
||||
};
|
||||
use crate::pattern::{loc_closure_param, loc_pattern};
|
||||
use crate::pattern::loc_closure_param;
|
||||
use crate::type_annotation;
|
||||
use bumpalo::collections::string::String;
|
||||
use bumpalo::collections::Vec;
|
||||
|
@ -1150,19 +1150,43 @@ mod when {
|
|||
min_indent: u16,
|
||||
) -> impl Parser<'a, (Vec<'a, Located<Pattern<'a>>>, Option<Located<Expr<'a>>>), SyntaxError<'a>>
|
||||
{
|
||||
specialize(
|
||||
|e, r, c| SyntaxError::Expr(EExpr::When(e, r, c)),
|
||||
branch_alternatives_help(min_indent),
|
||||
)
|
||||
}
|
||||
|
||||
fn branch_alternatives_help<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, (Vec<'a, Located<Pattern<'a>>>, Option<Located<Expr<'a>>>), When<'a>> {
|
||||
and!(
|
||||
sep_by1(
|
||||
ascii_char(b'|'),
|
||||
space0_around(loc_pattern(min_indent), min_indent),
|
||||
word1(b'|', When::Bar),
|
||||
space0_around_e(
|
||||
specialize(When::Pattern, crate::pattern::loc_pattern_help(min_indent)),
|
||||
min_indent,
|
||||
When::Space,
|
||||
When::IndentPattern
|
||||
),
|
||||
),
|
||||
optional(skip_first!(
|
||||
parser::keyword(keyword::IF, min_indent),
|
||||
// TODO we should require space before the expression but not after
|
||||
space1_around(
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent
|
||||
)
|
||||
))
|
||||
one_of![
|
||||
map!(
|
||||
skip_first!(
|
||||
parser::keyword_e(keyword::IF, When::IfToken),
|
||||
// TODO we should require space before the expression but not after
|
||||
space0_around_e(
|
||||
loc!(specialize_ref(When::IfGuard, move |arena, state| {
|
||||
parse_expr(min_indent, arena, state)
|
||||
})),
|
||||
min_indent,
|
||||
When::Space,
|
||||
When::IndentIfGuard,
|
||||
)
|
||||
),
|
||||
Some
|
||||
),
|
||||
|_, s| Ok((NoProgress, None, s))
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -390,6 +390,10 @@ pub enum When<'a> {
|
|||
Is(Row, Col),
|
||||
Pattern(EPattern<'a>, Row, Col),
|
||||
Arrow(Row, Col),
|
||||
Bar(Row, Col),
|
||||
IfToken(Row, Col),
|
||||
// TODO make EExpr
|
||||
IfGuard(&'a SyntaxError<'a>, Row, Col),
|
||||
Condition(&'a EExpr<'a>, Row, Col),
|
||||
Branch(&'a EExpr<'a>, Row, Col),
|
||||
Syntax(&'a SyntaxError<'a>, Row, Col),
|
||||
|
@ -399,6 +403,7 @@ pub enum When<'a> {
|
|||
IndentPattern(Row, Col),
|
||||
IndentArrow(Row, Col),
|
||||
IndentBranch(Row, Col),
|
||||
IndentIfGuard(Row, Col),
|
||||
PatternAlignment(u16, Row, Col),
|
||||
}
|
||||
|
||||
|
@ -967,16 +972,17 @@ pub fn keyword<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn keyword_e<'a, E>(keyword: &'static str, if_error: E) -> impl Parser<'a, (), E>
|
||||
pub fn keyword_e<'a, ToError, E>(keyword: &'static str, if_error: ToError) -> impl Parser<'a, (), E>
|
||||
where
|
||||
E: 'a + Clone,
|
||||
ToError: Fn(Row, Col) -> E,
|
||||
E: 'a,
|
||||
{
|
||||
move |arena, state: State<'a>| {
|
||||
let initial_state = state.clone();
|
||||
// first parse the keyword characters
|
||||
let (_, _, after_keyword_state) = ascii_string(keyword)
|
||||
.parse(arena, state)
|
||||
.map_err(|(_, _, state)| (NoProgress, if_error.clone(), state))?;
|
||||
.map_err(|(_, _, state)| (NoProgress, if_error(state.line, state.column), state))?;
|
||||
|
||||
// then we must have at least one space character
|
||||
// TODO this is potentially wasteful if there are a lot of spaces
|
||||
|
@ -990,7 +996,11 @@ where
|
|||
// this is not a keyword, maybe it's `whence` or `iffy`
|
||||
// anyway, make no progress and return the initial state
|
||||
// so we can try something else
|
||||
Err((NoProgress, if_error.clone(), initial_state))
|
||||
Err((
|
||||
NoProgress,
|
||||
if_error(initial_state.line, initial_state.column),
|
||||
initial_state,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ pub fn loc_pattern<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>,
|
|||
)
|
||||
}
|
||||
|
||||
fn loc_pattern_help<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>, EPattern<'a>> {
|
||||
pub fn loc_pattern_help<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<Pattern<'a>>, EPattern<'a>> {
|
||||
one_of!(
|
||||
specialize(EPattern::PInParens, loc_pattern_in_parens_help(min_indent)),
|
||||
loc!(underscore_pattern_help()),
|
||||
|
|
|
@ -66,7 +66,7 @@ fn term<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Typ
|
|||
and!(
|
||||
skip_second!(
|
||||
backtrackable(space0_e(min_indent, Type::TSpace, Type::TIndentEnd)),
|
||||
crate::parser::keyword_e(keyword::AS, Type::TEnd(0, 0))
|
||||
crate::parser::keyword_e(keyword::AS, Type::TEnd)
|
||||
),
|
||||
space0_before_e(
|
||||
term(min_indent),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue