diff options
-rw-r--r-- | dhall/src/normalize.rs | 2 | ||||
-rw-r--r-- | dhall_core/src/core.rs | 19 | ||||
-rw-r--r-- | dhall_core/src/parser.rs | 340 | ||||
-rw-r--r-- | dhall_parser/build.rs | 7 | ||||
-rw-r--r-- | dhall_parser/src/dhall.abnf | 312 | ||||
-rw-r--r-- | dhall_parser/src/dhall.pest.visibility | 100 | ||||
-rwxr-xr-x | do.pl | 103 | ||||
-rw-r--r-- | iter_patterns/src/lib.rs | 14 |
8 files changed, 502 insertions, 395 deletions
diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs index a3a2318..d9bd08a 100644 --- a/dhall/src/normalize.rs +++ b/dhall/src/normalize.rs @@ -107,7 +107,7 @@ where break dhall_expr!( g (List a0) - (λ(a : a0) -> λ(as : List a1) -> [ a ] # as) + (λ(x : a0) -> λ(xs : List a1) -> [ x ] # xs) ([] : List a0) ); } 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] diff --git a/dhall_parser/build.rs b/dhall_parser/build.rs index 4e75181..615a55c 100644 --- a/dhall_parser/build.rs +++ b/dhall_parser/build.rs @@ -42,13 +42,6 @@ fn main() -> std::io::Result<()> { )?; writeln!( &mut file, - "keyword = _{{ - let_ | in_ | if_ | then - | else_ | Infinity | NaN - }}" - )?; - writeln!( - &mut file, "final_expression = ${{ SOI ~ complete_expression ~ EOI }}" )?; diff --git a/dhall_parser/src/dhall.abnf b/dhall_parser/src/dhall.abnf index 02edc84..847da02 100644 --- a/dhall_parser/src/dhall.abnf +++ b/dhall_parser/src/dhall.abnf @@ -100,10 +100,9 @@ ;
; For simplicity this supports Unix and Windows line-endings, which are the most
; common
-end-of-line-silent =
+end-of-line =
%x0A ; "\n"
/ %x0D.0A ; "\r\n"
-end-of-line = end-of-line-silent
tab = %x09 ; "\t"
@@ -113,7 +112,7 @@ block-comment-chunk = block-comment
/ %x20-10FFFF
/ tab
- / end-of-line-silent
+ / end-of-line
block-comment-continue = "-}" / block-comment-chunk block-comment-continue
@@ -121,18 +120,19 @@ not-end-of-line = %x20-10FFFF / tab ; NOTE: Slightly different from Haskell-style single-line comments because this
; does not require a space after the dashes
-line-comment = "--" *not-end-of-line end-of-line-silent
+line-comment = "--" *not-end-of-line end-of-line
whitespace-chunk =
" "
/ tab
- / end-of-line-silent
+ / end-of-line
/ line-comment
/ block-comment
-whitespace = *whitespace-chunk
+whsp = *whitespace-chunk
-nonempty-whitespace = 1*whitespace-chunk
+; nonempty whitespace
+whsp1 = 1*whitespace-chunk
; Uppercase or lowercase ASCII letter
ALPHA = %x41-5A / %x61-7A
@@ -142,19 +142,13 @@ DIGIT = %x30-39 ; 0-9 HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
-; A simple label cannot be one of the following reserved keywords:
-;
-; * if
-; * then
-; * else
-; * let
-; * in
-; * as
-; * using
-; * merge
-; * missing
-; * Infinity
-; * Some
+; A simple label cannot be one of the reserved keywords
+; listed in the `keyword` rule.
+; A PEG parser could use negative lookahead to
+; enforce this, e.g. as follows:
+; simple-label =
+; keyword 1*simple-label-next-char
+; / !keyword (simple-label-first-char *simple-label-next-char)
simple-label-first-char = ALPHA / "_"
simple-label-next-char = ALPHA / DIGIT / "-" / "/" / "_"
simple-label = simple-label-first-char *simple-label-next-char
@@ -170,11 +164,12 @@ quoted-label = 1*quoted-label-char ; for code obfuscation
label = ("`" quoted-label "`" / simple-label)
-; An unreserved-label cannot not be any of the reserved identifiers for builtins (unless quoted).
+; A nonreserved-label cannot not be any of the reserved identifiers for builtins (unless quoted).
; Their list can be found in semantics.md. This is not enforced by the grammar but
; should be checked by implementations. The only place where this restriction applies
; is bound variables.
-unreserved-label = label
+; A PEG parser could use negative lookahead to avoid parsing those identifiers.
+nonreserved-label = label
; An any-label is allowed to be one of the reserved identifiers.
any-label = label
@@ -216,8 +211,8 @@ any-label = label ; > "\uD834\uDD1E".
double-quote-chunk =
interpolation
- ; '\'
- / %x5C double-quote-escaped
+ ; '\' Beginning of escape sequence
+ / %x5C double-quote-escaped
/ double-quote-char
double-quote-escaped =
@@ -273,7 +268,6 @@ single-quote-char = single-quote-literal = "''" end-of-line single-quote-continue
-; Interpolation
interpolation = "${" complete-expression "}"
text-literal = (double-quote-literal / single-quote-literal)
@@ -281,25 +275,34 @@ text-literal = (double-quote-literal / single-quote-literal) ; RFC 5234 interprets string literals as case-insensitive and recommends using
; hex instead for case-sensitive strings
;
-; If you don't feel like reading hex, these are all the same as the rule name,
-; except without the '' ending.
+; If you don't feel like reading hex, these are all the same as the rule name.
; Keywords that should never be parsed as identifiers
-if = %x69.66
-then = %x74.68.65.6e
-else = %x65.6c.73.65
-let = %x6c.65.74
-in = %x69.6e
-as = %x61.73
-using = %x75.73.69.6e.67
-merge = %x6d.65.72.67.65
-missing = %x6d.69.73.73.69.6e.67
-Infinity = %x49.6e.66.69.6e.69.74.79
+if = %x69.66
+then = %x74.68.65.6e
+else = %x65.6c.73.65
+let = %x6c.65.74
+in = %x69.6e
+as = %x61.73
+using = %x75.73.69.6e.67
+merge = %x6d.65.72.67.65
+missing = %x6d.69.73.73.69.6e.67
+Infinity = %x49.6e.66.69.6e.69.74.79
+NaN = %x4e.61.4e
+Some = %x53.6f.6d.65
+
+; Unused rule that could be used as negative lookahead in the
+; `simple-label` rule for parsers that support this.
+keyword =
+ if / then / else
+ / let / in
+ / using / missing / as
+ / Infinity / NaN
+ / merge / Some
+
; Reserved identifiers, only needed for some special cases of parsing
Optional = %x4f.70.74.69.6f.6e.61.6c
Text = %x54.65.78.74
List = %x4c.69.73.74
-NaN = %x4e.61.4e
-Some = %x53.6f.6d.65
combine = %x2227 / "/\"
combine-types = %x2A53 / "//\\"
@@ -310,7 +313,20 @@ arrow = %x2192 / "->" exponent = "e" [ "+" / "-" ] 1*DIGIT
-double-literal = [ "+" / "-" ] 1*DIGIT ( "." 1*DIGIT [ exponent ] / exponent)
+numeric-double-literal = [ "+" / "-" ] 1*DIGIT ( "." 1*DIGIT [ exponent ] / exponent)
+
+minus-infinity-literal = "-" Infinity
+plus-infinity-literal = Infinity
+
+double-literal =
+ ; "2.0"
+ numeric-double-literal
+ ; "-Infinity"
+ / minus-infinity-literal
+ ; "Infinity"
+ / plus-infinity-literal
+ ; "NaN"
+ / NaN
natural-literal = 1*DIGIT
@@ -318,7 +334,7 @@ integer-literal = ( "+" / "-" ) natural-literal ; The implementation should recognize reserved names for builtins and treat them as special
; values instead of variables.
-identifier = any-label [ whitespace "@" whitespace natural-literal ]
+identifier = any-label [ whsp "@" whsp natural-literal ]
; Printable characters other than " ()[]{}<>/\,"
;
@@ -363,6 +379,8 @@ quoted-path-component = 1*quoted-path-character path-component = "/" ( unquoted-path-component / %x22 quoted-path-component %x22 )
+; The last path-component matched by this rule is referred to as "file" in the semantics,
+; and the other path-components as "directory".
path = 1*path-component
local =
@@ -445,7 +463,7 @@ sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" http =
http-raw
- [ whitespace using nonempty-whitespace (import-hashed / "(" whitespace import-hashed whitespace ")") ]
+ [ whsp using whsp1 (import-hashed / "(" whsp import-hashed whsp ")") ]
; Dhall supports unquoted environment variables that are Bash-compliant or
; quoted environment variables that are POSIX-compliant
@@ -513,117 +531,106 @@ posix-environment-variable-character = import-type = missing / local / http / env
-hash = %x73.68.61.32.35.36.3a 64HEXDIG ; "sha256:XXX...XXX"
+hash = %x73.68.61.32.35.36.3a 64HEXDIG ; "sha256:XXX...XXX"
-import-hashed = import-type [ whitespace hash ]
+import-hashed = import-type [ whsp hash ]
; "http://example.com"
; "./foo/bar"
; "env:FOO"
-import = import-hashed [ whitespace as nonempty-whitespace Text ]
-
-; NOTE: Every rule past this point should only reference rules that end with
-; whitespace. This ensures consistent handling of whitespace in the absence of
-; a separate lexing step.
-; The exception is the rules ending in , which should _not_ end in whitespace.
-; This is important to avoid the need for sequential backtracking in application-expression.
+import = import-hashed [ whsp as whsp1 Text ]
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 whitespace "(" whitespace unreserved-label whitespace ":" nonempty-whitespace expression ")" whitespace arrow whitespace expression
-
-; "if a then b else c"
-ifthenelse-expression = if nonempty-whitespace expression then nonempty-whitespace expression else nonempty-whitespace 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 nonempty-whitespace expression
-let-binding = let nonempty-whitespace unreserved-label whitespace [ ":" nonempty-whitespace expression ] "=" whitespace expression
-
-; "forall (x : a) -> b"
-forall-expression = forall whitespace "(" whitespace unreserved-label whitespace ":" nonempty-whitespace expression ")" whitespace arrow whitespace expression
+; Nonempty-whitespace to disambiguate `env:VARIABLE` from type annotations
+annotated-expression = operator-expression [ whsp ":" whsp1 expression ]
-; "a -> b"
-arrow-expression = operator-expression arrow whitespace expression
+; "let x = e1"
+let-binding = let whsp1 nonreserved-label whsp [ ":" whsp1 expression whsp ] "=" whsp expression whsp
-; "merge e1 e2 : t"
-; "merge e1 e2"
-merge-expression = merge nonempty-whitespace import-expression whitespace import-expression whitespace [ ":" nonempty-whitespace application-expression ]
-
-; "[] : List t"
-; "[] : Optional t"
-; "[x] : Optional t"
-empty-list-or-optional = "[" whitespace (empty-collection / non-empty-optional)
-empty-collection = "]" whitespace ":" nonempty-whitespace (List whitespace / Optional whitespace) import-expression whitespace
-non-empty-optional = expression "]" whitespace ":" nonempty-whitespace Optional whitespace import-expression whitespace
-
-; "x : t"
-annotated-expression = operator-expression [ ":" nonempty-whitespace expression ]
+; "] : List t"
+; "] : Optional t"
+empty-collection = "]" whsp ":" whsp1 (List / Optional) whsp import-expression
+; "x] : Optional t"
+non-empty-optional = expression whsp "]" whsp ":" whsp1 Optional whsp import-expression
operator-expression = import-alt-expression
-import-alt-expression = or-expression *("?" nonempty-whitespace or-expression)
-or-expression = plus-expression *("||" whitespace plus-expression )
-plus-expression = text-append-expression *("+" nonempty-whitespace text-append-expression )
-text-append-expression = list-append-expression *("++" whitespace list-append-expression )
-list-append-expression = and-expression *("#" whitespace and-expression )
-and-expression = combine-expression *("&&" whitespace combine-expression )
-combine-expression = prefer-expression *(combine whitespace prefer-expression )
-prefer-expression = combine-types-expression *(prefer whitespace combine-types-expression)
-combine-types-expression = times-expression *(combine-types whitespace times-expression )
-times-expression = equal-expression *("*" whitespace equal-expression )
-equal-expression = not-equal-expression *("==" whitespace not-equal-expression )
-not-equal-expression = application-expression *("!=" whitespace application-expression )
+; Nonempty-whitespace to disambiguate `http://a/a?a`
+import-alt-expression = or-expression *(whsp "?" whsp1 or-expression)
+or-expression = plus-expression *(whsp "||" whsp plus-expression)
+; Nonempty-whitespace to disambiguate `f +2`
+plus-expression = text-append-expression *(whsp "+" whsp1 text-append-expression)
+text-append-expression = list-append-expression *(whsp "++" whsp list-append-expression)
+list-append-expression = and-expression *(whsp "#" whsp and-expression)
+and-expression = combine-expression *(whsp "&&" whsp combine-expression)
+combine-expression = prefer-expression *(whsp combine whsp prefer-expression)
+prefer-expression = combine-types-expression *(whsp prefer whsp combine-types-expression)
+combine-types-expression = times-expression *(whsp combine-types whsp times-expression)
+times-expression = equal-expression *(whsp "*" whsp equal-expression)
+equal-expression = not-equal-expression *(whsp "==" whsp not-equal-expression)
+not-equal-expression = application-expression *(whsp "!=" whsp application-expression)
; Import expressions need to be separated by some whitespace, otherwise there
; would be ambiguity: `./ab` could be interpreted as "import the file `./ab`",
; or "apply the import `./a` to label `b`"
application-expression =
- import-expression *(nonempty-whitespace import-expression) whitespace
+ [ Some whsp1 ] import-expression *(whsp1 import-expression)
-import-expression =
- import
- / selector-expression
+import-expression = import / selector-expression
; `record.field` extracts one field of a record
+;
; `record.{ field0, field1, field2 }` projects out several fields of a record
;
-; NOTE: Backtrack when parsing the `*(dot ...)`. The reason why is that you
+; NOTE: Backtrack when parsing the `*("." ...)`. The reason why is that you
; can't tell from parsing just the period whether "foo." will become "foo.bar"
; (i.e. accessing field `bar` of the record `foo`) or `foo./bar` (i.e. applying
; the function `foo` to the relative path `./bar`)
-selector-expression = primitive-expression *(whitespace "." whitespace selector)
+selector-expression = primitive-expression *(whsp "." whsp selector)
selector = any-label / labels
-labels = "{" whitespace [ any-label whitespace *("," whitespace any-label whitespace) ] "}"
-
-
-primitive-expression =
- literal-expression
- / "{" whitespace record-type-or-literal "}"
- / "<" whitespace union-type-or-literal ">"
- / non-empty-list-literal
- / parenthesized-expression
+labels = "{" whsp [ any-label whsp *("," whsp any-label whsp) ] "}"
; NOTE: Backtrack when parsing the first three alternatives (i.e. the numeric
; literals). This is because they share leading characters in common
-literal-expression =
+primitive-expression =
; "2.0"
double-literal
@@ -633,60 +640,65 @@ literal-expression = ; "+2"
/ integer-literal
- ; "-Infinity"
- / minus-infinity-literal
- ; "Infinity"
- / plus-infinity-literal
- ; "NaN"
- / NaN
-
; '"ABC"'
/ text-literal
+ ; "{ foo = 1 , bar = True }"
+ ; "{ foo : Integer, bar : Bool }"
+ / "{" whsp record-type-or-literal whsp "}"
+
+ ; "< Foo : Integer | Bar : Bool >"
+ ; "< Foo : Integer | Bar = True | Baz : Bool >"
+ ; "< Foo | Bar : Bool >"
+ / "<" whsp union-type-or-literal whsp ">"
+
+ ; "[1, 2, 3]"
+ ; `empty-collection` handles empty lists
+ / non-empty-list-literal
+
; "x"
; "x@2"
/ identifier
+
+ ; "( e )"
+ / "(" complete-expression ")"
-minus-infinity-literal = "-" Infinity
-plus-infinity-literal = Infinity
-
-; "{ foo = 1 , bar = True }"
-; "{ foo : Integer, bar : Bool }"
record-type-or-literal =
empty-record-literal
/ non-empty-record-type-or-literal
/ empty-record-type
-empty-record-literal = "=" whitespace
+
+empty-record-literal = "="
empty-record-type = ""
+
non-empty-record-type-or-literal =
- any-label whitespace (non-empty-record-literal / non-empty-record-type)
-non-empty-record-type = ":" nonempty-whitespace expression *("," whitespace record-type-entry)
-record-type-entry = any-label whitespace ":" nonempty-whitespace expression
-non-empty-record-literal = "=" whitespace expression *("," whitespace record-literal-entry)
-record-literal-entry = any-label whitespace "=" whitespace expression
-
-; "< Foo : Integer | Bar : Bool >"
-; "< Foo : Integer | Bar = True >"
+ any-label whsp (non-empty-record-literal / non-empty-record-type)
+
+non-empty-record-type = ":" whsp1 expression *(whsp "," whsp record-type-entry)
+record-type-entry = any-label whsp ":" whsp1 expression
+
+non-empty-record-literal = "=" whsp expression *(whsp "," whsp record-literal-entry)
+record-literal-entry = any-label whsp "=" whsp expression
+
union-type-or-literal =
non-empty-union-type-or-literal
/ empty-union-type
+
empty-union-type = ""
+
non-empty-union-type-or-literal =
- any-label whitespace
- ( "=" whitespace expression union-type-entries
- / ":" nonempty-whitespace expression [ "|" whitespace non-empty-union-type-or-literal ]
- )
-union-type-entries = *("|" whitespace union-type-entry)
-union-type-entry = any-label whitespace ":" nonempty-whitespace expression
+ any-label [ whsp ( union-literal-variant-value / union-type-or-literal-variant-type) ]
+
+; = True | ...
+union-literal-variant-value = "=" whsp expression *(whsp "|" whsp union-type-entry)
+union-type-entry = any-label whsp ":" whsp1 expression
-; "[1, 2, 3]"
-; `empty-list-or-optional` handles empty lists
-non-empty-list-literal = "[" whitespace expression *("," whitespace expression) "]"
+; : Integer | ...
+; | ...
+union-type-or-literal-variant-type = [ ":" whsp1 expression ] [ whsp "|" whsp non-empty-union-type-or-literal ]
-; "( e )"
-parenthesized-expression = "(" whitespace expression ")"
+non-empty-list-literal = "[" whsp expression whsp *("," whsp expression whsp) "]"
-; All expressions end with trailing whitespace. This just adds a final
-; whitespace prefix for the top-level of the program
-complete-expression = whitespace expression
+; This just adds surrounding whitespace for the top-level of the program
+complete-expression = whsp expression whsp
diff --git a/dhall_parser/src/dhall.pest.visibility b/dhall_parser/src/dhall.pest.visibility index ee5ea2b..f881a50 100644 --- a/dhall_parser/src/dhall.pest.visibility +++ b/dhall_parser/src/dhall.pest.visibility @@ -1,5 +1,4 @@ -end_of_line -# end_of_line_silent +# end_of_line # tab # block_comment # block_comment_chunk @@ -7,91 +6,71 @@ end_of_line # not_end_of_line # line_comment # whitespace_chunk -# whitespace -# whitespace_ -# nonempty_whitespace +# whsp +# whsp1 # ALPHA # DIGIT # HEXDIG # simple_label_first_char -# simple_label_next_other_char # simple_label_next_char -# simple_label_start simple_label # quoted_label_char quoted_label label +nonreserved_label # any_label double_quote_chunk double_quote_escaped +double_quote_char double_quote_literal single_quote_continue +escaped_quote_pair +escaped_interpolation +single_quote_char single_quote_literal +interpolation # text_literal -# if -# then -# else -# let -# in -# as -# using -# merge -missing -# if_ +if_ # then # else_ # let_ -# in_ +in_ # as_ # using -# merge +merge +missing # Infinity +NaN +Some +# keyword Optional Text List -# equal -# or -# plus -# text_append -# list_append -# and -# times -# double_equal -# not_equal -# dot -# bar -# comma -# at -# colon -# import_alt -# open_parens -# close_parens -# close_parens -# open_brace -# close_brace -# close_brace -# open_bracket -# close_bracket -# close_bracket -# open_angle -# close_angle -# close_angle # combine # combine_types # prefer -# lambda -# forall -# arrow +lambda +forall +arrow # exponent +numeric_double_literal +minus_infinity_literal +plus_infinity_literal double_literal natural_literal integer_literal identifier # path_character # quoted_path_character +unquoted_path_component +quoted_path_component path_component path # local +parent_path +here_path +home_path +absolute_path scheme http_raw authority @@ -108,7 +87,6 @@ authority # reg_name # pchar query -fragment # pct_encoded # unreserved # sub_delims @@ -121,17 +99,11 @@ import_type hash import_hashed import -# expression -lambda_expression -ifthenelse_expression -let_expression -forall_expression -arrow_expression -merge_expression -# empty_list_or_optional +expression +annotated_expression +let_binding empty_collection non_empty_optional -annotated_expression # operator_expression import_alt_expression or_expression @@ -146,22 +118,24 @@ times_expression equal_expression not_equal_expression application_expression -# atomic_expression # import_expression selector_expression selector labels -# primitive_expression -literal_expression +primitive_expression # record_type_or_literal empty_record_literal empty_record_type non_empty_record_type_or_literal non_empty_record_type +record_type_entry non_empty_record_literal +record_literal_entry union_type_or_literal empty_union_type non_empty_union_type_or_literal +union_literal_variant_value +union_type_entry +union_type_or_literal_variant_type non_empty_list_literal -# parenthesized_expression # complete_expression @@ -0,0 +1,103 @@ +#!/usr/bin/env -S perl -i -p +# next if /^ *;/; s/\b(?<!-)if\b(?!-)/if-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)then\b(?!-)/then-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)else\b(?!-)/else-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)let\b(?!-)/let-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)in\b(?!-)/in-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)as\b(?!-)/as-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)using\b(?!-)/using-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)merge\b(?!-)/merge-raw whsp1/g; +# next if /^ *;/; s/\b(?<!-)Some\b(?!-)/Some-raw whsp1/g; + +# next if /^ *;/; s/\b(?<!-)Optional\b(?!-)/Optional whsp/g; +# next if /^ *;/; s/\b(?<!-)Text\b(?!-)/Text whsp/g; +# next if /^ *;/; s/\b(?<!-)List\b(?!-)/List whsp/g; + +# next if /^ *;/; s/\b(?<!-)or\b(?!-)/"||" whsp/g; +# next if /^ *;/; s/\b(?<!-)plus\b(?!-)/"+" whsp1/g; +# next if /^ *;/; s/\b(?<!-)text-append\b(?!-)/"++" whsp/g; +# next if /^ *;/; s/\b(?<!-)list-append\b(?!-)/"#" whsp/g; +# next if /^ *;/; s/\b(?<!-)and\b(?!-)/"&&" whsp/g; +# next if /^ *;/; s/\b(?<!-)times\b(?!-)/"*" whsp/g; +# next if /^ *;/; s/\b(?<!-)double-equal\b(?!-)/"==" whsp/g; +# next if /^ *;/; s/\b(?<!-)not-equal\b(?!-)/"!=" whsp/g; +# next if /^ *;/; s/\b(?<!-)equal\b(?!-)/"=" whsp/g; +# next if /^ *;/; s/\b(?<!-)dot\b(?!-)/"." whsp/g; +# next if /^ *;/; s/\b(?<!-)bar\b(?!-)/"|" whsp/g; +# next if /^ *;/; s/\b(?<!-)comma\b(?!-)/"," whsp/g; +# next if /^ *;/; s/\b(?<!-)at\b(?!-)/"@" whsp/g; +# next if /^ *;/; s/\b(?<!-)open-parens\b(?!-)/"(" whsp/g; +# next if /^ *;/; s/\b(?<!-)close-parens\b(?!-)/")" whsp/g; +# next if /^ *;/; s/\b(?<!-)open-brace\b(?!-)/"{" whsp/g; +# next if /^ *;/; s/\b(?<!-)close-brace\b(?!-)/"}" whsp/g; +# next if /^ *;/; s/\b(?<!-)open-bracket\b(?!-)/"[" whsp/g; +# next if /^ *;/; s/\b(?<!-)close-bracket\b(?!-)/"]" whsp/g; +# next if /^ *;/; s/\b(?<!-)open-angle\b(?!-)/"<" whsp/g; +# next if /^ *;/; s/\b(?<!-)close-angle\b(?!-)/">" whsp/g; +# next if /^ *;/; s/\b(?<!-)colon\b(?!-)/":" whsp1/g; +# next if /^ *;/; s/\b(?<!-)import-alt\b(?!-)/"?" whsp1/g; + +# next if /^ *;/; s/\b(?<!-)combine-types\b(?!-)/combine-types whsp/g; +# next if /^ *;/; s/\b(?<!-)combine\b(?!-)/combine whsp/g; +# next if /^ *;/; s/\b(?<!-)prefer\b(?!-)/prefer whsp/g; +# next if /^ *;/; s/\b(?<!-)lambda\b(?!-)/lambda whsp/g; +# next if /^ *;/; s/\b(?<!-)forall\b(?!-)/forall whsp/g; +# next if /^ *;/; s/\b(?<!-)arrow\b(?!-)/arrow whsp/g; + +# next if /^ *;/; s/\b(?<!-)label\b(?!-)/label whsp/g; +# next if /^ *;/; s/\b(?<!-)identifier\b(?!-)/identifier whsp/g; +# next if /^ *;/; s/\b(?<!-)text-literal\b(?!-)/text-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)double-literal\b(?!-)/double-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)integer-literal\b(?!-)/integer-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)natural-literal\b(?!-)/natural-literal whsp/g; + +# next if /^ *;/; s/\b(?<!-)import-hashed\b(?!-)/import-hashed whsp/g; +# next if /^ *;/; s/\b(?<!-)import-type\b(?!-)/import-type whsp/g; +# next if /^ *;/; s/\b(?<!-)import\b(?!-)/import whsp/g; +# next if /^ *;/; s/\b(?<!-)local\b(?!-)/local whsp/g; +# next if /^ *;/; s/\b(?<!-)env\b(?!-)/env whsp/g; +# next if /^ *;/; s/\b(?<!-)http\b(?!-)/http whsp/g; +# next if /^ *;/; s/\b(?<!-)missing\b(?!-)/missing whsp/g; + +# next if /^ *;/; s/\b(?<!-)labels\b(?!-)/labels whsp/g; +# next if /^ *;/; s/\b(?<!-)record-type-or-literal\b(?!-)/record-type-or-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)non-empty-record-type-or-literal\b(?!-)/non-empty-record-type-or-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)non-empty-record-type\b(?!-)/non-empty-record-type whsp/g; +# next if /^ *;/; s/\b(?<!-)non-empty-record-literal\b(?!-)/non-empty-record-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)union-type-or-literal\b(?!-)/union-type-or-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)non-empty-union-type-or-literal\b(?!-)/non-empty-union-type-or-literal whsp/g; +# next if /^ *;/; s/\b(?<!-)non-empty-list-literal\b(?!-)/non-empty-list-literal whsp/g; +# +# next if /^ *;/; s/\b(?<!-)expression\b(?!-)/expression whsp/g; +# next if /^ *;/; s/\b(?<!-)lambda-expression\b(?!-)/lambda-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)ifthenelse-expression\b(?!-)/ifthenelse-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)let-expression\b(?!-)/let-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)forall-expression\b(?!-)/forall-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)arrow-expression\b(?!-)/arrow-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)merge-expression\b(?!-)/merge-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)annotated-expression\b(?!-)/annotated-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)empty-list-or-optional\b(?!-)/empty-list-or-optional whsp/g; +# next if /^ *;/; s/\b(?<!-)empty-collection\b(?!-)/empty-collection whsp/g; +# next if /^ *;/; s/\b(?<!-)non-empty-optional\b(?!-)/non-empty-optional whsp/g; +# next if /^ *;/; s/\b(?<!-)operator-expression\b(?!-)/operator-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)import-alt-expression\b(?!-)/import-alt-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)or-expression\b(?!-)/or-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)plus-expression\b(?!-)/plus-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)text-append-expression\b(?!-)/text-append-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)list-append-expression\b(?!-)/list-append-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)and-expression\b(?!-)/and-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)combine-expression\b(?!-)/combine-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)prefer-expression\b(?!-)/prefer-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)combine-types-expression\b(?!-)/combine-types-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)times-expression\b(?!-)/times-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)equal-expression\b(?!-)/equal-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)not-equal-expression\b(?!-)/not-equal-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)application-expression\b(?!-)/application-expression whsp/g; +# +# next if /^ *;/; s/\b(?<!-)import-expression\b(?!-)/import-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)selector-expression\b(?!-)/selector-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)primitive-expression\b(?!-)/primitive-expression whsp/g; +# next if /^ *;/; s/\b(?<!-)complete-expression\b(?!-)/complete-expression whsp/g; + +# next if /^ *;/; s/\b(?<!-)whitespace\b(?!-)/whsp/g; +# next if /^ *;/; s/\b(?<!-)nonempty-whitespace\b(?!-)/whsp1/g; diff --git a/iter_patterns/src/lib.rs b/iter_patterns/src/lib.rs index a4be783..6d3649e 100644 --- a/iter_patterns/src/lib.rs +++ b/iter_patterns/src/lib.rs @@ -60,23 +60,23 @@ macro_rules! destructure_iter { }; // Single item pattern (@match_forwards, $iter:expr, ($body:expr), $x:pat, $($rest:tt)*) => { - if let Some($x) = $iter.next() { + if let std::option::Option::Some($x) = $iter.next() { $crate::destructure_iter!(@match_forwards, $iter, ($body), $($rest)* ) } else { - None + std::option::Option::None } }; // Single item pattern after a variable length one: declare reversed and take from the end (@match_backwards, $iter:expr, ($body:expr), $x:pat, $($rest:tt)*) => { $crate::destructure_iter!(@match_backwards, $iter, ( - if let Some($x) = $iter.next_back() { + if let std::option::Option::Some($x) = $iter.next_back() { $body } else { - None + std::option::Option::None } ), $($rest)*) }; @@ -84,7 +84,7 @@ macro_rules! destructure_iter { // Check no elements remain (@match_forwards, $iter:expr, ($body:expr) $(,)*) => { if $iter.next().is_some() { - None + std::option::Option::None } else { $body } @@ -100,7 +100,7 @@ macro_rules! destructure_iter { let mut iter = $iter; $crate::destructure_iter!(@match_forwards, iter, - (Some($body)), + (std::option::Option::Some($body)), $($args)*, ) } @@ -216,7 +216,7 @@ macro_rules! match_vec { $crate::destructure_iter!(iter; [$($args)*] => $body) } )* - _ => None, + _ => std::option::Option::None, } } }; |