diff options
-rw-r--r-- | dhall_core/src/parser.rs | 93 | ||||
-rw-r--r-- | dhall_parser/src/dhall.abnf | 64 | ||||
-rw-r--r-- | dhall_parser/src/dhall.pest.visibility | 22 |
3 files changed, 84 insertions, 95 deletions
diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index 68796c4..f888f94 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -116,8 +116,10 @@ fn debug_pair(pair: Pair<Rule>) -> String { macro_rules! make_parser { (@pattern, rule, $name:ident) => (Rule::$name); + (@pattern, token_rule, $name:ident) => (Rule::$name); (@pattern, rule_group, $name:ident) => (_); (@filter, rule) => (true); + (@filter, token_rule) => (true); (@filter, rule_group) => (false); (@body, @@ -164,6 +166,13 @@ macro_rules! make_parser { ).ok_or_else(|| -> String { unreachable!() })?; Ok(ParsedValue::$group(res)) }); + (@body, + $pair:expr, + $children:expr, + token_rule!($name:ident<$o:ty>) + ) => ({ + Ok(ParsedValue::$name(())) + }); (@body, $pair:expr, $children:expr, rule_group!( $name:ident<$o:ty> )) => ( unreachable!() ); @@ -235,7 +244,8 @@ fn do_parse<'a>(initial_pair: Pair<'a, Rule>) -> ParseResult<ParsedValue<'a>> { fn can_be_shortcutted(rule: Rule) -> bool { use Rule::*; match rule { - import_alt_expression + expression + | import_alt_expression | or_expression | plus_expression | text_append_expression @@ -255,7 +265,7 @@ fn can_be_shortcutted(rule: Rule) -> bool { } make_parser! { - rule!(EOI<()>; captured_str!(_) => ()); + token_rule!(EOI<()>); rule!(simple_label<Label>; captured_str!(s) => Label::from(s.trim().to_owned()) @@ -321,7 +331,7 @@ make_parser! { captured_str!(s) => s ); - rule!(end_of_line<()>; captured_str!(_) => ()); + token_rule!(end_of_line<()>); rule!(single_quote_literal<ParsedText>; children!( [end_of_line(eol), single_quote_continue(lines)] => { @@ -392,9 +402,9 @@ make_parser! { }, )); - rule!(NaN<()>; captured_str!(_) => ()); - rule!(minus_infinity_literal<()>; captured_str!(_) => ()); - rule!(plus_infinity_literal<()>; captured_str!(_) => ()); + token_rule!(NaN<()>); + token_rule!(minus_infinity_literal<()>); + token_rule!(plus_infinity_literal<()>); rule!(double_literal<core::Double>; captured_str!(s) => { @@ -491,7 +501,7 @@ make_parser! { rule!(bash_environment_variable<String>; captured_str!(s) => s.to_owned()); rule!(posix_environment_variable<String>; captured_str!(s) => s.to_owned()); - rule!(missing<()>; captured_str!(_) => ()); + token_rule!(missing<()>); rule!(import_type<ImportLocation>; children!( [missing(_)] => { @@ -522,9 +532,7 @@ make_parser! { ImportHashed { location, hash: Some(h) }, )); - rule_group!(expression<ParsedExpr>); - - rule!(Text<()>; captured_str!(_) => ()); + token_rule!(Text<()>); rule!(import<ParsedExpr> as expression; children!( [import_hashed(location_hashed)] => { @@ -541,25 +549,39 @@ make_parser! { }, )); - rule!(lambda_expression<ParsedExpr> as expression; children!( - [nonreserved_label(l), expression(typ), expression(body)] => { - Expr::Lam(l, rc(typ), rc(body)) - } - )); + token_rule!(lambda<()>); + token_rule!(forall<()>); + token_rule!(arrow<()>); + token_rule!(merge<()>); + token_rule!(if_<()>); + token_rule!(in_<()>); - rule!(ifthenelse_expression<ParsedExpr> as expression; children!( - [expression(cond), expression(left), expression(right)] => { + rule!(expression<ParsedExpr> as expression; children!( + [lambda(()), nonreserved_label(l), expression(typ), arrow(()), expression(body)] => { + Expr::Lam(l, rc(typ), rc(body)) + }, + [if_(()), expression(cond), expression(left), expression(right)] => { Expr::BoolIf(rc(cond), rc(left), rc(right)) - } - )); - - rule!(let_expression<ParsedExpr> as expression; children!( - [let_binding(bindings).., expression(final_expr)] => { + }, + [let_binding(bindings).., in_(()), expression(final_expr)] => { bindings.fold( final_expr, |acc, x| Expr::Let(x.0, x.1, x.2, rc(acc)) ) - } + }, + [forall(()), nonreserved_label(l), expression(typ), arrow(()), expression(body)] => { + Expr::Pi(l, rc(typ), rc(body)) + }, + [expression(typ), arrow(()), expression(body)] => { + Expr::Pi("_".into(), rc(typ), rc(body)) + }, + [merge(()), expression(x), expression(y), expression(z)] => { + Expr::Merge(rc(x), rc(y), Some(rc(z))) + }, + [merge(()), expression(x), expression(y)] => { + Expr::Merge(rc(x), rc(y), None) + }, + [expression(e)] => e, )); rule!(let_binding<(Label, Option<ParsedSubExpr>, ParsedSubExpr)>; children!( @@ -569,27 +591,8 @@ make_parser! { (name, None, rc(expr)), )); - rule!(forall_expression<ParsedExpr> as expression; children!( - [nonreserved_label(l), expression(typ), expression(body)] => { - Expr::Pi(l, rc(typ), rc(body)) - } - )); - - rule!(arrow_expression<ParsedExpr> as expression; children!( - [expression(typ), expression(body)] => { - Expr::Pi("_".into(), rc(typ), rc(body)) - } - )); - - rule!(merge_expression<ParsedExpr> as expression; children!( - [expression(x), expression(y), expression(z)] => - Expr::Merge(rc(x), rc(y), Some(rc(z))), - [expression(x), expression(y)] => - Expr::Merge(rc(x), rc(y), None), - )); - - rule!(List<()>; captured_str!(_) => ()); - rule!(Optional<()>; captured_str!(_) => ()); + token_rule!(List<()>); + token_rule!(Optional<()>); rule!(empty_collection<ParsedExpr> as expression; children!( [List(_), expression(t)] => { @@ -830,7 +833,7 @@ make_parser! { }, )); - rule!(empty_union_type<()>; captured_str!(_) => ()); + token_rule!(empty_union_type<()>); rule!(non_empty_union_type_or_literal <(Option<(Label, ParsedSubExpr)>, BTreeMap<Label, ParsedSubExpr>)>; diff --git a/dhall_parser/src/dhall.abnf b/dhall_parser/src/dhall.abnf index 8964f44..2fad4d4 100644 --- a/dhall_parser/src/dhall.abnf +++ b/dhall_parser/src/dhall.abnf @@ -529,52 +529,46 @@ import = import-hashed [ whsp as whsp1 Text ] ; This is important to avoid the need for sequential backtracking in application-expression.
expression =
- lambda-expression
- / ifthenelse-expression
- / let-expression
- / forall-expression
+ ; "\(x : a) -> b"
+ lambda whsp "(" whsp nonreserved-label whsp ":" whsp1 expression whsp ")" whsp arrow whsp expression
+
+ ; "if a then b else c"
+ / if whsp1 expression whsp then whsp1 expression whsp else whsp1 expression
+
+ ; "let x : t = e1 in e2"
+ ; "let x = e1 in e2"
+ ; "let x = e1 let y = e2 in e3"
+ / 1*let-binding in whsp1 expression
+
+ ; "forall (x : a) -> b"
+ / forall whsp "(" whsp nonreserved-label whsp ":" whsp1 expression whsp ")" whsp arrow whsp expression
+
+ ; "a -> b"
; NOTE: Backtrack if parsing this alternative fails
- / arrow-expression
- / merge-expression
+ / operator-expression whsp arrow whsp expression
+
+ ; "merge e1 e2 : t"
+ ; "merge e1 e2"
+ / merge whsp1 import-expression whsp import-expression [ whsp ":" whsp1 application-expression ]
+
+ ; "[] : List t"
+ ; "[] : Optional t"
+ ; "[x] : Optional t"
; NOTE: Backtrack if parsing this alternative fails since we can't tell
; from the opening bracket whether or not this will be an empty list or
; a non-empty list
- / empty-list-or-optional
+ / "[" whsp (empty-collection / non-empty-optional)
+
+ ; "x : t"
/ annotated-expression
-; "\(x : a) -> b"
-lambda-expression = lambda whsp "(" whsp nonreserved-label whsp ":" whsp1 expression whsp ")" whsp arrow whsp expression
-
-; "if a then b else c"
-ifthenelse-expression = if whsp1 expression whsp then whsp1 expression whsp else whsp1 expression
+; "x : t"
+annotated-expression = operator-expression [ whsp ":" whsp1 expression ]
-; "let x : t = e1 in e2"
-; "let x = e1 in e2"
-; "let x = e1 let y = e2 in e3"
-let-expression = 1*let-binding in whsp1 expression
let-binding = let whsp1 nonreserved-label whsp [ ":" whsp1 expression whsp ] "=" whsp expression whsp
-
-; "forall (x : a) -> b"
-forall-expression = forall whsp "(" whsp nonreserved-label whsp ":" whsp1 expression whsp ")" whsp arrow whsp expression
-
-; "a -> b"
-arrow-expression = operator-expression whsp arrow whsp expression
-
-; "merge e1 e2 : t"
-; "merge e1 e2"
-merge-expression = merge whsp1 import-expression whsp import-expression [ whsp ":" whsp1 application-expression ]
-
-; "[] : List t"
-; "[] : Optional t"
-; "[x] : Optional t"
-empty-list-or-optional = "[" whsp (empty-collection / non-empty-optional)
empty-collection = "]" whsp ":" whsp1 (List / Optional) whsp import-expression
non-empty-optional = expression whsp "]" whsp ":" whsp1 Optional whsp import-expression
-; "x : t"
-annotated-expression = operator-expression [ whsp ":" whsp1 expression ]
-
-
operator-expression = import-alt-expression
; Nonempty-whitespace to disambiguate `http://a/a?a`
diff --git a/dhall_parser/src/dhall.pest.visibility b/dhall_parser/src/dhall.pest.visibility index e95cd32..ac3ea30 100644 --- a/dhall_parser/src/dhall.pest.visibility +++ b/dhall_parser/src/dhall.pest.visibility @@ -34,16 +34,15 @@ single_quote_literal # in # as # using -# merge missing -# if_ +if_ # then # else_ # let_ -# in_ +in_ # as_ # using -# merge +merge # Infinity Optional Text @@ -78,9 +77,9 @@ List # combine # combine_types # prefer -# lambda -# forall -# arrow +lambda +forall +arrow # exponent double_literal natural_literal @@ -120,14 +119,7 @@ import_type hash import_hashed import -# expression -lambda_expression -ifthenelse_expression -let_expression -forall_expression -arrow_expression -merge_expression -# empty_list_or_optional +expression empty_collection non_empty_optional annotated_expression |