summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/tests/common/mod.rs2
-rw-r--r--dhall_core/src/lib.rs1
-rw-r--r--dhall_core/src/parser.rs173
3 files changed, 50 insertions, 126 deletions
diff --git a/dhall/tests/common/mod.rs b/dhall/tests/common/mod.rs
index 2ee9724..a635fb1 100644
--- a/dhall/tests/common/mod.rs
+++ b/dhall/tests/common/mod.rs
@@ -32,7 +32,7 @@ macro_rules! make_spec_test {
// The parser stack overflows even on small files
// when compiled without optimizations
thread::Builder::new()
- .stack_size(8 * 1024 * 1024)
+ .stack_size(16 * 1024 * 1024)
.spawn(move || {
run_test($path, Feature::$type);
})
diff --git a/dhall_core/src/lib.rs b/dhall_core/src/lib.rs
index 508ad3a..6215456 100644
--- a/dhall_core/src/lib.rs
+++ b/dhall_core/src/lib.rs
@@ -1,6 +1,5 @@
#![feature(trace_macros)]
#![feature(slice_patterns)]
-#![recursion_limit = "128"]
#![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 30e3367..cbba8ca 100644
--- a/dhall_core/src/parser.rs
+++ b/dhall_core/src/parser.rs
@@ -107,7 +107,7 @@ macro_rules! match_pair {
{
let pair = $pair.clone();
let rule = pair.as_rule();
- let parsed: Vec<_> = pair.clone().into_inner().map(ParseWrapped::parse_any_fast).collect::<Result<_, _>>()?;
+ let parsed: Vec<_> = pair.clone().into_inner().map(parse_any).collect::<Result<_, _>>()?;
#[allow(unreachable_code)]
iter_patterns::match_vec!(parsed;
$($acc)*
@@ -119,48 +119,32 @@ macro_rules! match_pair {
($pair:expr; $( $submac:ident!($($args:tt)*) => $body:expr ),* $(,)*) => {
match_pair!(@make_matches, $pair, (), $( $submac!($($args)*) => $body ),* ,)
};
- ($pair:expr; $($args:tt)*) => {
- {
- let pair = $pair;
- let result = match_iter_branching!(@noclone, match_pair; pair; $($args)*);
- result.map_err(|e| match e {
- IterMatchError::Other(e) => e,
- _ => custom_parse_error(&pair, "No match found".to_owned()),
- })
- }
- };
}
macro_rules! make_parser {
- (@branch_rules, $pair:expr, ($($acc:tt)*), rule!( $name:ident<$o:ty>; $($args:tt)* ); $($rest:tt)*) => (
- make_parser!(@branch_rules, $pair, ($($acc)* Rule::$name => {
- ParseWrapped::$name($pair)
- },), $($rest)*)
- );
- (@branch_rules, $pair:expr, ($($acc:tt)*), rule_in_group!( $name:ident<$o:ty>; $group:ident; $($args:tt)* ); $($rest:tt)*) => (
- make_parser!(@branch_rules, $pair, ($($acc)* Rule::$name => {
- ParseWrapped::$name($pair).map(|x| x.$name()).map(ParsedValue::$group)
- },), $($rest)*)
- );
- (@branch_rules, $pair:expr, ($($acc:tt)*), binop!( $name:ident<$o:ty>; $op:ident ); $($rest:tt)*) => (
- make_parser!(@branch_rules, $pair, ($($acc)* Rule::$name => {
- parse_binop($pair, BinOp::$op).map(ParsedValue::expression)
- },), $($rest)*)
+ // Filter out definitions that should not be matched on
+ (@filter, rule) => (true);
+ (@filter, rule_in_group) => (true);
+ (@filter, binop) => (true);
+ (@filter, rule_group) => (false);
+
+ (@body, $pair:expr, rule!( $name:ident<$o:ty>; $($args:tt)* )) => ( {
+ let res: $o = match_pair!($pair; $($args)*)?;
+ Ok(ParsedValue::$name(res))
+ });
+ (@body, $pair:expr, rule_in_group!( $name:ident<$o:ty>; $group:ident; $($args:tt)* )) => ( {
+ let res: $o = match_pair!($pair; $($args)*)?;
+ Ok(ParsedValue::$group(res))
+ });
+ (@body, $pair:expr, binop!( $name:ident<$o:ty>; $op:ident )) => ( {
+ parse_binop($pair, BinOp::$op)
+ });
+ (@body, $pair:expr, rule_group!( $name:ident<$o:ty> )) => (
+ unreachable!()
);
- // (@branch_rules, $pair:expr, ($($acc:tt)*), rule_group!( $name:ident<$o:ty>; $($ty:ident),* ); $($rest:tt)*) => (
- // make_parser!(@branch_rules, $pair, ($($acc)* $( Rule::$ty => ParseUnwrapped::$ty($pair).map(ParsedValue::$name),)* ), $($rest)*)
- // );
- (@branch_rules, $pair:expr, ($($acc:tt)*), $submac:ident!( $name:ident<$o:ty>; $($args:tt)* ); $($rest:tt)*) => (
- make_parser!(@branch_rules, $pair, ($($acc)*), $($rest)*)
- );
- (@branch_rules, $pair:expr, ($($acc:tt)*),) => (
- #[allow(unreachable_patterns)]
- match $pair.as_rule() {
- $($acc)*
- r => Err(custom_parse_error(&$pair, format!("parse_any_fast: Unexpected {:?}", r))),
- }
- );
- ($( $submac:ident!( $name:ident<$o:ty>; $($args:tt)* ); )*) => (
+
+
+ ($( $submac:ident!( $name:ident<$o:ty> $($args:tt)* ); )*) => (
// #[allow(non_camel_case_types, dead_code)]
// enum ParsedType {
// $( $name, )*
@@ -182,8 +166,6 @@ macro_rules! make_parser {
// // }
// // }
// }
- struct ParseWrapped;
- struct ParseUnwrapped;
#[allow(non_camel_case_types, dead_code)]
#[derive(Debug)]
@@ -203,71 +185,22 @@ macro_rules! make_parser {
)*
}
- impl ParseWrapped {
- #[allow(non_snake_case, dead_code)]
- fn parse_any_fast(pair: Pair<Rule>) -> ParseResult<ParsedValue> {
- make_parser!(@branch_rules, pair, (), $( $submac!( $name<$o>; $($args)* ); )*)
+ #[allow(non_snake_case, dead_code)]
+ fn parse_any<'a>(pair: Pair<'a, Rule>) -> ParseResult<ParsedValue<'a>> {
+ #[allow(unreachable_patterns)]
+ match pair.as_rule() {
+ $(
+ Rule::$name if make_parser!(@filter, $submac)
+ =>
+ make_parser!(@body, pair, $submac!( $name<$o> $($args)* ))
+ ,
+ )*
+ r => Err(custom_parse_error(&pair, format!("parse_any: Unexpected {:?}", r))),
}
}
-
- impl ParseUnwrapped {
- #[allow(unused_variables, non_snake_case, dead_code, clippy::all)]
- fn expression<'a>(pair: Pair<'a, Rule>) -> ParseResult<RcExpr> {
- ParseWrapped::expression(pair).map(|x| x.expression())
- }
- }
- impl ParseWrapped {
- #[allow(unused_variables, non_snake_case, dead_code, clippy::all)]
- fn expression<'a>(pair: Pair<'a, Rule>) -> ParseResult<ParsedValue<'a>> {
- ParseWrapped::parse_any_fast(pair)
- }
- }
-
- // fn do_the_parse(s: &str, r: Rule, ty: ParsedType) -> ParseResult<ParsedValue> {
- // let pairs = DhallParser::parse(r, s)?;
- // match_iter!(pairs; (e) => ty.parse(e))
- // }
-
- $(
- $submac!($name<$o>; $($args)*);
- )*
);
}
-macro_rules! make_pest_parse_function {
- ($name:ident<$o:ty>; $submac:ident!( $($args:tt)* )) => (
- impl ParseUnwrapped {
- #[allow(unused_variables, non_snake_case, dead_code, clippy::all)]
- fn $name<'a>(pair: Pair<'a, Rule>) -> ParseResult<$o> {
- ParseWrapped::$name(pair).map(|x| x.$name())
- }
- }
- impl ParseWrapped {
- #[allow(unused_variables, non_snake_case, dead_code, clippy::all)]
- fn $name<'a>(pair: Pair<'a, Rule>) -> ParseResult<ParsedValue<'a>> {
- let res: ParseResult<$o> = $submac!(pair; $($args)*);
- Ok(ParsedValue::$name(res?))
- }
- }
- );
-}
-
-macro_rules! rule {
- ($name:ident<$o:ty>; $($args:tt)*) => (
- make_pest_parse_function!($name<$o>; match_pair!( $($args)* ));
- );
-}
-
-macro_rules! rule_in_group {
- ($name:ident<$o:ty>; $group:ident; $($args:tt)*) => (
- make_pest_parse_function!($name<$o>; match_pair!( $($args)* ));
- );
-}
-
-macro_rules! rule_group {
- ($name:ident<$o:ty>; $($ty:ident),*) => ();
-}
-
// List of rules that can be shortcutted as implemented in parse_binop
fn can_be_shortcutted(rule: Rule) -> bool {
use Rule::*;
@@ -291,21 +224,25 @@ fn can_be_shortcutted(rule: Rule) -> bool {
}
}
-fn parse_binop(pair: Pair<Rule>, o: BinOp) -> ParseResult<RcExpr> {
+fn parse_binop(pair: Pair<Rule>, o: BinOp) -> ParseResult<ParsedValue> {
// This all could be a trivial fold, but to avoid stack explosion
// we try to cut down on the recursion level here, by consuming
// chains of blah_expression > ... > blih_expression in one go.
let mut pair = pair;
let mut pairs = pair.into_inner();
let first = pairs.next().unwrap();
- let rest: Vec<_> = pairs.map(ParseUnwrapped::expression).collect::<Result<_, _>>()?;
+ let rest: Vec<_> = pairs
+ .map(|p| parse_any(p).map(|x| x.expression()))
+ .collect::<Result<_, _>>()?;
if !rest.is_empty() {
// If there is more than one subexpression, handle it normally
- let first = ParseUnwrapped::expression(first)?;
- Ok(rest.into_iter().fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))))
+ let first = parse_any(first)?.expression();
+ Ok(ParsedValue::expression(
+ rest.into_iter()
+ .fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))),
+ ))
} else {
// Otherwise, consume short-cuttable rules as long as they contain only one subexpression.
- // println!("short-cutting {}", debug_pair(pair.clone()));
pair = first;
while can_be_shortcutted(pair.as_rule()) {
let mut pairs = pair.clone().into_inner();
@@ -316,22 +253,10 @@ fn parse_binop(pair: Pair<Rule>, o: BinOp) -> ParseResult<RcExpr> {
}
pair = first;
}
- // println!("short-cutted {}", debug_pair(pair.clone()));
- // println!();
- Ok(ParseUnwrapped::expression(pair)?)
+ parse_any(pair)
}
}
-macro_rules! binop {
- ($rule:ident<$ty:ty>; $op:ident) => {
- rule!($rule<$ty>;
- raw_pair!(pair) => {
- parse_binop(pair, BinOp::$op)?
- }
- );
- };
-}
-
make_parser! {
rule!(EOI<()>; children!() => ());
@@ -450,7 +375,7 @@ rule!(path<PathBuf>;
captured_str!(s) => (".".to_owned() + s).into()
);
-rule_group!(local_raw<(FilePrefix, PathBuf)>;);
+rule_group!(local_raw<(FilePrefix, PathBuf)>);
rule_in_group!(parent_path<(FilePrefix, PathBuf)>; local_raw;
children!(p: path) => (FilePrefix::Parent, p)
@@ -492,7 +417,7 @@ rule!(import_hashed_raw<(ImportLocation, Option<()>)>;
}
);
-rule_group!(expression<RcExpr>;);
+rule_group!(expression<RcExpr>);
rule_in_group!(import_raw<RcExpr>; expression;
// TODO: handle "as Text"
@@ -746,11 +671,11 @@ pub fn parse_expr(s: &str) -> ParseResult<RcExpr> {
let pairs = DhallParser::parse(Rule::final_expression, s)?;
// Match the only item in the pairs iterator
// println!("{}", debug_pair(pairs.clone().next().unwrap()));
- let expr = iter_patterns::destructure_iter!(pairs; [p] => ParseUnwrapped::expression(p))
+ let expr = iter_patterns::destructure_iter!(pairs; [p] => parse_any(p))
.unwrap()?;
// expr.expression()
- // Ok(expr.expression())
- Ok(expr)
+ Ok(expr.expression())
+ // Ok(expr)
// Ok(bx(Expr::BoolLit(false)))
}