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 keyword;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
pub mod number_literal;
|
pub mod number_literal;
|
||||||
|
#[macro_use]
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod problems;
|
pub mod problems;
|
||||||
pub mod record;
|
pub mod record;
|
||||||
|
@ -27,7 +28,7 @@ use parse::collection::collection;
|
||||||
use parse::ident::{ident, unqualified_ident, variant_or_ident, Ident};
|
use parse::ident::{ident, unqualified_ident, variant_or_ident, Ident};
|
||||||
use parse::number_literal::number_literal;
|
use parse::number_literal::number_literal;
|
||||||
use parse::parser::{
|
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,
|
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,
|
skip_second, string, then, unexpected, unexpected_eof, zero_or_more, Either, Fail, FailReason,
|
||||||
ParseResult, Parser, State,
|
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>> {
|
fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>> {
|
||||||
map(
|
map(
|
||||||
and(
|
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")),
|
and(mod_header_list("exposes"), mod_header_list("imports")),
|
||||||
),
|
),
|
||||||
|(
|
|(
|
||||||
|
@ -118,7 +119,7 @@ fn mod_header_list<'a>(
|
||||||
> {
|
> {
|
||||||
and(
|
and(
|
||||||
and(skip_second(space1(1), string(kw)), space1(1)),
|
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>>> {
|
) -> ParseResult<'a, Located<Expr<'a>>> {
|
||||||
one_of10(
|
one_of10(
|
||||||
loc_parenthetical_expr(min_indent),
|
loc_parenthetical_expr(min_indent),
|
||||||
loc(string_literal()),
|
loc!(string_literal()),
|
||||||
loc(number_literal()),
|
loc!(number_literal()),
|
||||||
loc(closure(min_indent)),
|
loc!(closure(min_indent)),
|
||||||
loc(record_literal(min_indent)),
|
loc!(record_literal(min_indent)),
|
||||||
loc(list_literal(min_indent)),
|
loc!(list_literal(min_indent)),
|
||||||
loc(unary_op(min_indent)),
|
loc!(unary_op(min_indent)),
|
||||||
loc(case_expr(min_indent)),
|
loc!(case_expr(min_indent)),
|
||||||
loc(if_expr(min_indent)),
|
loc!(if_expr(min_indent)),
|
||||||
loc(ident_etc(min_indent)),
|
loc!(ident_etc(min_indent)),
|
||||||
)
|
)
|
||||||
.parse(arena, state)
|
.parse(arena, state)
|
||||||
}
|
}
|
||||||
|
@ -170,8 +171,8 @@ pub fn unary_op<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
one_of2(
|
one_of2(
|
||||||
map_with_arena(
|
map_with_arena(
|
||||||
and(
|
and(
|
||||||
loc(char('!')),
|
loc!(char('!')),
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
),
|
),
|
||||||
|arena, (loc_op, loc_expr)| {
|
|arena, (loc_op, loc_expr)| {
|
||||||
Expr::UnaryOp(arena.alloc(loc_expr), loc_op.map(|_| UnaryOp::Not))
|
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(
|
map_with_arena(
|
||||||
and(
|
and(
|
||||||
loc(char('-')),
|
loc!(char('-')),
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
),
|
),
|
||||||
|arena, (loc_op, loc_expr)| {
|
|arena, (loc_op, loc_expr)| {
|
||||||
Expr::UnaryOp(arena.alloc(loc_expr), loc_op.map(|_| UnaryOp::Negate))
|
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
|
// parse the spaces and then attach them retroactively to the expression
|
||||||
// preceding the operator (the one we parsed before considering operators).
|
// preceding the operator (the one we parsed before considering operators).
|
||||||
optional(and(
|
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 spaces *after* the operator can be attached directly to
|
||||||
// the expression following the operator.
|
// the expression following the operator.
|
||||||
space0_before(
|
space0_before(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
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>>> {
|
pub fn loc_parenthetical_expr<'a>(min_indent: u16) -> impl Parser<'a, Located<Expr<'a>>> {
|
||||||
then(
|
then(
|
||||||
loc(and(
|
loc!(and(
|
||||||
between(
|
between(
|
||||||
char('('),
|
char('('),
|
||||||
space0_around(
|
space0_around(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
char(')'),
|
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) = ...`
|
/// 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>>> {
|
pub fn loc_parenthetical_def<'a>(min_indent: u16) -> impl Parser<'a, Located<Expr<'a>>> {
|
||||||
move |arena, state| {
|
move |arena, state| {
|
||||||
let (loc_tuple, state) = loc(and(
|
let (loc_tuple, state) = loc!(and(
|
||||||
space0_after(
|
space0_after(
|
||||||
between(
|
between(
|
||||||
char('('),
|
char('('),
|
||||||
space0_around(loc(pattern(min_indent)), min_indent),
|
space0_around(loc!(pattern(min_indent)), min_indent),
|
||||||
char(')'),
|
char(')'),
|
||||||
),
|
),
|
||||||
min_indent,
|
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.
|
// Spaces after the '=' (at a normal indentation level) and then the expr.
|
||||||
// The expr itself must be indented more than the pattern and '='
|
// The expr itself must be indented more than the pattern and '='
|
||||||
space0_before(
|
space0_before(
|
||||||
loc(move |arena, state| parse_expr(indented_more, arena, state)),
|
loc!(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -579,17 +580,17 @@ fn parse_def_expr<'a>(
|
||||||
//
|
//
|
||||||
// It should be indented more than the original, and it will
|
// It should be indented more than the original, and it will
|
||||||
// end when outdented again.
|
// 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(
|
and(
|
||||||
// Optionally parse additional defs.
|
// Optionally parse additional defs.
|
||||||
zero_or_more(allocated(space1_before(
|
zero_or_more(allocated(space1_before(
|
||||||
loc(def(original_indent)),
|
loc!(def(original_indent)),
|
||||||
original_indent,
|
original_indent,
|
||||||
))),
|
))),
|
||||||
// Parse the final expression that will be returned.
|
// Parse the final expression that will be returned.
|
||||||
// It should be indented the same amount as the original.
|
// It should be indented the same amount as the original.
|
||||||
space1_before(
|
space1_before(
|
||||||
loc(move |arena, state| parse_expr(original_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(original_indent, arena, state)),
|
||||||
original_indent,
|
original_indent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -640,15 +641,15 @@ fn loc_parse_function_arg<'a>(
|
||||||
) -> ParseResult<'a, Located<Expr<'a>>> {
|
) -> ParseResult<'a, Located<Expr<'a>>> {
|
||||||
one_of10(
|
one_of10(
|
||||||
loc_parenthetical_expr(min_indent),
|
loc_parenthetical_expr(min_indent),
|
||||||
loc(string_literal()),
|
loc!(string_literal()),
|
||||||
loc(number_literal()),
|
loc!(number_literal()),
|
||||||
loc(closure(min_indent)),
|
loc!(closure(min_indent)),
|
||||||
loc(record_literal(min_indent)),
|
loc!(record_literal(min_indent)),
|
||||||
loc(list_literal(min_indent)),
|
loc!(list_literal(min_indent)),
|
||||||
loc(unary_op(min_indent)),
|
loc!(unary_op(min_indent)),
|
||||||
loc(case_expr(min_indent)),
|
loc!(case_expr(min_indent)),
|
||||||
loc(if_expr(min_indent)),
|
loc!(if_expr(min_indent)),
|
||||||
loc(ident_without_apply()),
|
loc!(ident_without_apply()),
|
||||||
)
|
)
|
||||||
.parse(arena, state)
|
.parse(arena, state)
|
||||||
}
|
}
|
||||||
|
@ -689,7 +690,7 @@ fn closure<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
attempt(
|
attempt(
|
||||||
Attempting::ClosureBody,
|
Attempting::ClosureBody,
|
||||||
space0_before(
|
space0_before(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -714,20 +715,20 @@ fn parse_closure_param<'a>(
|
||||||
) -> ParseResult<'a, Located<Pattern<'a>>> {
|
) -> ParseResult<'a, Located<Pattern<'a>>> {
|
||||||
one_of5(
|
one_of5(
|
||||||
// An ident is the most common param, e.g. \foo -> ...
|
// An ident is the most common param, e.g. \foo -> ...
|
||||||
loc(ident_pattern()),
|
loc!(ident_pattern()),
|
||||||
// Underscore is also common, e.g. \_ -> ...
|
// Underscore is also common, e.g. \_ -> ...
|
||||||
loc(underscore_pattern()),
|
loc!(underscore_pattern()),
|
||||||
// You can destructure records in params, e.g. \{ x, y } -> ...
|
// 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.
|
// If you wrap it in parens, you can match any arbitrary pattern at all.
|
||||||
// e.g. \User.UserId userId -> ...
|
// e.g. \User.UserId userId -> ...
|
||||||
between(
|
between(
|
||||||
char('('),
|
char('('),
|
||||||
space0_around(loc(pattern(min_indent)), min_indent),
|
space0_around(loc!(pattern(min_indent)), min_indent),
|
||||||
char(')'),
|
char(')'),
|
||||||
),
|
),
|
||||||
// The least common, but still allowed, e.g. \Foo -> ...
|
// The least common, but still allowed, e.g. \Foo -> ...
|
||||||
loc(map(unqualified_variant(), |name| {
|
loc!(map(unqualified_variant(), |name| {
|
||||||
Pattern::Variant(&[], name)
|
Pattern::Variant(&[], name)
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
|
@ -766,7 +767,7 @@ fn record_destructure<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
||||||
map(
|
map(
|
||||||
collection(
|
collection(
|
||||||
char('{'),
|
char('{'),
|
||||||
loc(ident_pattern()),
|
loc!(ident_pattern()),
|
||||||
char(','),
|
char(','),
|
||||||
char('}'),
|
char('}'),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
@ -791,7 +792,7 @@ pub fn case_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
Attempting::CaseCondition,
|
Attempting::CaseCondition,
|
||||||
skip_second(
|
skip_second(
|
||||||
space1_around(
|
space1_around(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
string(keyword::WHEN),
|
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.
|
// 2. Parse the other branches. Their indentation levels must be == the first branch's.
|
||||||
|
|
||||||
let (mut loc_first_pattern, state) =
|
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 original_indent = state.indent_col;
|
||||||
let indented_more = original_indent + 1;
|
let indented_more = original_indent + 1;
|
||||||
let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?;
|
let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?;
|
||||||
|
@ -844,7 +845,7 @@ pub fn case_branches<'a>(
|
||||||
string("->"),
|
string("->"),
|
||||||
// The expr must be indented more than the pattern preceding it
|
// The expr must be indented more than the pattern preceding it
|
||||||
space0_before(
|
space0_before(
|
||||||
loc(move |arena, state| parse_expr(indented_more, arena, state)),
|
loc!(move |arena, state| parse_expr(indented_more, arena, state)),
|
||||||
indented_more,
|
indented_more,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -855,7 +856,7 @@ pub fn case_branches<'a>(
|
||||||
|
|
||||||
let branch_parser = and(
|
let branch_parser = and(
|
||||||
then(
|
then(
|
||||||
space1_around(loc(pattern(min_indent)), min_indent),
|
space1_around(loc!(pattern(min_indent)), min_indent),
|
||||||
move |_arena, state, loc_pattern| {
|
move |_arena, state, loc_pattern| {
|
||||||
if state.indent_col == original_indent {
|
if state.indent_col == original_indent {
|
||||||
Ok((loc_pattern, state))
|
Ok((loc_pattern, state))
|
||||||
|
@ -869,7 +870,7 @@ pub fn case_branches<'a>(
|
||||||
skip_first(
|
skip_first(
|
||||||
string("->"),
|
string("->"),
|
||||||
space1_before(
|
space1_before(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -900,7 +901,7 @@ pub fn if_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
skip_first(
|
skip_first(
|
||||||
string(keyword::IF),
|
string(keyword::IF),
|
||||||
space1_around(
|
space1_around(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -908,14 +909,14 @@ pub fn if_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
skip_first(
|
skip_first(
|
||||||
string(keyword::THEN),
|
string(keyword::THEN),
|
||||||
space1_around(
|
space1_around(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
skip_first(
|
skip_first(
|
||||||
string(keyword::ELSE),
|
string(keyword::ELSE),
|
||||||
space1_before(
|
space1_before(
|
||||||
loc(move |arena, state| parse_expr(min_indent, arena, state)),
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
min_indent,
|
min_indent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -945,7 +946,7 @@ fn unary_negate_function_arg<'a>(min_indent: u16) -> impl Parser<'a, Located<Exp
|
||||||
then(
|
then(
|
||||||
// Spaces, then '-', then *not* more spaces.
|
// Spaces, then '-', then *not* more spaces.
|
||||||
not_followed_by(
|
not_followed_by(
|
||||||
and(space1(min_indent), loc(char('-'))),
|
and(space1(min_indent), loc!(char('-'))),
|
||||||
one_of3(char(' '), char('#'), char('\n')),
|
one_of3(char(' '), char('#'), char('\n')),
|
||||||
),
|
),
|
||||||
move |arena, state, (spaces, loc_minus_char)| {
|
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>> {
|
pub fn ident_etc<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
then(
|
then(
|
||||||
and(
|
and(
|
||||||
loc(ident()),
|
loc!(ident()),
|
||||||
optional(either(
|
optional(either(
|
||||||
// There may optionally be function args after this ident
|
// There may optionally be function args after this ident
|
||||||
loc_function_args(min_indent),
|
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>> {
|
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))
|
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>> {
|
pub fn list_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
let elems = collection(
|
let elems = collection(
|
||||||
char('['),
|
char('['),
|
||||||
loc(expr(min_indent)),
|
loc!(expr(min_indent)),
|
||||||
char(','),
|
char(','),
|
||||||
char(']'),
|
char(']'),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
@ -1181,7 +1182,7 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
and(
|
and(
|
||||||
attempt(
|
attempt(
|
||||||
Attempting::Record,
|
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())),
|
optional(and(space0(min_indent), equals_with_indent())),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use bumpalo::collections::vec::Vec;
|
use bumpalo::collections::vec::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use parse::ast::Attempting;
|
use parse::ast::Attempting;
|
||||||
use region::{Located, Region};
|
use region::Region;
|
||||||
use std::{char, u16};
|
use std::{char, u16};
|
||||||
|
|
||||||
/// A position in a source file.
|
/// 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)]
|
#[inline(always)]
|
||||||
pub fn zero_or_more_impl<'a, P, A>(parser: P) -> impl Parser<'a, Vec<'a, A>>
|
pub fn zero_or_more_impl<'a, P, A>(parser: P) -> impl Parser<'a, Vec<'a, A>>
|
||||||
where
|
where
|
||||||
|
@ -1334,15 +1307,6 @@ where
|
||||||
BoxedParser::new(map_with_arena_impl(parser, transform))
|
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>
|
pub fn attempt<'a, P, Val>(attempting: Attempting, parser: P) -> BoxedParser<'a, Val>
|
||||||
where
|
where
|
||||||
P: Parser<'a, Val>,
|
P: Parser<'a, Val>,
|
||||||
|
@ -1379,3 +1343,29 @@ where
|
||||||
{
|
{
|
||||||
BoxedParser::new(one_or_more_impl(parser))
|
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::blankspace::{space0, space0_before};
|
||||||
use parse::collection::collection;
|
use parse::collection::collection;
|
||||||
use parse::ident::unqualified_ident;
|
use parse::ident::unqualified_ident;
|
||||||
use parse::parser::{and, char, loc, map_with_arena, optional, skip_first, Parser};
|
use parse::parser::{and, char, map_with_arena, optional, skip_first, Parser, State};
|
||||||
use region::Located;
|
use region::{Located, Region};
|
||||||
|
|
||||||
/// Parse a record - generally one of these two:
|
/// 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>>
|
fn record_field<'a, P, S>(val_parser: P, min_indent: u16) -> impl Parser<'a, AssignedField<'a, S>>
|
||||||
where
|
where
|
||||||
P: Parser<'a, Located<S>>,
|
P: Parser<'a, Located<S>>,
|
||||||
|
@ -42,7 +51,7 @@ where
|
||||||
map_with_arena(
|
map_with_arena(
|
||||||
and(
|
and(
|
||||||
// You must have a field name, e.g. "email"
|
// You must have a field name, e.g. "email"
|
||||||
loc(unqualified_ident()),
|
loc!(unqualified_ident()),
|
||||||
and(
|
and(
|
||||||
space0(min_indent),
|
space0(min_indent),
|
||||||
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
|
// 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::ast::{Attempting, TypeAnnotation};
|
||||||
use parse::blankspace::{space0_around, space1_before};
|
use parse::blankspace::{space0_around, space1_before};
|
||||||
use parse::parser::{
|
use parse::parser::{
|
||||||
and, between, char, loc, map, map_with_arena, one_of5, optional, skip_first, string,
|
and, between, char, map, map_with_arena, one_of5, optional, skip_first, string, unexpected,
|
||||||
unexpected, unexpected_eof, zero_or_more, ParseResult, Parser, State,
|
unexpected_eof, zero_or_more, ParseResult, Parser, State,
|
||||||
};
|
};
|
||||||
use parse::record::record;
|
use parse::record::record;
|
||||||
use region::Located;
|
use region::{Located, Region};
|
||||||
|
|
||||||
pub fn located<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>> {
|
pub fn located<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>> {
|
||||||
one_of5(
|
one_of5(
|
||||||
// The `*` type variable, e.g. in (List *) Wildcard,
|
// The `*` type variable, e.g. in (List *) Wildcard,
|
||||||
map(loc(char('*')), |loc_val| {
|
map(loc!(char('*')), |loc_val| {
|
||||||
loc_val.map(|_| TypeAnnotation::Wildcard)
|
loc_val.map(|_| TypeAnnotation::Wildcard)
|
||||||
}),
|
}),
|
||||||
loc_parenthetical_type(min_indent),
|
loc_parenthetical_type(min_indent),
|
||||||
loc(record_type(min_indent)),
|
loc!(record_type(min_indent)),
|
||||||
loc(applied_type(min_indent)),
|
loc!(applied_type(min_indent)),
|
||||||
loc(parse_type_variable),
|
loc!(parse_type_variable),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
extern crate bumpalo;
|
extern crate bumpalo;
|
||||||
extern crate roc;
|
|
||||||
|
|
||||||
use self::bumpalo::Bump;
|
use self::bumpalo::Bump;
|
||||||
use roc::can;
|
use roc::can;
|
||||||
|
@ -13,11 +12,41 @@ use roc::ident::Ident;
|
||||||
use roc::parse;
|
use roc::parse;
|
||||||
use roc::parse::ast::{self, Attempting};
|
use roc::parse::ast::{self, Attempting};
|
||||||
use roc::parse::blankspace::space0_before;
|
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::region::{Located, Region};
|
||||||
use roc::subs::{Subs, Variable};
|
use roc::subs::{Subs, Variable};
|
||||||
use roc::types::{Expected, Type};
|
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)]
|
#[allow(dead_code)]
|
||||||
pub fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<ast::Expr<'a>, Fail> {
|
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)
|
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)]
|
#[allow(dead_code)]
|
||||||
pub fn parse_loc_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Located<ast::Expr<'a>>, Fail> {
|
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 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);
|
let answer = parser.parse(&arena, state);
|
||||||
|
|
||||||
answer
|
answer
|
||||||
|
|
|
@ -3,6 +3,7 @@ extern crate pretty_assertions;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate indoc;
|
extern crate indoc;
|
||||||
extern crate bumpalo;
|
extern crate bumpalo;
|
||||||
|
#[macro_use]
|
||||||
extern crate roc;
|
extern crate roc;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -11,11 +12,12 @@ mod test_format {
|
||||||
use roc::parse;
|
use roc::parse;
|
||||||
use roc::parse::ast::{format, Attempting, Expr};
|
use roc::parse::ast::{format, Attempting, Expr};
|
||||||
use roc::parse::blankspace::space0_before;
|
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> {
|
fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Expr<'a>, Fail> {
|
||||||
let state = State::new(&input, Attempting::Module);
|
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);
|
let answer = parser.parse(&arena, state);
|
||||||
|
|
||||||
answer
|
answer
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue