mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 00:09:33 +03:00
Merge pull request #4464 from joshuawarner32/fix-one_of
Fix one_of bug, properly return MadeProgress from "when" parsing
This commit is contained in:
commit
2110540a53
@ -346,6 +346,7 @@ fn parse_expr_start<'a>(
|
|||||||
loc!(move |a, s, m| parse_expr_operator_chain(m, options, a, s)),
|
loc!(move |a, s, m| parse_expr_operator_chain(m, options, a, s)),
|
||||||
fail_expr_start_e()
|
fail_expr_start_e()
|
||||||
]
|
]
|
||||||
|
.trace("expr_start")
|
||||||
.parse(arena, state, min_indent)
|
.parse(arena, state, min_indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2076,10 +2077,10 @@ mod when {
|
|||||||
parser::keyword_e(keyword::IS, EWhen::Is)
|
parser::keyword_e(keyword::IS, EWhen::Is)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
move |arena, state, progress, (case_indent, loc_condition), min_indent| {
|
move |arena, state, _progress, (case_indent, loc_condition), min_indent| {
|
||||||
if case_indent < min_indent {
|
if case_indent < min_indent {
|
||||||
return Err((
|
return Err((
|
||||||
progress,
|
MadeProgress,
|
||||||
// TODO maybe pass case_indent here?
|
// TODO maybe pass case_indent here?
|
||||||
EWhen::PatternAlignment(5, state.pos()),
|
EWhen::PatternAlignment(5, state.pos()),
|
||||||
state,
|
state,
|
||||||
@ -2089,15 +2090,18 @@ mod when {
|
|||||||
// Everything in the branches must be indented at least as much as the case itself.
|
// Everything in the branches must be indented at least as much as the case itself.
|
||||||
let min_indent = case_indent;
|
let min_indent = case_indent;
|
||||||
|
|
||||||
let (p1, branches, state) = branches(options).parse(arena, state, min_indent)?;
|
let (_p1, branches, state) = branches(options)
|
||||||
|
.parse(arena, state, min_indent)
|
||||||
|
.map_err(|(_p, e, s)| (MadeProgress, e, s))?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
progress.or(p1),
|
MadeProgress,
|
||||||
Expr::When(arena.alloc(loc_condition), branches.into_bump_slice()),
|
Expr::When(arena.alloc(loc_condition), branches.into_bump_slice()),
|
||||||
state,
|
state,
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
.trace("when")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parsing when with indentation.
|
/// Parsing when with indentation.
|
||||||
|
@ -737,6 +737,7 @@ pub trait Parser<'a, Output, Error> {
|
|||||||
) -> ParseResult<'a, Output, Error>;
|
) -> ParseResult<'a, Output, Error>;
|
||||||
|
|
||||||
#[cfg(not(feature = "parse_debug_trace"))]
|
#[cfg(not(feature = "parse_debug_trace"))]
|
||||||
|
#[inline(always)]
|
||||||
fn trace(self, _message: &'static str) -> Self
|
fn trace(self, _message: &'static str) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
@ -789,7 +790,7 @@ impl<'a, O: std::fmt::Debug, E: std::fmt::Debug, P: Parser<'a, O, E>> Parser<'a,
|
|||||||
where
|
where
|
||||||
E: 'a,
|
E: 'a,
|
||||||
{
|
{
|
||||||
fn parse(&self, arena: &'a Bump, state: State<'a>) -> ParseResult<'a, O, E> {
|
fn parse(&self, arena: &'a Bump, state: State<'a>, min_indent: u32) -> ParseResult<'a, O, E> {
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
@ -803,7 +804,7 @@ where
|
|||||||
let cur_indent = INDENT.with(|i| *i.borrow());
|
let cur_indent = INDENT.with(|i| *i.borrow());
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{:>5?}: {}{:<50}",
|
"{:<5?}: {}{:<50}",
|
||||||
state.pos(),
|
state.pos(),
|
||||||
&indent_text[..cur_indent * 2],
|
&indent_text[..cur_indent * 2],
|
||||||
self.message
|
self.message
|
||||||
@ -1379,11 +1380,12 @@ macro_rules! and {
|
|||||||
macro_rules! one_of {
|
macro_rules! one_of {
|
||||||
($p1:expr, $p2:expr) => {
|
($p1:expr, $p2:expr) => {
|
||||||
move |arena: &'a bumpalo::Bump, state: $crate::state::State<'a>, min_indent: u32| {
|
move |arena: &'a bumpalo::Bump, state: $crate::state::State<'a>, min_indent: u32| {
|
||||||
|
let original_state = state.clone();
|
||||||
|
|
||||||
match $p1.parse(arena, state, min_indent) {
|
match $p1.parse(arena, state, min_indent) {
|
||||||
valid @ Ok(_) => valid,
|
valid @ Ok(_) => valid,
|
||||||
Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state)),
|
Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state)),
|
||||||
Err((NoProgress, _, state)) => $p2.parse(arena, state, min_indent),
|
Err((NoProgress, _, _)) => $p2.parse(arena, original_state, min_indent),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Expr(When(Condition(Start(@30), @29), @24), @0)
|
@ -0,0 +1,6 @@
|
|||||||
|
when Just 4 is
|
||||||
|
Just when ->
|
||||||
|
4
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
2
|
@ -0,0 +1 @@
|
|||||||
|
Expr(When(Arrow(@26), @20), @0)
|
@ -0,0 +1,3 @@
|
|||||||
|
when 5 is
|
||||||
|
1 -> 2
|
||||||
|
_
|
@ -124,6 +124,8 @@ mod test_parse {
|
|||||||
fail/lambda_missing_indent.expr,
|
fail/lambda_missing_indent.expr,
|
||||||
fail/type_argument_no_arrow.expr,
|
fail/type_argument_no_arrow.expr,
|
||||||
fail/type_double_comma.expr,
|
fail/type_double_comma.expr,
|
||||||
|
fail/when_missing_arrow.expr,
|
||||||
|
fail/pattern_binds_keyword.expr,
|
||||||
pass/ability_demand_signature_is_multiline.expr,
|
pass/ability_demand_signature_is_multiline.expr,
|
||||||
pass/ability_multi_line.expr,
|
pass/ability_multi_line.expr,
|
||||||
pass/ability_single_line.expr,
|
pass/ability_single_line.expr,
|
||||||
|
@ -133,7 +133,8 @@ impl Position {
|
|||||||
|
|
||||||
impl Debug for Position {
|
impl Debug for Position {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "@{}", self.offset)
|
write!(f, "@")?;
|
||||||
|
self.offset.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4847,14 +4847,27 @@ mod test_reporting {
|
|||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
@r###"
|
@r###"
|
||||||
── MISSING EXPRESSION ───────────────────── tmp/pattern_binds_keyword/Test.roc ─
|
── MISSING ARROW ────────────────────────── tmp/pattern_binds_keyword/Test.roc ─
|
||||||
|
|
||||||
I am partway through parsing a `when` expression, but I got stuck here:
|
I am partway through parsing a `when` expression, but got stuck here:
|
||||||
|
|
||||||
5│ Just when ->
|
5│ Just when ->
|
||||||
^
|
^
|
||||||
|
|
||||||
I was expecting to see an expression like 42 or "hello".
|
I was expecting to see an arrow next.
|
||||||
|
|
||||||
|
Note: Sometimes I get confused by indentation, so try to make your `when`
|
||||||
|
look something like this:
|
||||||
|
|
||||||
|
when List.first plants is
|
||||||
|
Ok n ->
|
||||||
|
n
|
||||||
|
|
||||||
|
Err _ ->
|
||||||
|
200
|
||||||
|
|
||||||
|
Notice the indentation. All patterns are aligned, and each branch is
|
||||||
|
indented a bit more than the corresponding pattern. That is important!
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user