summaryrefslogtreecommitdiff
path: root/dhall/src
diff options
context:
space:
mode:
Diffstat (limited to 'dhall/src')
-rw-r--r--dhall/src/parser.rs77
1 files changed, 58 insertions, 19 deletions
diff --git a/dhall/src/parser.rs b/dhall/src/parser.rs
index d9b405a..fb32ff0 100644
--- a/dhall/src/parser.rs
+++ b/dhall/src/parser.rs
@@ -277,10 +277,39 @@ macro_rules! match_iter_typed {
* using IterMatchError::Other.
* Allows multiple branches. The passed iterator must be Clone.
* Will check the branches in order, testing each branch using the callback macro provided.
+ *
+ * Example:
+ * ```
+ * macro_rules! callback {
+ * (@type_callback, positive, $x:expr) => {
+ * if $x >= 0 { Ok($x) } else { Err(()) }
+ * };
+ * (@type_callback, negative, $x:expr) => {
+ * if $x <= 0 { Ok($x) } else { Err(()) }
+ * };
+ * (@type_callback, any, $x:expr) => {
+ * Ok($x)
+ * };
+ * (@branch_callback, typed, $($args:tt)*) => {
+ * match_iter_typed!(@get_err, callback; $($args)*)
+ * };
+ * (@branch_callback, untyped, $($args:tt)*) => {
+ * match_iter!(@get_err, $($args)*)
+ * };
+ * }
+ *
+ * let vec = vec![-1, 2, 3];
+ *
+ * match_iter_branching!(branch_callback; vec.into_iter();
+ * typed!(x: positive, y?: negative, z: any) => { ... },
+ * untyped!(x, y, z) => { ... },
+ * )
+ * ```
+ *
*/
macro_rules! match_iter_branching {
// Entrypoints
- (@get_err, $callback:ident; $iter:expr; $( ($($args:tt)*) => $body:expr ),* $(,)*) => {
+ (@get_err, $callback:ident; $iter:expr; $( $submac:ident!($($args:tt)*) => $body:expr ),* $(,)*) => {
{
#[allow(unused_mut)]
let mut iter = $iter;
@@ -291,8 +320,7 @@ macro_rules! match_iter_branching {
#[allow(unreachable_code)]
loop {
$(
- let matched: Result<_, IterMatchError<_>> =
- match_iter_typed!(@get_err, $callback; iter.clone(); ($($args)*) => $body);
+ let matched: Result<_, IterMatchError<_>> = $callback!(@branch_callback, $submac, iter.clone(); ($($args)*) => $body);
#[allow(unused_assignments)]
match matched {
Ok(v) => break v,
@@ -328,17 +356,20 @@ macro_rules! named_rule {
);
}
-macro_rules! match_children {
+macro_rules! match_pest {
(@type_callback, $ty:ident, $x:expr) => {
$ty($x)
};
+ (@branch_callback, children, $($args:tt)*) => {
+ match_iter_typed!(@get_err, match_pest; $($args)*)
+ };
($pair:expr; $($args:tt)*) => {
{
let pair = $pair;
#[allow(unused_mut)]
let mut pairs = pair.clone().into_inner();
- let result = match_iter_branching!(@get_err, match_children; pairs; $($args)*);
+ let result = match_iter_branching!(@get_err, match_pest; pairs; $($args)*);
result.map_err(|e| match e {
IterMatchError::Other(e) => e,
_ => custom_parse_error(&pair, "No match found".to_owned()),
@@ -347,6 +378,12 @@ macro_rules! match_children {
};
}
+macro_rules! match_children {
+ ($pairs:expr; ($($args:tt)*) => $body:expr) => {
+ match_pest!($pairs; children!($($args)*) => $body)
+ };
+}
+
macro_rules! with_captured_str {
($pair:expr; $x:ident; $body:expr) => {{
#[allow(unused_mut)]
@@ -420,22 +457,22 @@ named!(raw_str<&'a str>; with_captured_str!(s; s));
named_rule!(escaped_quote_pair<&'a str>; plain_value!("''"));
named_rule!(escaped_interpolation<&'a str>; plain_value!("${"));
-named_rule!(single_quote_continue<Vec<&'a str>>; match_children!(
+named_rule!(single_quote_continue<Vec<&'a str>>; match_pest!(
// TODO: handle interpolation
- // (c: expression, rest: single_quote_continue) => {
+ // children!(c: expression, rest: single_quote_continue) => {
// rest.push(c); rest
// },
- (c: escaped_quote_pair, rest: single_quote_continue) => {
+ children!(c: escaped_quote_pair, rest: single_quote_continue) => {
rest.push(c); rest
},
- (c: escaped_interpolation, rest: single_quote_continue) => {
+ children!(c: escaped_interpolation, rest: single_quote_continue) => {
rest.push(c); rest
},
// capture interpolation as string
- (c: raw_str, rest: single_quote_continue) => {
+ children!(c: raw_str, rest: single_quote_continue) => {
rest.push(c); rest
},
- () => {
+ children!() => {
vec![]
},
));
@@ -488,16 +525,16 @@ named_rule!(union_type_entries<BTreeMap<&'a str, ParsedExpr<'a>>>;
named_rule!(non_empty_union_type_or_literal
<(Option<(&'a str, BoxExpr<'a>)>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
- match_children!(
- (label: str, e: expression, entries: union_type_entries) => {
+ match_pest!(
+ children!(label: str, e: expression, entries: union_type_entries) => {
(Some((label, e)), entries)
},
- (l: str, e: expression, rest: non_empty_union_type_or_literal) => {
+ children!(l: str, e: expression, rest: non_empty_union_type_or_literal) => {
let (x, mut entries) = rest;
entries.insert(l, *e);
(x, entries)
},
- (l: str, e: expression) => {
+ children!(l: str, e: expression) => {
let mut entries = BTreeMap::new();
entries.insert(l, *e);
(None, entries)
@@ -505,7 +542,9 @@ named_rule!(non_empty_union_type_or_literal
)
);
-named_rule!(empty_union_type<()>; plain_value!(()));
+named_rule!(empty_union_type<()>; match_children!(() => {
+ ()
+}));
named!(expression<BoxExpr<'a>>; match_rule!(
// TODO: parse escapes and interpolation
@@ -614,11 +653,11 @@ named!(expression<BoxExpr<'a>>; match_rule!(
}),
Rule::union_type_or_literal =>
- match_children!(
- (_e: empty_union_type) => {
+ match_pest!(
+ children!(_e: empty_union_type) => {
bx(Expr::Union(BTreeMap::new()))
},
- (x: non_empty_union_type_or_literal) => {
+ children!(x: non_empty_union_type_or_literal) => {
match x {
(Some((l, e)), entries) => bx(Expr::UnionLit(l, e, entries)),
(None, entries) => bx(Expr::Union(entries)),