mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Un-macro skip_first
This commit is contained in:
parent
e8ae2e12f8
commit
8a144149e2
5 changed files with 55 additions and 52 deletions
|
@ -11,7 +11,7 @@ use crate::ident::{integer_ident, lowercase_ident, parse_ident, Accessor, Ident}
|
|||
use crate::keyword;
|
||||
use crate::parser::{
|
||||
self, backtrackable, byte, byte_indent, increment_min_indent, line_min_indent, optional,
|
||||
reset_min_indent, sep_by1, sep_by1_e, set_min_indent, skip_second, specialize_err,
|
||||
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,
|
||||
};
|
||||
|
@ -157,7 +157,7 @@ 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),
|
||||
|
@ -1486,7 +1486,7 @@ mod ability {
|
|||
// Require the type to be more indented than the name
|
||||
absolute_indented_seq!(
|
||||
specialize_err(|_, pos| EAbility::DemandName(pos), loc!(lowercase_ident())),
|
||||
skip_first!(
|
||||
skip_first(
|
||||
and!(
|
||||
// TODO: do we get anything from picking up spaces here?
|
||||
space0_e(EAbility::DemandName),
|
||||
|
@ -1903,9 +1903,9 @@ fn parse_expr_end<'a>(
|
|||
min_indent
|
||||
};
|
||||
|
||||
let parser = skip_first!(
|
||||
let parser = skip_first(
|
||||
crate::blankspace::check_indent(EExpr::IndentEnd),
|
||||
loc_term_or_underscore(options)
|
||||
loc_term_or_underscore(options),
|
||||
);
|
||||
|
||||
match parser.parse(arena, state.clone(), inner_min_indent) {
|
||||
|
@ -2379,7 +2379,7 @@ fn closure_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EClo
|
|||
),
|
||||
EClosure::Arg,
|
||||
),
|
||||
skip_first!(
|
||||
skip_first(
|
||||
// Parse the -> which separates params from body
|
||||
two_bytes(b'-', b'>', EClosure::Arrow),
|
||||
// Parse the body
|
||||
|
@ -2514,7 +2514,7 @@ mod when {
|
|||
branch_alternatives_help(pattern_indent_level),
|
||||
one_of![
|
||||
map!(
|
||||
skip_first!(
|
||||
skip_first(
|
||||
parser::keyword(keyword::IF, EWhen::IfToken),
|
||||
// TODO we should require space before the expression but not after
|
||||
space0_around_ee(
|
||||
|
@ -2616,12 +2616,12 @@ mod when {
|
|||
/// Parsing the righthandside of a branch in a when conditional.
|
||||
fn branch_result<'a>(indent: u32) -> impl Parser<'a, Loc<Expr<'a>>, EWhen<'a>> {
|
||||
move |arena, state, _min_indent| {
|
||||
skip_first!(
|
||||
skip_first(
|
||||
two_bytes(b'-', b'>', EWhen::Arrow),
|
||||
space0_before_e(
|
||||
specialize_err_ref(EWhen::Branch, loc_expr(true)),
|
||||
EWhen::IndentBranch,
|
||||
)
|
||||
),
|
||||
)
|
||||
.parse(arena, state, indent)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::header::{
|
|||
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase, UppercaseIdent};
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{
|
||||
backtrackable, byte, increment_min_indent, optional, reset_min_indent, skip_second,
|
||||
backtrackable, byte, increment_min_indent, 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,
|
||||
};
|
||||
|
@ -54,35 +54,35 @@ pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||
comments: space0_e(EHeader::IndentStart),
|
||||
header: one_of![
|
||||
map!(
|
||||
skip_first!(
|
||||
skip_first(
|
||||
keyword("interface", EHeader::Start),
|
||||
increment_min_indent(interface_header())
|
||||
),
|
||||
Header::Interface
|
||||
),
|
||||
map!(
|
||||
skip_first!(
|
||||
skip_first(
|
||||
keyword("app", EHeader::Start),
|
||||
increment_min_indent(app_header())
|
||||
),
|
||||
Header::App
|
||||
),
|
||||
map!(
|
||||
skip_first!(
|
||||
skip_first(
|
||||
keyword("package", EHeader::Start),
|
||||
increment_min_indent(package_header())
|
||||
),
|
||||
Header::Package
|
||||
),
|
||||
map!(
|
||||
skip_first!(
|
||||
skip_first(
|
||||
keyword("platform", EHeader::Start),
|
||||
increment_min_indent(platform_header())
|
||||
),
|
||||
Header::Platform
|
||||
),
|
||||
map!(
|
||||
skip_first!(
|
||||
skip_first(
|
||||
keyword("hosted", EHeader::Start),
|
||||
increment_min_indent(hosted_header())
|
||||
),
|
||||
|
@ -278,7 +278,7 @@ fn provides_exposed<'a>() -> impl Parser<
|
|||
#[inline(always)]
|
||||
fn provides_types<'a>(
|
||||
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>, EProvides<'a>> {
|
||||
skip_first!(
|
||||
skip_first(
|
||||
// We only support spaces here, not newlines, because this is not intended
|
||||
// to be the design forever. Someday it will hopefully work like Elm,
|
||||
// where platform authors can provide functions like Browser.sandbox which
|
||||
|
@ -296,7 +296,7 @@ fn provides_types<'a>(
|
|||
byte(b',', EProvides::ListEnd),
|
||||
byte(b'}', EProvides::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -367,16 +367,16 @@ fn requires_rigids<'a>(
|
|||
|
||||
#[inline(always)]
|
||||
fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>, ERequires<'a>> {
|
||||
skip_first!(
|
||||
skip_first(
|
||||
byte(b'{', ERequires::ListStart),
|
||||
skip_second(
|
||||
reset_min_indent(space0_around_ee(
|
||||
specialize_err(ERequires::TypedIdent, loc!(typed_ident()),),
|
||||
specialize_err(ERequires::TypedIdent, loc!(typed_ident())),
|
||||
ERequires::ListStart,
|
||||
ERequires::ListEnd
|
||||
ERequires::ListEnd,
|
||||
)),
|
||||
byte(b'}', ERequires::ListStart)
|
||||
)
|
||||
byte(b'}', ERequires::ListStart),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -568,7 +568,7 @@ fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<
|
|||
)),
|
||||
space0_e(ETypedIdent::IndentHasType)
|
||||
),
|
||||
skip_first!(
|
||||
skip_first(
|
||||
byte(b':', ETypedIdent::HasType),
|
||||
space0_before_e(
|
||||
specialize_err(
|
||||
|
@ -622,7 +622,7 @@ fn imports_entry<'a>() -> impl Parser<'a, Spaced<'a, ImportsEntry<'a>>, EImports
|
|||
module_name_help(EImports::ModuleName)
|
||||
),
|
||||
// e.g. `.{ Task, after}`
|
||||
optional(skip_first!(
|
||||
optional(skip_first(
|
||||
byte(b'.', EImports::ExposingDot),
|
||||
collection_trailing_sep_e!(
|
||||
byte(b'{', EImports::SetStart),
|
||||
|
|
|
@ -1387,7 +1387,7 @@ macro_rules! loc {
|
|||
/// # use bumpalo::Bump;
|
||||
/// # let arena = Bump::new();
|
||||
/// # fn foo<'a>(arena: &'a Bump) {
|
||||
/// let parser = skip_first!(
|
||||
/// let parser = skip_first(
|
||||
/// word("hello, ", |_| ()),
|
||||
/// lowercase_ident()
|
||||
/// );
|
||||
|
@ -1399,19 +1399,21 @@ macro_rules! loc {
|
|||
/// # }
|
||||
/// # foo(&arena);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! skip_first {
|
||||
($p1:expr, $p2:expr) => {
|
||||
move |arena, state: $crate::state::State<'a>, min_indent: u32| match $p1
|
||||
.parse(arena, state, min_indent)
|
||||
{
|
||||
Ok((p1, _, state)) => match $p2.parse(arena, state, min_indent) {
|
||||
Ok((p2, out2, state)) => Ok((p1.or(p2), out2, state)),
|
||||
Err((p2, fail)) => Err((p1.or(p2), fail)),
|
||||
},
|
||||
Err((progress, fail)) => Err((progress, fail)),
|
||||
}
|
||||
};
|
||||
pub fn skip_first<'a, P1, First, P2, Second, E>(p1: P1, p2: P2) -> impl Parser<'a, Second, E>
|
||||
where
|
||||
P1: Parser<'a, First, E>,
|
||||
P2: Parser<'a, Second, E>,
|
||||
E: 'a,
|
||||
{
|
||||
move |arena, state: crate::state::State<'a>, min_indent: u32| match p1
|
||||
.parse(arena, state, min_indent)
|
||||
{
|
||||
Ok((p1, _, state)) => match p2.parse(arena, state, min_indent) {
|
||||
Ok((p2, out2, state)) => Ok((p1.or(p2), out2, state)),
|
||||
Err((p2, fail)) => Err((p1.or(p2), fail)),
|
||||
},
|
||||
Err((progress, fail)) => Err((progress, fail)),
|
||||
}
|
||||
}
|
||||
|
||||
/// If the first one parses, parse the second one; if it also parses, use the
|
||||
|
@ -2537,9 +2539,9 @@ macro_rules! either {
|
|||
#[macro_export]
|
||||
macro_rules! between {
|
||||
($opening_brace:expr, $parser:expr, $closing_brace:expr) => {
|
||||
skip_first!(
|
||||
$crate::parser::skip_first(
|
||||
$opening_brace,
|
||||
$crate::parser::skip_second($parser, $closing_brace)
|
||||
$crate::parser::skip_second($parser, $closing_brace),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::ident::{lowercase_ident, parse_ident, Accessor, Ident};
|
|||
use crate::keyword;
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{
|
||||
self, backtrackable, byte, fail_when, optional, specialize_err, specialize_err_ref, then,
|
||||
three_bytes, two_bytes, EPattern, PInParens, PList, PRecord, Parser,
|
||||
self, backtrackable, byte, fail_when, optional, skip_first, specialize_err, specialize_err_ref,
|
||||
then, three_bytes, two_bytes, EPattern, PInParens, PList, PRecord, Parser,
|
||||
};
|
||||
use crate::state::State;
|
||||
use crate::string_literal::StrLikeLiteral;
|
||||
|
@ -503,7 +503,7 @@ fn loc_ident_pattern_help<'a>(
|
|||
|
||||
fn underscore_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>> {
|
||||
map!(
|
||||
skip_first!(
|
||||
skip_first(
|
||||
byte(b'_', EPattern::Underscore),
|
||||
optional(lowercase_ident_pattern())
|
||||
),
|
||||
|
|
|
@ -9,7 +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, increment_min_indent, skip_second, then, ERecord, ETypeAbilityImpl,
|
||||
absolute_column_min_indent, increment_min_indent, skip_first, skip_second, then, ERecord,
|
||||
ETypeAbilityImpl,
|
||||
};
|
||||
use crate::parser::{
|
||||
allocated, backtrackable, byte, fail, optional, specialize_err, specialize_err_ref, two_bytes,
|
||||
|
@ -437,7 +438,7 @@ 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())),
|
||||
|
@ -469,7 +470,7 @@ fn implements_clause<'a>() -> impl Parser<'a, Loc<ImplementsClause<'a>>, EType<'
|
|||
EType::TIndentStart,
|
||||
EType::TIndentEnd
|
||||
),
|
||||
skip_first!(
|
||||
skip_first(
|
||||
// Parse "implements"; we don't care about this keyword
|
||||
word(crate::keyword::IMPLEMENTS, EType::TImplementsClause),
|
||||
// Parse "Hash & ..."; this may be qualified from another module like "Hash.Hash"
|
||||
|
@ -505,7 +506,7 @@ 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()
|
||||
))
|
||||
|
@ -524,7 +525,7 @@ fn implements_clause_chain<'a>(
|
|||
|
||||
/// Parse a implements-abilities clause, e.g. `implements [Eq, Hash]`.
|
||||
pub fn implements_abilities<'a>() -> impl Parser<'a, Loc<ImplementsAbilities<'a>>, EType<'a>> {
|
||||
increment_min_indent(skip_first!(
|
||||
increment_min_indent(skip_first(
|
||||
// Parse "implements"; we don't care about this keyword
|
||||
word(crate::keyword::IMPLEMENTS, EType::TImplementsClause),
|
||||
// Parse "Hash"; this may be qualified from another module like "Hash.Hash"
|
||||
|
@ -540,7 +541,7 @@ pub fn implements_abilities<'a>() -> impl Parser<'a, Loc<ImplementsAbilities<'a>
|
|||
ImplementsAbilities::Implements
|
||||
)),
|
||||
EType::TIndentEnd,
|
||||
)
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -584,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(
|
||||
|
@ -635,9 +636,9 @@ fn expression<'a>(
|
|||
}
|
||||
Err(err) => {
|
||||
if !is_trailing_comma_valid {
|
||||
let (_, comma, _) = optional(backtrackable(skip_first!(
|
||||
let (_, comma, _) = optional(backtrackable(skip_first(
|
||||
space0_e(EType::TIndentStart),
|
||||
byte(b',', EType::TStart)
|
||||
byte(b',', EType::TStart),
|
||||
)))
|
||||
.trace("check trailing comma")
|
||||
.parse(arena, state.clone(), min_indent)?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue