mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
parameterize Parser on an Error type
This commit is contained in:
parent
da28486184
commit
148fffe969
17 changed files with 372 additions and 271 deletions
|
@ -2,9 +2,9 @@ use crate::ast::CommentOrNewline::{self, *};
|
|||
use crate::ast::{Attempting, Spaceable};
|
||||
use crate::parser::{
|
||||
self, and, ascii_char, ascii_string, backtrackable, optional, parse_utf8, peek_utf8_char, then,
|
||||
unexpected, unexpected_eof, FailReason, Parser,
|
||||
unexpected, unexpected_eof, Parser,
|
||||
Progress::{self, *},
|
||||
State,
|
||||
State, SyntaxError,
|
||||
};
|
||||
use bumpalo::collections::string::String;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
|
@ -15,12 +15,15 @@ use roc_region::all::Located;
|
|||
/// Returns a Located<Expr> where the location is around the Expr, ignoring the spaces.
|
||||
/// If any newlines or comments were found, the Expr will be wrapped in a SpaceBefore and/or
|
||||
/// SpaceAfter as appropriate.
|
||||
pub fn space0_around<'a, P, S>(parser: P, min_indent: u16) -> impl Parser<'a, Located<S>>
|
||||
pub fn space0_around<'a, P, S>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<S>, SyntaxError>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
S: 'a,
|
||||
S: Sized,
|
||||
P: Parser<'a, Located<S>>,
|
||||
P: Parser<'a, Located<S>, SyntaxError>,
|
||||
P: 'a,
|
||||
{
|
||||
parser::map_with_arena(
|
||||
|
@ -62,11 +65,14 @@ where
|
|||
/// Returns a Located<Expr> where the location is around the Expr, ignoring the spaces.
|
||||
/// If any newlines or comments were found, the Expr will be wrapped in a SpaceBefore and/or
|
||||
/// SpaceAfter as appropriate.
|
||||
pub fn space1_around<'a, P, S>(parser: P, min_indent: u16) -> impl Parser<'a, Located<S>>
|
||||
pub fn space1_around<'a, P, S>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<S>, SyntaxError>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
S: 'a,
|
||||
P: Parser<'a, Located<S>>,
|
||||
P: Parser<'a, Located<S>, SyntaxError>,
|
||||
P: 'a,
|
||||
{
|
||||
parser::map_with_arena(
|
||||
|
@ -100,11 +106,14 @@ where
|
|||
/// Parses the given expression with 0 or more (spaces/comments/newlines) before it.
|
||||
/// Returns a Located<Expr> where the location is around the Expr, ignoring the spaces.
|
||||
/// The Expr will be wrapped in a SpaceBefore if there were any newlines or comments found.
|
||||
pub fn space0_before<'a, P, S>(parser: P, min_indent: u16) -> impl Parser<'a, Located<S>>
|
||||
pub fn space0_before<'a, P, S>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<S>, SyntaxError>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
S: 'a,
|
||||
P: Parser<'a, Located<S>>,
|
||||
P: Parser<'a, Located<S>, SyntaxError>,
|
||||
P: 'a,
|
||||
{
|
||||
parser::map_with_arena(
|
||||
|
@ -124,11 +133,14 @@ where
|
|||
/// Parses the given expression with 1 or more (spaces/comments/newlines) before it.
|
||||
/// Returns a Located<Expr> where the location is around the Expr, ignoring the spaces.
|
||||
/// The Expr will be wrapped in a SpaceBefore if there were any newlines or comments found.
|
||||
pub fn space1_before<'a, P, S>(parser: P, min_indent: u16) -> impl Parser<'a, Located<S>>
|
||||
pub fn space1_before<'a, P, S>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<S>, SyntaxError>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
S: 'a,
|
||||
P: Parser<'a, Located<S>>,
|
||||
P: Parser<'a, Located<S>, SyntaxError>,
|
||||
P: 'a,
|
||||
{
|
||||
parser::map_with_arena(
|
||||
|
@ -148,11 +160,14 @@ where
|
|||
/// Parses the given expression with 0 or more (spaces/comments/newlines) after it.
|
||||
/// Returns a Located<Expr> where the location is around the Expr, ignoring the spaces.
|
||||
/// The Expr will be wrapped in a SpaceAfter if there were any newlines or comments found.
|
||||
pub fn space0_after<'a, P, S>(parser: P, min_indent: u16) -> impl Parser<'a, Located<S>>
|
||||
pub fn space0_after<'a, P, S>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<S>, SyntaxError>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
S: 'a,
|
||||
P: Parser<'a, Located<S>>,
|
||||
P: Parser<'a, Located<S>, SyntaxError>,
|
||||
P: 'a,
|
||||
{
|
||||
parser::map_with_arena(
|
||||
|
@ -172,11 +187,14 @@ where
|
|||
/// Parses the given expression with 1 or more (spaces/comments/newlines) after it.
|
||||
/// Returns a Located<Expr> where the location is around the Expr, ignoring the spaces.
|
||||
/// The Expr will be wrapped in a SpaceAfter if there were any newlines or comments found.
|
||||
pub fn space1_after<'a, P, S>(parser: P, min_indent: u16) -> impl Parser<'a, Located<S>>
|
||||
pub fn space1_after<'a, P, S>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<S>, SyntaxError>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
S: 'a,
|
||||
P: Parser<'a, Located<S>>,
|
||||
P: Parser<'a, Located<S>, SyntaxError>,
|
||||
P: 'a,
|
||||
{
|
||||
parser::map_with_arena(
|
||||
|
@ -194,12 +212,12 @@ where
|
|||
}
|
||||
|
||||
/// Zero or more (spaces/comments/newlines).
|
||||
pub fn space0<'a>(min_indent: u16) -> impl Parser<'a, &'a [CommentOrNewline<'a>]> {
|
||||
pub fn space0<'a>(min_indent: u16) -> impl Parser<'a, &'a [CommentOrNewline<'a>], SyntaxError> {
|
||||
spaces(false, min_indent)
|
||||
}
|
||||
|
||||
/// One or more (spaces/comments/newlines).
|
||||
pub fn space1<'a>(min_indent: u16) -> impl Parser<'a, &'a [CommentOrNewline<'a>]> {
|
||||
pub fn space1<'a>(min_indent: u16) -> impl Parser<'a, &'a [CommentOrNewline<'a>], SyntaxError> {
|
||||
// TODO try benchmarking a short-circuit for the typical case: see if there is
|
||||
// exactly one space followed by char that isn't [' ', '\n', or '#'], and
|
||||
// if so, return empty slice. The case where there's exactly 1 space should
|
||||
|
@ -214,7 +232,7 @@ enum LineState {
|
|||
DocComment,
|
||||
}
|
||||
|
||||
pub fn line_comment<'a>() -> impl Parser<'a, &'a str> {
|
||||
pub fn line_comment<'a>() -> impl Parser<'a, &'a str, SyntaxError> {
|
||||
then(
|
||||
and!(ascii_char(b'#'), optional(ascii_string("# "))),
|
||||
|arena: &'a Bump, state: State<'a>, _, (_, opt_doc)| {
|
||||
|
@ -242,7 +260,7 @@ pub fn line_comment<'a>() -> impl Parser<'a, &'a str> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn spaces_exactly<'a>(spaces_expected: u16) -> impl Parser<'a, ()> {
|
||||
pub fn spaces_exactly<'a>(spaces_expected: u16) -> impl Parser<'a, (), SyntaxError> {
|
||||
move |arena: &'a Bump, state: State<'a>| {
|
||||
if spaces_expected == 0 {
|
||||
return Ok((NoProgress, (), state));
|
||||
|
@ -269,10 +287,10 @@ pub fn spaces_exactly<'a>(spaces_expected: u16) -> impl Parser<'a, ()> {
|
|||
));
|
||||
}
|
||||
|
||||
Err(FailReason::BadUtf8) => {
|
||||
Err(SyntaxError::BadUtf8) => {
|
||||
// If we hit an invalid UTF-8 character, bail out immediately.
|
||||
let progress = Progress::progress_when(spaces_seen != 0);
|
||||
return state.fail(arena, progress, FailReason::BadUtf8);
|
||||
return state.fail(arena, progress, SyntaxError::BadUtf8);
|
||||
}
|
||||
Err(_) => {
|
||||
if spaces_seen == 0 {
|
||||
|
@ -306,7 +324,7 @@ pub fn spaces_exactly<'a>(spaces_expected: u16) -> impl Parser<'a, ()> {
|
|||
fn spaces<'a>(
|
||||
require_at_least_one: bool,
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, &'a [CommentOrNewline<'a>]> {
|
||||
) -> impl Parser<'a, &'a [CommentOrNewline<'a>], SyntaxError> {
|
||||
move |arena: &'a Bump, state: State<'a>| {
|
||||
let original_state = state.clone();
|
||||
let mut space_list = Vec::new_in(arena);
|
||||
|
@ -478,10 +496,10 @@ fn spaces<'a>(
|
|||
}
|
||||
}
|
||||
}
|
||||
Err(FailReason::BadUtf8) => {
|
||||
Err(SyntaxError::BadUtf8) => {
|
||||
// If we hit an invalid UTF-8 character, bail out immediately.
|
||||
let progress = Progress::from_lengths(start_bytes_len, state.bytes.len());
|
||||
return state.fail(arena, progress, FailReason::BadUtf8);
|
||||
return state.fail(arena, progress, SyntaxError::BadUtf8);
|
||||
}
|
||||
Err(_) => {
|
||||
if require_at_least_one && bytes_parsed == 0 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue