summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall_core/src/lib.rs1
-rw-r--r--dhall_core/src/parser.rs152
2 files changed, 30 insertions, 123 deletions
diff --git a/dhall_core/src/lib.rs b/dhall_core/src/lib.rs
index 3d8fbe1..86b0363 100644
--- a/dhall_core/src/lib.rs
+++ b/dhall_core/src/lib.rs
@@ -1,5 +1,4 @@
#![feature(box_patterns)]
-#![feature(slice_patterns)]
#![feature(trace_macros)]
#![allow(
clippy::many_single_char_names,
diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs
index b5d4b1a..ddf3f8f 100644
--- a/dhall_core/src/parser.rs
+++ b/dhall_core/src/parser.rs
@@ -77,14 +77,14 @@ fn debug_pair(pair: Pair<Rule>) -> String {
* ```
* let vec = vec![1, 2, 3];
*
- * match_iter!(vec.into_iter(); (x, y, z) => {
+ * match_iter!(vec.into_iter(); (x, y?, z) => {
* // x: T
- * // y: T
+ * // y: Option<T>
* // z: T
* })
*
* // or
- * match_iter!(vec.into_iter(); (x, y, z..) => {
+ * match_iter!(vec.into_iter(); (x, y, z*) => {
* // x, y: T
* // z: impl Iterator<T>
* })
@@ -98,68 +98,28 @@ enum IterMatchError<T> {
NoMatchFound,
Other(T), // Allow other macros to inject their own errors
}
-// macro_rules! match_iter {
-// (@as_expr, $e:expr) => {
-// $e
-// };
-// // Everything else pattern
-// (@match 0, $x:ident* $($rest:tt)*) => {
-// match_iter!(@match 0, $iter $($rest)*);
-// #[allow(unused_mut)]
-// let mut $x = $x;
-// };
-// // Alias to use in macros
-// (@match 0, $x:ident.. $($rest:tt)*) => {
-// match_iter!(@match 0, $iter $($rest)*);
-// #[allow(unused_mut)]
-// let mut $x = $x;
-// };
-// // Normal pattern
-// (@match 0, $x:ident $($rest:tt)*) => {
-// #[allow(unused_mut)]
-// let mut $x = match $x.next() {
-// Some(x) => x,
-// None => break Err(IterMatchError::NotEnoughItems),
-// };
-// match_iter!(@match 0, $iter $($rest)*);
-// };
-
-// (@match $_:expr, $iter:expr) => {};
-
-// (@panic; $($args:tt)*) => {
-// {
-// let ret: Result<_, IterMatchError<()>> = match_iter!($($args)*);
-// ret.unwrap()
-// }
-// };
-// ($iter:expr; ($($args:tt)*) => $body:expr) => {
-// {
-// #[allow(unused_mut)]
-// let mut iter = $iter;
-// // Not a real loop; used for error handling
-// let ret: Result<_, IterMatchError<_>> = loop {
-// let vec: Vec<_> = iter.collect();
-// break match_iter!(@as_expr, match *vec.into_boxed_slice() {
-// [$($args)*] => {
-// match_iter!(@match 0, $($args)*);
-// Ok($body)
-// },
-// _ => Err(IterMatchError::NotEnoughItems),
-// });
-// // match_iter!(@match 0, iter, $($args)*);
-// // break Ok($body);
-// };
-// ret
-// }
-// };
-// }
macro_rules! match_iter {
// Everything else pattern
- (@match 0, $iter:expr, $x:ident.. $($rest:tt)*) => {
+ (@match 0, $iter:expr, $x:ident* $($rest:tt)*) => {
match_iter!(@match 2, $iter $($rest)*);
#[allow(unused_mut)]
let mut $x = $iter;
};
+ // Alias to use in macros
+ (@match 0, $iter:expr, $x:ident?? $($rest:tt)*) => {
+ match_iter!(@match 2, $iter $($rest)*);
+ #[allow(unused_mut)]
+ let mut $x = $iter;
+ };
+ // Optional pattern
+ (@match 0, $iter:expr, $x:ident? $($rest:tt)*) => {
+ match_iter!(@match 1, $iter $($rest)*);
+ #[allow(unused_mut)]
+ let mut $x = $iter.next();
+ if $iter.next().is_some() {
+ break Err(IterMatchError::TooManyItems);
+ }
+ };
// Normal pattern
(@match 0, $iter:expr, $x:ident $($rest:tt)*) => {
#[allow(unused_mut)]
@@ -229,7 +189,7 @@ macro_rules! match_iter {
* let vec = vec![-1, 2, 3];
*
* match_iter_typed!(callback; vec.into_iter();
- * (x: positive, y*: negative, z: any) => { ... },
+ * (x: positive, y?: negative, z: any) => { ... },
* )
* ```
*
@@ -239,8 +199,11 @@ macro_rules! match_iter_typed {
(@collect, ($($vars:tt)*), ($($args:tt)*), ($($acc:tt)*), ($x:ident : $ty:ident, $($rest:tt)*)) => {
match_iter_typed!(@collect, ($($vars)*), ($($args)*), ($($acc)*, $x), ($($rest)*))
};
+ (@collect, ($($vars:tt)*), ($($args:tt)*), ($($acc:tt)*), ($x:ident? : $ty:ident, $($rest:tt)*)) => {
+ match_iter_typed!(@collect, ($($vars)*), ($($args)*), ($($acc)*, $x?), ($($rest)*))
+ };
(@collect, ($($vars:tt)*), ($($args:tt)*), ($($acc:tt)*), ($x:ident* : $ty:ident, $($rest:tt)*)) => {
- match_iter_typed!(@collect, ($($vars)*), ($($args)*), ($($acc)*, $x..), ($($rest)*))
+ match_iter_typed!(@collect, ($($vars)*), ($($args)*), ($($acc)*, $x??), ($($rest)*))
};
// Catch extra comma if exists
(@collect, ($($vars:tt)*), ($($args:tt)*), (,$($acc:tt)*), ($(,)*)) => {
@@ -326,7 +289,7 @@ macro_rules! match_iter_typed {
* let vec = vec![-1, 2, 3];
*
* match_iter_branching!(branch_callback; vec.into_iter();
- * typed!(x: positive, y*: negative, z: any) => { ... },
+ * typed!(x: positive, y?: negative, z: any) => { ... },
* untyped!(x, y, z) => { ... },
* )
* ```
@@ -457,56 +420,6 @@ macro_rules! match_rule {
};
}
-enum ParsedValue<'a> {
- Expr(ParsedExpr),
- Label(Label),
- Str(&'a str),
- RawStr(&'a str),
- Text(ParsedText),
- TextContents(ParsedTextContents<'a>),
- VecTextContents(Vec<ParsedTextContents<'a>>),
-}
-
-fn parse_pair(p: Pair<Rule>) -> ParseResult<ParsedValue> {
- let rule = p.as_rule();
- let mut values: Vec<_> = p
- .clone()
- .into_inner()
- .map(parse_pair)
- .collect::<Result<_, _>>()?;
- use crate::Expr::*;
- use crate::Label;
- use std::mem;
- use ParsedValue::*;
- match rule {
- Rule::lambda_expression => match *values.as_mut_slice() {
- [Label(ref mut l), Expr(ref mut typ), Expr(ref mut body)] => {
- let l: Label = mem::replace(l, Label::from(""));
- let typ: BoxExpr = bx(mem::replace(typ, BoolLit(false)));
- let body: BoxExpr = bx(mem::replace(body, BoolLit(false)));
- return Ok(ParsedValue::Expr(Lam(l, typ, body)));
- }
- _ => {}
- },
- Rule::application_expression => match *values.as_mut_slice() {
- [Expr(ref mut first), ref mut rest..] => {
- let first: ParsedExpr = mem::replace(first, BoolLit(false));
- let rest: Vec<ParsedExpr> = rest.into_iter()
- .map(|x| match *x {
- Expr(ref mut e) => Ok(mem::replace(e, BoolLit(false))),
- _ => Err(custom_parse_error(&p, "No match found".to_owned())),
- })
- .collect::<Result<Vec<_>, _>>()?;
- let rest = rest.into_iter();
- return Ok(ParsedValue::Expr(rest.fold(first, |acc, e| App(bx(acc), bx(e)))));
- }
- _ => {}
- },
- _ => {}
- }
- Err(custom_parse_error(&p, "No match found".to_owned()))
-}
-
rule!(EOI<()>; children!() => ());
named!(str<&'a str>; captured_str!(s) => s.trim());
@@ -711,8 +624,7 @@ rule!(let_expression<BoxExpr>;
);
rule!(let_binding<(Label, Option<BoxExpr>, BoxExpr)>;
- children!(name: label, expr: expression) => (name, None, expr),
- children!(name: label, annot: expression, expr: expression) => (name, Some(annot), expr),
+ children!(name: label, annot?: expression, expr: expression) => (name, annot, expr)
);
rule!(forall_expression<BoxExpr>;
@@ -728,12 +640,9 @@ rule!(arrow_expression<BoxExpr>;
);
rule!(merge_expression<BoxExpr>;
- children!(x: expression, y: expression) => {
- bx(Expr::Merge(x, y, None))
- },
- children!(x: expression, y: expression, z: expression) => {
- bx(Expr::Merge(x, y, Some(z)))
- },
+ children!(x: expression, y: expression, z?: expression) => {
+ bx(Expr::Merge(x, y, z))
+ }
);
rule!(empty_collection<BoxExpr>;
@@ -860,8 +769,7 @@ rule!(literal_expression_raw<BoxExpr>;
);
rule!(identifier_raw<BoxExpr>;
- children!(name: str, idx*: natural_literal_raw) => {
- let idx = idx.next();
+ children!(name: str, idx?: natural_literal_raw) => {
match Builtin::parse(name) {
Some(b) => bx(Expr::Builtin(b)),
None => match name {