diff options
author | Nadrieril Feneanar | 2019-04-04 23:51:46 +0200 |
---|---|---|
committer | GitHub | 2019-04-04 23:51:46 +0200 |
commit | a9f4e9b10196d75e674d95160955360d388a772b (patch) | |
tree | 20d869202eadc1193e449d3b3320f9b1d89ae578 /dhall_core | |
parent | 7336787af41adc4dfe650f7c7f10f9c7c3c011db (diff) | |
parent | 74eb88c42d938672137771fab33ef0118903b5e1 (diff) |
Merge pull request #42 from Nadrieril/move-to-upstream-grammar
Move to upstream grammar
Diffstat (limited to 'dhall_core')
-rw-r--r-- | dhall_core/src/core.rs | 19 | ||||
-rw-r--r-- | dhall_core/src/parser.rs | 340 |
2 files changed, 192 insertions, 167 deletions
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index 0ea8c83..afa3d3f 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -324,6 +324,25 @@ pub fn rc<T>(x: T) -> Rc<T> { Rc::new(x) } +pub fn app<N, E>(f: Expr<N, E>, args: Vec<SubExpr<N, E>>) -> Expr<N, E> { + if args.is_empty() { + f + } else { + Expr::App(rc(f), args) + } +} + +pub fn app_rc<N, E>( + f: SubExpr<N, E>, + args: Vec<SubExpr<N, E>>, +) -> SubExpr<N, E> { + if args.is_empty() { + f + } else { + rc(Expr::App(f, args)) + } +} + fn add_ui(u: usize, i: isize) -> usize { if i < 0 { u.checked_sub(i.checked_neg().unwrap() as usize).unwrap() diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index b7ac3f6..b0d80c0 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -13,6 +13,8 @@ use crate::*; // their own crate because they are quite general and useful. For now they // are here and hopefully you can figure out how they work. +type ParsedExpr = Expr<X, Import>; +type ParsedSubExpr = SubExpr<X, Import>; type ParsedText = InterpolatedText<X, Import>; type ParsedTextContents = InterpolatedTextContents<X, Import>; @@ -114,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, @@ -162,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!() ); @@ -233,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 @@ -253,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()) @@ -265,7 +277,7 @@ make_parser! { [simple_label(l)] => l, [quoted_label(l)] => l, )); - rule!(unreserved_label<Label>; children!( + rule!(nonreserved_label<Label>; children!( [label(l)] => { if Builtin::parse(&String::from(&l)).is_some() { Err( @@ -284,7 +296,7 @@ make_parser! { rule!(double_quote_chunk<ParsedTextContents>; children!( [interpolation(e)] => { - InterpolatedTextContents::Expr(e) + InterpolatedTextContents::Expr(rc(e)) }, [double_quote_escaped(s)] => { InterpolatedTextContents::Text(s) @@ -319,10 +331,8 @@ make_parser! { captured_str!(s) => s ); - rule!(end_of_line<()>; captured_str!(_) => ()); - rule!(single_quote_literal<ParsedText>; children!( - [end_of_line(eol), single_quote_continue(lines)] => { + [single_quote_continue(lines)] => { let space = InterpolatedTextContents::Text(" ".to_owned()); let newline = InterpolatedTextContents::Text("\n".to_owned()); let min_indent = lines @@ -357,7 +367,7 @@ make_parser! { rule!(single_quote_continue<Vec<Vec<ParsedTextContents>>>; children!( [interpolation(c), single_quote_continue(lines)] => { - let c = InterpolatedTextContents::Expr(c); + let c = InterpolatedTextContents::Expr(rc(c)); let mut lines = lines; lines.last_mut().unwrap().push(c); lines @@ -390,11 +400,11 @@ 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>; + rule!(numeric_double_literal<core::Double>; captured_str!(s) => { let s = s.trim(); match s.parse::<f64>() { @@ -406,6 +416,13 @@ make_parser! { } ); + rule!(double_literal<core::Double>; children!( + [numeric_double_literal(n)] => n, + [minus_infinity_literal(n)] => std::f64::NEG_INFINITY.into(), + [plus_infinity_literal(n)] => std::f64::INFINITY.into(), + [NaN(n)] => std::f64::NAN.into(), + )); + rule!(natural_literal<core::Natural>; captured_str!(s) => { s.trim() @@ -460,15 +477,15 @@ make_parser! { scheme: sch, authority: auth, path: p, - query: None, - headers: None, + query: Option::None, + headers: Option::None, }, [scheme(sch), authority(auth), path(p), query(q)] => URL { scheme: sch, authority: auth, path: p, - query: Some(q), - headers: None, + query: Option::Some(q), + headers: Option::None, }, )); @@ -479,7 +496,7 @@ make_parser! { rule!(http<URL>; children!( [http_raw(url)] => url, [http_raw(url), import_hashed(ih)] => - URL { headers: Some(Box::new(ih)), ..url }, + URL { headers: Option::Some(Box::new(ih)), ..url }, )); rule!(env<String>; children!( @@ -489,7 +506,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(_)] => { @@ -515,92 +532,85 @@ make_parser! { rule!(import_hashed<ImportHashed>; children!( [import_type(location)] => - ImportHashed { location, hash: None }, + ImportHashed { location, hash: Option::None }, [import_type(location), hash(h)] => - ImportHashed { location, hash: Some(h) }, + ImportHashed { location, hash: Option::Some(h) }, )); - rule_group!(expression<ParsedExpr>); - - rule!(Text<()>; captured_str!(_) => ()); + token_rule!(Text<()>); rule!(import<ParsedExpr> as expression; children!( [import_hashed(location_hashed)] => { - bx(Expr::Embed(Import { + Expr::Embed(Import { mode: ImportMode::Code, location_hashed - })) + }) }, [import_hashed(location_hashed), Text(_)] => { - bx(Expr::Embed(Import { + Expr::Embed(Import { mode: ImportMode::RawText, location_hashed - })) + }) }, )); - rule!(lambda_expression<ParsedExpr> as expression; children!( - [unreserved_label(l), expression(typ), expression(body)] => { - bx(Expr::Lam(l, typ, body)) - } - )); - - rule!(ifthenelse_expression<ParsedExpr> as expression; children!( - [expression(cond), expression(left), expression(right)] => { - bx(Expr::BoolIf(cond, left, right)) - } - )); + token_rule!(lambda<()>); + token_rule!(forall<()>); + token_rule!(arrow<()>); + token_rule!(merge<()>); + token_rule!(if_<()>); + token_rule!(in_<()>); - rule!(let_expression<ParsedExpr> as expression; children!( - [let_binding(bindings).., expression(final_expr)] => { + 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)) + }, + [let_binding(bindings).., in_(()), expression(final_expr)] => { bindings.fold( final_expr, - |acc, x| bx(Expr::Let(x.0, x.1, x.2, acc)) + |acc, x| Expr::Let(x.0, x.1, x.2, rc(acc)) ) - } - )); - - rule!(let_binding<(Label, Option<ParsedExpr>, ParsedExpr)>; children!( - [unreserved_label(name), expression(annot), expression(expr)] => - (name, Some(annot), expr), - [unreserved_label(name), expression(expr)] => - (name, None, expr), - )); - - rule!(forall_expression<ParsedExpr> as expression; children!( - [unreserved_label(l), expression(typ), expression(body)] => { - bx(Expr::Pi(l, typ, body)) - } - )); - - rule!(arrow_expression<ParsedExpr> as expression; children!( - [expression(typ), expression(body)] => { - bx(Expr::Pi("_".into(), typ, body)) - } + }, + [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), Option::Some(rc(z))) + }, + [merge(()), expression(x), expression(y)] => { + Expr::Merge(rc(x), rc(y), Option::None) + }, + [expression(e)] => e, )); - rule!(merge_expression<ParsedExpr> as expression; children!( - [expression(x), expression(y), expression(z)] => - bx(Expr::Merge(x, y, Some(z))), - [expression(x), expression(y)] => - bx(Expr::Merge(x, y, None)), + rule!(let_binding<(Label, Option<ParsedSubExpr>, ParsedSubExpr)>; children!( + [nonreserved_label(name), expression(annot), expression(expr)] => + (name, Option::Some(rc(annot)), rc(expr)), + [nonreserved_label(name), expression(expr)] => + (name, Option::None, rc(expr)), )); - rule!(List<()>; captured_str!(_) => ()); - rule!(Optional<()>; captured_str!(_) => ()); + token_rule!(List<()>); + token_rule!(Optional<()>); rule!(empty_collection<ParsedExpr> as expression; children!( [List(_), expression(t)] => { - bx(Expr::EmptyListLit(t)) + Expr::EmptyListLit(rc(t)) }, [Optional(_), expression(t)] => { - bx(Expr::EmptyOptionalLit(t)) + Expr::EmptyOptionalLit(rc(t)) }, )); rule!(non_empty_optional<ParsedExpr> as expression; children!( [expression(x), Optional(_), expression(t)] => { - rc(Expr::Annot(rc(Expr::NEOptionalLit(x)), t)) + Expr::Annot(rc(Expr::NEOptionalLit(rc(x))), rc(t)) } )); @@ -608,118 +618,107 @@ make_parser! { [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::ImportAlt; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(or_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::BoolOr; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(plus_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::NaturalPlus; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(text_append_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::TextAppend; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(list_append_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::ListAppend; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(and_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::BoolAnd; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(combine_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::Combine; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(prefer_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::Prefer; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(combine_types_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::CombineTypes; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(times_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::NaturalTimes; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(equal_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::BoolEQ; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(not_equal_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), expression(rest)..] => { let o = BinOp::BoolNE; - rest.fold(first, |acc, e| bx(Expr::BinOp(o, acc, e))) + rest.fold(first, |acc, e| Expr::BinOp(o, rc(acc), rc(e))) }, )); rule!(annotated_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(e), expression(annot)] => { - bx(Expr::Annot(e, annot)) + Expr::Annot(rc(e), rc(annot)) }, )); + token_rule!(Some<()>); + rule!(application_expression<ParsedExpr> as expression; children!( [expression(e)] => e, - [expression(first), expression(second)] => { - match first.as_ref() { - Expr::Builtin(Builtin::OptionalNone) => - bx(Expr::EmptyOptionalLit(second)), - Expr::Builtin(Builtin::OptionalSome) => - bx(Expr::NEOptionalLit(second)), - _ => bx(Expr::App(first, vec![second])), - } + [expression(Expr::Builtin(Builtin::OptionalNone)), + expression(e), expression(rest)..] => { + app(Expr::EmptyOptionalLit(rc(e)), rest.map(rc).collect()) }, - [expression(first), expression(second), expression(rest)..] => { - match first.as_ref() { - Expr::Builtin(Builtin::OptionalNone) => - bx(Expr::App(bx(Expr::EmptyOptionalLit(second)), - rest.collect())), - Expr::Builtin(Builtin::OptionalSome) => - bx(Expr::App(bx(Expr::NEOptionalLit(second)), - rest.collect())), - _ => bx(Expr::App(first, - std::iter::once(second) - .chain(rest) - .collect())), - } + [Some(()), expression(e), expression(rest)..] => { + app(Expr::NEOptionalLit(rc(e)), rest.map(rc).collect()) + }, + [expression(first), expression(rest)..] => { + app(first, rest.map(rc).collect()) }, )); @@ -727,8 +726,8 @@ make_parser! { [expression(e)] => e, [expression(first), selector(rest)..] => { rest.fold(first, |acc, e| match e { - Either::Left(l) => bx(Expr::Field(acc, l)), - Either::Right(ls) => bx(Expr::Projection(acc, ls)), + Either::Left(l) => Expr::Field(rc(acc), l), + Either::Right(ls) => Expr::Projection(rc(acc), ls), }) } )); @@ -742,17 +741,12 @@ make_parser! { [label(ls)..] => ls.collect(), )); - rule!(literal_expression<ParsedExpr> as expression; children!( - [double_literal(n)] => bx(Expr::DoubleLit(n)), - [minus_infinity_literal(n)] => - bx(Expr::DoubleLit(std::f64::NEG_INFINITY.into())), - [plus_infinity_literal(n)] => - bx(Expr::DoubleLit(std::f64::INFINITY.into())), - [NaN(n)] => bx(Expr::DoubleLit(std::f64::NAN.into())), - [natural_literal(n)] => bx(Expr::NaturalLit(n)), - [integer_literal(n)] => bx(Expr::IntegerLit(n)), - [double_quote_literal(s)] => bx(Expr::TextLit(s)), - [single_quote_literal(s)] => bx(Expr::TextLit(s)), + rule!(primitive_expression<ParsedExpr> as expression; children!( + [double_literal(n)] => Expr::DoubleLit(n), + [natural_literal(n)] => Expr::NaturalLit(n), + [integer_literal(n)] => Expr::IntegerLit(n), + [double_quote_literal(s)] => Expr::TextLit(s), + [single_quote_literal(s)] => Expr::TextLit(s), [expression(e)] => e, )); @@ -760,116 +754,128 @@ make_parser! { [label(l), natural_literal(idx)] => { let name = String::from(&l); match Builtin::parse(name.as_str()) { - Some(b) => bx(Expr::Builtin(b)), - None => match name.as_str() { - "True" => bx(Expr::BoolLit(true)), - "False" => bx(Expr::BoolLit(false)), - "Type" => bx(Expr::Const(Const::Type)), - "Kind" => bx(Expr::Const(Const::Kind)), - _ => bx(Expr::Var(V(l, idx))), + Option::Some(b) => Expr::Builtin(b), + Option::None => match name.as_str() { + "True" => Expr::BoolLit(true), + "False" => Expr::BoolLit(false), + "Type" => Expr::Const(Const::Type), + "Kind" => Expr::Const(Const::Kind), + _ => Expr::Var(V(l, idx)), } } }, [label(l)] => { let name = String::from(&l); match Builtin::parse(name.as_str()) { - Some(b) => bx(Expr::Builtin(b)), - None => match name.as_str() { - "True" => bx(Expr::BoolLit(true)), - "False" => bx(Expr::BoolLit(false)), - "Type" => bx(Expr::Const(Const::Type)), - "Kind" => bx(Expr::Const(Const::Kind)), - _ => bx(Expr::Var(V(l, 0))), + Option::Some(b) => Expr::Builtin(b), + Option::None => match name.as_str() { + "True" => Expr::BoolLit(true), + "False" => Expr::BoolLit(false), + "Type" => Expr::Const(Const::Type), + "Kind" => Expr::Const(Const::Kind), + _ => Expr::Var(V(l, 0)), } } }, )); rule!(empty_record_literal<ParsedExpr> as expression; - captured_str!(_) => bx(Expr::RecordLit(BTreeMap::new())) + captured_str!(_) => Expr::RecordLit(BTreeMap::new()) ); rule!(empty_record_type<ParsedExpr> as expression; - captured_str!(_) => bx(Expr::RecordType(BTreeMap::new())) + captured_str!(_) => Expr::RecordType(BTreeMap::new()) ); rule!(non_empty_record_type_or_literal<ParsedExpr> as expression; children!( [label(first_label), non_empty_record_type(rest)] => { let (first_expr, mut map) = rest; - map.insert(first_label, first_expr); - bx(Expr::RecordType(map)) + map.insert(first_label, rc(first_expr)); + Expr::RecordType(map) }, [label(first_label), non_empty_record_literal(rest)] => { let (first_expr, mut map) = rest; - map.insert(first_label, first_expr); - bx(Expr::RecordLit(map)) + map.insert(first_label, rc(first_expr)); + Expr::RecordLit(map) }, )); rule!(non_empty_record_type - <(ParsedExpr, BTreeMap<Label, ParsedExpr>)>; children!( + <(ParsedExpr, BTreeMap<Label, ParsedSubExpr>)>; children!( [expression(expr), record_type_entry(entries)..] => { (expr, entries.collect()) } )); - rule!(record_type_entry<(Label, ParsedExpr)>; children!( - [label(name), expression(expr)] => (name, expr) + rule!(record_type_entry<(Label, ParsedSubExpr)>; children!( + [label(name), expression(expr)] => (name, rc(expr)) )); rule!(non_empty_record_literal - <(ParsedExpr, BTreeMap<Label, ParsedExpr>)>; children!( + <(ParsedExpr, BTreeMap<Label, ParsedSubExpr>)>; children!( [expression(expr), record_literal_entry(entries)..] => { (expr, entries.collect()) } )); - rule!(record_literal_entry<(Label, ParsedExpr)>; children!( - [label(name), expression(expr)] => (name, expr) + rule!(record_literal_entry<(Label, ParsedSubExpr)>; children!( + [label(name), expression(expr)] => (name, rc(expr)) )); rule!(union_type_or_literal<ParsedExpr> as expression; children!( [empty_union_type(_)] => { - bx(Expr::UnionType(BTreeMap::new())) + Expr::UnionType(BTreeMap::new()) }, - [non_empty_union_type_or_literal((Some((l, e)), entries))] => { - bx(Expr::UnionLit(l, e, entries)) + [non_empty_union_type_or_literal((Option::Some((l, e)), entries))] => { + Expr::UnionLit(l, e, entries) }, - [non_empty_union_type_or_literal((None, entries))] => { - bx(Expr::UnionType(entries)) + [non_empty_union_type_or_literal((Option::None, entries))] => { + Expr::UnionType(entries) }, )); - rule!(empty_union_type<()>; captured_str!(_) => ()); + token_rule!(empty_union_type<()>); rule!(non_empty_union_type_or_literal - <(Option<(Label, ParsedExpr)>, BTreeMap<Label, ParsedExpr>)>; + <(Option<(Label, ParsedSubExpr)>, BTreeMap<Label, ParsedSubExpr>)>; children!( - [label(l), expression(e), union_type_entries(entries)] => { - (Some((l, e)), entries) + [label(l), union_literal_variant_value((e, entries))] => { + (Option::Some((l, rc(e))), entries) }, - [label(l), expression(e), non_empty_union_type_or_literal(rest)] => { + [label(l), union_type_or_literal_variant_type((e, rest))] => { let (x, mut entries) = rest; - entries.insert(l, e); + entries.insert(l, rc(e)); (x, entries) }, - [label(l), expression(e)] => { - let mut entries = BTreeMap::new(); - entries.insert(l, e); - (None, entries) + )); + + rule!(union_literal_variant_value + <(ParsedExpr, BTreeMap<Label, ParsedSubExpr>)>; + children!( + [expression(e), union_type_entry(entries)..] => { + (e, entries.collect()) }, )); - rule!(union_type_entries<BTreeMap<Label, ParsedExpr>>; children!( - [union_type_entry(entries)..] => entries.collect() + rule!(union_type_entry<(Label, ParsedSubExpr)>; children!( + [label(name), expression(expr)] => (name, rc(expr)) )); - rule!(union_type_entry<(Label, ParsedExpr)>; children!( - [label(name), expression(expr)] => (name, expr) + // TODO: unary union variants + rule!(union_type_or_literal_variant_type + <(ParsedExpr, + (Option<(Label, ParsedSubExpr)>, BTreeMap<Label, ParsedSubExpr>))>; + children!( + [expression(e), non_empty_union_type_or_literal(rest)] => { + (e, rest) + }, + [expression(e)] => { + (e, (Option::None, BTreeMap::new())) + }, )); rule!(non_empty_list_literal<ParsedExpr> as expression; children!( - [expression(items)..] => bx(Expr::NEListLit(items.collect())) + [expression(items)..] => Expr::NEListLit(items.map(rc).collect()) )); rule!(final_expression<ParsedExpr> as expression; children!( @@ -877,15 +883,15 @@ make_parser! { )); } -pub fn parse_expr(s: &str) -> ParseResult<ParsedExpr> { +pub fn parse_expr(s: &str) -> ParseResult<ParsedSubExpr> { let mut pairs = DhallParser::parse(Rule::final_expression, s)?; let expr = do_parse(pairs.next().unwrap())?; assert_eq!(pairs.next(), None); match expr { - ParsedValue::expression(e) => Ok(e), + ParsedValue::expression(e) => Ok(rc(e)), _ => unreachable!(), } - // Ok(bx(Expr::BoolLit(false))) + // Ok(rc(Expr::BoolLit(false))) } #[test] |