From 4d616450d6883e68672a91f447999660fa17636c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 20 Mar 2019 23:11:06 +0100 Subject: Cleanup parser --- dhall_core/src/parser.rs | 155 +++++++++++++++++++---------------------------- 1 file changed, 64 insertions(+), 91 deletions(-) (limited to 'dhall_core') diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index ef7fcc9..caeebd0 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -72,9 +72,15 @@ fn debug_pair(pair: Pair) -> String { } macro_rules! match_pair { - (@make_child_match, ($($vars:tt)*), ($($outer_acc:tt)*), ($($acc:tt)*), ($(,)* $ty:ident ($x:ident..) $($rest_of_match:tt)*) => $body:expr, $($rest:tt)*) => { - match_pair!(@make_child_match, ($($vars)*), ($($outer_acc)*), ($($acc)*, x..), ($($rest_of_match)*) => { - let $x = x.map(|x| x.$ty()); + (@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_pair!(@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(custom_parse_error(&$pair, + format!("Unexpected child: {:?}", x) + )), + }).collect::, _>>()?; + let $x = xs.into_iter(); $body }, $($rest)*) }; @@ -93,13 +99,16 @@ macro_rules! match_pair { }; (@make_matches, ($pair:expr, $parsed:expr), ($($acc:tt)*) $(,)*) => { { - let pair = $pair; - let rule = pair.as_rule(); + let pair = $pair.clone(); #[allow(unreachable_code)] iter_patterns::match_vec!($parsed; $($acc)* - [x..] => panic!("Unexpected children while parsing rule '{:?}': {:?}", rule, x.collect::>()), - ).ok_or_else(|| custom_parse_error(&pair, "No match found".to_owned())) + [x..] => Err( + custom_parse_error(&pair, + format!("Unexpected children: {:?}", x.collect::>()) + ) + )?, + ).ok_or_else(|| unreachable!()) } }; @@ -111,23 +120,22 @@ macro_rules! match_pair { macro_rules! make_parser { // Filter out definitions that should not be matched on (i.e. rule_group) (@filter, rule) => (true); - (@filter, rule_in_group) => (true); (@filter, rule_group) => (false); (@body, $pair:expr, $parsed:expr, rule!( $name:ident<$o:ty>; $($args:tt)* )) => ( - make_parser!(@body, $pair, $parsed, rule_in_group!( $name<$o>; $name; $($args)* )) + make_parser!(@body, $pair, $parsed, rule!( $name<$o> as $name; $($args)* )) ); - (@body, $pair:expr, $parsed:expr, rule_in_group!( $name:ident<$o:ty>; $group:ident; raw_pair!($x:pat) => $body:expr )) => ( { - let $x = $pair.clone(); + (@body, $pair:expr, $parsed:expr, rule!( $name:ident<$o:ty> as $group:ident; raw_pair!($x:pat) => $body:expr )) => ( { + let $x = $pair; let res: $o = $body; Ok(ParsedValue::$group(res)) }); - (@body, $pair:expr, $parsed:expr, rule_in_group!( $name:ident<$o:ty>; $group:ident; captured_str!($x:ident) => $body:expr )) => ( { + (@body, $pair:expr, $parsed:expr, rule!( $name:ident<$o:ty> as $group:ident; captured_str!($x:ident) => $body:expr )) => ( { let $x = $pair.as_str(); let res: $o = $body; Ok(ParsedValue::$group(res)) }); - (@body, $pair:expr, $parsed:expr, rule_in_group!( $name:ident<$o:ty>; $group:ident; children!( $($args:tt)* ) )) => ( { + (@body, $pair:expr, $parsed:expr, rule!( $name:ident<$o:ty> as $group:ident; children!( $($args:tt)* ) )) => ( { let res: $o = match_pair!(($pair, $parsed); $($args)*)?; Ok(ParsedValue::$group(res)) }); @@ -137,46 +145,12 @@ macro_rules! make_parser { ($( $submac:ident!( $name:ident<$o:ty> $($args:tt)* ); )*) => ( - // #[allow(non_camel_case_types, dead_code)] - // enum ParsedType { - // $( $name, )* - // } - - // impl ParsedType { - // #[allow(dead_code)] - // fn parse(self, pair: Pair) -> ParseResult { - // match self { - // $( ParsedType::$name => { - // let ret = $name(pair)?; - // Ok(ParsedValue::$name(ret)) - // }, )* - // } - // } - // // fn parse(self, pair: Pair) -> ParseResult { - // // match self { - // // $( ParsedType::$name => $name(pair), )* - // // } - // // } - // } - #[allow(non_camel_case_types, dead_code)] #[derive(Debug)] enum ParsedValue<'a> { $( $name($o), )* } - impl<'a> ParsedValue<'a> { - $( - #[allow(non_snake_case, dead_code)] - fn $name(self) -> $o { - match self { - ParsedValue::$name(x) => x, - _ => unreachable!(), - } - } - )* - } - // Non-recursive implementation to avoid stack overflows fn parse_any<'a>(initial_pair: Pair<'a, Rule>) -> ParseResult> { enum StackFrame<'a> { @@ -366,19 +340,19 @@ rule!(path; rule_group!(local_raw<(FilePrefix, PathBuf)>); -rule_in_group!(parent_path<(FilePrefix, PathBuf)>; local_raw; children!( +rule!(parent_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Parent, p) )); -rule_in_group!(here_path<(FilePrefix, PathBuf)>; local_raw; children!( +rule!(here_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Here, p) )); -rule_in_group!(home_path<(FilePrefix, PathBuf)>; local_raw; children!( +rule!(home_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Home, p) )); -rule_in_group!(absolute_path<(FilePrefix, PathBuf)>; local_raw; children!( +rule!(absolute_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Absolute, p) )); @@ -405,7 +379,7 @@ rule!(import_hashed_raw<(ImportLocation, Option<()>)>; children!( rule_group!(expression); -rule_in_group!(import_raw; expression; children!( +rule!(import_raw as expression; children!( // TODO: handle "as Text" [import_hashed_raw((location, hash))] => { bx(Expr::Embed(Import { @@ -416,19 +390,19 @@ rule_in_group!(import_raw; expression; children!( } )); -rule_in_group!(lambda_expression; expression; children!( +rule!(lambda_expression as expression; children!( [label_raw(l), expression(typ), expression(body)] => { bx(Expr::Lam(l, typ, body)) } )); -rule_in_group!(ifthenelse_expression; expression; children!( +rule!(ifthenelse_expression as expression; children!( [expression(cond), expression(left), expression(right)] => { bx(Expr::BoolIf(cond, left, right)) } )); -rule_in_group!(let_expression; expression; children!( +rule!(let_expression as expression; children!( [let_binding(bindings..), expression(final_expr)] => { bindings.fold(final_expr, |acc, x| bx(Expr::Let(x.0, x.1, x.2, acc))) } @@ -439,19 +413,19 @@ rule!(let_binding<(Label, Option, RcExpr)>; children!( [label_raw(name), expression(expr)] => (name, None, expr), )); -rule_in_group!(forall_expression; expression; children!( +rule!(forall_expression as expression; children!( [label_raw(l), expression(typ), expression(body)] => { bx(Expr::Pi(l, typ, body)) } )); -rule_in_group!(arrow_expression; expression; children!( +rule!(arrow_expression as expression; children!( [expression(typ), expression(body)] => { bx(Expr::Pi("_".into(), typ, body)) } )); -rule_in_group!(merge_expression; expression; children!( +rule!(merge_expression as expression; children!( [expression(x), expression(y), expression(z)] => bx(Expr::Merge(x, y, Some(z))), [expression(x), expression(y)] => bx(Expr::Merge(x, y, None)), )); @@ -459,7 +433,7 @@ rule_in_group!(merge_expression; expression; children!( rule!(List<()>; raw_pair!(_) => ()); rule!(Optional<()>; raw_pair!(_) => ()); -rule_in_group!(empty_collection; expression; children!( +rule!(empty_collection as expression; children!( [List(_), expression(y)] => { bx(Expr::EmptyListLit(y)) }, @@ -468,93 +442,93 @@ rule_in_group!(empty_collection; expression; children!( }, )); -rule_in_group!(non_empty_optional; expression; children!( +rule!(non_empty_optional as expression; children!( [expression(x), Optional(_), expression(z)] => { bx(Expr::OptionalLit(Some(z), Some(x))) } )); -rule_in_group!(import_alt_expression; expression; children!( +rule!(import_alt_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::ImportAlt, acc, e))) }, )); -rule_in_group!(or_expression; expression; children!( +rule!(or_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::BoolOr, acc, e))) }, )); -rule_in_group!(plus_expression; expression; children!( +rule!(plus_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::NaturalPlus, acc, e))) }, )); -rule_in_group!(text_append_expression; expression; children!( +rule!(text_append_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::TextAppend, acc, e))) }, )); -rule_in_group!(list_append_expression; expression; children!( +rule!(list_append_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::ListAppend, acc, e))) }, )); -rule_in_group!(and_expression; expression; children!( +rule!(and_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::BoolAnd, acc, e))) }, )); -rule_in_group!(combine_expression; expression; children!( +rule!(combine_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::Combine, acc, e))) }, )); -rule_in_group!(prefer_expression; expression; children!( +rule!(prefer_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::Prefer, acc, e))) }, )); -rule_in_group!(combine_types_expression; expression; children!( +rule!(combine_types_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::CombineTypes, acc, e))) }, )); -rule_in_group!(times_expression; expression; children!( +rule!(times_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::NaturalTimes, acc, e))) }, )); -rule_in_group!(equal_expression; expression; children!( +rule!(equal_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::BoolEQ, acc, e))) }, )); -rule_in_group!(not_equal_expression; expression; children!( +rule!(not_equal_expression as expression; children!( [expression(e)] => e, [expression(first), expression(rest..)] => { rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::BoolNE, acc, e))) }, )); -rule_in_group!(annotated_expression; expression; children!( +rule!(annotated_expression as expression; children!( [expression(e), expression(annot)] => { bx(Expr::Annot(e, annot)) }, [expression(e)] => e, )); -rule_in_group!(application_expression; expression; children!( +rule!(application_expression as expression; children!( [expression(first), expression(rest..)] => { let rest: Vec<_> = rest.collect(); if rest.is_empty() { @@ -565,7 +539,7 @@ rule_in_group!(application_expression; expression; children!( } )); -rule_in_group!(selector_expression_raw; expression; children!( +rule!(selector_expression_raw as expression; children!( [expression(first), selector_raw(rest..)] => { rest.fold(first, |acc, e| bx(Expr::Field(acc, e))) } @@ -576,7 +550,7 @@ rule!(selector_raw