summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/src/parser.rs294
1 files changed, 124 insertions, 170 deletions
diff --git a/dhall/src/parser.rs b/dhall/src/parser.rs
index 712c618..6fb6e1d 100644
--- a/dhall/src/parser.rs
+++ b/dhall/src/parser.rs
@@ -95,56 +95,11 @@ macro_rules! match_iter {
-macro_rules! make_parser {
- ($( named!( $name:ident<$o:ty>; $($args:tt)* ); )*) => (
- #[allow(dead_code)]
- #[allow(non_camel_case_types)]
- enum ParsedType {
- $( $name, )*
- }
-
- impl ParsedType {
- #[allow(dead_code)]
- fn parse(self, pair: Pair<Rule>) -> ParseResult<ParsedValue> {
- match self {
- $( ParsedType::$name => $name(pair), )*
- }
- }
- }
-
- #[allow(non_camel_case_types)]
- enum ParsedValue<'a> {
- $( $name($o), )*
- }
-
- impl<'a> ParsedValue<'a> {
- $(
- fn $name(self) -> ParseResult<$o> {
- match self {
- ParsedValue::$name(x) => Ok(x),
- _ => unreachable!(),
- }
- }
- )*
- }
-
- 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))
- }
-
- $(
- named!($name<$o>; $($args)*);
- )*
- );
-}
-
macro_rules! named {
($name:ident<$o:ty>; $submac:ident!( $($args:tt)* )) => (
#[allow(unused_variables)]
- fn $name<'a>(pair: Pair<'a, Rule>) -> ParseResult<ParsedValue<'a>> {
- let res: ParseResult<$o> = $submac!(pair; $($args)*);
- Ok(ParsedValue::$name(res?))
+ fn $name<'a>(pair: Pair<'a, Rule>) -> ParseResult<$o> {
+ $submac!(pair; $($args)*)
}
);
}
@@ -167,16 +122,16 @@ macro_rules! match_children {
};
(@parse, $pairs:expr, $x:ident : $ty:ident $($rest:tt)*) => {
- let $x = $ty($x)?.$ty()?;
+ let $x = $ty($x)?;
match_children!(@parse, $pairs $($rest)*);
};
(@parse, $pairs:expr, $x:ident? : $ty:ident $($rest:tt)*) => {
- let $x = $x.map($ty).map(|x| x?.$ty()).transpose()?;
+ let $x = $x.map($ty).transpose()?;
match_children!(@parse, $pairs $($rest)*);
};
(@parse, $pairs:expr, $x:ident* : $ty:ident $($rest:tt)*) => {
#[allow(unused_mut)]
- let mut $x = $x.map($ty).map(|x| x?.$ty());
+ let mut $x = $x.map($ty);
match_children!(@parse, $pairs $($rest)*);
};
(@parse, $pairs:expr) => {};
@@ -217,7 +172,7 @@ macro_rules! with_raw_pair {
macro_rules! map {
($pair:expr; $ty:ident; $f:expr) => {
{
- let x = $ty($pair)?.$ty()?;
+ let x = $ty($pair)?;
Ok($f(x))
}
};
@@ -265,137 +220,136 @@ macro_rules! match_rule {
}
-make_parser!{
- named!(eoi<()>; plain_value!(()));
+named!(eoi<()>; plain_value!(()));
- named!(str<&'a str>; with_captured_str!(s; { s.trim() }));
+named!(str<&'a str>; with_captured_str!(s; { s.trim() }));
- named!(natural<usize>; with_raw_pair!(pair; {
- pair.as_str().trim()
- .parse()
- .map_err(|e: std::num::ParseIntError| custom_parse_error(&pair, format!("{}", e)))?
- }));
+named!(natural<usize>; with_raw_pair!(pair; {
+ pair.as_str().trim()
+ .parse()
+ .map_err(|e: std::num::ParseIntError| custom_parse_error(&pair, format!("{}", e)))?
+}));
- named!(integer<isize>; with_raw_pair!(pair; {
- pair.as_str().trim()
- .parse()
- .map_err(|e: std::num::ParseIntError| custom_parse_error(&pair, format!("{}", e)))?
- }));
+named!(integer<isize>; with_raw_pair!(pair; {
+ pair.as_str().trim()
+ .parse()
+ .map_err(|e: std::num::ParseIntError| custom_parse_error(&pair, format!("{}", e)))?
+}));
- named!(letbinding<(&'a str, Option<BoxExpr<'a>>, BoxExpr<'a>)>;
- match_children!((name: str, annot?: expression, expr: expression) => (name, annot, expr))
- );
-
- named!(record_entry<(&'a str, BoxExpr<'a>)>;
- match_children!((name: str, expr: expression) => (name, expr))
- );
+named!(letbinding<(&'a str, Option<BoxExpr<'a>>, BoxExpr<'a>)>;
+ match_children!((name: str, annot?: expression, expr: expression) => (name, annot, expr))
+);
- named!(partial_record_entries<(Rule, BoxExpr<'a>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
- with_rule!(rule;
- match_children!((expr: expression, entries*: record_entry) => {
- let mut map: BTreeMap<&str, ParsedExpr> = BTreeMap::new();
- for entry in entries {
- let (n, e) = entry?;
- map.insert(n, *e);
- }
- (rule, expr, map)
- })
- )
- );
+named!(record_entry<(&'a str, BoxExpr<'a>)>;
+ match_children!((name: str, expr: expression) => (name, expr))
+);
- named!(expression<BoxExpr<'a>>; match_rule!(
- Rule::natural_literal_raw => map!(natural; |n| bx(Expr::NaturalLit(n))),
- Rule::integer_literal_raw => map!(integer; |n| bx(Expr::IntegerLit(n))),
-
- Rule::identifier_raw =>
- match_children!((name: str, idx?: natural) => {
- match Builtin::parse(name) {
- Some(b) => bx(Expr::Builtin(b)),
- None => match name {
- "True" => bx(Expr::BoolLit(true)),
- "False" => bx(Expr::BoolLit(false)),
- "Type" => bx(Expr::Const(Const::Type)),
- "Kind" => bx(Expr::Const(Const::Kind)),
- name => bx(Expr::Var(V(name, idx.unwrap_or(0)))),
- }
- }
- }),
-
- Rule::lambda_expression =>
- match_children!((label: str, typ: expression, body: expression) => {
- bx(Expr::Lam(label, typ, body))
- }),
-
- Rule::ifthenelse_expression =>
- match_children!((cond: expression, left: expression, right: expression) => {
- bx(Expr::BoolIf(cond, left, right))
- }),
-
- Rule::let_expression =>
- match_children!((bindings*: letbinding, final_expr: expression) => {
- bindings.fold_results(final_expr, |acc, x| bx(Expr::Let(x.0, x.1, x.2, acc)))?
- }),
-
- Rule::forall_expression =>
- match_children!((label: str, typ: expression, body: expression) => {
- bx(Expr::Pi(label, typ, body))
- }),
-
- Rule::arrow_expression =>
- match_children!((typ: expression, body: expression) => {
- bx(Expr::Pi("_", typ, body))
- }),
-
- Rule::annotated_expression => binop!(Expr::Annot),
- Rule::import_alt_expression => binop!(Expr::ImportAlt),
- Rule::or_expression => binop!(Expr::BoolOr),
- Rule::plus_expression => binop!(Expr::NaturalPlus),
- Rule::text_append_expression => binop!(Expr::TextAppend),
- Rule::list_append_expression => binop!(Expr::ListAppend),
- Rule::and_expression => binop!(Expr::BoolAnd),
- Rule::combine_expression => binop!(Expr::Combine),
- Rule::prefer_expression => binop!(Expr::Prefer),
- Rule::combine_types_expression => binop!(Expr::CombineTypes),
- Rule::times_expression => binop!(Expr::NaturalTimes),
- Rule::equal_expression => binop!(Expr::BoolEQ),
- Rule::not_equal_expression => binop!(Expr::BoolNE),
- Rule::application_expression => binop!(Expr::App),
-
- Rule::selector_expression_raw =>
- match_children!((first: expression, rest*: str) => {
- rest.fold_results(first, |acc, e| bx(Expr::Field(acc, e)))?
- }),
-
- Rule::empty_record_type => plain_value!(bx(Expr::Record(BTreeMap::new()))),
- Rule::empty_record_literal => plain_value!(bx(Expr::RecordLit(BTreeMap::new()))),
- Rule::non_empty_record_type_or_literal =>
- match_children!((first_label: str, rest: partial_record_entries) => {
- let (rule, first_expr, mut map) = rest;
- map.insert(first_label, *first_expr);
- match rule {
- Rule::non_empty_record_type => bx(Expr::Record(map)),
- Rule::non_empty_record_literal => bx(Expr::RecordLit(map)),
- _ => unreachable!()
+named!(partial_record_entries<(Rule, BoxExpr<'a>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
+ with_rule!(rule;
+ match_children!((expr: expression, entries*: record_entry) => {
+ let mut map: BTreeMap<&str, ParsedExpr> = BTreeMap::new();
+ for entry in entries {
+ let (n, e) = entry?;
+ map.insert(n, *e);
+ }
+ (rule, expr, map)
+ })
+ )
+);
+
+named!(expression<BoxExpr<'a>>; match_rule!(
+ Rule::natural_literal_raw => map!(natural; |n| bx(Expr::NaturalLit(n))),
+ Rule::integer_literal_raw => map!(integer; |n| bx(Expr::IntegerLit(n))),
+
+ Rule::identifier_raw =>
+ match_children!((name: str, idx?: natural) => {
+ match Builtin::parse(name) {
+ Some(b) => bx(Expr::Builtin(b)),
+ None => match name {
+ "True" => bx(Expr::BoolLit(true)),
+ "False" => bx(Expr::BoolLit(false)),
+ "Type" => bx(Expr::Const(Const::Type)),
+ "Kind" => bx(Expr::Const(Const::Kind)),
+ name => bx(Expr::Var(V(name, idx.unwrap_or(0)))),
}
- }),
+ }
+ }),
+
+ Rule::lambda_expression =>
+ match_children!((label: str, typ: expression, body: expression) => {
+ bx(Expr::Lam(label, typ, body))
+ }),
+
+ Rule::ifthenelse_expression =>
+ match_children!((cond: expression, left: expression, right: expression) => {
+ bx(Expr::BoolIf(cond, left, right))
+ }),
+
+ Rule::let_expression =>
+ match_children!((bindings*: letbinding, final_expr: expression) => {
+ bindings.fold_results(final_expr, |acc, x| bx(Expr::Let(x.0, x.1, x.2, acc)))?
+ }),
+
+ Rule::forall_expression =>
+ match_children!((label: str, typ: expression, body: expression) => {
+ bx(Expr::Pi(label, typ, body))
+ }),
+
+ Rule::arrow_expression =>
+ match_children!((typ: expression, body: expression) => {
+ bx(Expr::Pi("_", typ, body))
+ }),
+
+ Rule::annotated_expression => binop!(Expr::Annot),
+ Rule::import_alt_expression => binop!(Expr::ImportAlt),
+ Rule::or_expression => binop!(Expr::BoolOr),
+ Rule::plus_expression => binop!(Expr::NaturalPlus),
+ Rule::text_append_expression => binop!(Expr::TextAppend),
+ Rule::list_append_expression => binop!(Expr::ListAppend),
+ Rule::and_expression => binop!(Expr::BoolAnd),
+ Rule::combine_expression => binop!(Expr::Combine),
+ Rule::prefer_expression => binop!(Expr::Prefer),
+ Rule::combine_types_expression => binop!(Expr::CombineTypes),
+ Rule::times_expression => binop!(Expr::NaturalTimes),
+ Rule::equal_expression => binop!(Expr::BoolEQ),
+ Rule::not_equal_expression => binop!(Expr::BoolNE),
+ Rule::application_expression => binop!(Expr::App),
+
+ Rule::selector_expression_raw =>
+ match_children!((first: expression, rest*: str) => {
+ rest.fold_results(first, |acc, e| bx(Expr::Field(acc, e)))?
+ }),
+
+ Rule::empty_record_type => plain_value!(bx(Expr::Record(BTreeMap::new()))),
+ Rule::empty_record_literal => plain_value!(bx(Expr::RecordLit(BTreeMap::new()))),
+ Rule::non_empty_record_type_or_literal =>
+ match_children!((first_label: str, rest: partial_record_entries) => {
+ let (rule, first_expr, mut map) = rest;
+ map.insert(first_label, *first_expr);
+ match rule {
+ Rule::non_empty_record_type => bx(Expr::Record(map)),
+ Rule::non_empty_record_literal => bx(Expr::RecordLit(map)),
+ _ => unreachable!()
+ }
+ }),
- _ => with_rule!(rule;
- match_children!((exprs*: expression) => {
- // panic!();
- let rulename = format!("{:?}", rule);
- bx(Expr::FailedParse(rulename, exprs.map_results(|x| *x).collect::<ParseResult<_>>()?))
- })
- ),
- ));
+ _ => with_rule!(rule;
+ match_children!((exprs*: expression) => {
+ // panic!();
+ let rulename = format!("{:?}", rule);
+ bx(Expr::FailedParse(rulename, exprs.map_results(|x| *x).collect::<ParseResult<_>>()?))
+ })
+ ),
+));
- named!(final_expression<BoxExpr<'a>>;
- match_children!((e: expression, _eoi: eoi) => e)
- );
-}
+named!(final_expression<BoxExpr<'a>>;
+ match_children!((e: expression, _eoi: eoi) => e)
+);
pub fn parse_expr_pest(s: &str) -> ParseResult<BoxExpr> {
- do_the_parse(s, Rule::final_expression, ParsedType::final_expression)?.final_expression()
+ let pairs = DhallParser::parse(Rule::final_expression, s)?;
+ match_iter!(pairs; (e) => final_expression(e))
}