From 345e9d23f8b8e6e7d5fb6eb3071b46c7f6fba420 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 27 Mar 2019 01:35:01 +0100 Subject: Integrate the special patterns from match_children!() into iter_patterns Considerably simplifies parser macros --- dhall_core/src/lib.rs | 1 + dhall_core/src/parser.rs | 168 +++++++++++------------------------------------ 2 files changed, 39 insertions(+), 130 deletions(-) (limited to 'dhall_core') diff --git a/dhall_core/src/lib.rs b/dhall_core/src/lib.rs index 0874b09..2042b04 100644 --- a/dhall_core/src/lib.rs +++ b/dhall_core/src/lib.rs @@ -1,5 +1,6 @@ #![feature(trace_macros)] #![feature(slice_patterns)] +#![feature(bind_by_move_pattern_guards)] #![allow( clippy::many_single_char_names, clippy::should_implement_trait, diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index 560d177..b7ac3f6 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -112,106 +112,6 @@ fn debug_pair(pair: Pair) -> String { s } -macro_rules! match_children { - (@make_child_match, - ($pair:expr, $($vars:tt)*), - ($($outer_acc:tt)*), - ($($acc:tt)*), - ($(,)* $ty:ident ($x:ident..) $($rest_of_match:tt)*) => $body:expr, - $($rest:tt)* - ) => { - match_children!(@make_child_match, - ($pair, $($vars)*), - ($($outer_acc)*), - ($($acc)*, xs..), - ($($rest_of_match)*) => { - let xs = xs.map(|x| match x { - ParsedValue::$ty(y) => Ok(y), - x => Err(format!("Unexpected child: {:?}", x)), - }).collect::, _>>()?; - let $x = xs.into_iter(); - $body - }, - $($rest)* - ) - }; - (@make_child_match, - ($($vars:tt)*), - ($($outer_acc:tt)*), - ($($acc:tt)*), - ($(,)* $ty:ident ($x:pat) $($rest_of_match:tt)*) => $body:expr, - $($rest:tt)* - ) => { - match_children!(@make_child_match, - ($($vars)*), - ($($outer_acc)*), - ($($acc)*, ParsedValue::$ty($x)), - ($($rest_of_match)*) => $body, - $($rest)* - ) - }; - (@make_child_match, - ($($vars:tt)*), - ($($outer_acc:tt)*), - (, $($acc:tt)*), - ($(,)*) => $body:expr, - $($rest:tt)* - ) => { - match_children!(@make_matches, - ($($vars)*), - ($($outer_acc)* [$($acc)*] => { $body },), - $($rest)* - ) - }; - (@make_child_match, - ($($vars:tt)*), - ($($outer_acc:tt)*), - (), - ($(,)*) => $body:expr, - $($rest:tt)* - ) => { - match_children!(@make_matches, - ($($vars)*), - ($($outer_acc)* [] => { $body },), - $($rest)* - ) - }; - - (@make_matches, - ($($vars:tt)*), - ($($acc:tt)*), - [$($args:tt)*] => $body:expr, - $($rest:tt)* - ) => { - match_children!(@make_child_match, - ($($vars)*), - ($($acc)*), - (), - ($($args)*) => $body, - $($rest)* - ) - }; - (@make_matches, ($pair:expr, $children:expr), ($($acc:tt)*) $(,)*) => { - { - #[allow(unreachable_code)] - iter_patterns::match_vec!($children; - $($acc)* - [x..] => Err( - format!("Unexpected children: {:?}", x.collect::>()) - )?, - ).ok_or_else(|| -> String { unreachable!() }) - } - }; - - (($($vars:tt)*); $( [$($args:tt)*] => $body:expr ),* $(,)*) => { - match_children!(@make_matches, - ($($vars)*), - (), - $( [$($args)*] => $body ),* , - ) - }; -} - macro_rules! make_parser { (@pattern, rule, $name:ident) => (Rule::$name); (@pattern, rule_group, $name:ident) => (_); @@ -248,10 +148,18 @@ macro_rules! make_parser { rule!( $name:ident<$o:ty> as $group:ident; - children!( $($args:tt)* ) + children!( $( [$($args:tt)*] => $body:expr ),* $(,)* ) ) ) => ({ - let res: $o = match_children!(($pair, $children); $($args)*)?; + #[allow(unused_imports)] + use ParsedValue::*; + #[allow(unreachable_code)] + let res: $o = iter_patterns::match_vec!($children; + $( [$($args)*] => $body, )* + [x..] => Err( + format!("Unexpected children: {:?}", x.collect::>()) + )?, + ).ok_or_else(|| -> String { unreachable!() })?; Ok(ParsedValue::$group(res)) }); (@body, $pair:expr, $children:expr, rule_group!( $name:ident<$o:ty> )) => ( @@ -369,7 +277,7 @@ make_parser! { )); rule!(double_quote_literal; children!( - [double_quote_chunk(chunks..)] => { + [double_quote_chunk(chunks)..] => { chunks.collect() } )); @@ -521,7 +429,7 @@ make_parser! { [quoted_path_component(s)] => s, )); rule!(path; children!( - [path_component(components..)] => { + [path_component(components)..] => { components.collect() } )); @@ -570,8 +478,8 @@ make_parser! { rule!(http; children!( [http_raw(url)] => url, - [http_raw(url), import_hashed(import_hashed)] => - URL { headers: Some(Box::new(import_hashed)), ..url }, + [http_raw(url), import_hashed(ih)] => + URL { headers: Some(Box::new(ih)), ..url }, )); rule!(env; children!( @@ -593,8 +501,8 @@ make_parser! { [http(url)] => { ImportLocation::Remote(url) }, - [local((prefix, path))] => { - ImportLocation::Local(prefix, path) + [local((prefix, p))] => { + ImportLocation::Local(prefix, p) }, )); @@ -608,8 +516,8 @@ make_parser! { rule!(import_hashed; children!( [import_type(location)] => ImportHashed { location, hash: None }, - [import_type(location), hash(hash)] => - ImportHashed { location, hash: Some(hash) }, + [import_type(location), hash(h)] => + ImportHashed { location, hash: Some(h) }, )); rule_group!(expression); @@ -644,7 +552,7 @@ make_parser! { )); rule!(let_expression as expression; children!( - [let_binding(bindings..), expression(final_expr)] => { + [let_binding(bindings).., expression(final_expr)] => { bindings.fold( final_expr, |acc, x| bx(Expr::Let(x.0, x.1, x.2, acc)) @@ -698,84 +606,84 @@ make_parser! { rule!(import_alt_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::ImportAlt; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(or_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::BoolOr; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(plus_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::NaturalPlus; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(text_append_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::TextAppend; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(list_append_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::ListAppend; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(and_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::BoolAnd; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(combine_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::Combine; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(prefer_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::Prefer; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(combine_types_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::CombineTypes; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(times_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::NaturalTimes; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(equal_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::BoolEQ; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, )); rule!(not_equal_expression as expression; children!( [expression(e)] => e, - [expression(first), expression(rest..)] => { + [expression(first), expression(rest)..] => { let o = BinOp::BoolNE; rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) }, @@ -799,7 +707,7 @@ make_parser! { _ => bx(Expr::App(first, vec![second])), } }, - [expression(first), expression(second), expression(rest..)] => { + [expression(first), expression(second), expression(rest)..] => { match first.as_ref() { Expr::Builtin(Builtin::OptionalNone) => bx(Expr::App(bx(Expr::EmptyOptionalLit(second)), @@ -817,7 +725,7 @@ make_parser! { rule!(selector_expression as expression; children!( [expression(e)] => e, - [expression(first), selector(rest..)] => { + [expression(first), selector(rest)..] => { rest.fold(first, |acc, e| match e { Either::Left(l) => bx(Expr::Field(acc, l)), Either::Right(ls) => bx(Expr::Projection(acc, ls)), @@ -831,7 +739,7 @@ make_parser! { )); rule!(labels>; children!( - [label(ls..)] => ls.collect(), + [label(ls)..] => ls.collect(), )); rule!(literal_expression as expression; children!( @@ -900,7 +808,7 @@ make_parser! { rule!(non_empty_record_type <(ParsedExpr, BTreeMap)>; children!( - [expression(expr), record_type_entry(entries..)] => { + [expression(expr), record_type_entry(entries)..] => { (expr, entries.collect()) } )); @@ -911,7 +819,7 @@ make_parser! { rule!(non_empty_record_literal <(ParsedExpr, BTreeMap)>; children!( - [expression(expr), record_literal_entry(entries..)] => { + [expression(expr), record_literal_entry(entries)..] => { (expr, entries.collect()) } )); @@ -953,7 +861,7 @@ make_parser! { )); rule!(union_type_entries>; children!( - [union_type_entry(entries..)] => entries.collect() + [union_type_entry(entries)..] => entries.collect() )); rule!(union_type_entry<(Label, ParsedExpr)>; children!( @@ -961,7 +869,7 @@ make_parser! { )); rule!(non_empty_list_literal as expression; children!( - [expression(items..)] => bx(Expr::NEListLit(items.collect())) + [expression(items)..] => bx(Expr::NEListLit(items.collect())) )); rule!(final_expression as expression; children!( -- cgit v1.2.3