mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Use loc! macro instead of loc()
This commit is contained in:
parent
155ae60348
commit
cc74c37045
6 changed files with 138 additions and 107 deletions
111
src/parse/mod.rs
111
src/parse/mod.rs
|
@ -5,6 +5,7 @@ pub mod ident;
|
|||
pub mod keyword;
|
||||
pub mod module;
|
||||
pub mod number_literal;
|
||||
#[macro_use]
|
||||
pub mod parser;
|
||||
pub mod problems;
|
||||
pub mod record;
|
||||
|
@ -27,7 +28,7 @@ use parse::collection::collection;
|
|||
use parse::ident::{ident, unqualified_ident, variant_or_ident, Ident};
|
||||
use parse::number_literal::number_literal;
|
||||
use parse::parser::{
|
||||
allocated, and, attempt, between, char, either, loc, map, map_with_arena, not, not_followed_by,
|
||||
allocated, and, attempt, between, char, either, map, map_with_arena, not, not_followed_by,
|
||||
one_of10, one_of17, one_of2, one_of3, one_of5, one_of6, one_or_more, optional, skip_first,
|
||||
skip_second, string, then, unexpected, unexpected_eof, zero_or_more, Either, Fail, FailReason,
|
||||
ParseResult, Parser, State,
|
||||
|
@ -57,7 +58,7 @@ fn app_module<'a>() -> impl Parser<'a, Module<'a>> {
|
|||
fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>> {
|
||||
map(
|
||||
and(
|
||||
skip_first(string("interface"), and(space1(1), loc(ident()))),
|
||||
skip_first(string("interface"), and(space1(1), loc!(ident()))),
|
||||
and(mod_header_list("exposes"), mod_header_list("imports")),
|
||||
),
|
||||
|(
|
||||
|
@ -118,7 +119,7 @@ fn mod_header_list<'a>(
|
|||
> {
|
||||
and(
|
||||
and(skip_second(space1(1), string(kw)), space1(1)),
|
||||
collection(char('['), loc(mod_header_entry()), char(','), char(']'), 1),
|
||||
collection(char('['), loc!(mod_header_entry()), char(','), char(']'), 1),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -150,15 +151,15 @@ fn loc_parse_expr_body_without_operators<'a>(
|
|||
) -> ParseResult<'a, Located<Expr<'a>>> {
|
||||
one_of10(
|
||||
loc_parenthetical_expr(min_indent),
|
||||
loc(string_literal()),
|
||||
loc(number_literal()),
|
||||
loc(closure(min_indent)),
|
||||
loc(record_literal(min_indent)),
|
||||
loc(list_literal(min_indent)),
|
||||
loc(unary_op(min_indent)),
|
||||
loc(case_expr(min_indent)),
|
||||
loc(if_expr(min_indent)),
|
||||
loc(ident_etc(min_indent)),
|
||||
loc!(string_literal()),
|
||||
loc!(number_literal()),
|
||||
loc!(closure(min_indent)),
|
||||
loc!(record_literal(min_indent)),
|
||||
loc!(list_literal(min_indent)),
|
||||
loc!(unary_op(min_indent)),
|
||||
loc!(case_expr(min_indent)),
|
||||
loc!(if_expr(min_indent)),
|
||||
loc!(ident_etc(min_indent)),
|
||||
)
|
||||
.parse(arena, state)
|
||||
}
|
||||
|
@ -170,8 +171,8 @@ pub fn unary_op<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
one_of2(
|
||||
map_with_arena(
|
||||
and(
|
||||
loc(char('!')),
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(char('!')),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
),
|
||||
|arena, (loc_op, loc_expr)| {
|
||||
Expr::UnaryOp(arena.alloc(loc_expr), loc_op.map(|_| UnaryOp::Not))
|
||||
|
@ -179,8 +180,8 @@ pub fn unary_op<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
),
|
||||
map_with_arena(
|
||||
and(
|
||||
loc(char('-')),
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(char('-')),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
),
|
||||
|arena, (loc_op, loc_expr)| {
|
||||
Expr::UnaryOp(arena.alloc(loc_expr), loc_op.map(|_| UnaryOp::Negate))
|
||||
|
@ -200,11 +201,11 @@ fn parse_expr<'a>(min_indent: u16, arena: &'a Bump, state: State<'a>) -> ParseRe
|
|||
// parse the spaces and then attach them retroactively to the expression
|
||||
// preceding the operator (the one we parsed before considering operators).
|
||||
optional(and(
|
||||
and(space0(min_indent), loc(binop())),
|
||||
and(space0(min_indent), loc!(binop())),
|
||||
// The spaces *after* the operator can be attached directly to
|
||||
// the expression following the operator.
|
||||
space0_before(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
)),
|
||||
|
@ -232,11 +233,11 @@ fn parse_expr<'a>(min_indent: u16, arena: &'a Bump, state: State<'a>) -> ParseRe
|
|||
|
||||
pub fn loc_parenthetical_expr<'a>(min_indent: u16) -> impl Parser<'a, Located<Expr<'a>>> {
|
||||
then(
|
||||
loc(and(
|
||||
loc!(and(
|
||||
between(
|
||||
char('('),
|
||||
space0_around(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
char(')'),
|
||||
|
@ -427,11 +428,11 @@ fn expr_to_pattern<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<'a>,
|
|||
/// It would be too weird to parse; imagine `(UserId userId) : ...` above `(UserId userId) = ...`
|
||||
pub fn loc_parenthetical_def<'a>(min_indent: u16) -> impl Parser<'a, Located<Expr<'a>>> {
|
||||
move |arena, state| {
|
||||
let (loc_tuple, state) = loc(and(
|
||||
let (loc_tuple, state) = loc!(and(
|
||||
space0_after(
|
||||
between(
|
||||
char('('),
|
||||
space0_around(loc(pattern(min_indent)), min_indent),
|
||||
space0_around(loc!(pattern(min_indent)), min_indent),
|
||||
char(')'),
|
||||
),
|
||||
min_indent,
|
||||
|
@ -484,7 +485,7 @@ pub fn def<'a>(min_indent: u16) -> impl Parser<'a, Def<'a>> {
|
|||
// Spaces after the '=' (at a normal indentation level) and then the expr.
|
||||
// The expr itself must be indented more than the pattern and '='
|
||||
space0_before(
|
||||
loc(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
),
|
||||
|
@ -579,17 +580,17 @@ fn parse_def_expr<'a>(
|
|||
//
|
||||
// It should be indented more than the original, and it will
|
||||
// end when outdented again.
|
||||
loc(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||
and(
|
||||
// Optionally parse additional defs.
|
||||
zero_or_more(allocated(space1_before(
|
||||
loc(def(original_indent)),
|
||||
loc!(def(original_indent)),
|
||||
original_indent,
|
||||
))),
|
||||
// Parse the final expression that will be returned.
|
||||
// It should be indented the same amount as the original.
|
||||
space1_before(
|
||||
loc(move |arena, state| parse_expr(original_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(original_indent, arena, state)),
|
||||
original_indent,
|
||||
),
|
||||
),
|
||||
|
@ -640,15 +641,15 @@ fn loc_parse_function_arg<'a>(
|
|||
) -> ParseResult<'a, Located<Expr<'a>>> {
|
||||
one_of10(
|
||||
loc_parenthetical_expr(min_indent),
|
||||
loc(string_literal()),
|
||||
loc(number_literal()),
|
||||
loc(closure(min_indent)),
|
||||
loc(record_literal(min_indent)),
|
||||
loc(list_literal(min_indent)),
|
||||
loc(unary_op(min_indent)),
|
||||
loc(case_expr(min_indent)),
|
||||
loc(if_expr(min_indent)),
|
||||
loc(ident_without_apply()),
|
||||
loc!(string_literal()),
|
||||
loc!(number_literal()),
|
||||
loc!(closure(min_indent)),
|
||||
loc!(record_literal(min_indent)),
|
||||
loc!(list_literal(min_indent)),
|
||||
loc!(unary_op(min_indent)),
|
||||
loc!(case_expr(min_indent)),
|
||||
loc!(if_expr(min_indent)),
|
||||
loc!(ident_without_apply()),
|
||||
)
|
||||
.parse(arena, state)
|
||||
}
|
||||
|
@ -689,7 +690,7 @@ fn closure<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
attempt(
|
||||
Attempting::ClosureBody,
|
||||
space0_before(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
),
|
||||
|
@ -714,20 +715,20 @@ fn parse_closure_param<'a>(
|
|||
) -> ParseResult<'a, Located<Pattern<'a>>> {
|
||||
one_of5(
|
||||
// An ident is the most common param, e.g. \foo -> ...
|
||||
loc(ident_pattern()),
|
||||
loc!(ident_pattern()),
|
||||
// Underscore is also common, e.g. \_ -> ...
|
||||
loc(underscore_pattern()),
|
||||
loc!(underscore_pattern()),
|
||||
// You can destructure records in params, e.g. \{ x, y } -> ...
|
||||
loc(record_destructure(min_indent)),
|
||||
loc!(record_destructure(min_indent)),
|
||||
// If you wrap it in parens, you can match any arbitrary pattern at all.
|
||||
// e.g. \User.UserId userId -> ...
|
||||
between(
|
||||
char('('),
|
||||
space0_around(loc(pattern(min_indent)), min_indent),
|
||||
space0_around(loc!(pattern(min_indent)), min_indent),
|
||||
char(')'),
|
||||
),
|
||||
// The least common, but still allowed, e.g. \Foo -> ...
|
||||
loc(map(unqualified_variant(), |name| {
|
||||
loc!(map(unqualified_variant(), |name| {
|
||||
Pattern::Variant(&[], name)
|
||||
})),
|
||||
)
|
||||
|
@ -766,7 +767,7 @@ fn record_destructure<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
|||
map(
|
||||
collection(
|
||||
char('{'),
|
||||
loc(ident_pattern()),
|
||||
loc!(ident_pattern()),
|
||||
char(','),
|
||||
char('}'),
|
||||
min_indent,
|
||||
|
@ -791,7 +792,7 @@ pub fn case_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
Attempting::CaseCondition,
|
||||
skip_second(
|
||||
space1_around(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
string(keyword::WHEN),
|
||||
|
@ -825,7 +826,7 @@ pub fn case_branches<'a>(
|
|||
// 2. Parse the other branches. Their indentation levels must be == the first branch's.
|
||||
|
||||
let (mut loc_first_pattern, state) =
|
||||
space1_before(loc(pattern(min_indent)), min_indent).parse(arena, state)?;
|
||||
space1_before(loc!(pattern(min_indent)), min_indent).parse(arena, state)?;
|
||||
let original_indent = state.indent_col;
|
||||
let indented_more = original_indent + 1;
|
||||
let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?;
|
||||
|
@ -844,7 +845,7 @@ pub fn case_branches<'a>(
|
|||
string("->"),
|
||||
// The expr must be indented more than the pattern preceding it
|
||||
space0_before(
|
||||
loc(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||
indented_more,
|
||||
),
|
||||
)
|
||||
|
@ -855,7 +856,7 @@ pub fn case_branches<'a>(
|
|||
|
||||
let branch_parser = and(
|
||||
then(
|
||||
space1_around(loc(pattern(min_indent)), min_indent),
|
||||
space1_around(loc!(pattern(min_indent)), min_indent),
|
||||
move |_arena, state, loc_pattern| {
|
||||
if state.indent_col == original_indent {
|
||||
Ok((loc_pattern, state))
|
||||
|
@ -869,7 +870,7 @@ pub fn case_branches<'a>(
|
|||
skip_first(
|
||||
string("->"),
|
||||
space1_before(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
),
|
||||
|
@ -900,7 +901,7 @@ pub fn if_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
skip_first(
|
||||
string(keyword::IF),
|
||||
space1_around(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
),
|
||||
|
@ -908,14 +909,14 @@ pub fn if_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
skip_first(
|
||||
string(keyword::THEN),
|
||||
space1_around(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
),
|
||||
skip_first(
|
||||
string(keyword::ELSE),
|
||||
space1_before(
|
||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
),
|
||||
),
|
||||
|
@ -945,7 +946,7 @@ fn unary_negate_function_arg<'a>(min_indent: u16) -> impl Parser<'a, Located<Exp
|
|||
then(
|
||||
// Spaces, then '-', then *not* more spaces.
|
||||
not_followed_by(
|
||||
and(space1(min_indent), loc(char('-'))),
|
||||
and(space1(min_indent), loc!(char('-'))),
|
||||
one_of3(char(' '), char('#'), char('\n')),
|
||||
),
|
||||
move |arena, state, (spaces, loc_minus_char)| {
|
||||
|
@ -1009,7 +1010,7 @@ fn loc_function_args<'a>(min_indent: u16) -> impl Parser<'a, Vec<'a, Located<Exp
|
|||
pub fn ident_etc<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||
then(
|
||||
and(
|
||||
loc(ident()),
|
||||
loc!(ident()),
|
||||
optional(either(
|
||||
// There may optionally be function args after this ident
|
||||
loc_function_args(min_indent),
|
||||
|
@ -1074,7 +1075,7 @@ pub fn ident_etc<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
}
|
||||
|
||||
pub fn ident_without_apply<'a>() -> impl Parser<'a, Expr<'a>> {
|
||||
then(loc(ident()), move |_arena, state, loc_ident| {
|
||||
then(loc!(ident()), move |_arena, state, loc_ident| {
|
||||
Ok((ident_to_expr(loc_ident.value), state))
|
||||
})
|
||||
}
|
||||
|
@ -1155,7 +1156,7 @@ fn binop<'a>() -> impl Parser<'a, BinOp> {
|
|||
pub fn list_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||
let elems = collection(
|
||||
char('['),
|
||||
loc(expr(min_indent)),
|
||||
loc!(expr(min_indent)),
|
||||
char(','),
|
||||
char(']'),
|
||||
min_indent,
|
||||
|
@ -1181,7 +1182,7 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
and(
|
||||
attempt(
|
||||
Attempting::Record,
|
||||
loc(record(loc(expr(min_indent)), min_indent)),
|
||||
loc!(record(loc!(expr(min_indent)), min_indent)),
|
||||
),
|
||||
optional(and(space0(min_indent), equals_with_indent())),
|
||||
),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use parse::ast::Attempting;
|
||||
use region::{Located, Region};
|
||||
use region::Region;
|
||||
use std::{char, u16};
|
||||
|
||||
/// A position in a source file.
|
||||
|
@ -330,33 +330,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn loc_impl<'a, P, Val>(parser: P) -> impl Parser<'a, Located<Val>>
|
||||
where
|
||||
P: Parser<'a, Val>,
|
||||
{
|
||||
move |arena, state: State<'a>| {
|
||||
let start_col = state.column;
|
||||
let start_line = state.line;
|
||||
|
||||
match parser.parse(arena, state) {
|
||||
Ok((value, state)) => {
|
||||
let end_col = state.column;
|
||||
let end_line = state.line;
|
||||
let region = Region {
|
||||
start_col,
|
||||
start_line,
|
||||
end_col,
|
||||
end_line,
|
||||
};
|
||||
|
||||
Ok((Located { region, value }, state))
|
||||
}
|
||||
Err((fail, state)) => Err((fail, state)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn zero_or_more_impl<'a, P, A>(parser: P) -> impl Parser<'a, Vec<'a, A>>
|
||||
where
|
||||
|
@ -1334,15 +1307,6 @@ where
|
|||
BoxedParser::new(map_with_arena_impl(parser, transform))
|
||||
}
|
||||
|
||||
pub fn loc<'a, P, Val>(parser: P) -> BoxedParser<'a, Located<Val>>
|
||||
where
|
||||
P: Parser<'a, Val>,
|
||||
P: 'a,
|
||||
Val: 'a,
|
||||
{
|
||||
BoxedParser::new(loc_impl(parser))
|
||||
}
|
||||
|
||||
pub fn attempt<'a, P, Val>(attempting: Attempting, parser: P) -> BoxedParser<'a, Val>
|
||||
where
|
||||
P: Parser<'a, Val>,
|
||||
|
@ -1379,3 +1343,29 @@ where
|
|||
{
|
||||
BoxedParser::new(one_or_more_impl(parser))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! loc {
|
||||
($parser:expr) => {
|
||||
move |arena, state: State<'a>| {
|
||||
let start_col = state.column;
|
||||
let start_line = state.line;
|
||||
|
||||
match $parser.parse(arena, state) {
|
||||
Ok((value, state)) => {
|
||||
let end_col = state.column;
|
||||
let end_line = state.line;
|
||||
let region = Region {
|
||||
start_col,
|
||||
start_line,
|
||||
end_col,
|
||||
end_line,
|
||||
};
|
||||
|
||||
Ok((Located { region, value }, state))
|
||||
}
|
||||
Err((fail, state)) => Err((fail, state)),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ use parse::ast::Spaceable;
|
|||
use parse::blankspace::{space0, space0_before};
|
||||
use parse::collection::collection;
|
||||
use parse::ident::unqualified_ident;
|
||||
use parse::parser::{and, char, loc, map_with_arena, optional, skip_first, Parser};
|
||||
use region::Located;
|
||||
use parse::parser::{and, char, map_with_arena, optional, skip_first, Parser, State};
|
||||
use region::{Located, Region};
|
||||
|
||||
/// Parse a record - generally one of these two:
|
||||
///
|
||||
|
@ -30,6 +30,15 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
/// For some reason, record() needs to use this instead of using the loc! macro directly.
|
||||
#[inline(always)]
|
||||
pub fn loc<'a, P, Val>(parser: P) -> impl Parser<'a, Located<Val>>
|
||||
where
|
||||
P: Parser<'a, Val>,
|
||||
{
|
||||
loc!(parser)
|
||||
}
|
||||
|
||||
fn record_field<'a, P, S>(val_parser: P, min_indent: u16) -> impl Parser<'a, AssignedField<'a, S>>
|
||||
where
|
||||
P: Parser<'a, Located<S>>,
|
||||
|
@ -42,7 +51,7 @@ where
|
|||
map_with_arena(
|
||||
and(
|
||||
// You must have a field name, e.g. "email"
|
||||
loc(unqualified_ident()),
|
||||
loc!(unqualified_ident()),
|
||||
and(
|
||||
space0(min_indent),
|
||||
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
|
||||
|
|
|
@ -5,22 +5,22 @@ use collections::arena_join;
|
|||
use parse::ast::{Attempting, TypeAnnotation};
|
||||
use parse::blankspace::{space0_around, space1_before};
|
||||
use parse::parser::{
|
||||
and, between, char, loc, map, map_with_arena, one_of5, optional, skip_first, string,
|
||||
unexpected, unexpected_eof, zero_or_more, ParseResult, Parser, State,
|
||||
and, between, char, map, map_with_arena, one_of5, optional, skip_first, string, unexpected,
|
||||
unexpected_eof, zero_or_more, ParseResult, Parser, State,
|
||||
};
|
||||
use parse::record::record;
|
||||
use region::Located;
|
||||
use region::{Located, Region};
|
||||
|
||||
pub fn located<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>> {
|
||||
one_of5(
|
||||
// The `*` type variable, e.g. in (List *) Wildcard,
|
||||
map(loc(char('*')), |loc_val| {
|
||||
map(loc!(char('*')), |loc_val| {
|
||||
loc_val.map(|_| TypeAnnotation::Wildcard)
|
||||
}),
|
||||
loc_parenthetical_type(min_indent),
|
||||
loc(record_type(min_indent)),
|
||||
loc(applied_type(min_indent)),
|
||||
loc(parse_type_variable),
|
||||
loc!(record_type(min_indent)),
|
||||
loc!(applied_type(min_indent)),
|
||||
loc!(parse_type_variable),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
extern crate bumpalo;
|
||||
extern crate roc;
|
||||
|
||||
use self::bumpalo::Bump;
|
||||
use roc::can;
|
||||
|
@ -13,11 +12,41 @@ use roc::ident::Ident;
|
|||
use roc::parse;
|
||||
use roc::parse::ast::{self, Attempting};
|
||||
use roc::parse::blankspace::space0_before;
|
||||
use roc::parse::parser::{loc, Fail, Parser, State};
|
||||
use roc::parse::parser::{Fail, Parser, State};
|
||||
use roc::region::{Located, Region};
|
||||
use roc::subs::{Subs, Variable};
|
||||
use roc::types::{Expected, Type};
|
||||
|
||||
// TODO Figure out some way to import this macro from roc::parse::parser - it has been
|
||||
// surprisingly difficult to convince an integration test to do this.
|
||||
//
|
||||
// See https://users.rust-lang.org/t/sharing-code-and-macros-in-tests-directory/3098/4
|
||||
#[macro_export]
|
||||
macro_rules! loc {
|
||||
($parser:expr) => {
|
||||
move |arena, state: State<'a>| {
|
||||
let start_col = state.column;
|
||||
let start_line = state.line;
|
||||
|
||||
match $parser.parse(arena, state) {
|
||||
Ok((value, state)) => {
|
||||
let end_col = state.column;
|
||||
let end_line = state.line;
|
||||
let region = Region {
|
||||
start_col,
|
||||
start_line,
|
||||
end_col,
|
||||
end_line,
|
||||
};
|
||||
|
||||
Ok((Located { region, value }, state))
|
||||
}
|
||||
Err((fail, state)) => Err((fail, state)),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<ast::Expr<'a>, Fail> {
|
||||
parse_loc_with(arena, input).map(|loc_expr| loc_expr.value)
|
||||
|
@ -26,7 +55,7 @@ pub fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<ast::Expr<'a>,
|
|||
#[allow(dead_code)]
|
||||
pub fn parse_loc_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Located<ast::Expr<'a>>, Fail> {
|
||||
let state = State::new(&input, Attempting::Module);
|
||||
let parser = space0_before(loc(parse::expr(0)), 0);
|
||||
let parser = space0_before(loc!(parse::expr(0)), 0);
|
||||
let answer = parser.parse(&arena, state);
|
||||
|
||||
answer
|
||||
|
|
|
@ -3,6 +3,7 @@ extern crate pretty_assertions;
|
|||
#[macro_use]
|
||||
extern crate indoc;
|
||||
extern crate bumpalo;
|
||||
#[macro_use]
|
||||
extern crate roc;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -11,11 +12,12 @@ mod test_format {
|
|||
use roc::parse;
|
||||
use roc::parse::ast::{format, Attempting, Expr};
|
||||
use roc::parse::blankspace::space0_before;
|
||||
use roc::parse::parser::{loc, Fail, Parser, State};
|
||||
use roc::parse::parser::{Fail, Parser, State};
|
||||
use roc::region::{Located, Region};
|
||||
|
||||
fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Expr<'a>, Fail> {
|
||||
let state = State::new(&input, Attempting::Module);
|
||||
let parser = space0_before(loc(parse::expr(0)), 0);
|
||||
let parser = space0_before(loc!(parse::expr(0)), 0);
|
||||
let answer = parser.parse(&arena, state);
|
||||
|
||||
answer
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue