number parsing with new errors

This commit is contained in:
Folkert 2021-02-26 15:06:24 +01:00
parent d4de440943
commit bb9a2525b5
8 changed files with 187 additions and 263 deletions

View file

@ -371,7 +371,7 @@ pub fn line_comment<'a>() -> impl Parser<'a, &'a str, SyntaxError<'a>> {
}
let comment = &state.bytes[..length];
let state = state.advance_without_indenting(arena, length + 1)?;
let state = state.advance_without_indenting(length + 1)?;
match parse_utf8(comment) {
Ok(comment_str) => Ok((MadeProgress, comment_str, state)),
Err(reason) => state.fail(arena, MadeProgress, reason),
@ -535,7 +535,7 @@ where
.map_err(|(fail, _)| {
(progress, fail, original_state.clone())
})?
.advance_without_indenting_e(arena, 1, space_problem)?;
.advance_without_indenting_e(1, space_problem)?;
// We're now parsing a line comment!
line_state = LineState::Comment;
@ -584,11 +584,7 @@ where
match ch {
' ' => {
// If we're in a line comment, this won't affect indentation anyway.
state = state.advance_without_indenting_e(
arena,
1,
space_problem,
)?;
state = state.advance_without_indenting_e(1, space_problem)?;
if comment_line_buf.len() == 1 {
match comment_line_buf.chars().next() {
@ -650,7 +646,6 @@ where
nonblank => {
// Chars can have btye lengths of more than 1!
state = state.advance_without_indenting_e(
arena,
nonblank.len_utf8(),
space_problem,
)?;
@ -663,11 +658,7 @@ where
match ch {
' ' => {
// If we're in a doc comment, this won't affect indentation anyway.
state = state.advance_without_indenting_e(
arena,
1,
space_problem,
)?;
state = state.advance_without_indenting_e(1, space_problem)?;
comment_line_buf.push(ch);
}
@ -692,11 +683,8 @@ where
));
}
nonblank => {
state = state.advance_without_indenting_e(
arena,
utf8_len,
space_problem,
)?;
state = state
.advance_without_indenting_e(utf8_len, space_problem)?;
comment_line_buf.push(nonblank);
}

View file

@ -7,7 +7,6 @@ use crate::blankspace::{
};
use crate::ident::{ident, lowercase_ident, Ident};
use crate::keyword;
use crate::number_literal::number_literal;
use crate::parser::{
self, allocated, and_then_with_indent_level, ascii_char, ascii_string, attempt, backtrackable,
map, newline_char, not, not_followed_by, optional, sep_by1, sep_by1_e, specialize,
@ -673,7 +672,7 @@ fn equals_for_def<'a>() -> impl Parser<'a, (), SyntaxError<'a>> {
Some(b'=') => match state.bytes.get(1) {
Some(b'=') | Some(b'>') => Err((NoProgress, SyntaxError::ConditionFailed, state)),
_ => {
let state = state.advance_without_indenting(arena, 1)?;
let state = state.advance_without_indenting(1)?;
Ok((MadeProgress, (), state))
}
@ -1831,7 +1830,7 @@ pub fn equals_with_indent_help<'a>() -> impl Parser<'a, u16, EExpr<'a>> {
// The '=' must not be followed by another `=` or `>`
// (See equals_for_def() for explanation)
Some(b'=') | Some(b'>') => Err((NoProgress, equals, state)),
Some(_) => match state.advance_without_indenting_e(arena, 1, EExpr::Space) {
Some(_) => match state.advance_without_indenting_e(1, EExpr::Space) {
Err(bad) => Err(bad),
Ok(good) => Ok((MadeProgress, indent_col, good)),
},
@ -1856,11 +1855,11 @@ pub fn equals_with_indent<'a>() -> impl Parser<'a, u16, SyntaxError<'a>> {
Some(_) => Ok((
MadeProgress,
state.indent_col,
state.advance_without_indenting(arena, 1)?,
state.advance_without_indenting(1)?,
)),
None => Err(unexpected_eof(
arena,
state.advance_without_indenting(arena, 1)?,
state.advance_without_indenting(1)?,
1,
)),
}
@ -1876,7 +1875,7 @@ pub fn colon_with_indent<'a>() -> impl Parser<'a, u16, SyntaxError<'a>> {
Some(&byte) if byte == b':' => Ok((
MadeProgress,
state.indent_col,
state.advance_without_indenting(arena, 1)?,
state.advance_without_indenting(1)?,
)),
Some(_) => Err(unexpected(arena, 0, Attempting::Def, state)),
None => Err(unexpected_eof(arena, state, 0)),
@ -2239,6 +2238,15 @@ fn string_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EString> {
}
#[allow(dead_code)]
fn number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, Number> {
specialize(|_, _, _| Number::NumberEnd, number_literal())
fn number_literal<'a>() -> impl Parser<'a, Expr<'a>, SyntaxError<'a>> {
// use crate::number_literal::number_literal;
specialize(
|e, r, c| SyntaxError::Expr(EExpr::Number(e, r, c)),
crate::number_literal::number_literal(),
)
}
#[allow(dead_code)]
fn number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, Number> {
crate::number_literal::number_literal()
}

View file

@ -91,20 +91,20 @@ pub fn parse_ident<'a>(
is_capitalized = first_ch.is_uppercase();
is_accessor_fn = false;
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
} else if first_ch == '.' {
is_capitalized = false;
is_accessor_fn = true;
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
} else if first_ch == '@' {
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
// '@' must always be followed by a capital letter!
match peek_utf8_char(&state) {
Ok((next_ch, next_bytes_parsed)) => {
if next_ch.is_uppercase() {
state = state.advance_without_indenting(arena, next_bytes_parsed)?;
state = state.advance_without_indenting(next_bytes_parsed)?;
part_buf.push('@');
part_buf.push(next_ch);
@ -193,7 +193,7 @@ pub fn parse_ident<'a>(
break;
}
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
}
Err(reason) => {
let progress = Progress::from_lengths(start_bytes_len, state.bytes.len());
@ -308,7 +308,7 @@ fn malformed<'a>(
break;
}
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
}
Err(reason) => return state.fail(arena, MadeProgress, reason),
}
@ -351,7 +351,7 @@ where
buf.push(first_letter);
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
while !state.bytes.is_empty() {
match peek_utf8_char(&state) {
@ -364,7 +364,7 @@ where
if ch.is_alphabetic() || ch.is_ascii_digit() {
buf.push(ch);
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
} else {
// This is the end of the field. We're done!
break;

View file

@ -99,7 +99,7 @@ pub fn parse_package_part<'a>(
if ch == '-' || ch.is_ascii_alphanumeric() {
part_buf.push(ch);
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
} else {
let progress = Progress::progress_when(!part_buf.is_empty());
return Ok((progress, part_buf.into_bump_str(), state));
@ -128,7 +128,7 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, SyntaxError<'a>> {
buf.push(first_letter);
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
while !state.bytes.is_empty() {
match peek_utf8_char(&state) {
@ -139,7 +139,7 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, SyntaxError<'a>> {
// * ASCII digits - e.g. `1` but not `¾`, both of which pass .is_numeric()
// * A '.' separating module parts
if ch.is_alphabetic() || ch.is_ascii_digit() {
state = state.advance_without_indenting(arena, bytes_parsed)?;
state = state.advance_without_indenting(bytes_parsed)?;
buf.push(ch);
} else if ch == '.' {
@ -151,7 +151,6 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, SyntaxError<'a>> {
buf.push(next);
state = state.advance_without_indenting(
arena,
bytes_parsed + next_bytes_parsed,
)?;
} else {

View file

@ -1,189 +1,131 @@
use crate::ast::{Attempting, Base, Expr};
use crate::parser::{
parse_utf8, unexpected, unexpected_eof, ParseResult, Parser, Progress, State, SyntaxError,
};
use bumpalo::Bump;
use crate::ast::{Base, Expr};
use crate::parser::{parse_utf8, Number, ParseResult, Parser, Progress, State, SyntaxError};
use std::char;
use std::str::from_utf8_unchecked;
pub fn number_literal<'a>() -> impl Parser<'a, Expr<'a>, SyntaxError<'a>> {
pub fn number_literal<'a>() -> impl Parser<'a, Expr<'a>, Number> {
move |arena, state: State<'a>| {
let bytes = &mut state.bytes.iter();
match bytes.next() {
Some(&first_byte) => {
// Number literals must start with either an '-' or a digit.
if first_byte == b'-' || (first_byte as char).is_ascii_digit() {
parse_number_literal(first_byte as char, bytes, arena, state)
} else {
Err(unexpected(arena, 1, Attempting::NumberLiteral, state))
}
match state.bytes.get(0) {
Some(first_byte) if *first_byte == b'-' => {
// drop the minus
parse_number_base(true, &state.bytes[1..], state)
}
Some(first_byte) if (*first_byte as char).is_ascii_digit() => {
parse_number_base(false, &state.bytes, state)
}
_ => {
// this is not a number at all
Err((Progress::NoProgress, Number::End, state))
}
None => Err(unexpected_eof(arena, state, 0)),
}
}
}
#[inline(always)]
fn parse_number_literal<'a, I>(
first_ch: char,
bytes: &mut I,
arena: &'a Bump,
fn parse_number_base<'a>(
is_negated: bool,
bytes: &'a [u8],
state: State<'a>,
) -> ParseResult<'a, Expr<'a>, SyntaxError<'a>>
where
I: Iterator<Item = &'a u8>,
{
use self::LiteralType::*;
let mut typ = Num;
// We already parsed 1 character (which may have been a minus sign).
let mut bytes_parsed = 1;
let mut prev_byte = first_ch as u8;
let mut has_parsed_digits = first_ch.is_ascii_digit();
for &next_byte in bytes {
let err_unexpected = || {
Err(unexpected(
arena,
bytes_parsed,
Attempting::NumberLiteral,
state.clone(),
))
};
let is_potentially_non_base10 = || {
(bytes_parsed == 1 && first_ch == '0')
|| (bytes_parsed == 2 && first_ch == '-' && prev_byte == b'0')
};
match next_byte as char {
'.' => {
if typ == Float {
// You only get one decimal point!
return err_unexpected();
} else {
typ = Float;
}
}
'x' => {
if is_potentially_non_base10() {
typ = Hex;
} else {
return err_unexpected();
}
}
'b' if typ == Num => {
// We have to check for typ == Num because otherwise we get a false
// positive here when parsing a hex literal that happens to have
// a 'b' in it, e.g. 0xbbbb
if is_potentially_non_base10() {
typ = Binary;
} else {
return err_unexpected();
}
}
'o' => {
if is_potentially_non_base10() {
typ = Octal;
} else {
return err_unexpected();
}
}
'_' => {
// Underscores are ignored.
}
next_ch => {
if next_ch.is_ascii_digit() {
has_parsed_digits = true;
} else {
if !has_parsed_digits {
// No digits! We likely parsed a minus sign
// that's actually a unary negation operator.
return err_unexpected();
}
// ASCII alphabetic chars (like 'a' and 'f') are
// allowed in Hex int literals. We verify them in
// canonicalization, so if there's a problem, we can
// give a more helpful error (e.g. "the character 'f'
// is not allowed in Octal literals" or
// "the character 'g' is outside the range of valid
// Hex literals") while still allowing the formatter
// to format them normally.
if !next_ch.is_ascii_alphabetic() {
// We hit an invalid number literal character; we're done!
break;
}
}
}
}
// Since we only consume characters in the ASCII range for number literals,
// this will always be exactly 1. There's no need to call next_ch.utf8_len().
bytes_parsed += 1;
prev_byte = next_byte;
}
// At this point we have a number, and will definitely succeed.
// If the number is malformed (outside the supported range),
// we'll succeed with an appropriate Expr which records that.
match typ {
Num => Ok((
Progress::from_consumed(bytes_parsed),
// SAFETY: it's safe to use from_utf8_unchecked here, because we've
// already validated that this range contains only ASCII digits
Expr::Num(unsafe { from_utf8_unchecked(&state.bytes[0..bytes_parsed]) }),
state.advance_without_indenting(arena, bytes_parsed)?,
)),
Float => Ok((
Progress::from_consumed(bytes_parsed),
// SAFETY: it's safe to use from_utf8_unchecked here, because we've
// already validated that this range contains only ASCII digits
Expr::Float(unsafe { from_utf8_unchecked(&state.bytes[0..bytes_parsed]) }),
state.advance_without_indenting(arena, bytes_parsed)?,
)),
// For these we trim off the 0x/0o/0b part
Hex => from_base(Base::Hex, first_ch, bytes_parsed, arena, state),
Octal => from_base(Base::Octal, first_ch, bytes_parsed, arena, state),
Binary => from_base(Base::Binary, first_ch, bytes_parsed, arena, state),
) -> ParseResult<'a, Expr<'a>, Number> {
match bytes.get(0..2) {
Some(b"0b") => chomp_number_base(Base::Binary, is_negated, &bytes[2..], state),
Some(b"0o") => chomp_number_base(Base::Octal, is_negated, &bytes[2..], state),
Some(b"0x") => chomp_number_base(Base::Hex, is_negated, &bytes[2..], state),
_ => chomp_number_dec(is_negated, bytes, state),
}
}
#[derive(Debug, PartialEq, Eq)]
enum LiteralType {
Num,
Float,
Hex,
Octal,
Binary,
}
fn from_base<'a>(
fn chomp_number_base<'a>(
base: Base,
first_ch: char,
bytes_parsed: usize,
arena: &'a Bump,
is_negative: bool,
bytes: &'a [u8],
state: State<'a>,
) -> ParseResult<'a, Expr<'a>, SyntaxError<'a>> {
let is_negative = first_ch == '-';
let bytes = if is_negative {
&state.bytes[3..bytes_parsed]
} else {
&state.bytes[2..bytes_parsed]
};
) -> ParseResult<'a, Expr<'a>, Number> {
let (_is_float, mut chomped) = chomp_number(bytes);
chomped += 2 + (is_negative as usize);
match parse_utf8(bytes) {
Ok(string) => Ok((
Progress::from_consumed(bytes_parsed),
Expr::NonBase10Int {
is_negative,
string,
base,
},
state.advance_without_indenting(arena, bytes_parsed)?,
)),
Err(reason) => state.fail(arena, Progress::from_consumed(bytes_parsed), reason),
match parse_utf8(&bytes[0..chomped]) {
Ok(string) => match state.advance_without_indenting(chomped) {
Ok(new) => {
// all is well
Ok((
Progress::MadeProgress,
Expr::NonBase10Int {
is_negative,
string,
base: Base::Binary,
},
new,
))
}
Err((_, SyntaxError::LineTooLong(_), new)) => {
// the only error we care about in this context
Err((Progress::MadeProgress, Number::LineTooLong, new))
}
Err(_) => unreachable!("we know advancing will succeed if there is space on the line"),
},
Err(_) => unreachable!("no invalid utf8 could have been chomped"),
}
}
fn chomp_number_dec<'a>(
is_negative: bool,
bytes: &'a [u8],
state: State<'a>,
) -> ParseResult<'a, Expr<'a>, Number> {
let (is_float, mut chomped) = chomp_number(bytes);
chomped += is_negative as usize;
let string = unsafe { from_utf8_unchecked(&state.bytes[0..chomped]) };
match state.advance_without_indenting(chomped) {
Ok(new) => {
// all is well
Ok((
Progress::MadeProgress,
if is_float {
Expr::Float(string)
} else {
Expr::Num(string)
},
new,
))
}
Err((_, SyntaxError::LineTooLong(_), new)) => {
// the only error we care about in this context
Err((Progress::MadeProgress, Number::LineTooLong, new))
}
Err(_) => unreachable!("we know advancing will succeed if there is space on the line"),
}
}
fn chomp_number<'a>(mut bytes: &'a [u8]) -> (bool, usize) {
let start_bytes_len = bytes.len();
let mut is_float = false;
while let Some(byte) = bytes.get(0) {
match byte {
b'.' => {
// skip, fix multiple `.`s in canonicalization
is_float = true;
bytes = &bytes[1..];
}
b'_' => {
// skip
bytes = &bytes[1..];
}
_ if byte.is_ascii_digit() || byte.is_ascii_alphabetic() => {
// valid digits (alphabetic in hex digits, and the `e` in `12e26` scientific notation
bytes = &bytes[1..];
}
_ => {
// not a valid digit; we're done
return (is_float, start_bytes_len - bytes.len());
}
}
}
// if the above loop exits, we must be dealing with an empty slice
// therefore we parsed all of the bytes in the input
(is_float, start_bytes_len)
}

View file

@ -135,15 +135,13 @@ impl<'a> State<'a> {
/// they weren't eligible to indent anyway.
pub fn advance_without_indenting(
self,
arena: &'a Bump,
quantity: usize,
) -> Result<Self, (Progress, SyntaxError<'a>, Self)> {
self.advance_without_indenting_e(arena, quantity, bad_input_to_syntax_error)
self.advance_without_indenting_e(quantity, bad_input_to_syntax_error)
}
pub fn advance_without_indenting_e<TE, E>(
self,
arena: &'a Bump,
quantity: usize,
to_error: TE,
) -> Result<Self, (Progress, E, Self)>
@ -160,7 +158,7 @@ impl<'a> State<'a> {
..self
})
}
_ => Err(line_too_long_e(arena, self.clone(), to_error)),
_ => Err(line_too_long_e(self.clone(), to_error)),
}
}
@ -214,7 +212,7 @@ impl<'a> State<'a> {
original_len: self.original_len,
})
}
_ => Err(line_too_long_e(arena, self.clone(), to_error)),
_ => Err(line_too_long_e(self.clone(), to_error)),
}
}
@ -403,8 +401,8 @@ pub enum EExpr<'a> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Number {
NumberEnd,
NumberDot(i64),
End,
LineTooLong,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@ -878,9 +876,7 @@ pub fn unexpected_eof<'a>(
state: State<'a>,
chars_consumed: usize,
) -> (Progress, SyntaxError<'a>, State<'a>) {
checked_unexpected(arena, state, chars_consumed, |region| {
SyntaxError::Eof(region)
})
checked_unexpected(state, chars_consumed, |region| SyntaxError::Eof(region))
}
pub fn unexpected<'a>(
@ -891,7 +887,7 @@ pub fn unexpected<'a>(
) -> (Progress, SyntaxError<'a>, State<'a>) {
// NOTE state is the last argument because chars_consumed often depends on the state's fields
// having state be the final argument prevents borrowing issues
checked_unexpected(arena, state, chars_consumed, |region| {
checked_unexpected(state, chars_consumed, |region| {
SyntaxError::Unexpected(region)
})
}
@ -901,7 +897,6 @@ pub fn unexpected<'a>(
/// If maximum line length was exceeded, return a Problem indicating as much.
#[inline(always)]
fn checked_unexpected<'a, F>(
arena: &'a Bump,
state: State<'a>,
chars_consumed: usize,
problem_from_region: F,
@ -926,17 +921,13 @@ where
(Progress::NoProgress, problem_from_region(region), state)
}
_ => {
let (_progress, fail, state) = line_too_long(arena, state);
let (_progress, fail, state) = line_too_long(state);
(Progress::NoProgress, fail, state)
}
}
}
fn line_too_long_e<'a, TE, E>(
_arena: &'a Bump,
state: State<'a>,
to_error: TE,
) -> (Progress, E, State<'a>)
fn line_too_long_e<'a, TE, E>(state: State<'a>, to_error: TE) -> (Progress, E, State<'a>)
where
TE: Fn(BadInputError, Row, Col) -> E,
{
@ -961,8 +952,8 @@ where
(Progress::NoProgress, problem, state)
}
fn line_too_long<'a>(arena: &'a Bump, state: State<'a>) -> (Progress, SyntaxError<'a>, State<'a>) {
line_too_long_e(arena, state, |_, line, _| SyntaxError::LineTooLong(line))
fn line_too_long<'a>(state: State<'a>) -> (Progress, SyntaxError<'a>, State<'a>) {
line_too_long_e(state, |_, line, _| SyntaxError::LineTooLong(line))
}
/// A single ASCII char that isn't a newline.
@ -975,7 +966,7 @@ pub fn ascii_char<'a>(expected: u8) -> impl Parser<'a, (), SyntaxError<'a>> {
Some(&actual) if expected == actual => Ok((
Progress::MadeProgress,
(),
state.advance_without_indenting(arena, 1)?,
state.advance_without_indenting(1)?,
)),
Some(_) => Err(unexpected(arena, 0, Attempting::Keyword, state)),
_ => Err(unexpected_eof(arena, state, 0)),
@ -1006,7 +997,7 @@ pub fn ascii_hex_digits<'a>() -> impl Parser<'a, &'a str, SyntaxError<'a>> {
// We didn't find any hex digits!
return Err(unexpected(arena, 0, Attempting::Keyword, state));
} else {
let state = state.advance_without_indenting(arena, buf.len())?;
let state = state.advance_without_indenting(buf.len())?;
return Ok((Progress::MadeProgress, buf.into_bump_str(), state));
}
@ -1150,7 +1141,7 @@ pub fn ascii_string<'a>(keyword: &'static str) -> impl Parser<'a, (), SyntaxErro
Ok((
Progress::MadeProgress,
(),
state.advance_without_indenting(arena, len)?,
state.advance_without_indenting(len)?,
))
} else {
let (_, fail, state) = unexpected(arena, len, Attempting::Keyword, state);

View file

@ -27,7 +27,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, SyntaxError<'a>> {
}
// Advance past the opening quotation mark.
state = state.advance_without_indenting(arena, 1)?;
state = state.advance_without_indenting(1)?;
// At the parsing stage we keep the entire raw string, because the formatter
// needs the raw string. (For example, so it can "remember" whether you
@ -44,7 +44,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, SyntaxError<'a>> {
segments.push(StrSegment::EscapedChar($ch));
// Advance past the segment we just added
state = state.advance_without_indenting(arena, segment_parsed_bytes)?;
state = state.advance_without_indenting(segment_parsed_bytes)?;
// Reset the segment
segment_parsed_bytes = 0;
@ -63,7 +63,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, SyntaxError<'a>> {
match parse_utf8(string_bytes) {
Ok(string) => {
state = state.advance_without_indenting(arena, string.len())?;
state = state.advance_without_indenting(string.len())?;
segments.push($transform(string));
}
@ -105,7 +105,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, SyntaxError<'a>> {
return Ok((
MadeProgress,
PlainLine(""),
state.advance_without_indenting(arena, 1)?,
state.advance_without_indenting(1)?,
));
}
}
@ -128,11 +128,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, SyntaxError<'a>> {
};
// Advance the state 1 to account for the closing `"`
return Ok((
MadeProgress,
expr,
state.advance_without_indenting(arena, 1)?,
));
return Ok((MadeProgress, expr, state.advance_without_indenting(1)?));
};
}
b'\n' => {
@ -163,7 +159,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, SyntaxError<'a>> {
match bytes.next() {
Some(b'(') => {
// Advance past the `\(` before using the expr parser
state = state.advance_without_indenting(arena, 2)?;
state = state.advance_without_indenting(2)?;
let original_byte_count = state.bytes.len();
@ -188,7 +184,7 @@ pub fn parse<'a>() -> impl Parser<'a, StrLiteral<'a>, SyntaxError<'a>> {
}
Some(b'u') => {
// Advance past the `\u` before using the expr parser
state = state.advance_without_indenting(arena, 2)?;
state = state.advance_without_indenting(2)?;
let original_byte_count = state.bytes.len();

View file

@ -208,19 +208,19 @@ where
buf.push('@');
buf.push(second_letter);
state = state
.advance_without_indenting(arena, total_parsed)
.map_err(|(progress, _, state)| {
state = state.advance_without_indenting(total_parsed).map_err(
|(progress, _, state)| {
(progress, to_problem(state.line, state.column), state)
})?;
},
)?;
}
_ => {
// important for error messages
state = state
.advance_without_indenting(arena, bytes_parsed)
.map_err(|(progress, _, state)| {
state = state.advance_without_indenting(bytes_parsed).map_err(
|(progress, _, state)| {
(progress, to_problem(state.line, state.column), state)
})?;
},
)?;
let row = state.line;
let col = state.column;
@ -234,11 +234,11 @@ where
buf.push(first_letter);
state = state
.advance_without_indenting(arena, bytes_parsed)
.map_err(|(progress, _, state)| {
state = state.advance_without_indenting(bytes_parsed).map_err(
|(progress, _, state)| {
(progress, to_problem(state.line, state.column), state)
})?;
},
)?;
}
_ => {
@ -265,11 +265,11 @@ where
if ch.is_alphabetic() || ch.is_ascii_digit() {
buf.push(ch);
state = state
.advance_without_indenting(arena, bytes_parsed)
.map_err(|(progress, _, state)| {
state = state.advance_without_indenting(bytes_parsed).map_err(
|(progress, _, state)| {
(progress, to_problem(state.line, state.column), state)
})?;
},
)?;
} else {
// This is the end of the field. We're done!
break;
@ -528,7 +528,7 @@ fn parse_concrete_type<'a>(
return Err((NoProgress, problem, state));
}
state = state.advance_without_indenting_e(arena, bytes_parsed, TApply::Space)?;
state = state.advance_without_indenting_e(bytes_parsed, TApply::Space)?;
}
Err(reason) => return Err((NoProgress, reason, state)),
}
@ -582,7 +582,7 @@ fn parse_concrete_type<'a>(
break;
}
state = state.advance_without_indenting_e(arena, bytes_parsed, TApply::Space)?;
state = state.advance_without_indenting_e(bytes_parsed, TApply::Space)?;
}
Err(reason) => {
return Err((MadeProgress, reason, state));
@ -634,7 +634,7 @@ fn parse_type_variable<'a>(
));
}
state = state.advance_without_indenting_e(arena, bytes_parsed, TVariable::Space)?;
state = state.advance_without_indenting_e(bytes_parsed, TVariable::Space)?;
}
Err(reason) => return Err((NoProgress, reason, state)),
}
@ -653,7 +653,7 @@ fn parse_type_variable<'a>(
break;
}
state = state.advance_without_indenting_e(arena, bytes_parsed, TVariable::Space)?;
state = state.advance_without_indenting_e(bytes_parsed, TVariable::Space)?;
}
Err(reason) => {
return state.fail(arena, MadeProgress, reason);