Un-macro zero_or_more

This commit is contained in:
Jackson Wambolt 2024-04-15 20:39:29 -05:00
parent a9724dda5e
commit f88e46fc32
No known key found for this signature in database
GPG key ID: 76F29A42FEE8811C
5 changed files with 70 additions and 70 deletions

View file

@ -13,8 +13,8 @@ use crate::parser::{
self, and, backtrackable, between, byte, byte_indent, increment_min_indent, indented_seq,
line_min_indent, loc, map, map_with_arena, optional, reset_min_indent, sep_by1, sep_by1_e,
set_min_indent, skip_first, skip_second, specialize_err, specialize_err_ref, then, two_bytes,
EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern, ERecord, EString, EType,
EWhen, Either, ParseResult, Parser,
zero_or_more, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern, ERecord,
EString, EType, EWhen, Either, ParseResult, Parser,
};
use crate::pattern::{closure_param, loc_implements_parser};
use crate::state::State;
@ -158,15 +158,15 @@ fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>
}
fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, Accessor<'a>>, EExpr<'a>> {
zero_or_more!(skip_first(
zero_or_more(skip_first(
byte(b'.', EExpr::Access),
specialize_err(
|_, pos| EExpr::Access(pos),
one_of!(
map(lowercase_ident(), Accessor::RecordField),
map(integer_ident(), Accessor::TupleIndex),
)
)
),
),
))
}

View file

@ -10,9 +10,9 @@ use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase, Uppercas
use crate::parser::Progress::{self, *};
use crate::parser::{
and, backtrackable, byte, increment_min_indent, loc, map, optional, reset_min_indent,
skip_first, skip_second, specialize_err, two_bytes, EExposes, EGenerates, EGeneratesWith,
EHeader, EImports, EPackages, EProvides, ERequires, ETypedIdent, Parser, SourceError,
SpaceProblem, SyntaxError,
skip_first, skip_second, specialize_err, two_bytes, zero_or_more, EExposes, EGenerates,
EGeneratesWith, EHeader, EImports, EPackages, EProvides, ERequires, ETypedIdent, Parser,
SourceError, SpaceProblem, SyntaxError,
};
use crate::state::State;
use crate::string_literal::{self, parse_str_literal};
@ -284,12 +284,12 @@ fn provides_types<'a>(
// to be the design forever. Someday it will hopefully work like Elm,
// where platform authors can provide functions like Browser.sandbox which
// present an API based on ordinary-looking type variables.
zero_or_more!(byte(
zero_or_more(byte(
b' ',
// HACK: If this errors, EProvides::Provides is not an accurate reflection
// of what went wrong. However, this is both skipped and zero_or_more,
// so this error should never be visible to anyone in practice!
EProvides::Provides
EProvides::Provides,
)),
collection_trailing_sep_e!(
byte(b'{', EProvides::ListStart),

View file

@ -2216,63 +2216,63 @@ pub fn map<'a, Output, MappedOutput, E: 'a>(
/// Applies the parser as many times as possible.
/// This parser will only fail if the given parser makes partial progress.
#[macro_export]
macro_rules! zero_or_more {
($parser:expr) => {
move |arena, state: State<'a>, min_indent: u32| {
use bumpalo::collections::Vec;
pub fn zero_or_more<'a, Output, E: 'a>(
parser: impl Parser<'a, Output, E>,
) -> impl Parser<'a, bumpalo::collections::Vec<'a, Output>, E> {
move |arena, state: State<'a>, min_indent: u32| {
let original_state = state.clone();
let original_state = state.clone();
let start_bytes_len = state.bytes().len();
let start_bytes_len = state.bytes().len();
match parser.parse(arena, state, min_indent) {
Ok((_, first_output, next_state)) => {
let mut state = next_state;
let mut buf = Vec::with_capacity_in(1, arena);
match $parser.parse(arena, state, min_indent) {
Ok((_, first_output, next_state)) => {
let mut state = next_state;
let mut buf = Vec::with_capacity_in(1, arena);
buf.push(first_output);
buf.push(first_output);
loop {
let old_state = state.clone();
match $parser.parse(arena, state, min_indent) {
Ok((_, next_output, next_state)) => {
state = next_state;
buf.push(next_output);
}
Err((fail_progress, fail)) => {
match fail_progress {
MadeProgress => {
// made progress on an element and then failed; that's an error
return Err((MadeProgress, fail));
}
NoProgress => {
// the next element failed with no progress
// report whether we made progress before
let progress = Progress::from_lengths(start_bytes_len, old_state.bytes().len());
return Ok((progress, buf, old_state));
}
loop {
let old_state = state.clone();
match parser.parse(arena, state, min_indent) {
Ok((_, next_output, next_state)) => {
state = next_state;
buf.push(next_output);
}
Err((fail_progress, fail)) => {
match fail_progress {
MadeProgress => {
// made progress on an element and then failed; that's an error
return Err((MadeProgress, fail));
}
NoProgress => {
// the next element failed with no progress
// report whether we made progress before
let progress = Progress::from_lengths(
start_bytes_len,
old_state.bytes().len(),
);
return Ok((progress, buf, old_state));
}
}
}
}
}
Err((fail_progress, fail)) => {
match fail_progress {
MadeProgress => {
// made progress on an element and then failed; that's an error
Err((MadeProgress, fail))
}
NoProgress => {
// the first element failed (with no progress), but that's OK
// because we only need to parse 0 elements
Ok((NoProgress, Vec::new_in(arena), original_state))
}
}
Err((fail_progress, fail)) => {
match fail_progress {
MadeProgress => {
// made progress on an element and then failed; that's an error
Err((MadeProgress, fail))
}
NoProgress => {
// the first element failed (with no progress), but that's OK
// because we only need to parse 0 elements
Ok((NoProgress, Vec::new_in(arena), original_state))
}
}
}
}
};
}
}
/// Creates a parser that matches one or more times.
@ -2285,7 +2285,7 @@ macro_rules! zero_or_more {
/// # use roc_parse::state::State;
/// # use crate::roc_parse::parser::{Parser, Progress, Progress::{MadeProgress, NoProgress}, word};
/// # use roc_region::all::Position;
/// # use roc_parse::one_or_more;
/// # use roc_parse::one_or_more!;
/// # use bumpalo::Bump;
/// # #[derive(Debug, PartialEq)]
/// # enum Problem {
@ -2293,7 +2293,7 @@ macro_rules! zero_or_more {
/// # }
/// # let arena = Bump::new();
/// # fn foo<'a>(arena: &'a Bump) {
/// let parser = one_or_more!(
/// let parser = one_or_more(
/// word("hello, ", Problem::NotFound),
/// Problem::NotFound
/// );

View file

@ -2,11 +2,11 @@ use crate::ast::{Implements, Pattern, PatternAs, Spaceable};
use crate::blankspace::{space0_e, spaces, spaces_before};
use crate::ident::{lowercase_ident, parse_ident, Accessor, Ident};
use crate::keyword;
use crate::parser::Progress::{self, *};
use crate::parser::Progress::*;
use crate::parser::{
self, backtrackable, byte, fail_when, loc, map, map_with_arena, optional, skip_first,
specialize_err, specialize_err_ref, then, three_bytes, two_bytes, EPattern, PInParens, PList,
PRecord, Parser,
specialize_err, specialize_err_ref, then, three_bytes, two_bytes, zero_or_more, EPattern,
PInParens, PList, PRecord, Parser,
};
use crate::state::State;
use crate::string_literal::StrLikeLiteral;
@ -125,13 +125,13 @@ fn pattern_as<'a>() -> impl Parser<'a, PatternAs<'a>, EPattern<'a>> {
}
fn loc_tag_pattern_args_help<'a>() -> impl Parser<'a, Vec<'a, Loc<Pattern<'a>>>, EPattern<'a>> {
zero_or_more!(loc_tag_pattern_arg(false))
zero_or_more(loc_tag_pattern_arg(false))
}
/// Like `loc_tag_pattern_args_help`, but stops if a "implements" keyword is seen (indicating an ability).
fn loc_type_def_tag_pattern_args_help<'a>(
) -> impl Parser<'a, Vec<'a, Loc<Pattern<'a>>>, EPattern<'a>> {
zero_or_more!(loc_tag_pattern_arg(true))
zero_or_more(loc_tag_pattern_arg(true))
}
fn loc_tag_pattern_arg<'a>(

View file

@ -10,12 +10,12 @@ use crate::ident::{lowercase_ident, lowercase_ident_keyword_e};
use crate::keyword;
use crate::parser::{
absolute_column_min_indent, and, increment_min_indent, loc, map, map_with_arena, skip_first,
skip_second, succeed, then, ERecord, ETypeAbilityImpl,
skip_second, succeed, then, zero_or_more, ERecord, ETypeAbilityImpl,
};
use crate::parser::{
allocated, backtrackable, byte, fail, optional, specialize_err, specialize_err_ref, two_bytes,
word, EType, ETypeApply, ETypeInParens, ETypeInlineAlias, ETypeRecord, ETypeTagUnion, Parser,
Progress::{self, *},
Progress::*,
};
use crate::state::State;
use bumpalo::collections::vec::Vec;
@ -426,7 +426,7 @@ fn applied_type<'a>(stop_at_surface_has: bool) -> impl Parser<'a, TypeAnnotation
fn loc_applied_args_e<'a>(
stop_at_surface_has: bool,
) -> impl Parser<'a, Vec<'a, Loc<TypeAnnotation<'a>>>, EType<'a>> {
zero_or_more!(loc_applied_arg(stop_at_surface_has))
zero_or_more(loc_applied_arg(stop_at_surface_has))
}
// Hash & Eq & ...
@ -438,13 +438,13 @@ fn ability_chain<'a>() -> impl Parser<'a, Vec<'a, Loc<TypeAnnotation<'a>>>, ETyp
EType::TIndentStart,
EType::TIndentEnd,
),
zero_or_more!(skip_first(
zero_or_more(skip_first(
byte(b'&', EType::TImplementsClause),
space0_before_optional_after(
specialize_err(EType::TApply, loc(concrete_type())),
EType::TIndentStart,
EType::TIndentEnd,
)
),
)),
),
|(first_ability, mut other_abilities): (
@ -506,9 +506,9 @@ fn implements_clause_chain<'a>(
// Parse the first clause (there must be one), then the rest
let (_, first_clause, state) = implements_clause().parse(arena, state, min_indent)?;
let (_, mut clauses, state) = zero_or_more!(skip_first(
let (_, mut clauses, state) = zero_or_more(skip_first(
byte(b',', EType::TImplementsClause),
implements_clause()
implements_clause(),
))
.parse(arena, state, min_indent)?;
@ -585,7 +585,7 @@ fn expression<'a>(
.parse(arena, state, min_indent)?;
let result = and(
zero_or_more!(skip_first(
zero_or_more(skip_first(
byte(b',', EType::TFunctionArgument),
one_of![
space0_around_ee(
@ -594,7 +594,7 @@ fn expression<'a>(
EType::TIndentEnd
),
fail(EType::TFunctionArgument)
]
],
))
.trace("type_annotation:expression:rest_args"),
skip_second(