mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Always combine line,column into Position
This commit is contained in:
parent
f19220473a
commit
4d7070ce3b
22 changed files with 1181 additions and 1293 deletions
|
@ -1,17 +1,18 @@
|
|||
use crate::ast::CommentOrNewline;
|
||||
use crate::ast::Spaceable;
|
||||
use crate::parser::{self, and, backtrackable, BadInputError, Col, Parser, Progress::*, Row};
|
||||
use crate::parser::{self, and, backtrackable, BadInputError, Parser, Progress::*};
|
||||
use crate::state::State;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::Loc;
|
||||
use roc_region::all::Position;
|
||||
|
||||
pub fn space0_around_ee<'a, P, S, E>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||
indent_before_problem: fn(Row, Col) -> E,
|
||||
indent_after_problem: fn(Row, Col) -> E,
|
||||
space_problem: fn(BadInputError, Position) -> E,
|
||||
indent_before_problem: fn(Position) -> E,
|
||||
indent_after_problem: fn(Position) -> E,
|
||||
) -> impl Parser<'a, Loc<S>, E>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
|
@ -35,9 +36,9 @@ where
|
|||
pub fn space0_before_optional_after<'a, P, S, E>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||
indent_before_problem: fn(Row, Col) -> E,
|
||||
indent_after_problem: fn(Row, Col) -> E,
|
||||
space_problem: fn(BadInputError, Position) -> E,
|
||||
indent_before_problem: fn(Position) -> E,
|
||||
indent_after_problem: fn(Position) -> E,
|
||||
) -> impl Parser<'a, Loc<S>, E>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
|
@ -100,8 +101,8 @@ where
|
|||
pub fn space0_before_e<'a, P, S, E>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||
indent_problem: fn(Row, Col) -> E,
|
||||
space_problem: fn(BadInputError, Position) -> E,
|
||||
indent_problem: fn(Position) -> E,
|
||||
) -> impl Parser<'a, Loc<S>, E>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
|
@ -127,8 +128,8 @@ where
|
|||
pub fn space0_after_e<'a, P, S, E>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||
indent_problem: fn(Row, Col) -> E,
|
||||
space_problem: fn(BadInputError, Position) -> E,
|
||||
indent_problem: fn(Position) -> E,
|
||||
) -> impl Parser<'a, Loc<S>, E>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
|
@ -153,24 +154,24 @@ where
|
|||
|
||||
pub fn check_indent<'a, E>(
|
||||
min_indent: u16,
|
||||
indent_problem: fn(Row, Col) -> E,
|
||||
indent_problem: fn(Position) -> E,
|
||||
) -> impl Parser<'a, (), E>
|
||||
where
|
||||
E: 'a,
|
||||
{
|
||||
move |_, state: State<'a>| {
|
||||
if state.column >= min_indent {
|
||||
if state.pos.column >= min_indent {
|
||||
Ok((NoProgress, (), state))
|
||||
} else {
|
||||
Err((NoProgress, indent_problem(state.line, state.column), state))
|
||||
Err((NoProgress, indent_problem(state.pos), state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn space0_e<'a, E>(
|
||||
min_indent: u16,
|
||||
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||
indent_problem: fn(Row, Col) -> E,
|
||||
space_problem: fn(BadInputError, Position) -> E,
|
||||
indent_problem: fn(Position) -> E,
|
||||
) -> impl Parser<'a, &'a [CommentOrNewline<'a>], E>
|
||||
where
|
||||
E: 'a,
|
||||
|
@ -181,8 +182,8 @@ where
|
|||
#[inline(always)]
|
||||
fn spaces_help_help<'a, E>(
|
||||
min_indent: u16,
|
||||
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||
indent_problem: fn(Row, Col) -> E,
|
||||
space_problem: fn(BadInputError, Position) -> E,
|
||||
indent_problem: fn(Position) -> E,
|
||||
) -> impl Parser<'a, &'a [CommentOrNewline<'a>], E>
|
||||
where
|
||||
E: 'a,
|
||||
|
@ -194,53 +195,49 @@ where
|
|||
|
||||
match eat_spaces(
|
||||
state.bytes(),
|
||||
state.line,
|
||||
state.column,
|
||||
state.pos,
|
||||
comments_and_newlines,
|
||||
) {
|
||||
HasTab { row, col } => {
|
||||
HasTab(pos) => {
|
||||
// there was a tab character
|
||||
let mut state = state;
|
||||
state.line = row;
|
||||
state.column = col;
|
||||
state.pos = pos;
|
||||
// TODO: it _seems_ like if we're changing the line/column, we should also be
|
||||
// advancing the state by the corresponding number of bytes.
|
||||
// Not doing this is likely a bug!
|
||||
// state = state.advance(<something>);
|
||||
Err((
|
||||
MadeProgress,
|
||||
space_problem(BadInputError::HasTab, row, col),
|
||||
space_problem(BadInputError::HasTab, pos),
|
||||
state,
|
||||
))
|
||||
}
|
||||
Good {
|
||||
row,
|
||||
col,
|
||||
pos,
|
||||
bytes,
|
||||
comments_and_newlines,
|
||||
} => {
|
||||
if bytes == state.bytes() {
|
||||
Ok((NoProgress, &[] as &[_], state))
|
||||
} else if state.line != row {
|
||||
} else if state.pos.line != pos.line {
|
||||
// we parsed at least one newline
|
||||
|
||||
state.indent_col = col;
|
||||
state.indent_col = pos.column;
|
||||
|
||||
if col >= min_indent {
|
||||
state.line = row;
|
||||
state.column = col;
|
||||
if pos.column >= min_indent {
|
||||
state.pos = pos;
|
||||
state = state.advance(state.bytes().len() - bytes.len());
|
||||
|
||||
Ok((MadeProgress, comments_and_newlines.into_bump_slice(), state))
|
||||
} else {
|
||||
Err((
|
||||
MadeProgress,
|
||||
indent_problem(state.line, state.column),
|
||||
indent_problem(state.pos),
|
||||
state,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
state.column = col;
|
||||
state.pos.column = pos.column;
|
||||
state = state.advance(state.bytes().len() - bytes.len());
|
||||
|
||||
Ok((MadeProgress, comments_and_newlines.into_bump_slice(), state))
|
||||
|
@ -252,21 +249,16 @@ where
|
|||
|
||||
enum SpaceState<'a> {
|
||||
Good {
|
||||
row: Row,
|
||||
col: Col,
|
||||
pos: Position,
|
||||
bytes: &'a [u8],
|
||||
comments_and_newlines: Vec<'a, CommentOrNewline<'a>>,
|
||||
},
|
||||
HasTab {
|
||||
row: Row,
|
||||
col: Col,
|
||||
},
|
||||
HasTab(Position),
|
||||
}
|
||||
|
||||
fn eat_spaces<'a>(
|
||||
mut bytes: &'a [u8],
|
||||
mut row: Row,
|
||||
mut col: Col,
|
||||
mut pos: Position,
|
||||
mut comments_and_newlines: Vec<'a, CommentOrNewline<'a>>,
|
||||
) -> SpaceState<'a> {
|
||||
use SpaceState::*;
|
||||
|
@ -275,30 +267,30 @@ fn eat_spaces<'a>(
|
|||
match c {
|
||||
b' ' => {
|
||||
bytes = &bytes[1..];
|
||||
col += 1;
|
||||
pos.column += 1;
|
||||
}
|
||||
b'\n' => {
|
||||
bytes = &bytes[1..];
|
||||
row += 1;
|
||||
col = 0;
|
||||
pos.line += 1;
|
||||
pos.column = 0;
|
||||
comments_and_newlines.push(CommentOrNewline::Newline);
|
||||
}
|
||||
b'\r' => {
|
||||
bytes = &bytes[1..];
|
||||
}
|
||||
b'\t' => {
|
||||
return HasTab { row, col };
|
||||
return HasTab(pos);
|
||||
}
|
||||
b'#' => {
|
||||
return eat_line_comment(&bytes[1..], row, col + 1, comments_and_newlines);
|
||||
pos.column += 1;
|
||||
return eat_line_comment(&bytes[1..], pos, comments_and_newlines);
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
Good {
|
||||
row,
|
||||
col,
|
||||
pos,
|
||||
bytes,
|
||||
comments_and_newlines,
|
||||
}
|
||||
|
@ -306,8 +298,7 @@ fn eat_spaces<'a>(
|
|||
|
||||
fn eat_line_comment<'a>(
|
||||
mut bytes: &'a [u8],
|
||||
row: Row,
|
||||
mut col: Col,
|
||||
mut pos: Position,
|
||||
mut comments_and_newlines: Vec<'a, CommentOrNewline<'a>>,
|
||||
) -> SpaceState<'a> {
|
||||
use SpaceState::*;
|
||||
|
@ -316,7 +307,7 @@ fn eat_line_comment<'a>(
|
|||
match bytes.get(1) {
|
||||
Some(b' ') => {
|
||||
bytes = &bytes[2..];
|
||||
col += 2;
|
||||
pos.column += 2;
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -325,16 +316,17 @@ fn eat_line_comment<'a>(
|
|||
bytes = &bytes[2..];
|
||||
|
||||
comments_and_newlines.push(CommentOrNewline::DocComment(""));
|
||||
return eat_spaces(bytes, row + 1, 0, comments_and_newlines);
|
||||
pos.line += 1;
|
||||
pos.column = 0;
|
||||
return eat_spaces(bytes, pos, comments_and_newlines);
|
||||
}
|
||||
None => {
|
||||
// consume the second #
|
||||
col += 1;
|
||||
pos.column += 1;
|
||||
bytes = &bytes[1..];
|
||||
|
||||
return Good {
|
||||
row,
|
||||
col,
|
||||
pos,
|
||||
bytes,
|
||||
comments_and_newlines,
|
||||
};
|
||||
|
@ -347,13 +339,13 @@ fn eat_line_comment<'a>(
|
|||
};
|
||||
|
||||
let initial = bytes;
|
||||
let initial_col = col;
|
||||
let initial_column = pos.column;
|
||||
|
||||
for c in bytes {
|
||||
match c {
|
||||
b'\t' => return HasTab { row, col },
|
||||
b'\t' => return HasTab(pos),
|
||||
b'\n' => {
|
||||
let delta = (col - initial_col) as usize;
|
||||
let delta = (pos.column - initial_column) as usize;
|
||||
let comment = unsafe { std::str::from_utf8_unchecked(&initial[..delta]) };
|
||||
|
||||
if is_doc_comment {
|
||||
|
@ -361,17 +353,19 @@ fn eat_line_comment<'a>(
|
|||
} else {
|
||||
comments_and_newlines.push(CommentOrNewline::LineComment(comment));
|
||||
}
|
||||
return eat_spaces(&bytes[1..], row + 1, 0, comments_and_newlines);
|
||||
pos.line += 1;
|
||||
pos.column = 0;
|
||||
return eat_spaces(&bytes[1..], pos, comments_and_newlines);
|
||||
}
|
||||
_ => {
|
||||
bytes = &bytes[1..];
|
||||
col += 1;
|
||||
pos.column += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We made it to the end of the bytes. This means there's a comment without a trailing newline.
|
||||
let delta = (col - initial_col) as usize;
|
||||
let delta = (pos.column - initial_column) as usize;
|
||||
let comment = unsafe { std::str::from_utf8_unchecked(&initial[..delta]) };
|
||||
|
||||
if is_doc_comment {
|
||||
|
@ -381,8 +375,7 @@ fn eat_line_comment<'a>(
|
|||
}
|
||||
|
||||
Good {
|
||||
row,
|
||||
col,
|
||||
pos,
|
||||
bytes,
|
||||
comments_and_newlines,
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ fn expr_end<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
|||
} else {
|
||||
Err((
|
||||
NoProgress,
|
||||
EExpr::BadExprEnd(state.line, state.column),
|
||||
EExpr::BadExprEnd(state.pos),
|
||||
state,
|
||||
))
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, &'a str>, EExpr<'a
|
|||
}
|
||||
Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state)),
|
||||
Err((NoProgress, _, state)) => {
|
||||
Err((NoProgress, EExpr::Access(state.line, state.column), state))
|
||||
Err((NoProgress, EExpr::Access(state.pos), state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, &'a str>, EExpr<'a
|
|||
fn record_field_access<'a>() -> impl Parser<'a, &'a str, EExpr<'a>> {
|
||||
skip_first!(
|
||||
word1(b'.', EExpr::Access),
|
||||
specialize(|_, r, c| EExpr::Access(r, c), lowercase_ident())
|
||||
specialize(|_, pos| EExpr::Access(pos), lowercase_ident())
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -243,13 +243,12 @@ fn parse_loc_term<'a>(
|
|||
|
||||
fn underscore_expression<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
||||
move |arena: &'a Bump, state: State<'a>| {
|
||||
let row = state.line;
|
||||
let col = state.column;
|
||||
let start = state.pos;
|
||||
|
||||
let (_, _, next_state) = word1(b'_', EExpr::Underscore).parse(arena, state)?;
|
||||
|
||||
let lowercase_ident_expr =
|
||||
{ specialize(move |_, _, _| EExpr::End(row, col), lowercase_ident()) };
|
||||
{ specialize(move |_, _| EExpr::End(start), lowercase_ident()) };
|
||||
|
||||
let (_, output, final_state) = optional(lowercase_ident_expr).parse(arena, next_state)?;
|
||||
|
||||
|
@ -295,7 +294,7 @@ fn loc_possibly_negative_or_negated_term<'a>(
|
|||
}
|
||||
|
||||
fn fail_expr_start_e<'a, T: 'a>() -> impl Parser<'a, T, EExpr<'a>> {
|
||||
|_arena, state: State<'a>| Err((NoProgress, EExpr::Start(state.line, state.column), state))
|
||||
|_arena, state: State<'a>| Err((NoProgress, EExpr::Start(state.pos), state))
|
||||
}
|
||||
|
||||
fn unary_negate<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
||||
|
@ -313,11 +312,11 @@ fn unary_negate<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
|||
if state.bytes().starts_with(b"-") && !followed_by_whitespace {
|
||||
// the negate is only unary if it is not followed by whitespace
|
||||
let mut state = state.advance(1);
|
||||
state.column += 1;
|
||||
state.pos.column += 1;
|
||||
Ok((MadeProgress, (), state))
|
||||
} else {
|
||||
// this is not a negated expression
|
||||
Err((NoProgress, EExpr::UnaryNot(state.line, state.column), state))
|
||||
Err((NoProgress, EExpr::UnaryNot(state.pos), state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +411,7 @@ impl<'a> ExprState<'a> {
|
|||
argument_error: F,
|
||||
) -> Result<Loc<Expr<'a>>, EExpr<'a>>
|
||||
where
|
||||
F: Fn(Region, Row, Col) -> EExpr<'a>,
|
||||
F: Fn(Region, Position) -> EExpr<'a>,
|
||||
{
|
||||
if !self.operators.is_empty() {
|
||||
// this `=` or `<-` likely occurred inline; treat it as an invalid operator
|
||||
|
@ -423,7 +422,7 @@ impl<'a> ExprState<'a> {
|
|||
};
|
||||
|
||||
let fail =
|
||||
EExpr::BadOperator(opchar, loc_op.region.start_line, loc_op.region.start_col);
|
||||
EExpr::BadOperator(opchar, loc_op.region.start());
|
||||
|
||||
Err(fail)
|
||||
} else if !self.arguments.is_empty() {
|
||||
|
@ -431,8 +430,7 @@ impl<'a> ExprState<'a> {
|
|||
|
||||
Err(argument_error(
|
||||
region,
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
loc_op.region.start(),
|
||||
))
|
||||
} else {
|
||||
self.consume_spaces(arena);
|
||||
|
@ -449,7 +447,7 @@ impl<'a> ExprState<'a> {
|
|||
|
||||
if !self.operators.is_empty() {
|
||||
// this `:` likely occurred inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(":", loc_op.region.start_line, loc_op.region.start_col);
|
||||
let fail = EExpr::BadOperator(":", loc_op.region.start());
|
||||
|
||||
Err(fail)
|
||||
} else {
|
||||
|
@ -532,8 +530,10 @@ fn numeric_negate_expression<'a, T>(
|
|||
) -> Loc<Expr<'a>> {
|
||||
debug_assert_eq!(state.bytes().get(0), Some(&b'-'));
|
||||
// for overflow reasons, we must make the unary minus part of the number literal.
|
||||
let mut region = expr.region;
|
||||
region.start_col -= 1;
|
||||
let start = expr.region.start();
|
||||
let region = Region::new(
|
||||
Position { column: start.column - 1, ..start},
|
||||
expr.region.end());
|
||||
|
||||
let new_expr = match &expr.value {
|
||||
Expr::Num(string) => {
|
||||
|
@ -789,14 +789,14 @@ fn parse_defs_end<'a>(
|
|||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, DefState<'a>, EExpr<'a>> {
|
||||
let min_indent = start.col;
|
||||
let min_indent = start.column;
|
||||
let initial = state.clone();
|
||||
|
||||
let state = match space0_e(min_indent, EExpr::Space, EExpr::IndentStart).parse(arena, state) {
|
||||
Err((MadeProgress, _, s)) => {
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EExpr::DefMissingFinalExpr(s.line, s.column),
|
||||
EExpr::DefMissingFinalExpr(s.pos),
|
||||
s,
|
||||
));
|
||||
}
|
||||
|
@ -907,7 +907,7 @@ fn parse_defs_expr<'a>(
|
|||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||
let min_indent = start.col;
|
||||
let min_indent = start.column;
|
||||
|
||||
match parse_defs_end(options, start, def_state, arena, state) {
|
||||
Err(bad) => Err(bad),
|
||||
|
@ -924,7 +924,7 @@ fn parse_defs_expr<'a>(
|
|||
Err((_, fail, state)) => {
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EExpr::DefMissingFinalExpr2(arena.alloc(fail), state.line, state.column),
|
||||
EExpr::DefMissingFinalExpr2(arena.alloc(fail), state.pos),
|
||||
state,
|
||||
));
|
||||
}
|
||||
|
@ -989,7 +989,7 @@ fn parse_expr_operator<'a>(
|
|||
}
|
||||
BinOp::Assignment => {
|
||||
let expr_region = expr_state.expr.region;
|
||||
let indented_more = start.col + 1;
|
||||
let indented_more = start.column + 1;
|
||||
|
||||
let call = expr_state
|
||||
.validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction)
|
||||
|
@ -1020,8 +1020,7 @@ fn parse_expr_operator<'a>(
|
|||
// this `=` likely occurred inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(
|
||||
arena.alloc("="),
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
loc_op.region.start(),
|
||||
);
|
||||
|
||||
return Err((MadeProgress, fail, state));
|
||||
|
@ -1038,11 +1037,11 @@ fn parse_expr_operator<'a>(
|
|||
}
|
||||
BinOp::Backpassing => {
|
||||
let expr_region = expr_state.expr.region;
|
||||
let indented_more = start.col + 1;
|
||||
let indented_more = start.column + 1;
|
||||
|
||||
let call = expr_state
|
||||
.validate_assignment_or_backpassing(arena, loc_op, |_, r, c| {
|
||||
EExpr::BadOperator("<-", r, c)
|
||||
.validate_assignment_or_backpassing(arena, loc_op, |_, pos| {
|
||||
EExpr::BadOperator("<-", pos)
|
||||
})
|
||||
.map_err(|fail| (MadeProgress, fail, state.clone()))?;
|
||||
|
||||
|
@ -1064,8 +1063,7 @@ fn parse_expr_operator<'a>(
|
|||
// this `=` likely occurred inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(
|
||||
"=",
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
loc_op.region.start()
|
||||
);
|
||||
|
||||
return Err((MadeProgress, fail, state));
|
||||
|
@ -1092,7 +1090,7 @@ fn parse_expr_operator<'a>(
|
|||
}
|
||||
BinOp::HasType => {
|
||||
let expr_region = expr_state.expr.region;
|
||||
let indented_more = start.col + 1;
|
||||
let indented_more = start.column + 1;
|
||||
|
||||
let (expr, arguments) = expr_state
|
||||
.validate_has_type(arena, loc_op)
|
||||
|
@ -1173,8 +1171,7 @@ fn parse_expr_operator<'a>(
|
|||
// this `:` likely occurred inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(
|
||||
":",
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
loc_op.region.start(),
|
||||
);
|
||||
|
||||
return Err((MadeProgress, fail, state));
|
||||
|
@ -1300,7 +1297,7 @@ fn parse_expr_end<'a>(
|
|||
// try multi-backpassing
|
||||
if options.accept_multi_backpassing && state.bytes().starts_with(b",") {
|
||||
state = state.advance(1);
|
||||
state.column += 1;
|
||||
state.pos.column += 1;
|
||||
|
||||
let (_, mut patterns, state) = specialize_ref(
|
||||
EExpr::Pattern,
|
||||
|
@ -1330,7 +1327,7 @@ fn parse_expr_end<'a>(
|
|||
match word2(b'<', b'-', EExpr::BackpassArrow).parse(arena, state) {
|
||||
Err((_, fail, state)) => Err((MadeProgress, fail, state)),
|
||||
Ok((_, _, state)) => {
|
||||
let min_indent = start.col;
|
||||
let min_indent = start.column;
|
||||
|
||||
let parse_body = space0_before_e(
|
||||
move |a, s| parse_loc_expr(min_indent + 1, a, s),
|
||||
|
@ -1362,7 +1359,7 @@ fn parse_expr_end<'a>(
|
|||
} else if options.check_for_arrow && state.bytes().starts_with(b"->") {
|
||||
Err((
|
||||
MadeProgress,
|
||||
EExpr::BadOperator("->", state.line, state.column),
|
||||
EExpr::BadOperator("->", state.pos),
|
||||
state,
|
||||
))
|
||||
} else {
|
||||
|
@ -1573,7 +1570,7 @@ pub fn defs<'a>(min_indent: u16) -> impl Parser<'a, Vec<'a, Loc<Def<'a>>>, EExpr
|
|||
let (_, def_state, state) = parse_defs_end(options, start, def_state, arena, state)?;
|
||||
|
||||
let (_, final_space, state) =
|
||||
space0_e(start.col, EExpr::Space, EExpr::IndentEnd).parse(arena, state)?;
|
||||
space0_e(start.column, EExpr::Space, EExpr::IndentEnd).parse(arena, state)?;
|
||||
|
||||
let mut output = Vec::with_capacity_in(def_state.defs.len(), arena);
|
||||
|
||||
|
@ -1684,7 +1681,7 @@ mod when {
|
|||
return Err((
|
||||
progress,
|
||||
// TODO maybe pass case_indent here?
|
||||
EWhen::PatternAlignment(5, state.line, state.column),
|
||||
EWhen::PatternAlignment(5, state.pos),
|
||||
state,
|
||||
));
|
||||
}
|
||||
|
@ -1724,7 +1721,7 @@ mod when {
|
|||
// 1. Parse the first branch and get its indentation level. (It must be >= min_indent.)
|
||||
// 2. Parse the other branches. Their indentation levels must be == the first branch's.
|
||||
|
||||
let (_, ((pattern_indent_level, loc_first_patterns), loc_first_guard), mut state) =
|
||||
let (_, ((pattern_indent_level, loc_first_patterns), loc_first_guard), mut state): (_, ((_, _), _), State<'a>) =
|
||||
branch_alternatives(min_indent, options, None).parse(arena, state)?;
|
||||
let original_indent = pattern_indent_level;
|
||||
|
||||
|
@ -1752,7 +1749,7 @@ mod when {
|
|||
let indent = pattern_indent_level - indent_col;
|
||||
Err((
|
||||
MadeProgress,
|
||||
EWhen::PatternAlignment(indent, state.line, state.column),
|
||||
EWhen::PatternAlignment(indent, state.pos),
|
||||
state,
|
||||
))
|
||||
}
|
||||
|
@ -1803,7 +1800,7 @@ mod when {
|
|||
) -> impl Parser<
|
||||
'a,
|
||||
(
|
||||
(Col, Vec<'a, Loc<Pattern<'a>>>),
|
||||
(u16, Vec<'a, Loc<Pattern<'a>>>),
|
||||
Option<Loc<Expr<'a>>>,
|
||||
),
|
||||
EWhen<'a>,
|
||||
|
@ -1869,7 +1866,7 @@ mod when {
|
|||
fn branch_alternatives_help<'a>(
|
||||
min_indent: u16,
|
||||
pattern_indent_level: Option<u16>,
|
||||
) -> impl Parser<'a, (Col, Vec<'a, Loc<Pattern<'a>>>), EWhen<'a>> {
|
||||
) -> impl Parser<'a, (u16, Vec<'a, Loc<Pattern<'a>>>), EWhen<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
let initial = state.clone();
|
||||
|
||||
|
@ -1879,19 +1876,19 @@ mod when {
|
|||
Err((NoProgress, fail, _)) => Err((NoProgress, fail, initial)),
|
||||
Ok((_progress, spaces, state)) => {
|
||||
match pattern_indent_level {
|
||||
Some(wanted) if state.column > wanted => {
|
||||
Some(wanted) if state.pos.column > wanted => {
|
||||
// this branch is indented too much
|
||||
Err((
|
||||
NoProgress,
|
||||
EWhen::IndentPattern(state.line, state.column),
|
||||
EWhen::IndentPattern(state.pos),
|
||||
initial,
|
||||
))
|
||||
}
|
||||
Some(wanted) if state.column < wanted => {
|
||||
let indent = wanted - state.column;
|
||||
Some(wanted) if state.pos.column < wanted => {
|
||||
let indent = wanted - state.pos.column;
|
||||
Err((
|
||||
NoProgress,
|
||||
EWhen::PatternAlignment(indent, state.line, state.column),
|
||||
EWhen::PatternAlignment(indent, state.pos),
|
||||
initial,
|
||||
))
|
||||
}
|
||||
|
@ -1900,7 +1897,7 @@ mod when {
|
|||
min_indent.max(pattern_indent_level.unwrap_or(min_indent));
|
||||
// the region is not reliable for the indent col in the case of
|
||||
// parentheses around patterns
|
||||
let pattern_indent_col = state.column;
|
||||
let pattern_indent_col = state.pos.column;
|
||||
|
||||
let parser = sep_by1(
|
||||
word1(b'|', EWhen::Bar),
|
||||
|
@ -2005,9 +2002,9 @@ fn expect_help<'a>(
|
|||
|
||||
let (_, condition, state) = space0_before_e(
|
||||
specialize_ref(EExpect::Condition, move |arena, state| {
|
||||
parse_loc_expr_with_options(start.col + 1, options, arena, state)
|
||||
parse_loc_expr_with_options(start.column + 1, options, arena, state)
|
||||
}),
|
||||
start.col + 1,
|
||||
start.column + 1,
|
||||
EExpect::Space,
|
||||
EExpect::IndentCondition,
|
||||
)
|
||||
|
@ -2187,7 +2184,7 @@ fn record_field_help<'a>(
|
|||
move |arena, state: State<'a>| {
|
||||
// You must have a field name, e.g. "email"
|
||||
let (progress, loc_label, state) =
|
||||
specialize(|_, r, c| ERecord::Field(r, c), loc!(lowercase_ident()))
|
||||
specialize(|_, pos| ERecord::Field(pos), loc!(lowercase_ident()))
|
||||
.parse(arena, state)?;
|
||||
debug_assert_eq!(progress, MadeProgress);
|
||||
|
||||
|
@ -2238,7 +2235,7 @@ fn record_field_help<'a>(
|
|||
|
||||
fn record_updateable_identifier<'a>() -> impl Parser<'a, Expr<'a>, ERecord<'a>> {
|
||||
specialize(
|
||||
|_, r, c| ERecord::Updateable(r, c),
|
||||
|_, pos| ERecord::Updateable(pos),
|
||||
map_with_arena!(parse_ident, ident_to_expr),
|
||||
)
|
||||
}
|
||||
|
@ -2390,8 +2387,6 @@ fn number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, ENumber> {
|
|||
|
||||
const BINOP_CHAR_SET: &[u8] = b"+-/*=.<>:&|^?%!";
|
||||
|
||||
use crate::parser::{Col, Row};
|
||||
|
||||
fn operator<'a>() -> impl Parser<'a, BinOp, EExpr<'a>> {
|
||||
|_, state| operator_help(EExpr::Start, EExpr::BadOperator, state)
|
||||
}
|
||||
|
@ -2403,15 +2398,15 @@ fn operator_help<'a, F, G, E>(
|
|||
mut state: State<'a>,
|
||||
) -> ParseResult<'a, BinOp, E>
|
||||
where
|
||||
F: Fn(Row, Col) -> E,
|
||||
G: Fn(&'a str, Row, Col) -> E,
|
||||
F: Fn(Position) -> E,
|
||||
G: Fn(&'a str, Position) -> E,
|
||||
E: 'a,
|
||||
{
|
||||
let chomped = chomp_ops(state.bytes());
|
||||
|
||||
macro_rules! good {
|
||||
($op:expr, $width:expr) => {{
|
||||
state.column += $width;
|
||||
state.pos.column += $width;
|
||||
state = state.advance($width);
|
||||
|
||||
Ok((MadeProgress, $op, state))
|
||||
|
@ -2420,12 +2415,12 @@ where
|
|||
|
||||
macro_rules! bad_made_progress {
|
||||
($op:expr) => {{
|
||||
Err((MadeProgress, to_error($op, state.line, state.column), state))
|
||||
Err((MadeProgress, to_error($op, state.pos), state))
|
||||
}};
|
||||
}
|
||||
|
||||
match chomped {
|
||||
"" => Err((NoProgress, to_expectation(state.line, state.column), state)),
|
||||
"" => Err((NoProgress, to_expectation(state.pos), state)),
|
||||
"+" => good!(BinOp::Plus, 1),
|
||||
"-" => good!(BinOp::Minus, 1),
|
||||
"*" => good!(BinOp::Star, 1),
|
||||
|
@ -2436,7 +2431,7 @@ where
|
|||
"<" => good!(BinOp::LessThan, 1),
|
||||
"." => {
|
||||
// a `.` makes no progress, so it does not interfere with `.foo` access(or)
|
||||
Err((NoProgress, to_error(".", state.line, state.column), state))
|
||||
Err((NoProgress, to_error(".", state.pos), state))
|
||||
}
|
||||
"=" => good!(BinOp::Assignment, 1),
|
||||
":" => good!(BinOp::HasType, 1),
|
||||
|
@ -2451,7 +2446,7 @@ where
|
|||
"%%" => good!(BinOp::DoublePercent, 2),
|
||||
"->" => {
|
||||
// makes no progress, so it does not interfere with `_ if isGood -> ...`
|
||||
Err((NoProgress, to_error("->", state.line, state.column), state))
|
||||
Err((NoProgress, to_error("->", state.pos), state))
|
||||
}
|
||||
"<-" => good!(BinOp::Backpassing, 2),
|
||||
_ => bad_made_progress!(chomped),
|
||||
|
|
|
@ -226,7 +226,7 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
|
|||
|
||||
let (_, opt_shorthand, state) = maybe!(and!(
|
||||
skip_second!(
|
||||
specialize(|_, r, c| EPackageEntry::Shorthand(r, c), lowercase_ident()),
|
||||
specialize(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()),
|
||||
word1(b':', EPackageEntry::Colon)
|
||||
),
|
||||
space0_e(
|
||||
|
@ -291,7 +291,7 @@ where
|
|||
if chomped == 0 {
|
||||
Ok((NoProgress, (), state))
|
||||
} else {
|
||||
state.column += chomped as u16;
|
||||
state.pos.column += chomped as u16;
|
||||
state = state.advance(chomped);
|
||||
|
||||
Ok((MadeProgress, (), state))
|
||||
|
@ -318,7 +318,7 @@ pub fn package_name<'a>() -> impl Parser<'a, PackageName<'a>, EPackageName> {
|
|||
|_, mut state: State<'a>| match chomp_package_part(state.bytes()) {
|
||||
Err(progress) => Err((
|
||||
progress,
|
||||
EPackageName::Account(state.line, state.column),
|
||||
EPackageName::Account(state.pos),
|
||||
state,
|
||||
)),
|
||||
Ok(account) => {
|
||||
|
@ -328,13 +328,13 @@ pub fn package_name<'a>() -> impl Parser<'a, PackageName<'a>, EPackageName> {
|
|||
match chomp_package_part(&state.bytes()[chomped..]) {
|
||||
Err(progress) => Err((
|
||||
progress,
|
||||
EPackageName::Pkg(state.line, state.column + chomped as u16),
|
||||
EPackageName::Pkg(state.pos.bump_column(chomped as u16)),
|
||||
state,
|
||||
)),
|
||||
Ok(pkg) => {
|
||||
chomped += pkg.len();
|
||||
|
||||
state.column += chomped as u16;
|
||||
state.pos.column += chomped as u16;
|
||||
state = state.advance(chomped);
|
||||
|
||||
let value = PackageName { account, pkg };
|
||||
|
@ -344,7 +344,7 @@ pub fn package_name<'a>() -> impl Parser<'a, PackageName<'a>, EPackageName> {
|
|||
} else {
|
||||
Err((
|
||||
MadeProgress,
|
||||
EPackageName::MissingSlash(state.line, state.column + chomped as u16),
|
||||
EPackageName::MissingSlash(state.pos.bump_column(chomped as u16)),
|
||||
state,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{BadInputError, Col, EExpr, ParseResult, Parser, Row};
|
||||
use crate::parser::{BadInputError, EExpr, ParseResult, Parser};
|
||||
use crate::state::State;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::Position;
|
||||
|
||||
/// 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
|
||||
|
@ -67,7 +68,7 @@ pub fn lowercase_ident<'a>() -> impl Parser<'a, &'a str, ()> {
|
|||
Err((NoProgress, (), state))
|
||||
} else {
|
||||
let width = ident.len();
|
||||
match state.advance_without_indenting_ee(width, |_, _| ()) {
|
||||
match state.advance_without_indenting_ee(width, |_| ()) {
|
||||
Ok(state) => Ok((MadeProgress, ident, state)),
|
||||
Err(bad) => Err(bad),
|
||||
}
|
||||
|
@ -79,12 +80,12 @@ pub fn lowercase_ident<'a>() -> impl Parser<'a, &'a str, ()> {
|
|||
pub fn tag_name<'a>() -> impl Parser<'a, &'a str, ()> {
|
||||
move |arena, state: State<'a>| {
|
||||
if state.bytes().starts_with(b"@") {
|
||||
match chomp_private_tag(state.bytes(), state.line, state.column) {
|
||||
Err(BadIdent::Start(_, _)) => Err((NoProgress, (), state)),
|
||||
match chomp_private_tag(state.bytes(), state.pos) {
|
||||
Err(BadIdent::Start(_)) => Err((NoProgress, (), state)),
|
||||
Err(_) => Err((MadeProgress, (), state)),
|
||||
Ok(ident) => {
|
||||
let width = ident.len();
|
||||
match state.advance_without_indenting_ee(width, |_, _| ()) {
|
||||
match state.advance_without_indenting_ee(width, |_| ()) {
|
||||
Ok(state) => Ok((MadeProgress, ident, state)),
|
||||
Err(bad) => Err(bad),
|
||||
}
|
||||
|
@ -106,7 +107,7 @@ pub fn uppercase_ident<'a>() -> impl Parser<'a, &'a str, ()> {
|
|||
Err(progress) => Err((progress, (), state)),
|
||||
Ok(ident) => {
|
||||
let width = ident.len();
|
||||
match state.advance_without_indenting_ee(width, |_, _| ()) {
|
||||
match state.advance_without_indenting_ee(width, |_| ()) {
|
||||
Ok(state) => Ok((MadeProgress, ident, state)),
|
||||
Err(bad) => Err(bad),
|
||||
}
|
||||
|
@ -122,7 +123,7 @@ pub fn unqualified_ident<'a>() -> impl Parser<'a, &'a str, ()> {
|
|||
Err((MadeProgress, (), state))
|
||||
} else {
|
||||
let width = ident.len();
|
||||
match state.advance_without_indenting_ee(width, |_, _| ()) {
|
||||
match state.advance_without_indenting_ee(width, |_| ()) {
|
||||
Ok(state) => Ok((MadeProgress, ident, state)),
|
||||
Err(bad) => Err(bad),
|
||||
}
|
||||
|
@ -133,8 +134,8 @@ pub fn unqualified_ident<'a>() -> impl Parser<'a, &'a str, ()> {
|
|||
|
||||
macro_rules! advance_state {
|
||||
($state:expr, $n:expr) => {
|
||||
$state.advance_without_indenting_ee($n, |r, c| {
|
||||
BadIdent::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
$state.advance_without_indenting_ee($n, |pos| {
|
||||
BadIdent::Space(crate::parser::BadInputError::LineTooLong, pos)
|
||||
})
|
||||
};
|
||||
}
|
||||
|
@ -151,7 +152,7 @@ pub fn parse_ident<'a>(arena: &'a Bump, state: State<'a>) -> ParseResult<'a, Ide
|
|||
if first == keyword {
|
||||
return Err((
|
||||
NoProgress,
|
||||
EExpr::Start(initial.line, initial.column),
|
||||
EExpr::Start(initial.pos),
|
||||
initial,
|
||||
));
|
||||
}
|
||||
|
@ -163,11 +164,11 @@ pub fn parse_ident<'a>(arena: &'a Bump, state: State<'a>) -> ParseResult<'a, Ide
|
|||
Ok((progress, ident, state))
|
||||
}
|
||||
Err((NoProgress, _, state)) => {
|
||||
Err((NoProgress, EExpr::Start(state.line, state.column), state))
|
||||
Err((NoProgress, EExpr::Start(state.pos), state))
|
||||
}
|
||||
Err((MadeProgress, fail, state)) => match fail {
|
||||
BadIdent::Start(r, c) => Err((NoProgress, EExpr::Start(r, c), state)),
|
||||
BadIdent::Space(e, r, c) => Err((NoProgress, EExpr::Space(e, r, c), state)),
|
||||
BadIdent::Start(pos) => Err((NoProgress, EExpr::Start(pos), state)),
|
||||
BadIdent::Space(e, pos) => Err((NoProgress, EExpr::Space(e, pos), state)),
|
||||
_ => malformed_identifier(initial.bytes(), fail, state),
|
||||
},
|
||||
}
|
||||
|
@ -182,8 +183,8 @@ fn malformed_identifier<'a>(
|
|||
let delta = initial_bytes.len() - state.bytes().len();
|
||||
let parsed_str = unsafe { std::str::from_utf8_unchecked(&initial_bytes[..chomped + delta]) };
|
||||
|
||||
state = state.advance_without_indenting_ee(chomped, |r, c| {
|
||||
EExpr::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
state = state.advance_without_indenting_ee(chomped, |pos| {
|
||||
EExpr::Space(crate::parser::BadInputError::LineTooLong, pos)
|
||||
})?;
|
||||
|
||||
Ok((MadeProgress, Ident::Malformed(parsed_str, problem), state))
|
||||
|
@ -209,16 +210,16 @@ pub fn chomp_malformed(bytes: &[u8]) -> usize {
|
|||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BadIdent {
|
||||
Start(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Start(Position),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
Underscore(Row, Col),
|
||||
QualifiedTag(Row, Col),
|
||||
WeirdAccessor(Row, Col),
|
||||
WeirdDotAccess(Row, Col),
|
||||
WeirdDotQualified(Row, Col),
|
||||
StrayDot(Row, Col),
|
||||
BadPrivateTag(Row, Col),
|
||||
Underscore(Position),
|
||||
QualifiedTag(Position),
|
||||
WeirdAccessor(Position),
|
||||
WeirdDotAccess(Position),
|
||||
WeirdDotQualified(Position),
|
||||
StrayDot(Position),
|
||||
BadPrivateTag(Position),
|
||||
}
|
||||
|
||||
fn chomp_lowercase_part(buffer: &[u8]) -> Result<&str, Progress> {
|
||||
|
@ -265,7 +266,7 @@ where
|
|||
}
|
||||
|
||||
/// a `.foo` accessor function
|
||||
fn chomp_accessor(buffer: &[u8], row: Row, col: Col) -> Result<&str, BadIdent> {
|
||||
fn chomp_accessor(buffer: &[u8], pos: Position) -> Result<&str, BadIdent> {
|
||||
// assumes the leading `.` has been chomped already
|
||||
use encode_unicode::CharExt;
|
||||
|
||||
|
@ -274,20 +275,20 @@ fn chomp_accessor(buffer: &[u8], row: Row, col: Col) -> Result<&str, BadIdent> {
|
|||
let chomped = name.len();
|
||||
|
||||
if let Ok(('.', _)) = char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||
Err(BadIdent::WeirdAccessor(row, col))
|
||||
Err(BadIdent::WeirdAccessor(pos))
|
||||
} else {
|
||||
Ok(name)
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// we've already made progress with the initial `.`
|
||||
Err(BadIdent::StrayDot(row, col + 1))
|
||||
Err(BadIdent::StrayDot(Position { line: pos.line, column: pos.column + 1 }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// a `@Token` private tag
|
||||
fn chomp_private_tag(buffer: &[u8], row: Row, col: Col) -> Result<&str, BadIdent> {
|
||||
fn chomp_private_tag(buffer: &[u8], pos: Position) -> Result<&str, BadIdent> {
|
||||
// assumes the leading `@` has NOT been chomped already
|
||||
debug_assert_eq!(buffer.get(0), Some(&b'@'));
|
||||
use encode_unicode::CharExt;
|
||||
|
@ -297,21 +298,20 @@ fn chomp_private_tag(buffer: &[u8], row: Row, col: Col) -> Result<&str, BadIdent
|
|||
let width = 1 + name.len();
|
||||
|
||||
if let Ok(('.', _)) = char::from_utf8_slice_start(&buffer[width..]) {
|
||||
Err(BadIdent::BadPrivateTag(row, col + width as u16))
|
||||
Err(BadIdent::BadPrivateTag(pos.bump_column(width as u16)))
|
||||
} else {
|
||||
let value = unsafe { std::str::from_utf8_unchecked(&buffer[..width]) };
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
Err(_) => Err(BadIdent::BadPrivateTag(row, col + 1)),
|
||||
Err(_) => Err(BadIdent::BadPrivateTag(Position { line: pos.line, column: pos.column + 1})),
|
||||
}
|
||||
}
|
||||
|
||||
fn chomp_identifier_chain<'a>(
|
||||
arena: &'a Bump,
|
||||
buffer: &'a [u8],
|
||||
row: Row,
|
||||
col: Col,
|
||||
pos: Position,
|
||||
) -> Result<(u16, Ident<'a>), (u16, BadIdent)> {
|
||||
use encode_unicode::CharExt;
|
||||
|
||||
|
@ -320,7 +320,7 @@ fn chomp_identifier_chain<'a>(
|
|||
|
||||
match char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||
Ok((ch, width)) => match ch {
|
||||
'.' => match chomp_accessor(&buffer[1..], row, col) {
|
||||
'.' => match chomp_accessor(&buffer[1..], pos) {
|
||||
Ok(accessor) => {
|
||||
let bytes_parsed = 1 + accessor.len();
|
||||
|
||||
|
@ -328,7 +328,7 @@ fn chomp_identifier_chain<'a>(
|
|||
}
|
||||
Err(fail) => return Err((1, fail)),
|
||||
},
|
||||
'@' => match chomp_private_tag(buffer, row, col) {
|
||||
'@' => match chomp_private_tag(buffer, pos) {
|
||||
Ok(tagname) => {
|
||||
let bytes_parsed = tagname.len();
|
||||
|
||||
|
@ -342,10 +342,10 @@ fn chomp_identifier_chain<'a>(
|
|||
first_is_uppercase = c.is_uppercase();
|
||||
}
|
||||
_ => {
|
||||
return Err((0, BadIdent::Start(row, col)));
|
||||
return Err((0, BadIdent::Start(pos)));
|
||||
}
|
||||
},
|
||||
Err(_) => return Err((0, BadIdent::Start(row, col))),
|
||||
Err(_) => return Err((0, BadIdent::Start(pos))),
|
||||
}
|
||||
|
||||
while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||
|
@ -391,15 +391,15 @@ fn chomp_identifier_chain<'a>(
|
|||
}
|
||||
Err(0) if !module_name.is_empty() => Err((
|
||||
chomped as u16,
|
||||
BadIdent::QualifiedTag(row, chomped as u16 + col),
|
||||
BadIdent::QualifiedTag(pos.bump_column(chomped as u16)),
|
||||
)),
|
||||
Err(1) if parts.is_empty() => Err((
|
||||
chomped as u16 + 1,
|
||||
BadIdent::WeirdDotQualified(row, chomped as u16 + col + 1),
|
||||
BadIdent::WeirdDotQualified(pos.bump_column(chomped as u16 + 1)),
|
||||
)),
|
||||
Err(width) => Err((
|
||||
chomped as u16 + width,
|
||||
BadIdent::WeirdDotAccess(row, chomped as u16 + col + width),
|
||||
BadIdent::WeirdDotAccess(pos.bump_column(chomped as u16 + width)),
|
||||
)),
|
||||
}
|
||||
} else if let Ok(('_', _)) = char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||
|
@ -408,7 +408,7 @@ fn chomp_identifier_chain<'a>(
|
|||
// to give good error messages for this case
|
||||
Err((
|
||||
chomped as u16 + 1,
|
||||
BadIdent::Underscore(row, col + chomped as u16 + 1),
|
||||
BadIdent::Underscore(pos.bump_column(chomped as u16 + 1)),
|
||||
))
|
||||
} else if first_is_uppercase {
|
||||
// just one segment, starting with an uppercase letter; that's a global tag
|
||||
|
@ -452,7 +452,7 @@ pub fn concrete_type<'a>() -> impl Parser<'a, (&'a str, &'a str), ()> {
|
|||
move |_, state: State<'a>| match chomp_concrete_type(state.bytes()) {
|
||||
Err(progress) => Err((progress, (), state)),
|
||||
Ok((module_name, type_name, width)) => {
|
||||
match state.advance_without_indenting_ee(width, |_, _| ()) {
|
||||
match state.advance_without_indenting_ee(width, |_| ()) {
|
||||
Ok(state) => Ok((MadeProgress, (module_name, type_name), state)),
|
||||
Err(bad) => Err(bad),
|
||||
}
|
||||
|
@ -528,7 +528,7 @@ fn parse_ident_help<'a>(
|
|||
arena: &'a Bump,
|
||||
mut state: State<'a>,
|
||||
) -> ParseResult<'a, Ident<'a>, BadIdent> {
|
||||
match chomp_identifier_chain(arena, state.bytes(), state.line, state.column) {
|
||||
match chomp_identifier_chain(arena, state.bytes(), state.pos) {
|
||||
Ok((width, ident)) => {
|
||||
state = advance_state!(state, width as usize)?;
|
||||
Ok((MadeProgress, ident, state))
|
||||
|
|
|
@ -8,14 +8,14 @@ use crate::header::{
|
|||
use crate::ident::{lowercase_ident, unqualified_ident, uppercase_ident};
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{
|
||||
backtrackable, specialize, word1, word2, Col, EEffects, EExposes, EHeader, EImports, EPackages,
|
||||
EProvides, ERequires, ETypedIdent, Parser, Row, SyntaxError,
|
||||
backtrackable, specialize, word1, word2, EEffects, EExposes, EHeader, EImports, EPackages,
|
||||
EProvides, ERequires, ETypedIdent, Parser, SyntaxError,
|
||||
};
|
||||
use crate::state::State;
|
||||
use crate::string_literal;
|
||||
use crate::type_annotation;
|
||||
use bumpalo::collections::Vec;
|
||||
use roc_region::all::Loc;
|
||||
use roc_region::all::{Loc, Position};
|
||||
|
||||
fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> {
|
||||
|_arena, state: State<'a>| {
|
||||
|
@ -24,7 +24,7 @@ fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> {
|
|||
} else {
|
||||
Err((
|
||||
NoProgress,
|
||||
SyntaxError::NotEndOfFile(state.line, state.column),
|
||||
SyntaxError::NotEndOfFile(state.pos),
|
||||
state,
|
||||
))
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ pub fn module_defs<'a>() -> impl Parser<'a, Vec<'a, Loc<Def<'a>>>, SyntaxError<'
|
|||
let min_indent = 0;
|
||||
skip_second!(
|
||||
specialize(
|
||||
|e, _, _| SyntaxError::Expr(e),
|
||||
|e, _| SyntaxError::Expr(e),
|
||||
crate::expr::defs(min_indent),
|
||||
),
|
||||
end_of_file()
|
||||
|
@ -175,7 +175,7 @@ fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, ()> {
|
|||
|_, mut state: State<'a>| match chomp_module_name(state.bytes()) {
|
||||
Ok(name) => {
|
||||
let width = name.len();
|
||||
state.column += width as u16;
|
||||
state.pos.column += width as u16;
|
||||
state = state.advance(width);
|
||||
|
||||
Ok((MadeProgress, ModuleName::new(name), state))
|
||||
|
@ -316,7 +316,7 @@ struct ProvidesTo<'a> {
|
|||
fn provides_to_package<'a>() -> impl Parser<'a, To<'a>, EProvides<'a>> {
|
||||
one_of![
|
||||
specialize(
|
||||
|_, r, c| EProvides::Identifier(r, c),
|
||||
|_, pos| EProvides::Identifier(pos),
|
||||
map!(lowercase_ident(), To::ExistingPackage)
|
||||
),
|
||||
specialize(EProvides::Package, map!(package_or_path(), To::NewPackage))
|
||||
|
@ -395,12 +395,12 @@ fn exposes_entry<'a, F, E>(
|
|||
to_expectation: F,
|
||||
) -> impl Parser<'a, Loc<Spaced<'a, ExposedName<'a>>>, E>
|
||||
where
|
||||
F: Fn(crate::parser::Row, crate::parser::Col) -> E,
|
||||
F: Fn(Position) -> E,
|
||||
F: Copy,
|
||||
E: 'a,
|
||||
{
|
||||
loc!(map!(
|
||||
specialize(|_, r, c| to_expectation(r, c), unqualified_ident()),
|
||||
specialize(|_, pos| to_expectation(pos), unqualified_ident()),
|
||||
|n| Spaced::Item(ExposedName::new(n))
|
||||
))
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ fn requires_rigids<'a>(
|
|||
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, PlatformRigid<'a>>>>, ERequires<'a>> {
|
||||
collection_trailing_sep_e!(
|
||||
word1(b'{', ERequires::ListStart),
|
||||
specialize(|_, r, c| ERequires::Rigid(r, c), loc!(requires_rigid())),
|
||||
specialize(|_, pos| ERequires::Rigid(pos), loc!(requires_rigid())),
|
||||
word1(b',', ERequires::ListEnd),
|
||||
word1(b'}', ERequires::ListEnd),
|
||||
min_indent,
|
||||
|
@ -464,7 +464,7 @@ fn requires_rigid<'a>() -> impl Parser<'a, Spaced<'a, PlatformRigid<'a>>, ()> {
|
|||
map!(
|
||||
and!(
|
||||
lowercase_ident(),
|
||||
skip_first!(word2(b'=', b'>', |_, _| ()), uppercase_ident())
|
||||
skip_first!(word2(b'=', b'>', |_| ()), uppercase_ident())
|
||||
),
|
||||
|(rigid, alias)| Spaced::Item(PlatformRigid { rigid, alias })
|
||||
)
|
||||
|
@ -525,10 +525,10 @@ fn exposes_values<'a>() -> impl Parser<
|
|||
fn spaces_around_keyword<'a, E>(
|
||||
min_indent: u16,
|
||||
keyword: &'static str,
|
||||
expectation: fn(Row, Col) -> E,
|
||||
space_problem: fn(crate::parser::BadInputError, Row, Col) -> E,
|
||||
indent_problem1: fn(Row, Col) -> E,
|
||||
indent_problem2: fn(Row, Col) -> E,
|
||||
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,
|
||||
|
@ -580,12 +580,12 @@ fn exposes_module<'a, F, E>(
|
|||
to_expectation: F,
|
||||
) -> impl Parser<'a, Loc<Spaced<'a, ModuleName<'a>>>, E>
|
||||
where
|
||||
F: Fn(crate::parser::Row, crate::parser::Col) -> E,
|
||||
F: Fn(Position) -> E,
|
||||
F: Copy,
|
||||
E: 'a,
|
||||
{
|
||||
loc!(map!(
|
||||
specialize(|_, r, c| to_expectation(r, c), module_name()),
|
||||
specialize(|_, pos| to_expectation(pos), module_name()),
|
||||
Spaced::Item
|
||||
))
|
||||
}
|
||||
|
@ -688,14 +688,14 @@ fn effects<'a>() -> impl Parser<'a, Effects<'a>, EEffects<'a>> {
|
|||
|
||||
// e.g. `fx.`
|
||||
let (_, type_shortname, state) = skip_second!(
|
||||
specialize(|_, r, c| EEffects::Shorthand(r, c), lowercase_ident()),
|
||||
specialize(|_, pos| EEffects::Shorthand(pos), lowercase_ident()),
|
||||
word1(b'.', EEffects::ShorthandDot)
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
// the type name, e.g. Effects
|
||||
let (_, (type_name, spaces_after_type_name), state) = and!(
|
||||
specialize(|_, r, c| EEffects::TypeName(r, c), uppercase_ident()),
|
||||
specialize(|_, pos| EEffects::TypeName(pos), uppercase_ident()),
|
||||
space0_e(min_indent, EEffects::Space, EEffects::IndentListStart)
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
@ -738,7 +738,7 @@ fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<
|
|||
and!(
|
||||
and!(
|
||||
loc!(specialize(
|
||||
|_, r, c| ETypedIdent::Identifier(r, c),
|
||||
|_, pos| ETypedIdent::Identifier(pos),
|
||||
lowercase_ident()
|
||||
)),
|
||||
space0_e(min_indent, ETypedIdent::Space, ETypedIdent::IndentHasType)
|
||||
|
@ -767,16 +767,16 @@ fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<
|
|||
}
|
||||
|
||||
fn shortname<'a>() -> impl Parser<'a, &'a str, EImports> {
|
||||
specialize(|_, r, c| EImports::Shorthand(r, c), lowercase_ident())
|
||||
specialize(|_, pos| EImports::Shorthand(pos), lowercase_ident())
|
||||
}
|
||||
|
||||
fn module_name_help<'a, F, E>(to_expectation: F) -> impl Parser<'a, ModuleName<'a>, E>
|
||||
where
|
||||
F: Fn(crate::parser::Row, crate::parser::Col) -> E,
|
||||
F: Fn(Position) -> E,
|
||||
E: 'a,
|
||||
F: 'a,
|
||||
{
|
||||
specialize(move |_, r, c| to_expectation(r, c), module_name())
|
||||
specialize(move |_, pos| to_expectation(pos), module_name())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -67,7 +67,7 @@ fn chomp_number_base<'a>(
|
|||
|
||||
let string = unsafe { std::str::from_utf8_unchecked(&bytes[..chomped]) };
|
||||
|
||||
let new = state.advance_without_indenting_ee(chomped + 2 + is_negative as usize, |_, _| {
|
||||
let new = state.advance_without_indenting_ee(chomped + 2 + is_negative as usize, |_| {
|
||||
ENumber::LineTooLong
|
||||
})?;
|
||||
|
||||
|
@ -102,7 +102,7 @@ fn chomp_number_dec<'a>(
|
|||
let string =
|
||||
unsafe { std::str::from_utf8_unchecked(&state.bytes()[0..chomped + is_negative as usize]) };
|
||||
|
||||
let new = state.advance_without_indenting_ee(chomped + is_negative as usize, |_, _| {
|
||||
let new = state.advance_without_indenting_ee(chomped + is_negative as usize, |_| {
|
||||
ENumber::LineTooLong
|
||||
})?;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::state::State;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_region::all::{Loc, Region, Position};
|
||||
use Progress::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
|
@ -63,151 +63,151 @@ pub enum SyntaxError<'a> {
|
|||
Expr(EExpr<'a>),
|
||||
Header(EHeader<'a>),
|
||||
Space(BadInputError),
|
||||
NotEndOfFile(Row, Col),
|
||||
NotEndOfFile(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EHeader<'a> {
|
||||
Provides(EProvides<'a>, Row, Col),
|
||||
Exposes(EExposes, Row, Col),
|
||||
Imports(EImports, Row, Col),
|
||||
Requires(ERequires<'a>, Row, Col),
|
||||
Packages(EPackages<'a>, Row, Col),
|
||||
Effects(EEffects<'a>, Row, Col),
|
||||
Provides(EProvides<'a>, Position),
|
||||
Exposes(EExposes, Position),
|
||||
Imports(EImports, Position),
|
||||
Requires(ERequires<'a>, Position),
|
||||
Packages(EPackages<'a>, Position),
|
||||
Effects(EEffects<'a>, Position),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
Start(Row, Col),
|
||||
ModuleName(Row, Col),
|
||||
AppName(EString<'a>, Row, Col),
|
||||
PlatformName(EPackageName, Row, Col),
|
||||
IndentStart(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
Start(Position),
|
||||
ModuleName(Position),
|
||||
AppName(EString<'a>, Position),
|
||||
PlatformName(EPackageName, Position),
|
||||
IndentStart(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EProvides<'a> {
|
||||
Provides(Row, Col),
|
||||
Open(Row, Col),
|
||||
To(Row, Col),
|
||||
IndentProvides(Row, Col),
|
||||
IndentTo(Row, Col),
|
||||
IndentListStart(Row, Col),
|
||||
IndentListEnd(Row, Col),
|
||||
IndentPackage(Row, Col),
|
||||
ListStart(Row, Col),
|
||||
ListEnd(Row, Col),
|
||||
Identifier(Row, Col),
|
||||
Package(EPackageOrPath<'a>, Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Provides(Position),
|
||||
Open(Position),
|
||||
To(Position),
|
||||
IndentProvides(Position),
|
||||
IndentTo(Position),
|
||||
IndentListStart(Position),
|
||||
IndentListEnd(Position),
|
||||
IndentPackage(Position),
|
||||
ListStart(Position),
|
||||
ListEnd(Position),
|
||||
Identifier(Position),
|
||||
Package(EPackageOrPath<'a>, Position),
|
||||
Space(BadInputError, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum EExposes {
|
||||
Exposes(Row, Col),
|
||||
Open(Row, Col),
|
||||
IndentExposes(Row, Col),
|
||||
IndentListStart(Row, Col),
|
||||
IndentListEnd(Row, Col),
|
||||
ListStart(Row, Col),
|
||||
ListEnd(Row, Col),
|
||||
Identifier(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Exposes(Position),
|
||||
Open(Position),
|
||||
IndentExposes(Position),
|
||||
IndentListStart(Position),
|
||||
IndentListEnd(Position),
|
||||
ListStart(Position),
|
||||
ListEnd(Position),
|
||||
Identifier(Position),
|
||||
Space(BadInputError, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ERequires<'a> {
|
||||
Requires(Row, Col),
|
||||
Open(Row, Col),
|
||||
IndentRequires(Row, Col),
|
||||
IndentListStart(Row, Col),
|
||||
IndentListEnd(Row, Col),
|
||||
ListStart(Row, Col),
|
||||
ListEnd(Row, Col),
|
||||
TypedIdent(ETypedIdent<'a>, Row, Col),
|
||||
Rigid(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Requires(Position),
|
||||
Open(Position),
|
||||
IndentRequires(Position),
|
||||
IndentListStart(Position),
|
||||
IndentListEnd(Position),
|
||||
ListStart(Position),
|
||||
ListEnd(Position),
|
||||
TypedIdent(ETypedIdent<'a>, Position),
|
||||
Rigid(Position),
|
||||
Space(BadInputError, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ETypedIdent<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
HasType(Row, Col),
|
||||
IndentHasType(Row, Col),
|
||||
Name(Row, Col),
|
||||
Type(EType<'a>, Row, Col),
|
||||
IndentType(Row, Col),
|
||||
Identifier(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
HasType(Position),
|
||||
IndentHasType(Position),
|
||||
Name(Position),
|
||||
Type(EType<'a>, Position),
|
||||
IndentType(Position),
|
||||
Identifier(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EPackages<'a> {
|
||||
Open(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Packages(Row, Col),
|
||||
IndentPackages(Row, Col),
|
||||
ListStart(Row, Col),
|
||||
ListEnd(Row, Col),
|
||||
IndentListStart(Row, Col),
|
||||
IndentListEnd(Row, Col),
|
||||
PackageEntry(EPackageEntry<'a>, Row, Col),
|
||||
Open(Position),
|
||||
Space(BadInputError, Position),
|
||||
Packages(Position),
|
||||
IndentPackages(Position),
|
||||
ListStart(Position),
|
||||
ListEnd(Position),
|
||||
IndentListStart(Position),
|
||||
IndentListEnd(Position),
|
||||
PackageEntry(EPackageEntry<'a>, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum EPackageName {
|
||||
MissingSlash(Row, Col),
|
||||
Account(Row, Col),
|
||||
Pkg(Row, Col),
|
||||
MissingSlash(Position),
|
||||
Account(Position),
|
||||
Pkg(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EPackageOrPath<'a> {
|
||||
BadPath(EString<'a>, Row, Col),
|
||||
BadPackage(EPackageName, Row, Col),
|
||||
BadPath(EString<'a>, Position),
|
||||
BadPackage(EPackageName, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EPackageEntry<'a> {
|
||||
BadPackageOrPath(EPackageOrPath<'a>, Row, Col),
|
||||
Shorthand(Row, Col),
|
||||
Colon(Row, Col),
|
||||
IndentPackageOrPath(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
BadPackageOrPath(EPackageOrPath<'a>, Position),
|
||||
Shorthand(Position),
|
||||
Colon(Position),
|
||||
IndentPackageOrPath(Position),
|
||||
Space(BadInputError, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EEffects<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
Effects(Row, Col),
|
||||
Open(Row, Col),
|
||||
IndentEffects(Row, Col),
|
||||
ListStart(Row, Col),
|
||||
ListEnd(Row, Col),
|
||||
IndentListStart(Row, Col),
|
||||
IndentListEnd(Row, Col),
|
||||
TypedIdent(ETypedIdent<'a>, Row, Col),
|
||||
ShorthandDot(Row, Col),
|
||||
Shorthand(Row, Col),
|
||||
TypeName(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
Effects(Position),
|
||||
Open(Position),
|
||||
IndentEffects(Position),
|
||||
ListStart(Position),
|
||||
ListEnd(Position),
|
||||
IndentListStart(Position),
|
||||
IndentListEnd(Position),
|
||||
TypedIdent(ETypedIdent<'a>, Position),
|
||||
ShorthandDot(Position),
|
||||
Shorthand(Position),
|
||||
TypeName(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum EImports {
|
||||
Open(Row, Col),
|
||||
Imports(Row, Col),
|
||||
IndentImports(Row, Col),
|
||||
IndentListStart(Row, Col),
|
||||
IndentListEnd(Row, Col),
|
||||
ListStart(Row, Col),
|
||||
ListEnd(Row, Col),
|
||||
Identifier(Row, Col),
|
||||
ExposingDot(Row, Col),
|
||||
ShorthandDot(Row, Col),
|
||||
Shorthand(Row, Col),
|
||||
ModuleName(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
IndentSetStart(Row, Col),
|
||||
IndentSetEnd(Row, Col),
|
||||
SetStart(Row, Col),
|
||||
SetEnd(Row, Col),
|
||||
Open(Position),
|
||||
Imports(Position),
|
||||
IndentImports(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)]
|
||||
|
@ -223,13 +223,12 @@ pub enum BadInputError {
|
|||
|
||||
pub fn bad_input_to_syntax_error<'a>(
|
||||
bad_input: BadInputError,
|
||||
row: Row,
|
||||
_col: Col,
|
||||
pos: Position,
|
||||
) -> SyntaxError<'a> {
|
||||
use crate::parser::BadInputError::*;
|
||||
match bad_input {
|
||||
HasTab => SyntaxError::NotYetImplemented("call error on tabs".to_string()),
|
||||
LineTooLong => SyntaxError::LineTooLong(row),
|
||||
LineTooLong => SyntaxError::LineTooLong(pos.line),
|
||||
TooManyLines => SyntaxError::TooManyLines,
|
||||
BadUtf8 => SyntaxError::BadUtf8,
|
||||
}
|
||||
|
@ -243,8 +242,7 @@ impl<'a> SyntaxError<'a> {
|
|||
bytes: &'a [u8],
|
||||
) -> ParseProblem<'a, SyntaxError<'a>> {
|
||||
ParseProblem {
|
||||
line: 0,
|
||||
column: 0,
|
||||
pos: Position::default(),
|
||||
problem: self,
|
||||
filename,
|
||||
bytes,
|
||||
|
@ -253,55 +251,52 @@ impl<'a> SyntaxError<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub type Row = u32;
|
||||
pub type Col = u16;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EExpr<'a> {
|
||||
Start(Row, Col),
|
||||
End(Row, Col),
|
||||
BadExprEnd(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Start(Position),
|
||||
End(Position),
|
||||
BadExprEnd(Position),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
Dot(Row, Col),
|
||||
Access(Row, Col),
|
||||
UnaryNot(Row, Col),
|
||||
UnaryNegate(Row, Col),
|
||||
BadOperator(&'a str, Row, Col),
|
||||
Dot(Position),
|
||||
Access(Position),
|
||||
UnaryNot(Position),
|
||||
UnaryNegate(Position),
|
||||
BadOperator(&'a str, Position),
|
||||
|
||||
DefMissingFinalExpr(Row, Col),
|
||||
DefMissingFinalExpr2(&'a EExpr<'a>, Row, Col),
|
||||
Type(EType<'a>, Row, Col),
|
||||
Pattern(&'a EPattern<'a>, Row, Col),
|
||||
IndentDefBody(Row, Col),
|
||||
IndentEquals(Row, Col),
|
||||
IndentAnnotation(Row, Col),
|
||||
Equals(Row, Col),
|
||||
Colon(Row, Col),
|
||||
DoubleColon(Row, Col),
|
||||
Ident(Row, Col),
|
||||
ElmStyleFunction(Region, Row, Col),
|
||||
MalformedPattern(Row, Col),
|
||||
QualifiedTag(Row, Col),
|
||||
BackpassComma(Row, Col),
|
||||
BackpassArrow(Row, Col),
|
||||
DefMissingFinalExpr(Position),
|
||||
DefMissingFinalExpr2(&'a EExpr<'a>, Position),
|
||||
Type(EType<'a>, Position),
|
||||
Pattern(&'a EPattern<'a>, Position),
|
||||
IndentDefBody(Position),
|
||||
IndentEquals(Position),
|
||||
IndentAnnotation(Position),
|
||||
Equals(Position),
|
||||
Colon(Position),
|
||||
DoubleColon(Position),
|
||||
Ident(Position),
|
||||
ElmStyleFunction(Region, Position),
|
||||
MalformedPattern(Position),
|
||||
QualifiedTag(Position),
|
||||
BackpassComma(Position),
|
||||
BackpassArrow(Position),
|
||||
|
||||
When(EWhen<'a>, Row, Col),
|
||||
If(EIf<'a>, Row, Col),
|
||||
When(EWhen<'a>, Position),
|
||||
If(EIf<'a>, Position),
|
||||
|
||||
Expect(EExpect<'a>, Row, Col),
|
||||
Expect(EExpect<'a>, Position),
|
||||
|
||||
Lambda(ELambda<'a>, Row, Col),
|
||||
Underscore(Row, Col),
|
||||
Lambda(ELambda<'a>, Position),
|
||||
Underscore(Position),
|
||||
|
||||
InParens(EInParens<'a>, Row, Col),
|
||||
Record(ERecord<'a>, Row, Col),
|
||||
Str(EString<'a>, Row, Col),
|
||||
Number(ENumber, Row, Col),
|
||||
List(EList<'a>, Row, Col),
|
||||
InParens(EInParens<'a>, Position),
|
||||
Record(ERecord<'a>, Position),
|
||||
Str(EString<'a>, Position),
|
||||
Number(ENumber, Position),
|
||||
List(EList<'a>, Position),
|
||||
|
||||
IndentStart(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentStart(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -312,265 +307,264 @@ pub enum ENumber {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EString<'a> {
|
||||
Open(Row, Col),
|
||||
Open(Position),
|
||||
|
||||
CodePtOpen(Row, Col),
|
||||
CodePtEnd(Row, Col),
|
||||
CodePtOpen(Position),
|
||||
CodePtEnd(Position),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
EndlessSingle(Row, Col),
|
||||
EndlessMulti(Row, Col),
|
||||
UnknownEscape(Row, Col),
|
||||
Format(&'a EExpr<'a>, Row, Col),
|
||||
FormatEnd(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
EndlessSingle(Position),
|
||||
EndlessMulti(Position),
|
||||
UnknownEscape(Position),
|
||||
Format(&'a EExpr<'a>, Position),
|
||||
FormatEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ERecord<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
End(Position),
|
||||
Open(Position),
|
||||
|
||||
Updateable(Row, Col),
|
||||
Field(Row, Col),
|
||||
Colon(Row, Col),
|
||||
QuestionMark(Row, Col),
|
||||
Bar(Row, Col),
|
||||
Ampersand(Row, Col),
|
||||
Updateable(Position),
|
||||
Field(Position),
|
||||
Colon(Position),
|
||||
QuestionMark(Position),
|
||||
Bar(Position),
|
||||
Ampersand(Position),
|
||||
|
||||
// TODO remove
|
||||
Expr(&'a EExpr<'a>, Row, Col),
|
||||
Expr(&'a EExpr<'a>, Position),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
IndentOpen(Row, Col),
|
||||
IndentColon(Row, Col),
|
||||
IndentBar(Row, Col),
|
||||
IndentAmpersand(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentOpen(Position),
|
||||
IndentColon(Position),
|
||||
IndentBar(Position),
|
||||
IndentAmpersand(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EInParens<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
End(Position),
|
||||
Open(Position),
|
||||
///
|
||||
Expr(&'a EExpr<'a>, Row, Col),
|
||||
Expr(&'a EExpr<'a>, Position),
|
||||
|
||||
///
|
||||
Space(BadInputError, Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
///
|
||||
IndentOpen(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentOpen(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ELambda<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
Start(Row, Col),
|
||||
Arrow(Row, Col),
|
||||
Comma(Row, Col),
|
||||
Arg(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
Start(Position),
|
||||
Arrow(Position),
|
||||
Comma(Position),
|
||||
Arg(Position),
|
||||
// TODO make EEXpr
|
||||
Pattern(EPattern<'a>, Row, Col),
|
||||
Body(&'a EExpr<'a>, Row, Col),
|
||||
IndentArrow(Row, Col),
|
||||
IndentBody(Row, Col),
|
||||
IndentArg(Row, Col),
|
||||
Pattern(EPattern<'a>, Position),
|
||||
Body(&'a EExpr<'a>, Position),
|
||||
IndentArrow(Position),
|
||||
IndentBody(Position),
|
||||
IndentArg(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EList<'a> {
|
||||
Open(Row, Col),
|
||||
End(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Open(Position),
|
||||
End(Position),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
Expr(&'a EExpr<'a>, Row, Col),
|
||||
Expr(&'a EExpr<'a>, Position),
|
||||
|
||||
IndentOpen(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentOpen(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EWhen<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
When(Row, Col),
|
||||
Is(Row, Col),
|
||||
Pattern(EPattern<'a>, Row, Col),
|
||||
Arrow(Row, Col),
|
||||
Bar(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
When(Position),
|
||||
Is(Position),
|
||||
Pattern(EPattern<'a>, Position),
|
||||
Arrow(Position),
|
||||
Bar(Position),
|
||||
|
||||
IfToken(Row, Col),
|
||||
IfGuard(&'a EExpr<'a>, Row, Col),
|
||||
IfToken(Position),
|
||||
IfGuard(&'a EExpr<'a>, Position),
|
||||
|
||||
Condition(&'a EExpr<'a>, Row, Col),
|
||||
Branch(&'a EExpr<'a>, Row, Col),
|
||||
Condition(&'a EExpr<'a>, Position),
|
||||
Branch(&'a EExpr<'a>, Position),
|
||||
|
||||
IndentIs(Row, Col),
|
||||
IndentCondition(Row, Col),
|
||||
IndentPattern(Row, Col),
|
||||
IndentArrow(Row, Col),
|
||||
IndentBranch(Row, Col),
|
||||
IndentIfGuard(Row, Col),
|
||||
PatternAlignment(u16, Row, Col),
|
||||
IndentIs(Position),
|
||||
IndentCondition(Position),
|
||||
IndentPattern(Position),
|
||||
IndentArrow(Position),
|
||||
IndentBranch(Position),
|
||||
IndentIfGuard(Position),
|
||||
PatternAlignment(u16, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EIf<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
If(Row, Col),
|
||||
Then(Row, Col),
|
||||
Else(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
If(Position),
|
||||
Then(Position),
|
||||
Else(Position),
|
||||
// TODO make EEXpr
|
||||
Condition(&'a EExpr<'a>, Row, Col),
|
||||
ThenBranch(&'a EExpr<'a>, Row, Col),
|
||||
ElseBranch(&'a EExpr<'a>, Row, Col),
|
||||
Condition(&'a EExpr<'a>, Position),
|
||||
ThenBranch(&'a EExpr<'a>, Position),
|
||||
ElseBranch(&'a EExpr<'a>, Position),
|
||||
|
||||
IndentCondition(Row, Col),
|
||||
IndentIf(Row, Col),
|
||||
IndentThenToken(Row, Col),
|
||||
IndentElseToken(Row, Col),
|
||||
IndentThenBranch(Row, Col),
|
||||
IndentElseBranch(Row, Col),
|
||||
IndentCondition(Position),
|
||||
IndentIf(Position),
|
||||
IndentThenToken(Position),
|
||||
IndentElseToken(Position),
|
||||
IndentThenBranch(Position),
|
||||
IndentElseBranch(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EExpect<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
Expect(Row, Col),
|
||||
Condition(&'a EExpr<'a>, Row, Col),
|
||||
Continuation(&'a EExpr<'a>, Row, Col),
|
||||
IndentCondition(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
Expect(Position),
|
||||
Condition(&'a EExpr<'a>, Position),
|
||||
Continuation(&'a EExpr<'a>, Position),
|
||||
IndentCondition(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EPattern<'a> {
|
||||
Record(PRecord<'a>, Row, Col),
|
||||
Underscore(Row, Col),
|
||||
Record(PRecord<'a>, Position),
|
||||
Underscore(Position),
|
||||
|
||||
Start(Row, Col),
|
||||
End(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
Start(Position),
|
||||
End(Position),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
PInParens(PInParens<'a>, Row, Col),
|
||||
NumLiteral(ENumber, Row, Col),
|
||||
PInParens(PInParens<'a>, Position),
|
||||
NumLiteral(ENumber, Position),
|
||||
|
||||
IndentStart(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
AsIndentStart(Row, Col),
|
||||
IndentStart(Position),
|
||||
IndentEnd(Position),
|
||||
AsIndentStart(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PRecord<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
End(Position),
|
||||
Open(Position),
|
||||
|
||||
Field(Row, Col),
|
||||
Colon(Row, Col),
|
||||
Optional(Row, Col),
|
||||
Field(Position),
|
||||
Colon(Position),
|
||||
Optional(Position),
|
||||
|
||||
Pattern(&'a EPattern<'a>, Row, Col),
|
||||
Expr(&'a EExpr<'a>, Row, Col),
|
||||
Pattern(&'a EPattern<'a>, Position),
|
||||
Expr(&'a EExpr<'a>, Position),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
IndentOpen(Row, Col),
|
||||
IndentColon(Row, Col),
|
||||
IndentOptional(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentOpen(Position),
|
||||
IndentColon(Position),
|
||||
IndentOptional(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PInParens<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
Pattern(&'a EPattern<'a>, Row, Col),
|
||||
End(Position),
|
||||
Open(Position),
|
||||
Pattern(&'a EPattern<'a>, Position),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
IndentOpen(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
IndentOpen(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EType<'a> {
|
||||
TRecord(ETypeRecord<'a>, Row, Col),
|
||||
TTagUnion(ETypeTagUnion<'a>, Row, Col),
|
||||
TInParens(ETypeInParens<'a>, Row, Col),
|
||||
TApply(ETypeApply, Row, Col),
|
||||
TBadTypeVariable(Row, Col),
|
||||
TWildcard(Row, Col),
|
||||
TInferred(Row, Col),
|
||||
TRecord(ETypeRecord<'a>, Position),
|
||||
TTagUnion(ETypeTagUnion<'a>, Position),
|
||||
TInParens(ETypeInParens<'a>, Position),
|
||||
TApply(ETypeApply, Position),
|
||||
TBadTypeVariable(Position),
|
||||
TWildcard(Position),
|
||||
TInferred(Position),
|
||||
///
|
||||
TStart(Row, Col),
|
||||
TEnd(Row, Col),
|
||||
TSpace(BadInputError, Row, Col),
|
||||
TFunctionArgument(Row, Col),
|
||||
TStart(Position),
|
||||
TEnd(Position),
|
||||
TSpace(BadInputError, Position),
|
||||
TFunctionArgument(Position),
|
||||
///
|
||||
TIndentStart(Row, Col),
|
||||
TIndentEnd(Row, Col),
|
||||
TAsIndentStart(Row, Col),
|
||||
TIndentStart(Position),
|
||||
TIndentEnd(Position),
|
||||
TAsIndentStart(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ETypeRecord<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
End(Position),
|
||||
Open(Position),
|
||||
|
||||
Field(Row, Col),
|
||||
Colon(Row, Col),
|
||||
Optional(Row, Col),
|
||||
Type(&'a EType<'a>, Row, Col),
|
||||
Field(Position),
|
||||
Colon(Position),
|
||||
Optional(Position),
|
||||
Type(&'a EType<'a>, Position),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
IndentOpen(Row, Col),
|
||||
IndentColon(Row, Col),
|
||||
IndentOptional(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentOpen(Position),
|
||||
IndentColon(Position),
|
||||
IndentOptional(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ETypeTagUnion<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
End(Position),
|
||||
Open(Position),
|
||||
|
||||
Type(&'a EType<'a>, Row, Col),
|
||||
Type(&'a EType<'a>, Position),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
IndentOpen(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentOpen(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ETypeInParens<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
End(Position),
|
||||
Open(Position),
|
||||
///
|
||||
Type(&'a EType<'a>, Row, Col),
|
||||
Type(&'a EType<'a>, Position),
|
||||
|
||||
///
|
||||
Space(BadInputError, Row, Col),
|
||||
Space(BadInputError, Position),
|
||||
///
|
||||
IndentOpen(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
IndentOpen(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ETypeApply {
|
||||
///
|
||||
StartNotUppercase(Row, Col),
|
||||
End(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
StartNotUppercase(Position),
|
||||
End(Position),
|
||||
Space(BadInputError, Position),
|
||||
///
|
||||
DoubleDot(Row, Col),
|
||||
TrailingDot(Row, Col),
|
||||
StartIsNumber(Row, Col),
|
||||
DoubleDot(Position),
|
||||
TrailingDot(Position),
|
||||
StartIsNumber(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParseProblem<'a, T> {
|
||||
pub line: u32,
|
||||
pub column: u16,
|
||||
pub pos: Position,
|
||||
pub problem: T,
|
||||
pub filename: std::path::PathBuf,
|
||||
pub bytes: &'a [u8],
|
||||
|
@ -723,30 +717,30 @@ where
|
|||
|
||||
pub fn keyword_e<'a, ToError, E>(keyword: &'static str, if_error: ToError) -> impl Parser<'a, (), E>
|
||||
where
|
||||
ToError: Fn(Row, Col) -> E,
|
||||
ToError: Fn(Position) -> E,
|
||||
E: 'a,
|
||||
{
|
||||
move |_, mut state: State<'a>| {
|
||||
let width = keyword.len();
|
||||
|
||||
if !state.bytes().starts_with(keyword.as_bytes()) {
|
||||
return Err((NoProgress, if_error(state.line, state.column), state));
|
||||
return Err((NoProgress, if_error(state.pos), state));
|
||||
}
|
||||
|
||||
// the next character should not be an identifier character
|
||||
// to prevent treating `whence` or `iffy` as keywords
|
||||
match state.bytes().get(width) {
|
||||
Some(next) if *next == b' ' || *next == b'#' || *next == b'\n' => {
|
||||
state.column += width as u16;
|
||||
state.pos.column += width as u16;
|
||||
state = state.advance(width);
|
||||
Ok((MadeProgress, (), state))
|
||||
}
|
||||
None => {
|
||||
state.column += width as u16;
|
||||
state.pos.column += width as u16;
|
||||
state = state.advance(width);
|
||||
Ok((MadeProgress, (), state))
|
||||
}
|
||||
Some(_) => Err((NoProgress, if_error(state.line, state.column), state)),
|
||||
Some(_) => Err((NoProgress, if_error(state.pos), state)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -944,7 +938,7 @@ pub fn sep_by1_e<'a, P, V, D, Val, Error>(
|
|||
where
|
||||
D: Parser<'a, (), Error>,
|
||||
P: Parser<'a, Val, Error>,
|
||||
V: Fn(Row, Col) -> Error,
|
||||
V: Fn(Position) -> Error,
|
||||
Error: 'a,
|
||||
{
|
||||
move |arena, state: State<'a>| {
|
||||
|
@ -973,7 +967,7 @@ where
|
|||
Err((NoProgress, _fail, state)) => {
|
||||
return Err((
|
||||
NoProgress,
|
||||
to_element_error(state.line, state.column),
|
||||
to_element_error(state.pos),
|
||||
state,
|
||||
));
|
||||
}
|
||||
|
@ -1001,7 +995,7 @@ where
|
|||
Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state)),
|
||||
Err((NoProgress, _fail, state)) => Err((
|
||||
NoProgress,
|
||||
to_element_error(state.line, state.column),
|
||||
to_element_error(state.pos),
|
||||
state,
|
||||
)),
|
||||
}
|
||||
|
@ -1052,19 +1046,12 @@ macro_rules! loc {
|
|||
move |arena, state: $crate::state::State<'a>| {
|
||||
use roc_region::all::{Loc, Region};
|
||||
|
||||
let start_col = state.column;
|
||||
let start_line = state.line;
|
||||
let start = state.pos;
|
||||
|
||||
match $parser.parse(arena, state) {
|
||||
Ok((progress, value, state)) => {
|
||||
let end_col = state.column;
|
||||
let end_line = state.line;
|
||||
let region = Region {
|
||||
start_line,
|
||||
end_line,
|
||||
start_col,
|
||||
end_col,
|
||||
};
|
||||
let end = state.pos;
|
||||
let region = Region::new(start, end);
|
||||
|
||||
Ok((progress, Loc { region, value }, state))
|
||||
}
|
||||
|
@ -1265,7 +1252,7 @@ macro_rules! one_of_with_error {
|
|||
match $p1.parse(arena, state) {
|
||||
valid @ Ok(_) => valid,
|
||||
Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state )),
|
||||
Err((NoProgress, _, state)) => Err((MadeProgress, $toerror(state.line, state.column), state)),
|
||||
Err((NoProgress, _, state)) => Err((MadeProgress, $toerror(state.pos), state)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1277,32 +1264,32 @@ macro_rules! one_of_with_error {
|
|||
|
||||
pub fn specialize<'a, F, P, T, X, Y>(map_error: F, parser: P) -> impl Parser<'a, T, Y>
|
||||
where
|
||||
F: Fn(X, Row, Col) -> Y,
|
||||
F: Fn(X, Position) -> Y,
|
||||
P: Parser<'a, T, X>,
|
||||
Y: 'a,
|
||||
{
|
||||
move |a, s| match parser.parse(a, s) {
|
||||
Ok(t) => Ok(t),
|
||||
Err((p, error, s)) => Err((p, map_error(error, s.line, s.column), s)),
|
||||
Err((p, error, s)) => Err((p, map_error(error, s.pos), s)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn specialize_ref<'a, F, P, T, X, Y>(map_error: F, parser: P) -> impl Parser<'a, T, Y>
|
||||
where
|
||||
F: Fn(&'a X, Row, Col) -> Y,
|
||||
F: Fn(&'a X, Position) -> Y,
|
||||
P: Parser<'a, T, X>,
|
||||
Y: 'a,
|
||||
X: 'a,
|
||||
{
|
||||
move |a, s| match parser.parse(a, s) {
|
||||
Ok(t) => Ok(t),
|
||||
Err((p, error, s)) => Err((p, map_error(a.alloc(error), s.line, s.column), s)),
|
||||
Err((p, error, s)) => Err((p, map_error(a.alloc(error), s.pos), s)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn word1<'a, ToError, E>(word: u8, to_error: ToError) -> impl Parser<'a, (), E>
|
||||
where
|
||||
ToError: Fn(Row, Col) -> E,
|
||||
ToError: Fn(Position) -> E,
|
||||
E: 'a,
|
||||
{
|
||||
debug_assert_ne!(word, b'\n');
|
||||
|
@ -1310,16 +1297,16 @@ where
|
|||
move |_arena: &'a Bump, state: State<'a>| match state.bytes().get(0) {
|
||||
Some(x) if *x == word => {
|
||||
let mut state = state.advance(1);
|
||||
state.column += 1;
|
||||
state.pos.column += 1;
|
||||
Ok((MadeProgress, (), state))
|
||||
}
|
||||
_ => Err((NoProgress, to_error(state.line, state.column), state)),
|
||||
_ => Err((NoProgress, to_error(state.pos), state)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn word2<'a, ToError, E>(word_1: u8, word_2: u8, to_error: ToError) -> impl Parser<'a, (), E>
|
||||
where
|
||||
ToError: Fn(Row, Col) -> E,
|
||||
ToError: Fn(Position) -> E,
|
||||
E: 'a,
|
||||
{
|
||||
debug_assert_ne!(word_1, b'\n');
|
||||
|
@ -1330,23 +1317,23 @@ where
|
|||
move |_arena: &'a Bump, state: State<'a>| {
|
||||
if state.bytes().starts_with(&needle) {
|
||||
let mut state = state.advance(2);
|
||||
state.column += 2;
|
||||
state.pos.column += 2;
|
||||
Ok((MadeProgress, (), state))
|
||||
} else {
|
||||
Err((NoProgress, to_error(state.line, state.column), state))
|
||||
Err((NoProgress, to_error(state.pos), state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_indent<'a, TE, E>(min_indent: u16, to_problem: TE) -> impl Parser<'a, (), E>
|
||||
where
|
||||
TE: Fn(Row, Col) -> E,
|
||||
TE: Fn(Position) -> E,
|
||||
E: 'a,
|
||||
{
|
||||
move |_arena, state: State<'a>| {
|
||||
dbg!(state.indent_col, min_indent);
|
||||
if state.indent_col < min_indent {
|
||||
Err((NoProgress, to_problem(state.line, state.column), state))
|
||||
Err((NoProgress, to_problem(state.pos), state))
|
||||
} else {
|
||||
Ok((NoProgress, (), state))
|
||||
}
|
||||
|
@ -1473,7 +1460,7 @@ macro_rules! one_or_more {
|
|||
}
|
||||
Err((progress, _, new_state)) => Err((
|
||||
progress,
|
||||
$to_error(new_state.line, new_state.column),
|
||||
$to_error(new_state.pos),
|
||||
new_state,
|
||||
)),
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ fn number_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>> {
|
|||
|
||||
fn string_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>> {
|
||||
specialize(
|
||||
|_, r, c| EPattern::Start(r, c),
|
||||
|_, pos| EPattern::Start(pos),
|
||||
map!(crate::string_literal::parse(), Pattern::StrLiteral),
|
||||
)
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ fn loc_ident_pattern_help<'a>(
|
|||
let original_state = state.clone();
|
||||
|
||||
let (_, loc_ident, state) =
|
||||
specialize(|_, r, c| EPattern::Start(r, c), loc!(parse_ident)).parse(arena, state)?;
|
||||
specialize(|_, pos| EPattern::Start(pos), loc!(parse_ident)).parse(arena, state)?;
|
||||
|
||||
match loc_ident.value {
|
||||
Ident::GlobalTag(tag) => {
|
||||
|
@ -236,7 +236,7 @@ fn loc_ident_pattern_help<'a>(
|
|||
if crate::keyword::KEYWORDS.contains(&parts[0]) {
|
||||
Err((
|
||||
NoProgress,
|
||||
EPattern::End(original_state.line, original_state.column),
|
||||
EPattern::End(original_state.pos),
|
||||
original_state,
|
||||
))
|
||||
} else if module_name.is_empty() && parts.len() == 1 {
|
||||
|
@ -308,10 +308,9 @@ fn lowercase_ident_pattern<'a>(
|
|||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, &'a str, EPattern<'a>> {
|
||||
let row = state.line;
|
||||
let col = state.column;
|
||||
let pos = state.pos;
|
||||
|
||||
specialize(move |_, _, _| EPattern::End(row, col), lowercase_ident()).parse(arena, state)
|
||||
specialize(move |_, _| EPattern::End(pos), lowercase_ident()).parse(arena, state)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -344,10 +343,9 @@ fn record_pattern_field<'a>(min_indent: u16) -> impl Parser<'a, Loc<Pattern<'a>>
|
|||
move |arena, state: State<'a>| {
|
||||
// You must have a field name, e.g. "email"
|
||||
// using the initial row/col is important for error reporting
|
||||
let row = state.line;
|
||||
let col = state.column;
|
||||
let pos = state.pos;
|
||||
let (progress, loc_label, state) = loc!(specialize(
|
||||
move |_, _, _| PRecord::Field(row, col),
|
||||
move |_, _| PRecord::Field(pos),
|
||||
lowercase_ident()
|
||||
))
|
||||
.parse(arena, state)?;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::parser::Progress::*;
|
||||
use crate::parser::{BadInputError, Col, Progress, Row};
|
||||
use crate::parser::{BadInputError, Progress};
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::{Position, Region};
|
||||
use std::fmt;
|
||||
|
@ -10,10 +10,8 @@ pub struct State<'a> {
|
|||
/// The raw input bytes from the file.
|
||||
bytes: &'a [u8],
|
||||
|
||||
/// Current line of the input
|
||||
pub line: u32,
|
||||
/// Current column of the input
|
||||
pub column: u16,
|
||||
/// Current position within the input (line/column)
|
||||
pub pos: Position,
|
||||
|
||||
/// Current indentation level, in columns
|
||||
/// (so no indent is col 1 - this saves an arithmetic operation.)
|
||||
|
@ -24,8 +22,7 @@ impl<'a> State<'a> {
|
|||
pub fn new(bytes: &'a [u8]) -> State<'a> {
|
||||
State {
|
||||
bytes,
|
||||
line: 0,
|
||||
column: 0,
|
||||
pos: Position::default(),
|
||||
indent_col: 0,
|
||||
}
|
||||
}
|
||||
|
@ -41,12 +38,10 @@ impl<'a> State<'a> {
|
|||
state
|
||||
}
|
||||
|
||||
/// Returns whether the parser has reached the end of the input
|
||||
/// Returns the current position
|
||||
// TODO: replace this with just accessing the field
|
||||
pub const fn get_position(&self) -> Position {
|
||||
Position {
|
||||
row: self.line,
|
||||
col: self.column,
|
||||
}
|
||||
self.pos
|
||||
}
|
||||
|
||||
/// Returns whether the parser has reached the end of the input
|
||||
|
@ -64,10 +59,10 @@ impl<'a> State<'a> {
|
|||
to_error: TE,
|
||||
) -> Result<Self, (Progress, E, Self)>
|
||||
where
|
||||
TE: Fn(BadInputError, Row, Col) -> E,
|
||||
TE: Fn(BadInputError, Position) -> E,
|
||||
{
|
||||
self.advance_without_indenting_ee(quantity, |r, c| {
|
||||
to_error(BadInputError::LineTooLong, r, c)
|
||||
self.advance_without_indenting_ee(quantity, |p| {
|
||||
to_error(BadInputError::LineTooLong, p)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -77,18 +72,21 @@ impl<'a> State<'a> {
|
|||
to_error: TE,
|
||||
) -> Result<Self, (Progress, E, Self)>
|
||||
where
|
||||
TE: Fn(Row, Col) -> E,
|
||||
TE: Fn(Position) -> E,
|
||||
{
|
||||
match (self.column as usize).checked_add(quantity) {
|
||||
match (self.pos.column as usize).checked_add(quantity) {
|
||||
Some(column_usize) if column_usize <= u16::MAX as usize => {
|
||||
Ok(State {
|
||||
bytes: &self.bytes[quantity..],
|
||||
column: column_usize as u16,
|
||||
pos: Position {
|
||||
line: self.pos.line,
|
||||
column: column_usize as u16,
|
||||
},
|
||||
// Once we hit a nonspace character, we are no longer indenting.
|
||||
..self
|
||||
})
|
||||
}
|
||||
_ => Err((NoProgress, to_error(self.line, self.column), self)),
|
||||
_ => Err((NoProgress, to_error(self.pos), self)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,15 +95,16 @@ impl<'a> State<'a> {
|
|||
/// useful when parsing something "manually" (using input.chars())
|
||||
/// and thus wanting a Region while not having access to loc().
|
||||
pub fn len_region(&self, length: u16) -> Region {
|
||||
Region {
|
||||
start_col: self.column,
|
||||
start_line: self.line,
|
||||
end_col: self
|
||||
.column
|
||||
.checked_add(length)
|
||||
.unwrap_or_else(|| panic!("len_region overflowed")),
|
||||
end_line: self.line,
|
||||
}
|
||||
Region::new(self.pos,
|
||||
Position {
|
||||
line: self.pos.line,
|
||||
column: self
|
||||
.pos
|
||||
.column
|
||||
.checked_add(length)
|
||||
.unwrap_or_else(|| panic!("len_region overflowed")),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Return a failing ParseResult for the given FailReason
|
||||
|
@ -128,7 +127,7 @@ impl<'a> fmt::Debug for State<'a> {
|
|||
Err(_) => write!(f, "\n\tbytes: [invalid utf8] {:?}", self.bytes)?,
|
||||
}
|
||||
|
||||
write!(f, "\n\t(line, col): ({}, {}),", self.line, self.column)?;
|
||||
write!(f, "\n\t(line, col): ({}, {}),", self.pos.line, self.pos.column)?;
|
||||
write!(f, "\n\tindent_col: {}", self.indent_col)?;
|
||||
write!(f, "\n}}")
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ fn ascii_hex_digits<'a>() -> impl Parser<'a, &'a str, EString<'a>> {
|
|||
// We didn't find any hex digits!
|
||||
return Err((
|
||||
NoProgress,
|
||||
EString::CodePtEnd(state.line, state.column),
|
||||
EString::CodePtEnd(state.pos),
|
||||
state,
|
||||
));
|
||||
} else {
|
||||
let state = state.advance_without_indenting_ee(buf.len(), |r, c| {
|
||||
EString::Space(BadInputError::LineTooLong, r, c)
|
||||
let state = state.advance_without_indenting_ee(buf.len(), |pos| {
|
||||
EString::Space(BadInputError::LineTooLong, pos)
|
||||
})?;
|
||||
|
||||
return Ok((MadeProgress, buf.into_bump_str(), state));
|
||||
|
@ -33,7 +33,7 @@ fn ascii_hex_digits<'a>() -> impl Parser<'a, &'a str, EString<'a>> {
|
|||
|
||||
Err((
|
||||
NoProgress,
|
||||
EString::CodePtEnd(state.line, state.column),
|
||||
EString::CodePtEnd(state.pos),
|
||||
state,
|
||||
))
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ fn ascii_hex_digits<'a>() -> impl Parser<'a, &'a str, EString<'a>> {
|
|||
|
||||
macro_rules! advance_state {
|
||||
($state:expr, $n:expr) => {
|
||||
$state.advance_without_indenting_ee($n, |r, c| {
|
||||
EString::Space(BadInputError::LineTooLong, r, c)
|
||||
$state.advance_without_indenting_ee($n, |pos| {
|
||||
EString::Space(BadInputError::LineTooLong, pos)
|
||||
})
|
||||
};
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, EString<'a>> {
|
|||
bytes = state.bytes()[1..].iter();
|
||||
state = advance_state!(state, 1)?;
|
||||
} else {
|
||||
return Err((NoProgress, EString::Open(state.line, state.column), state));
|
||||
return Err((NoProgress, EString::Open(state.pos), state));
|
||||
}
|
||||
|
||||
// At the parsing stage we keep the entire raw string, because the formatter
|
||||
|
@ -109,7 +109,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, EString<'a>> {
|
|||
Err(_) => {
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EString::Space(BadInputError::BadUtf8, state.line, state.column),
|
||||
EString::Space(BadInputError::BadUtf8, state.pos),
|
||||
state,
|
||||
));
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, EString<'a>> {
|
|||
// error starting from where the open quote appeared.
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EString::EndlessSingle(state.line, state.column),
|
||||
EString::EndlessSingle(state.pos),
|
||||
state,
|
||||
));
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, EString<'a>> {
|
|||
// escapable characters (\n, \t, \", \\, etc)
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EString::UnknownEscape(state.line, state.column),
|
||||
EString::UnknownEscape(state.pos),
|
||||
state,
|
||||
));
|
||||
}
|
||||
|
@ -312,9 +312,9 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, EString<'a>> {
|
|||
Err((
|
||||
MadeProgress,
|
||||
if is_multiline {
|
||||
EString::EndlessMulti(state.line, state.column)
|
||||
EString::EndlessMulti(state.pos)
|
||||
} else {
|
||||
EString::EndlessSingle(state.line, state.column)
|
||||
EString::EndlessSingle(state.pos)
|
||||
},
|
||||
state,
|
||||
))
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::parser::{
|
|||
use crate::state::State;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_region::all::{Loc, Region, Position};
|
||||
|
||||
pub fn located_help<'a>(
|
||||
min_indent: u16,
|
||||
|
@ -48,7 +48,7 @@ fn tag_union_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, ET
|
|||
}
|
||||
|
||||
fn fail_type_start<'a, T: 'a>() -> impl Parser<'a, T, EType<'a>> {
|
||||
|_arena, state: State<'a>| Err((NoProgress, EType::TStart(state.line, state.column), state))
|
||||
|_arena, state: State<'a>| Err((NoProgress, EType::TStart(state.pos), state))
|
||||
}
|
||||
|
||||
fn term<'a>(min_indent: u16) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> {
|
||||
|
@ -191,15 +191,14 @@ fn tag_type<'a>(min_indent: u16) -> impl Parser<'a, Tag<'a>, ETypeTagUnion<'a>>
|
|||
}
|
||||
}
|
||||
|
||||
use crate::parser::{Col, Row};
|
||||
fn parse_tag_name<'a, F, E>(to_problem: F) -> impl Parser<'a, &'a str, E>
|
||||
where
|
||||
F: Fn(Row, Col) -> E,
|
||||
F: Fn(Position) -> E,
|
||||
E: 'a,
|
||||
{
|
||||
move |arena, state: State<'a>| match crate::ident::tag_name().parse(arena, state) {
|
||||
Ok(good) => Ok(good),
|
||||
Err((progress, _, state)) => Err((progress, to_problem(state.line, state.column), state)),
|
||||
Err((progress, _, state)) => Err((progress, to_problem(state.pos), state)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,10 +212,9 @@ fn record_type_field<'a>(
|
|||
(move |arena, state: State<'a>| {
|
||||
// You must have a field name, e.g. "email"
|
||||
// using the initial row/col is important for error reporting
|
||||
let row = state.line;
|
||||
let col = state.column;
|
||||
let pos = state.pos;
|
||||
let (progress, loc_label, state) = loc!(specialize(
|
||||
move |_, _, _| ETypeRecord::Field(row, col),
|
||||
move |_, _| ETypeRecord::Field(pos),
|
||||
lowercase_ident()
|
||||
))
|
||||
.parse(arena, state)?;
|
||||
|
@ -370,7 +368,7 @@ fn expression<'a>(
|
|||
),
|
||||
|_, state: State<'a>| Err((
|
||||
NoProgress,
|
||||
EType::TFunctionArgument(state.line, state.column),
|
||||
EType::TFunctionArgument(state.pos),
|
||||
state
|
||||
))
|
||||
]
|
||||
|
@ -464,7 +462,7 @@ fn parse_concrete_type<'a>(
|
|||
Ok((MadeProgress, answer, state))
|
||||
}
|
||||
Err((NoProgress, _, state)) => {
|
||||
Err((NoProgress, ETypeApply::End(state.line, state.column), state))
|
||||
Err((NoProgress, ETypeApply::End(state.pos), state))
|
||||
}
|
||||
Err((MadeProgress, _, mut state)) => {
|
||||
// we made some progress, but ultimately failed.
|
||||
|
@ -474,8 +472,8 @@ fn parse_concrete_type<'a>(
|
|||
let parsed_str =
|
||||
unsafe { std::str::from_utf8_unchecked(&initial_bytes[..chomped + delta]) };
|
||||
|
||||
state = state.advance_without_indenting_ee(chomped, |r, c| {
|
||||
ETypeApply::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
state = state.advance_without_indenting_ee(chomped, |pos| {
|
||||
ETypeApply::Space(crate::parser::BadInputError::LineTooLong, pos)
|
||||
})?;
|
||||
|
||||
Ok((MadeProgress, TypeAnnotation::Malformed(parsed_str), state))
|
||||
|
@ -495,7 +493,7 @@ fn parse_type_variable<'a>(
|
|||
}
|
||||
Err((progress, _, state)) => Err((
|
||||
progress,
|
||||
EType::TBadTypeVariable(state.line, state.column),
|
||||
EType::TBadTypeVariable(state.pos),
|
||||
state,
|
||||
)),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue