Un-macro either

This commit is contained in:
Jackson Wambolt 2024-04-15 21:09:39 -05:00
parent 2f776f366f
commit 02c98f7519
No known key found for this signature in database
GPG key ID: 76F29A42FEE8811C
4 changed files with 37 additions and 39 deletions

View file

@ -10,11 +10,11 @@ use crate::blankspace::{
use crate::ident::{integer_ident, lowercase_ident, parse_ident, Accessor, Ident};
use crate::keyword;
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,
zero_or_more, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern, ERecord,
EString, EType, EWhen, Either, ParseResult, Parser,
self, and, backtrackable, between, byte, byte_indent, either, 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, 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;
@ -622,7 +622,7 @@ pub fn parse_single_def<'a>(
let parse_expect_vanilla = crate::parser::keyword(crate::keyword::EXPECT, EExpect::Expect);
let parse_expect_fx = crate::parser::keyword(crate::keyword::EXPECT_FX, EExpect::Expect);
let parse_expect = either!(parse_expect_fx, parse_expect_vanilla);
let parse_expect = either(parse_expect_fx, parse_expect_vanilla);
match space0_after_e(crate::pattern::loc_pattern_help(), EPattern::IndentEnd).parse(
arena,
@ -2983,12 +2983,12 @@ pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> {
specialize_err(|_, pos| ERecord::Field(pos), loc(lowercase_ident())),
and(
spaces(),
optional(either!(
optional(either(
and(byte(b':', ERecord::Colon), record_field_expr()),
and(
byte(b'?', ERecord::QuestionMark),
spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false)))
)
spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false))),
),
)),
),
),
@ -3029,12 +3029,12 @@ fn record_field_expr<'a>() -> impl Parser<'a, RecordFieldExpr<'a>, ERecord<'a>>
map_with_arena(
and(
spaces(),
either!(
either(
and(
two_bytes(b'<', b'-', ERecord::Arrow),
spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false)))
spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false))),
),
specialize_err_ref(ERecord::Expr, loc_expr(false))
specialize_err_ref(ERecord::Expr, loc_expr(false)),
),
),
|arena: &'a bumpalo::Bump, (spaces, either)| match either {

View file

@ -2403,7 +2403,7 @@ macro_rules! debug {
/// # }
/// # let arena = Bump::new();
/// # fn foo<'a>(arena: &'a Bump) {
/// let parser = either!(
/// let parser = either(
/// word("hello", Problem::NotFound),
/// word("bye", Problem::NotFound)
/// );
@ -2426,27 +2426,25 @@ macro_rules! debug {
/// # }
/// # foo(&arena);
/// ```
#[macro_export]
macro_rules! either {
($p1:expr, $p2:expr) => {
move |arena: &'a bumpalo::Bump, state: $crate::state::State<'a>, min_indent: u32| {
let original_state = state.clone();
match $p1.parse(arena, state, min_indent) {
Ok((progress, output, state)) => {
Ok((progress, $crate::parser::Either::First(output), state))
}
Err((NoProgress, _)) => {
match $p2.parse(arena, original_state.clone(), min_indent) {
Ok((progress, output, state)) => {
Ok((progress, $crate::parser::Either::Second(output), state))
}
Err((progress, fail)) => Err((progress, fail)),
}
}
Err((MadeProgress, fail)) => Err((MadeProgress, fail)),
pub fn either<'a, OutputLeft, OutputRight, E: 'a>(
p1: impl Parser<'a, OutputLeft, E>,
p2: impl Parser<'a, OutputRight, E>,
) -> impl Parser<'a, Either<OutputLeft, OutputRight>, E> {
move |arena: &'a bumpalo::Bump, state: crate::state::State<'a>, min_indent: u32| {
let original_state = state.clone();
match p1.parse(arena, state, min_indent) {
Ok((progress, output, state)) => {
Ok((progress, crate::parser::Either::First(output), state))
}
Err((NoProgress, _)) => match p2.parse(arena, original_state.clone(), min_indent) {
Ok((progress, output, state)) => {
Ok((progress, crate::parser::Either::Second(output), state))
}
Err((progress, fail)) => Err((progress, fail)),
},
Err((MadeProgress, fail)) => Err((MadeProgress, fail)),
}
};
}
}
/// Given three parsers, parse them all but ignore the output of the first and last one.

View file

@ -2,12 +2,12 @@ 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::*;
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, zero_or_more, EPattern,
PInParens, PList, PRecord, Parser,
};
use crate::parser::{either, Progress::*};
use crate::state::State;
use crate::string_literal::StrLikeLiteral;
use bumpalo::collections::string::String;
@ -547,9 +547,9 @@ fn record_pattern_field<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PRecord<'a>>
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
// (This is true in both literals and types.)
let (_, opt_loc_val, state) = optional(either!(
let (_, opt_loc_val, state) = optional(either(
byte(b':', PRecord::Colon),
byte(b'?', PRecord::Optional)
byte(b'?', PRecord::Optional),
))
.parse(arena, state, min_indent)?;

View file

@ -9,8 +9,8 @@ use crate::expr::{record_field, FoundApplyValue};
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, zero_or_more, ERecord, ETypeAbilityImpl,
absolute_column_min_indent, and, either, increment_min_indent, loc, map, map_with_arena,
skip_first, skip_second, succeed, then, zero_or_more, ERecord, ETypeAbilityImpl,
};
use crate::parser::{
allocated, backtrackable, byte, fail, optional, specialize_err, specialize_err_ref, two_bytes,
@ -332,9 +332,9 @@ fn record_type_field<'a>() -> impl Parser<'a, AssignedField<'a, TypeAnnotation<'
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
// (This is true in both literals and types.)
let (_, opt_loc_val, state) = optional(either!(
let (_, opt_loc_val, state) = optional(either(
byte(b':', ETypeRecord::Colon),
byte(b'?', ETypeRecord::Optional)
byte(b'?', ETypeRecord::Optional),
))
.parse(arena, state, min_indent)?;