mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
Un-macro loc
This commit is contained in:
parent
3394aab650
commit
5c0b2a0938
7 changed files with 130 additions and 172 deletions
|
@ -11,7 +11,7 @@ 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, map, optional, reset_min_indent, sep_by1, sep_by1_e, set_min_indent,
|
||||
line_min_indent, loc, map, 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,
|
||||
|
@ -94,7 +94,7 @@ pub fn expr_help<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
|||
|
||||
fn loc_expr_in_parens_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EInParens<'a>> {
|
||||
then(
|
||||
loc!(collection_trailing_sep_e!(
|
||||
loc(collection_trailing_sep_e!(
|
||||
byte(b'(', EInParens::Open),
|
||||
specialize_err_ref(EInParens::Expr, loc_expr(false)),
|
||||
byte(b',', EInParens::End),
|
||||
|
@ -132,7 +132,7 @@ fn loc_expr_in_parens_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EInParens<'a>
|
|||
|
||||
fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
map_with_arena!(
|
||||
loc!(and(
|
||||
loc(and(
|
||||
specialize_err(EExpr::InParens, loc_expr_in_parens_help()),
|
||||
record_field_access_chain()
|
||||
)),
|
||||
|
@ -177,19 +177,19 @@ fn loc_term_or_underscore_or_conditional<'a>(
|
|||
) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
one_of!(
|
||||
loc_expr_in_parens_etc_help(),
|
||||
loc!(specialize_err(EExpr::If, if_expr_help(options))),
|
||||
loc!(specialize_err(EExpr::When, when::expr_help(options))),
|
||||
loc!(specialize_err(EExpr::Str, string_like_literal_help())),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(EExpr::If, if_expr_help(options))),
|
||||
loc(specialize_err(EExpr::When, when::expr_help(options))),
|
||||
loc(specialize_err(EExpr::Str, string_like_literal_help())),
|
||||
loc(specialize_err(
|
||||
EExpr::Number,
|
||||
positive_number_literal_help()
|
||||
)),
|
||||
loc!(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc!(crash_kw()),
|
||||
loc!(underscore_expression()),
|
||||
loc!(record_literal_help()),
|
||||
loc!(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
loc(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc(crash_kw()),
|
||||
loc(underscore_expression()),
|
||||
loc(record_literal_help()),
|
||||
loc(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
)),
|
||||
|
@ -203,16 +203,16 @@ fn loc_term_or_underscore<'a>(
|
|||
) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
one_of!(
|
||||
loc_expr_in_parens_etc_help(),
|
||||
loc!(specialize_err(EExpr::Str, string_like_literal_help())),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(EExpr::Str, string_like_literal_help())),
|
||||
loc(specialize_err(
|
||||
EExpr::Number,
|
||||
positive_number_literal_help()
|
||||
)),
|
||||
loc!(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc!(underscore_expression()),
|
||||
loc!(record_literal_help()),
|
||||
loc!(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
loc(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc(underscore_expression()),
|
||||
loc(record_literal_help()),
|
||||
loc(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
)),
|
||||
|
@ -222,15 +222,15 @@ fn loc_term_or_underscore<'a>(
|
|||
fn loc_term<'a>(options: ExprParseOptions) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
one_of!(
|
||||
loc_expr_in_parens_etc_help(),
|
||||
loc!(specialize_err(EExpr::Str, string_like_literal_help())),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(EExpr::Str, string_like_literal_help())),
|
||||
loc(specialize_err(
|
||||
EExpr::Number,
|
||||
positive_number_literal_help()
|
||||
)),
|
||||
loc!(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc!(record_literal_help()),
|
||||
loc!(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
loc(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc(record_literal_help()),
|
||||
loc(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
)),
|
||||
|
@ -273,17 +273,17 @@ fn loc_possibly_negative_or_negated_term<'a>(
|
|||
let initial = state.clone();
|
||||
|
||||
let (_, (loc_op, loc_expr), state) =
|
||||
and(loc!(unary_negate()), loc_term(options)).parse(arena, state, min_indent)?;
|
||||
and(loc(unary_negate()), loc_term(options)).parse(arena, state, min_indent)?;
|
||||
|
||||
let loc_expr = numeric_negate_expression(arena, initial, loc_op, loc_expr, &[]);
|
||||
|
||||
Ok((MadeProgress, loc_expr, state))
|
||||
},
|
||||
// this will parse negative numbers, which the unary negate thing up top doesn't (for now)
|
||||
loc!(specialize_err(EExpr::Number, number_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
loc(specialize_err(EExpr::Number, number_literal_help())),
|
||||
loc(map_with_arena!(
|
||||
and(
|
||||
loc!(byte(b'!', EExpr::Start)),
|
||||
loc(byte(b'!', EExpr::Start)),
|
||||
space0_before_e(loc_term(options), EExpr::IndentStart)
|
||||
),
|
||||
|arena: &'a Bump, (loc_op, loc_expr): (Loc<_>, _)| {
|
||||
|
@ -323,12 +323,12 @@ fn unary_negate<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
|||
|
||||
fn expr_start<'a>(options: ExprParseOptions) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
one_of![
|
||||
loc!(specialize_err(EExpr::If, if_expr_help(options))),
|
||||
loc!(specialize_err(EExpr::When, when::expr_help(options))),
|
||||
loc!(specialize_err(EExpr::Expect, expect_help(options))),
|
||||
loc!(specialize_err(EExpr::Dbg, dbg_help(options))),
|
||||
loc!(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc!(expr_operator_chain(options)),
|
||||
loc(specialize_err(EExpr::If, if_expr_help(options))),
|
||||
loc(specialize_err(EExpr::When, when::expr_help(options))),
|
||||
loc(specialize_err(EExpr::Expect, expect_help(options))),
|
||||
loc(specialize_err(EExpr::Dbg, dbg_help(options))),
|
||||
loc(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc(expr_operator_chain(options)),
|
||||
fail_expr_start_e()
|
||||
]
|
||||
.trace("expr_start")
|
||||
|
@ -1486,7 +1486,7 @@ mod ability {
|
|||
map(
|
||||
// Require the type to be more indented than the name
|
||||
absolute_indented_seq(
|
||||
specialize_err(|_, pos| EAbility::DemandName(pos), loc!(lowercase_ident())),
|
||||
specialize_err(|_, pos| EAbility::DemandName(pos), loc(lowercase_ident())),
|
||||
skip_first(
|
||||
and(
|
||||
// TODO: do we get anything from picking up spaces here?
|
||||
|
@ -2010,7 +2010,7 @@ fn parse_expr_end<'a>(
|
|||
let before_op = state.clone();
|
||||
// try an operator
|
||||
let line_indent = state.line_indent();
|
||||
match loc!(operator()).parse(arena, state.clone(), min_indent) {
|
||||
match loc(operator()).parse(arena, state.clone(), min_indent) {
|
||||
Err((MadeProgress, f)) => Err((MadeProgress, f)),
|
||||
Ok((_, loc_op, state)) => {
|
||||
expr_state.consume_spaces(arena);
|
||||
|
@ -2980,7 +2980,7 @@ pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> {
|
|||
|
||||
map_with_arena!(
|
||||
and(
|
||||
specialize_err(|_, pos| ERecord::Field(pos), loc!(lowercase_ident())),
|
||||
specialize_err(|_, pos| ERecord::Field(pos), loc(lowercase_ident())),
|
||||
and(
|
||||
spaces(),
|
||||
optional(either!(
|
||||
|
@ -3078,12 +3078,12 @@ fn record_help<'a>() -> impl Parser<'a, RecordHelp<'a>, ERecord<'a>> {
|
|||
// so that we have a Spaceable value to work with,
|
||||
// and then in canonicalization verify that it's an Expr::Var
|
||||
// (and not e.g. an `Expr::Access`) and extract its string.
|
||||
loc!(record_updateable_identifier()),
|
||||
loc(record_updateable_identifier()),
|
||||
),
|
||||
byte(b'&', ERecord::Ampersand)
|
||||
))),
|
||||
fields: collection_inner!(
|
||||
loc!(record_field()),
|
||||
loc(record_field()),
|
||||
byte(b',', ERecord::End),
|
||||
RecordField::SpaceBefore
|
||||
),
|
||||
|
|
|
@ -4,7 +4,9 @@ use crate::ast::{
|
|||
use crate::blankspace::space0_e;
|
||||
use crate::expr::merge_spaces;
|
||||
use crate::ident::{lowercase_ident, UppercaseIdent};
|
||||
use crate::parser::{and, byte, skip_second, specialize_err, EPackageEntry, EPackageName, Parser};
|
||||
use crate::parser::{
|
||||
and, byte, loc, skip_second, specialize_err, EPackageEntry, EPackageName, Parser,
|
||||
};
|
||||
use crate::parser::{optional, then};
|
||||
use crate::string_literal;
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
|
@ -353,7 +355,7 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
|
|||
),
|
||||
space0_e(EPackageEntry::IndentPackage)
|
||||
)),
|
||||
loc!(specialize_err(EPackageEntry::BadPackage, package_name()))
|
||||
loc(specialize_err(EPackageEntry::BadPackage, package_name()))
|
||||
),
|
||||
move |arena, (opt_shorthand, package_or_path)| {
|
||||
let entry = match opt_shorthand {
|
||||
|
@ -380,9 +382,9 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
|
|||
|
||||
pub fn package_name<'a>() -> impl Parser<'a, PackageName<'a>, EPackageName<'a>> {
|
||||
then(
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
EPackageName::BadPath,
|
||||
string_literal::parse_str_literal()
|
||||
string_literal::parse_str_literal(),
|
||||
)),
|
||||
move |_arena, state, progress, text| match text.value {
|
||||
StrLiteral::PlainLine(text) => Ok((progress, PackageName(text), state)),
|
||||
|
|
|
@ -9,10 +9,10 @@ use crate::header::{
|
|||
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase, UppercaseIdent};
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{
|
||||
and, backtrackable, byte, increment_min_indent, 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,
|
||||
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,
|
||||
};
|
||||
use crate::state::State;
|
||||
use crate::string_literal::{self, parse_str_literal};
|
||||
|
@ -97,7 +97,7 @@ pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||
fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
|
||||
record!(InterfaceHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(module_name_help(EHeader::ModuleName)),
|
||||
name: loc(module_name_help(EHeader::ModuleName)),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_values()),
|
||||
imports: specialize_err(EHeader::Imports, imports()),
|
||||
})
|
||||
|
@ -108,7 +108,7 @@ fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
|
|||
fn hosted_header<'a>() -> impl Parser<'a, HostedHeader<'a>, EHeader<'a>> {
|
||||
record!(HostedHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(module_name_help(EHeader::ModuleName)),
|
||||
name: loc(module_name_help(EHeader::ModuleName)),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_values()),
|
||||
imports: specialize_err(EHeader::Imports, imports()),
|
||||
generates: specialize_err(EHeader::Generates, generates()),
|
||||
|
@ -180,7 +180,7 @@ fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, ()> {
|
|||
fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||
record!(AppHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(crate::parser::specialize_err(
|
||||
name: loc(crate::parser::specialize_err(
|
||||
EHeader::AppName,
|
||||
string_literal::parse_str_literal()
|
||||
)),
|
||||
|
@ -195,7 +195,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
|||
fn package_header<'a>() -> impl Parser<'a, PackageHeader<'a>, EHeader<'a>> {
|
||||
record!(PackageHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(specialize_err(EHeader::PackageName, package_name())),
|
||||
name: loc(specialize_err(EHeader::PackageName, package_name())),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_modules()),
|
||||
packages: specialize_err(EHeader::Packages, packages()),
|
||||
})
|
||||
|
@ -206,7 +206,7 @@ fn package_header<'a>() -> impl Parser<'a, PackageHeader<'a>, EHeader<'a>> {
|
|||
fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> {
|
||||
record!(PlatformHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(specialize_err(EHeader::PlatformName, package_name())),
|
||||
name: loc(specialize_err(EHeader::PlatformName, package_name())),
|
||||
requires: specialize_err(EHeader::Requires, requires()),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_modules()),
|
||||
packages: specialize_err(EHeader::Packages, packages()),
|
||||
|
@ -249,7 +249,7 @@ fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>, EProvides<'a>> {
|
|||
EProvides::IndentTo,
|
||||
EProvides::IndentListStart
|
||||
),
|
||||
to: loc!(provides_to_package()),
|
||||
to: loc(provides_to_package()),
|
||||
})
|
||||
.trace("provides_to")
|
||||
}
|
||||
|
@ -309,9 +309,9 @@ where
|
|||
F: Copy,
|
||||
E: 'a,
|
||||
{
|
||||
loc!(map(
|
||||
specialize_err(|_, pos| to_expectation(pos), ident::uppercase()),
|
||||
Spaced::Item
|
||||
loc(map(
|
||||
specialize_err(move |_, pos| to_expectation(pos), ident::uppercase()),
|
||||
Spaced::Item,
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -323,9 +323,9 @@ where
|
|||
F: Copy,
|
||||
E: 'a,
|
||||
{
|
||||
loc!(map(
|
||||
specialize_err(|_, pos| to_expectation(pos), unqualified_ident()),
|
||||
|n| Spaced::Item(ExposedName::new(n))
|
||||
loc(map(
|
||||
specialize_err(move |_, pos| to_expectation(pos), unqualified_ident()),
|
||||
|n| Spaced::Item(ExposedName::new(n)),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ fn requires_rigids<'a>(
|
|||
byte(b'{', ERequires::ListStart),
|
||||
specialize_err(
|
||||
|_, pos| ERequires::Rigid(pos),
|
||||
loc!(map(ident::uppercase(), Spaced::Item))
|
||||
loc(map(ident::uppercase(), Spaced::Item))
|
||||
),
|
||||
byte(b',', ERequires::ListEnd),
|
||||
byte(b'}', ERequires::ListEnd),
|
||||
|
@ -372,7 +372,7 @@ fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>
|
|||
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,
|
||||
)),
|
||||
|
@ -463,9 +463,9 @@ where
|
|||
F: Copy,
|
||||
E: 'a,
|
||||
{
|
||||
loc!(map(
|
||||
specialize_err(|_, pos| to_expectation(pos), module_name()),
|
||||
Spaced::Item
|
||||
loc(map(
|
||||
specialize_err(move |_, pos| to_expectation(pos), module_name()),
|
||||
Spaced::Item,
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -484,7 +484,7 @@ fn packages<'a>() -> impl Parser<
|
|||
),
|
||||
item: collection_trailing_sep_e!(
|
||||
byte(b'{', EPackages::ListStart),
|
||||
specialize_err(EPackages::PackageEntry, loc!(package_entry())),
|
||||
specialize_err(EPackages::PackageEntry, loc(package_entry())),
|
||||
byte(b',', EPackages::ListEnd),
|
||||
byte(b'}', EPackages::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
|
@ -544,7 +544,7 @@ fn imports<'a>() -> impl Parser<
|
|||
),
|
||||
item: collection_trailing_sep_e!(
|
||||
byte(b'[', EImports::ListStart),
|
||||
loc!(imports_entry()),
|
||||
loc(imports_entry()),
|
||||
byte(b',', EImports::ListEnd),
|
||||
byte(b']', EImports::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
|
@ -561,9 +561,9 @@ fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<
|
|||
map(
|
||||
and(
|
||||
and(
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
|_, pos| ETypedIdent::Identifier(pos),
|
||||
lowercase_ident()
|
||||
lowercase_ident(),
|
||||
)),
|
||||
space0_e(ETypedIdent::IndentHasType),
|
||||
),
|
||||
|
|
|
@ -1335,8 +1335,7 @@ where
|
|||
/// ```
|
||||
/// # #![forbid(unused_imports)]
|
||||
/// # use roc_parse::state::State;
|
||||
/// # use crate::roc_parse::parser::{Parser, Progress, word};
|
||||
/// # use roc_parse::loc;
|
||||
/// # use crate::roc_parse::parser::{Parser, Progress, word, loc};
|
||||
/// # use roc_region::all::{Loc, Position};
|
||||
/// # use bumpalo::Bump;
|
||||
/// # #[derive(Debug, PartialEq)]
|
||||
|
@ -1345,7 +1344,7 @@ where
|
|||
/// # }
|
||||
/// # let arena = Bump::new();
|
||||
/// # fn foo<'a>(arena: &'a Bump) {
|
||||
/// let parser = loc!(word("hello", Problem::NotFound));
|
||||
/// let parser = loc(word("hello", Problem::NotFound));
|
||||
///
|
||||
/// let (progress, output, state) = parser.parse(&arena, State::new("hello, world".as_bytes()), 0).unwrap();
|
||||
/// assert_eq!(progress, Progress::MadeProgress);
|
||||
|
@ -1354,25 +1353,22 @@ where
|
|||
/// # }
|
||||
/// # foo(&arena);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! loc {
|
||||
($parser:expr) => {
|
||||
move |arena, state: $crate::state::State<'a>, min_indent: u32| {
|
||||
use roc_region::all::{Loc, Region};
|
||||
pub fn loc<'a, Output, E: 'a>(
|
||||
parser: impl Parser<'a, Output, E>,
|
||||
) -> impl Parser<'a, Loc<Output>, E> {
|
||||
move |arena, state: crate::state::State<'a>, min_indent: u32| {
|
||||
let start = state.pos();
|
||||
|
||||
let start = state.pos();
|
||||
match parser.parse(arena, state, min_indent) {
|
||||
Ok((progress, value, state)) => {
|
||||
let end = state.pos();
|
||||
let region = Region::new(start, end);
|
||||
|
||||
match $parser.parse(arena, state, min_indent) {
|
||||
Ok((progress, value, state)) => {
|
||||
let end = state.pos();
|
||||
let region = Region::new(start, end);
|
||||
|
||||
Ok((progress, Loc { region, value }, state))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
Ok((progress, Loc { region, value }, state))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// If the first one parses, ignore its output and move on to parse with the second one.
|
||||
|
@ -2542,42 +2538,6 @@ pub fn between<'a, Before, Inner, After, Err: 'a>(
|
|||
skip_first(opening_brace, skip_second(inner, closing_brace))
|
||||
}
|
||||
|
||||
/// Adds location info. This is a function version the [`loc!`] macro.
|
||||
///
|
||||
/// For some reason, some usages won't compile unless they use this instead of the macro version.
|
||||
/// This is likely because the lifetime `'a` is not defined at the call site.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # #![forbid(unused_imports)]
|
||||
/// # use roc_parse::state::State;
|
||||
/// # use crate::roc_parse::parser::{Parser, Progress, word, loc};
|
||||
/// # use roc_region::all::{Loc, Position};
|
||||
/// # use bumpalo::Bump;
|
||||
/// # #[derive(Debug, PartialEq)]
|
||||
/// # enum Problem {
|
||||
/// # NotFound(Position),
|
||||
/// # }
|
||||
/// # let arena = Bump::new();
|
||||
/// # fn foo<'a>(arena: &'a Bump) {
|
||||
/// let parser = loc(word("hello", Problem::NotFound));
|
||||
///
|
||||
/// let (progress, output, state) = parser.parse(&arena, State::new("hello, world".as_bytes()), 0).unwrap();
|
||||
/// assert_eq!(progress, Progress::MadeProgress);
|
||||
/// assert_eq!(output, Loc::new(0, 5, ()));
|
||||
/// assert_eq!(state.pos().offset, 5);
|
||||
/// # }
|
||||
/// # foo(&arena);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn loc<'a, P, Val, Error>(parser: P) -> impl Parser<'a, Loc<Val>, Error>
|
||||
where
|
||||
P: Parser<'a, Val, Error>,
|
||||
Error: 'a,
|
||||
{
|
||||
loc!(parser)
|
||||
}
|
||||
|
||||
/// Maps/transforms the `Ok` result of parsing using the given function.
|
||||
/// Similar to [`map`], but the transform function also takes a bump allocator.
|
||||
///
|
||||
|
|
|
@ -4,7 +4,7 @@ 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, map, optional, skip_first, specialize_err,
|
||||
self, backtrackable, byte, fail_when, loc, map, optional, skip_first, specialize_err,
|
||||
specialize_err_ref, then, three_bytes, two_bytes, EPattern, PInParens, PList, PRecord, Parser,
|
||||
};
|
||||
use crate::state::State;
|
||||
|
@ -32,9 +32,9 @@ pub fn closure_param<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
|
|||
// An ident is the most common param, e.g. \foo -> ...
|
||||
loc_ident_pattern_help(true),
|
||||
// Underscore is also common, e.g. \_ -> ...
|
||||
loc!(underscore_pattern_help()),
|
||||
loc(underscore_pattern_help()),
|
||||
// You can destructure records in params, e.g. \{ x, y } -> ...
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
EPattern::Record,
|
||||
crate::pattern::record_pattern_help()
|
||||
)),
|
||||
|
@ -87,15 +87,15 @@ fn loc_pattern_help_help<'a>(
|
|||
) -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
|
||||
one_of!(
|
||||
specialize_err(EPattern::PInParens, loc_pattern_in_parens_help()),
|
||||
loc!(underscore_pattern_help()),
|
||||
loc(underscore_pattern_help()),
|
||||
loc_ident_pattern_help(can_have_arguments),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
EPattern::Record,
|
||||
crate::pattern::record_pattern_help()
|
||||
)),
|
||||
loc!(specialize_err(EPattern::List, list_pattern_help())),
|
||||
loc!(number_pattern_help()),
|
||||
loc!(string_like_pattern_help()),
|
||||
loc(specialize_err(EPattern::List, list_pattern_help())),
|
||||
loc(number_pattern_help()),
|
||||
loc(string_like_pattern_help()),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ fn pattern_as<'a>() -> impl Parser<'a, PatternAs<'a>, EPattern<'a>> {
|
|||
|
||||
let position = state.pos();
|
||||
|
||||
match loc!(lowercase_ident()).parse(arena, state, min_indent) {
|
||||
match loc(lowercase_ident()).parse(arena, state, min_indent) {
|
||||
Ok((_, identifier, state)) => Ok((
|
||||
MadeProgress,
|
||||
PatternAs {
|
||||
|
@ -199,7 +199,7 @@ pub fn loc_implements_parser<'a>() -> impl Parser<'a, Loc<Implements<'a>>, EPatt
|
|||
|
||||
fn loc_pattern_in_parens_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PInParens<'a>> {
|
||||
then(
|
||||
loc!(collection_trailing_sep_e!(
|
||||
loc(collection_trailing_sep_e!(
|
||||
byte(b'(', PInParens::Open),
|
||||
specialize_err_ref(PInParens::Pattern, loc_pattern_help()),
|
||||
byte(b',', PInParens::End),
|
||||
|
@ -290,16 +290,13 @@ fn list_element_pattern<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
|||
}
|
||||
|
||||
fn three_list_rest_pattern_error<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
||||
fail_when(
|
||||
PList::Rest,
|
||||
loc!(three_bytes(b'.', b'.', b'.', PList::Rest)),
|
||||
)
|
||||
fail_when(PList::Rest, loc(three_bytes(b'.', b'.', b'.', PList::Rest)))
|
||||
}
|
||||
|
||||
fn list_rest_pattern<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
||||
move |arena: &'a Bump, state: State<'a>, min_indent: u32| {
|
||||
let (_, loc_word, state) =
|
||||
loc!(two_bytes(b'.', b'.', PList::Open)).parse(arena, state, min_indent)?;
|
||||
loc(two_bytes(b'.', b'.', PList::Open)).parse(arena, state, min_indent)?;
|
||||
|
||||
let no_as = Loc::at(loc_word.region, Pattern::ListRest(None));
|
||||
|
||||
|
@ -334,9 +331,8 @@ fn loc_ident_pattern_help<'a>(
|
|||
move |arena: &'a Bump, state: State<'a>, min_indent: u32| {
|
||||
let original_state = state.clone();
|
||||
|
||||
let (_, loc_ident, state) =
|
||||
specialize_err(|_, pos| EPattern::Start(pos), loc!(parse_ident))
|
||||
.parse(arena, state, min_indent)?;
|
||||
let (_, loc_ident, state) = specialize_err(|_, pos| EPattern::Start(pos), loc(parse_ident))
|
||||
.parse(arena, state, min_indent)?;
|
||||
|
||||
match loc_ident.value {
|
||||
Ident::Tag(tag) => {
|
||||
|
@ -539,9 +535,9 @@ fn record_pattern_field<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PRecord<'a>>
|
|||
// You must have a field name, e.g. "email"
|
||||
// using the initial pos is important for error reporting
|
||||
let pos = state.pos();
|
||||
let (progress, loc_label, state) = loc!(specialize_err(
|
||||
let (progress, loc_label, state) = loc(specialize_err(
|
||||
move |_, _| PRecord::Field(pos),
|
||||
lowercase_ident()
|
||||
lowercase_ident(),
|
||||
))
|
||||
.parse(arena, state, min_indent)?;
|
||||
debug_assert_eq!(progress, MadeProgress);
|
||||
|
|
|
@ -73,7 +73,7 @@ pub enum StrLikeLiteral<'a> {
|
|||
|
||||
pub fn parse_str_literal<'a>() -> impl Parser<'a, StrLiteral<'a>, EString<'a>> {
|
||||
then(
|
||||
loc!(parse_str_like_literal()),
|
||||
loc(parse_str_like_literal()),
|
||||
|_arena, state, progress, str_like| match str_like.value {
|
||||
StrLikeLiteral::SingleQuote(_) => Err((
|
||||
progress,
|
||||
|
|
|
@ -9,7 +9,7 @@ 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, map, skip_first, skip_second, then,
|
||||
absolute_column_min_indent, and, increment_min_indent, loc, map, skip_first, skip_second, then,
|
||||
ERecord, ETypeAbilityImpl,
|
||||
};
|
||||
use crate::parser::{
|
||||
|
@ -41,7 +41,7 @@ fn tag_union_type<'a>(
|
|||
move |arena, state, min_indent| {
|
||||
let (_, tags, state) = collection_trailing_sep_e!(
|
||||
byte(b'[', ETypeTagUnion::Open),
|
||||
loc!(tag_type(false)),
|
||||
loc(tag_type(false)),
|
||||
byte(b',', ETypeTagUnion::End),
|
||||
byte(b']', ETypeTagUnion::End),
|
||||
Tag::SpaceBefore
|
||||
|
@ -122,16 +122,16 @@ fn term<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Loc<TypeAnnotation<'a>
|
|||
loc_wildcard(),
|
||||
loc_inferred(),
|
||||
specialize_err(EType::TInParens, loc_type_in_parens(stop_at_surface_has)),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
EType::TRecord,
|
||||
record_type(stop_at_surface_has)
|
||||
)),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
EType::TTagUnion,
|
||||
tag_union_type(stop_at_surface_has)
|
||||
)),
|
||||
loc!(applied_type(stop_at_surface_has)),
|
||||
loc!(parse_type_variable(stop_at_surface_has)),
|
||||
loc(applied_type(stop_at_surface_has)),
|
||||
loc(parse_type_variable(stop_at_surface_has)),
|
||||
fail(EType::TStart),
|
||||
),
|
||||
// Inline alias notation, e.g. [Nil, Cons a (List a)] as List a
|
||||
|
@ -170,7 +170,7 @@ fn term<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Loc<TypeAnnotation<'a>
|
|||
|
||||
/// The `*` type variable, e.g. in (List *) Wildcard,
|
||||
fn loc_wildcard<'a>() -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> {
|
||||
map(loc!(byte(b'*', EType::TWildcard)), |loc_val: Loc<()>| {
|
||||
map(loc(byte(b'*', EType::TWildcard)), |loc_val: Loc<()>| {
|
||||
loc_val.map(|_| TypeAnnotation::Wildcard)
|
||||
})
|
||||
}
|
||||
|
@ -215,16 +215,16 @@ fn loc_applied_arg<'a>(
|
|||
loc_wildcard(),
|
||||
loc_inferred(),
|
||||
specialize_err(EType::TInParens, loc_type_in_parens(stop_at_surface_has)),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
EType::TRecord,
|
||||
record_type(stop_at_surface_has)
|
||||
)),
|
||||
loc!(specialize_err(
|
||||
loc(specialize_err(
|
||||
EType::TTagUnion,
|
||||
tag_union_type(stop_at_surface_has)
|
||||
)),
|
||||
loc!(specialize_err(EType::TApply, concrete_type())),
|
||||
loc!(parse_type_variable(stop_at_surface_has))
|
||||
loc(specialize_err(EType::TApply, concrete_type())),
|
||||
loc(parse_type_variable(stop_at_surface_has))
|
||||
)
|
||||
),
|
||||
|arena: &'a Bump, (spaces, argument): (&'a [_], Loc<TypeAnnotation<'a>>)| {
|
||||
|
@ -242,7 +242,7 @@ fn loc_type_in_parens<'a>(
|
|||
stop_at_surface_has: bool,
|
||||
) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, ETypeInParens<'a>> {
|
||||
then(
|
||||
loc!(and(
|
||||
loc(and(
|
||||
collection_trailing_sep_e!(
|
||||
byte(b'(', ETypeInParens::Open),
|
||||
specialize_err_ref(ETypeInParens::Type, expression(true, false)),
|
||||
|
@ -252,8 +252,8 @@ fn loc_type_in_parens<'a>(
|
|||
),
|
||||
optional(allocated(specialize_err_ref(
|
||||
ETypeInParens::Type,
|
||||
term(stop_at_surface_has)
|
||||
)))
|
||||
term(stop_at_surface_has),
|
||||
))),
|
||||
)),
|
||||
|_arena, state, progress, item| {
|
||||
let Loc {
|
||||
|
@ -281,7 +281,7 @@ fn loc_type_in_parens<'a>(
|
|||
fn tag_type<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Tag<'a>, ETypeTagUnion<'a>> {
|
||||
move |arena, state: State<'a>, min_indent: u32| {
|
||||
let (_, name, state) =
|
||||
loc!(parse_tag_name(ETypeTagUnion::End)).parse(arena, state, min_indent)?;
|
||||
loc(parse_tag_name(ETypeTagUnion::End)).parse(arena, state, min_indent)?;
|
||||
|
||||
let (_, args, state) =
|
||||
specialize_err_ref(ETypeTagUnion::Type, loc_applied_args_e(stop_at_surface_has))
|
||||
|
@ -320,9 +320,9 @@ fn record_type_field<'a>() -> impl Parser<'a, AssignedField<'a, TypeAnnotation<'
|
|||
// You must have a field name, e.g. "email"
|
||||
// using the initial pos is important for error reporting
|
||||
let pos = state.pos();
|
||||
let (progress, loc_label, state) = loc!(specialize_err(
|
||||
let (progress, loc_label, state) = loc(specialize_err(
|
||||
move |_, _| ETypeRecord::Field(pos),
|
||||
lowercase_ident_keyword_e()
|
||||
lowercase_ident_keyword_e(),
|
||||
))
|
||||
.parse(arena, state, min_indent)?;
|
||||
debug_assert_eq!(progress, MadeProgress);
|
||||
|
@ -384,7 +384,7 @@ fn record_type<'a>(
|
|||
record!(TypeAnnotation::Record {
|
||||
fields: collection_trailing_sep_e!(
|
||||
byte(b'{', ETypeRecord::Open),
|
||||
loc!(record_type_field()),
|
||||
loc(record_type_field()),
|
||||
byte(b',', ETypeRecord::End),
|
||||
byte(b'}', ETypeRecord::End),
|
||||
AssignedField::SpaceBefore
|
||||
|
@ -434,14 +434,14 @@ fn ability_chain<'a>() -> impl Parser<'a, Vec<'a, Loc<TypeAnnotation<'a>>>, ETyp
|
|||
map(
|
||||
and(
|
||||
space0_before_optional_after(
|
||||
specialize_err(EType::TApply, loc!(concrete_type())),
|
||||
specialize_err(EType::TApply, loc(concrete_type())),
|
||||
EType::TIndentStart,
|
||||
EType::TIndentEnd,
|
||||
),
|
||||
zero_or_more!(skip_first(
|
||||
byte(b'&', EType::TImplementsClause),
|
||||
space0_before_optional_after(
|
||||
specialize_err(EType::TApply, loc!(concrete_type())),
|
||||
specialize_err(EType::TApply, loc(concrete_type())),
|
||||
EType::TIndentStart,
|
||||
EType::TIndentEnd,
|
||||
)
|
||||
|
@ -465,7 +465,7 @@ fn implements_clause<'a>() -> impl Parser<'a, Loc<ImplementsClause<'a>>, EType<'
|
|||
// Parse "a", with appropriate spaces
|
||||
specialize_err(
|
||||
|_, pos| EType::TBadTypeVariable(pos),
|
||||
loc!(map(lowercase_ident(), Spaced::Item)),
|
||||
loc(map(lowercase_ident(), Spaced::Item)),
|
||||
),
|
||||
EType::TIndentStart,
|
||||
EType::TIndentEnd,
|
||||
|
@ -530,15 +530,15 @@ pub fn implements_abilities<'a>() -> impl Parser<'a, Loc<ImplementsAbilities<'a>
|
|||
word(crate::keyword::IMPLEMENTS, EType::TImplementsClause),
|
||||
// Parse "Hash"; this may be qualified from another module like "Hash.Hash"
|
||||
space0_before_e(
|
||||
loc!(map(
|
||||
loc(map(
|
||||
collection_trailing_sep_e!(
|
||||
byte(b'[', EType::TStart),
|
||||
loc!(parse_implements_ability()),
|
||||
loc(parse_implements_ability()),
|
||||
byte(b',', EType::TEnd),
|
||||
byte(b']', EType::TEnd),
|
||||
ImplementsAbility::SpaceBefore
|
||||
),
|
||||
ImplementsAbilities::Implements
|
||||
ImplementsAbilities::Implements,
|
||||
)),
|
||||
EType::TIndentEnd,
|
||||
),
|
||||
|
@ -547,14 +547,14 @@ pub fn implements_abilities<'a>() -> impl Parser<'a, Loc<ImplementsAbilities<'a>
|
|||
|
||||
fn parse_implements_ability<'a>() -> impl Parser<'a, ImplementsAbility<'a>, EType<'a>> {
|
||||
increment_min_indent(record!(ImplementsAbility::ImplementsAbility {
|
||||
ability: loc!(specialize_err(EType::TApply, concrete_type())),
|
||||
ability: loc(specialize_err(EType::TApply, concrete_type())),
|
||||
impls: optional(backtrackable(space0_before_e(
|
||||
loc!(map(
|
||||
loc(map(
|
||||
specialize_err(
|
||||
EType::TAbilityImpl,
|
||||
collection_trailing_sep_e!(
|
||||
byte(b'{', ETypeAbilityImpl::Open),
|
||||
specialize_err(|e: ERecord<'_>, _| e.into(), loc!(ability_impl_field())),
|
||||
specialize_err(|e: ERecord<'_>, _| e.into(), loc(ability_impl_field())),
|
||||
byte(b',', ETypeAbilityImpl::End),
|
||||
byte(b'}', ETypeAbilityImpl::End),
|
||||
AssignedField::SpaceBefore
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue