summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall_generated_parser/src/dhall.pest.visibility2
-rw-r--r--dhall_syntax/src/parser.rs200
-rw-r--r--tests_buffer1
3 files changed, 95 insertions, 108 deletions
diff --git a/dhall_generated_parser/src/dhall.pest.visibility b/dhall_generated_parser/src/dhall.pest.visibility
index 8235735..2ac7fe4 100644
--- a/dhall_generated_parser/src/dhall.pest.visibility
+++ b/dhall_generated_parser/src/dhall.pest.visibility
@@ -160,7 +160,7 @@ not_equal_expression
equivalent_expression
application_expression
first_application_expression
-# import_expression
+import_expression
selector_expression
selector
labels
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index d11eb18..2debc8b 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -174,12 +174,11 @@ macro_rules! make_parser {
);
(@rule_alias,
rule!(
- $name:ident<$o:ty>
- as $group:ident;
+ $name:ident<$o:ty>;
$($args:tt)*
)
) => ({
- Rule::$group
+ Rule::$name
});
(@rule_alias,
token_rule!($name:ident<$o:ty>)
@@ -190,8 +189,7 @@ macro_rules! make_parser {
(@body,
($climbers:expr, $input:expr, $pair:expr),
rule!(
- $name:ident<$o:ty>
- as $group:ident;
+ $name:ident<$o:ty>;
$span:ident;
captured_str!($x:pat) => $body:expr
)
@@ -199,15 +197,14 @@ macro_rules! make_parser {
let res: Result<_, String> = try {
let $span = Span::make($input, $pair.as_span());
let $x = $pair.as_str();
- ParsedValue::$group($body)
+ ParsedValue::$name($body)
};
res.map_err(|msg| custom_parse_error(&$pair, msg))
});
(@body,
($climbers:expr, $input:expr, $pair:expr),
rule!(
- $name:ident<$o:ty>
- as $group:ident;
+ $name:ident<$o:ty>;
$span:ident;
children!( $( [$($args:tt)*] => $body:expr ),* $(,)* )
)
@@ -257,27 +254,33 @@ macro_rules! make_parser {
};
let res = res.map_err(|msg| custom_parse_error(&$pair, msg))?;
- Ok(ParsedValue::$group(res))
+ Ok(ParsedValue::$name(res))
});
(@body,
($climbers:expr, $input:expr, $pair:expr),
rule!(
- $name:ident<$o:ty>
- as $group:ident;
- prec_climb!( $_climber:expr, $args:pat => $body:expr $(,)* )
+ $name:ident<$o:ty>;
+ prec_climb!($other_name:ident, $_climber:expr, $args:pat => $body:expr $(,)* )
)
) => ({
- let climber = $climbers.get(&Rule::$name).unwrap();
+ let climber = $climbers.get(&Rule::$name).expect(&format!("UUUU: {:?}", $climbers));
climber.climb(
$pair.clone().into_inner(),
- |p| parse_any($climbers, $input.clone(), p),
+ |p| {
+ let parsed = parse_any($climbers, $input.clone(), p)?;
+ if let ParsedValue::$other_name(x) = parsed {
+ Ok(ParsedValue::$name(x))
+ } else {
+ unreachable!()
+ }
+ },
|l, op, r| {
let (l, r) = (l?, r?);
let res: Result<_, String> = try {
#[allow(unused_imports)]
use ParsedValue::*;
match (l, op, r) {
- $args => ParsedValue::$group($body),
+ $args => ParsedValue::$name($body),
children => Err(
format!("Unexpected children: {:?}", children)
)?,
@@ -289,26 +292,13 @@ macro_rules! make_parser {
});
(@body,
($($things:tt)*),
- rule!( $name:ident<$o:ty>; $($args:tt)* )
- ) => (
- make_parser!(@body,
- ($($things)*),
- rule!( $name<$o> as $name; $($args)* )
- )
- );
- (@body,
- ($($things:tt)*),
- rule!(
- $name:ident<$o:ty>
- as $group:ident;
- $($args:tt)*
+ rule!( $name:ident<$o:ty>; $($args:tt)*
)
) => ({
make_parser!(@body,
($($things)*),
rule!(
- $name<$o>
- as $group;
+ $name<$o>;
_span;
$($args)*
)
@@ -324,9 +314,8 @@ macro_rules! make_parser {
(@construct_climber,
($map:expr),
rule!(
- $name:ident<$o:ty>
- as $group:ident;
- prec_climb!( $climber:expr, $($_rest:tt)* )
+ $name:ident<$o:ty>;
+ prec_climb!( $other_name:ident, $climber:expr, $($_rest:tt)* )
)
) => ({
$map.insert(Rule::$name, $climber)
@@ -379,27 +368,8 @@ macro_rules! make_parser {
fn parse_any<'a>(
climbers: &HashMap<Rule, PrecClimber<Rule>>,
input: Rc<str>,
- mut pair: Pair<'a, Rule>,
+ pair: Pair<'a, Rule>,
) -> ParseResult<ParsedValue<'a>> {
- // Avoid parsing while the pair has exactly one child that can be returned as-is
- loop {
- if can_be_shortcutted(pair.as_rule()) {
- let mut i = pair.clone().into_inner();
- let first = i.next();
- let second = i.next();
- match (first, second) {
- // If pair has exactly one child, just go on parsing that child
- (Some(p), None) => {
- pair = p;
- continue;
- }
- // Otherwise parse normally
- _ => break,
- }
- }
- break;
- }
-
match pair.as_rule() {
$(
Rule::$name => Parsers::$name(climbers, input, pair),
@@ -418,20 +388,6 @@ fn do_parse<'a>(
parse_any(&climbers, input, pair)
}
-// List of rules that can be shortcutted if they have a single child
-fn can_be_shortcutted(rule: Rule) -> bool {
- use Rule::*;
- match rule {
- expression
- | operator_expression
- | application_expression
- | first_application_expression
- | selector_expression
- | annotated_expression => true,
- _ => false,
- }
-}
-
// Trim the shared indent off of a vec of lines, as defined by the Dhall semantics of multiline
// literals.
fn trim_indent(lines: &mut Vec<ParsedText>) {
@@ -591,10 +547,10 @@ make_parser! {
rule!(single_quote_char<&'a str>;
captured_str!(s) => s
);
- rule!(escaped_quote_pair<&'a str> as single_quote_char;
+ rule!(escaped_quote_pair<&'a str>;
captured_str!(_) => "''"
);
- rule!(escaped_interpolation<&'a str> as single_quote_char;
+ rule!(escaped_interpolation<&'a str>;
captured_str!(_) => "${"
);
rule!(interpolation<ParsedSubExpr>; children!(
@@ -609,6 +565,20 @@ make_parser! {
lines.last_mut().unwrap().push(c);
lines
},
+ [escaped_quote_pair(c), single_quote_continue(lines)] => {
+ let mut lines = lines;
+ // TODO: don't allocate for every char
+ let c = InterpolatedTextContents::Text(c.to_owned());
+ lines.last_mut().unwrap().push(c);
+ lines
+ },
+ [escaped_interpolation(c), single_quote_continue(lines)] => {
+ let mut lines = lines;
+ // TODO: don't allocate for every char
+ let c = InterpolatedTextContents::Text(c.to_owned());
+ lines.last_mut().unwrap().push(c);
+ lines
+ },
[single_quote_char(c), single_quote_continue(lines)] => {
let mut lines = lines;
if c == "\n" || c == "\r\n" {
@@ -682,7 +652,7 @@ make_parser! {
}
);
- rule!(identifier<ParsedSubExpr> as expression; span; children!(
+ rule!(identifier<ParsedSubExpr>; span; children!(
[variable(v)] => {
spanned(span, Var(v))
},
@@ -715,19 +685,22 @@ make_parser! {
));
rule!(local<(FilePrefix, Vec<String>)>; children!(
- [local(l)] => l
+ [parent_path(l)] => l,
+ [here_path(l)] => l,
+ [home_path(l)] => l,
+ [absolute_path(l)] => l,
));
- rule!(parent_path<(FilePrefix, Vec<String>)> as local; children!(
+ rule!(parent_path<(FilePrefix, Vec<String>)>; children!(
[path(p)] => (FilePrefix::Parent, p)
));
- rule!(here_path<(FilePrefix, Vec<String>)> as local; children!(
+ rule!(here_path<(FilePrefix, Vec<String>)>; children!(
[path(p)] => (FilePrefix::Here, p)
));
- rule!(home_path<(FilePrefix, Vec<String>)> as local; children!(
+ rule!(home_path<(FilePrefix, Vec<String>)>; children!(
[path(p)] => (FilePrefix::Home, p)
));
- rule!(absolute_path<(FilePrefix, Vec<String>)> as local; children!(
+ rule!(absolute_path<(FilePrefix, Vec<String>)>; children!(
[path(p)] => (FilePrefix::Absolute, p)
));
@@ -760,7 +733,7 @@ make_parser! {
rule!(http<URL<ParsedSubExpr>>; children!(
[http_raw(url)] => url,
- [http_raw(url), expression(e)] =>
+ [http_raw(url), import_expression(e)] =>
URL { headers: Some(e), ..url },
));
@@ -828,7 +801,7 @@ make_parser! {
token_rule!(Text<()>);
token_rule!(Location<()>);
- rule!(import<ParsedSubExpr> as expression; span; children!(
+ rule!(import<ParsedSubExpr>; span; children!(
[import_hashed(imp)] => {
spanned(span, Import(crate::Import {
mode: ImportMode::Code,
@@ -857,13 +830,13 @@ make_parser! {
token_rule!(if_<()>);
token_rule!(in_<()>);
- rule!(empty_list_literal<ParsedSubExpr> as expression; span; children!(
- [expression(e)] => {
+ rule!(empty_list_literal<ParsedSubExpr>; span; children!(
+ [application_expression(e)] => {
spanned(span, EmptyListLit(e))
},
));
- rule!(expression<ParsedSubExpr> as expression; span; children!(
+ rule!(expression<ParsedSubExpr>; span; children!(
[lambda(()), label(l), expression(typ),
arrow(()), expression(body)] => {
spanned(span, Lam(l, typ, body))
@@ -881,16 +854,17 @@ make_parser! {
arrow(()), expression(body)] => {
spanned(span, Pi(l, typ, body))
},
- [expression(typ), arrow(()), expression(body)] => {
+ [operator_expression(typ), arrow(()), expression(body)] => {
spanned(span, Pi("_".into(), typ, body))
},
- [merge(()), expression(x), expression(y), expression(z)] => {
+ [merge(()), import_expression(x), import_expression(y), application_expression(z)] => {
spanned(span, Merge(x, y, Some(z)))
},
+ [empty_list_literal(e)] => e,
[assert(()), expression(x)] => {
spanned(span, Assert(x))
},
- [expression(e)] => e,
+ [annotated_expression(e)] => e,
));
rule!(let_binding<(Label, Option<ParsedSubExpr>, ParsedSubExpr)>;
@@ -904,14 +878,14 @@ make_parser! {
token_rule!(List<()>);
token_rule!(Optional<()>);
- rule!(annotated_expression<ParsedSubExpr> as expression; span; children!(
- [expression(e)] => e,
- [expression(e), expression(annot)] => {
+ rule!(annotated_expression<ParsedSubExpr>; span; children!(
+ [operator_expression(e)] => e,
+ [operator_expression(e), expression(annot)] => {
spanned(span, Annot(e, annot))
},
));
- rule!(operator_expression<ParsedSubExpr> as expression; prec_climb!(
+ rule!(operator_expression<ParsedSubExpr>; prec_climb!(application_expression,
{
use Rule::*;
// In order of precedence
@@ -937,7 +911,7 @@ make_parser! {
.collect(),
)
},
- (expression(l), op, expression(r)) => {
+ (operator_expression(l), op, operator_expression(r)) => {
use crate::BinOp::*;
use Rule::*;
let op = match op.as_rule() {
@@ -966,32 +940,38 @@ make_parser! {
token_rule!(Some_<()>);
token_rule!(toMap<()>);
- rule!(application_expression<ParsedSubExpr> as expression; children!(
- [expression(e)] => e,
- [expression(first), expression(rest)..] => {
+ rule!(application_expression<ParsedSubExpr>; children!(
+ [first_application_expression(e)] => e,
+ [first_application_expression(first), import_expression(rest)..] => {
rest.fold(first, |acc, e| unspanned(App(acc, e)))
},
));
- rule!(first_application_expression<ParsedSubExpr> as expression; span;
+ rule!(first_application_expression<ParsedSubExpr>; span;
children!(
- [expression(e)] => e,
- [Some_(()), expression(e)] => {
+ [Some_(()), import_expression(e)] => {
spanned(span, SomeLit(e))
},
- [merge(()), expression(x), expression(y)] => {
+ [merge(()), import_expression(x), import_expression(y)] => {
spanned(span, Merge(x, y, None))
},
+ [import_expression(e)] => e,
));
- rule!(selector_expression<ParsedSubExpr> as expression; children!(
- [expression(e)] => e,
- [expression(first), selector(rest)..] => {
+ rule!(import_expression<ParsedSubExpr>; span;
+ children!(
+ [selector_expression(e)] => e,
+ [import(e)] => e,
+ ));
+
+ rule!(selector_expression<ParsedSubExpr>; children!(
+ [primitive_expression(e)] => e,
+ [primitive_expression(first), selector(rest)..] => {
rest.fold(first, |acc, e| unspanned(match e {
Either::Left(l) => Field(acc, l),
Either::Right(ls) => Projection(acc, ls),
}))
- }
+ },
));
rule!(selector<Either<Label, DupTreeSet<Label>>>; children!(
@@ -1004,24 +984,30 @@ make_parser! {
[label(ls)..] => ls.collect(),
));
- rule!(primitive_expression<ParsedSubExpr> as expression; span; children!(
+ rule!(primitive_expression<ParsedSubExpr>; span; children!(
[double_literal(n)] => spanned(span, DoubleLit(n)),
[natural_literal(n)] => spanned(span, NaturalLit(n)),
[integer_literal(n)] => spanned(span, IntegerLit(n)),
[double_quote_literal(s)] => spanned(span, TextLit(s)),
[single_quote_literal(s)] => spanned(span, TextLit(s)),
+ [empty_record_type(e)] => e,
+ [empty_record_literal(e)] => e,
+ [non_empty_record_type_or_literal(e)] => e,
+ [union_type(e)] => e,
+ [non_empty_list_literal(e)] => e,
+ [identifier(e)] => e,
[expression(e)] => e,
));
- rule!(empty_record_literal<ParsedSubExpr> as expression; span;
+ rule!(empty_record_literal<ParsedSubExpr>; span;
captured_str!(_) => spanned(span, RecordLit(Default::default()))
);
- rule!(empty_record_type<ParsedSubExpr> as expression; span;
+ rule!(empty_record_type<ParsedSubExpr>; span;
captured_str!(_) => spanned(span, RecordType(Default::default()))
);
- rule!(non_empty_record_type_or_literal<ParsedSubExpr> as expression; span;
+ rule!(non_empty_record_type_or_literal<ParsedSubExpr>; span;
children!(
[label(first_label), non_empty_record_type(rest)] => {
let (first_expr, mut map) = rest;
@@ -1057,7 +1043,7 @@ make_parser! {
[label(name), expression(expr)] => (name, expr)
));
- rule!(union_type<ParsedSubExpr> as expression; span; children!(
+ rule!(union_type<ParsedSubExpr>; span; children!(
[empty_union_type(_)] => {
spanned(span, UnionType(Default::default()))
},
@@ -1073,7 +1059,7 @@ make_parser! {
[label(name)] => (name, None),
));
- rule!(non_empty_list_literal<ParsedSubExpr> as expression; span;
+ rule!(non_empty_list_literal<ParsedSubExpr>; span;
children!(
[expression(items)..] => spanned(
span,
@@ -1081,7 +1067,7 @@ make_parser! {
)
));
- rule!(final_expression<ParsedSubExpr> as expression; children!(
+ rule!(final_expression<ParsedSubExpr>; children!(
[expression(e), EOI(_eoi)] => e
));
}
@@ -1092,7 +1078,7 @@ pub fn parse_expr(s: &str) -> ParseResult<ParsedSubExpr> {
let expr = do_parse(rc_input, pairs.next().unwrap())?;
assert_eq!(pairs.next(), None);
match expr {
- ParsedValue::expression(e) => Ok(e),
+ ParsedValue::final_expression(e) => Ok(e),
_ => unreachable!(),
}
}
diff --git a/tests_buffer b/tests_buffer
index 1ad880e..67de9eb 100644
--- a/tests_buffer
+++ b/tests_buffer
@@ -9,6 +9,7 @@ success/
PrecedenceAll2 a b != c == d * e ⩓ f ⫽ g ∧ h && i # j ++ k + l || m ? n
LetNoAnnot let x = y in e
LetAnnot let x: T = y in e
+ EmptyRecordLiteral {=}
failure/
AssertNoAnnotation assert