mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Un-macro zero_or_more
This commit is contained in:
parent
a9724dda5e
commit
f88e46fc32
5 changed files with 70 additions and 70 deletions
|
@ -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),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
/// );
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue