summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2019-09-03 23:01:55 +0200
committerNadrieril2019-09-06 11:42:37 +0200
commit2f6f21c52e60c560eb4c5fff9441b7d20c8c1d9a (patch)
treeb8b4af2ddd052b2c37d7b34ef46588141305daf3
parentbcaeab3b7b114d8782be9589ad673ab9ab8c59fd (diff)
Store Spans at every node when parsing
-rw-r--r--dhall_syntax/src/core/expr.rs18
-rw-r--r--dhall_syntax/src/parser.rs50
2 files changed, 51 insertions, 17 deletions
diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs
index 2cb23c9..455e42a 100644
--- a/dhall_syntax/src/core/expr.rs
+++ b/dhall_syntax/src/core/expr.rs
@@ -37,6 +37,16 @@ impl Span {
end: sp.end(),
}
}
+ /// Takes the union of the two spans. Assumes that the spans come from the same input.
+ /// This will also capture any input between the spans.
+ pub fn union(&self, other: &Span) -> Self {
+ use std::cmp::{max, min};
+ Span {
+ input: self.input.clone(),
+ start: min(self.start, other.start),
+ end: max(self.start, other.start),
+ }
+ }
}
/// Double with bitwise equality
@@ -324,8 +334,11 @@ impl<E> Expr<E> {
pub fn as_mut(&mut self) -> &mut RawExpr<E> {
&mut self.0.as_mut().0
}
+ pub fn span(&self) -> Option<&Span> {
+ self.0.as_ref().1.as_ref()
+ }
- pub fn new(x: RawExpr<E>, n: Span) -> Self {
+ pub(crate) fn new(x: RawExpr<E>, n: Span) -> Self {
Expr(Box::new((x, Some(n))))
}
@@ -387,9 +400,6 @@ pub fn rc<E>(x: RawExpr<E>) -> Expr<E> {
pub(crate) fn spanned<E>(span: Span, x: RawExpr<E>) -> Expr<E> {
Expr::new(x, span)
}
-pub(crate) fn unspanned<E>(x: RawExpr<E>) -> Expr<E> {
- Expr::from_expr_no_span(x)
-}
/// Add an isize to an usize
/// Panics on over/underflow
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index 3f961e8..4cce5ed 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -783,7 +783,12 @@ impl Parsers {
[let_binding(bindings).., expression(final_expr)] => {
bindings.rev().fold(
final_expr,
- |acc, x| unspanned(Let(x.0, x.1, x.2, acc))
+ |acc, x| {
+ spanned(
+ acc.span().unwrap().union(&x.3),
+ Let(x.0, x.1, x.2, acc)
+ )
+ }
)
},
[forall(()), label(l), expression(typ),
@@ -811,12 +816,12 @@ impl Parsers {
fn let_binding<E: Clone>(
input: ParseInput<Rule>,
- ) -> ParseResult<(Label, Option<Expr<E>>, Expr<E>)> {
+ ) -> ParseResult<(Label, Option<Expr<E>>, Expr<E>, Span)> {
Ok(parse_children!(input;
[label(name), expression(annot), expression(expr)] =>
- (name, Some(annot), expr),
+ (name, Some(annot), expr, input.as_span()),
[label(name), expression(expr)] =>
- (name, None, expr),
+ (name, None, expr, input.as_span()),
))
}
@@ -847,7 +852,10 @@ impl Parsers {
r => Err(input.error(format!("Rule {:?} isn't an operator", r)))?,
};
- Ok(unspanned(BinOp(op, l, r)))
+ Ok(spanned(
+ l.span().unwrap().union(r.span().unwrap()),
+ BinOp(op, l, r),
+ ))
}
fn Some_(_input: ParseInput<Rule>) -> ParseResult<()> {
@@ -861,7 +869,15 @@ impl Parsers {
Ok(parse_children!(input;
[expression(e)] => e,
[expression(first), expression(rest)..] => {
- rest.fold(first, |acc, e| unspanned(App(acc, e)))
+ rest.fold(
+ first,
+ |acc, e| {
+ spanned(
+ acc.span().unwrap().union(e.span().unwrap()),
+ App(acc, e)
+ )
+ }
+ )
},
))
}
@@ -892,20 +908,28 @@ impl Parsers {
Ok(parse_children!(input;
[expression(e)] => e,
[expression(first), selector(rest)..] => {
- rest.fold(first, |acc, e| unspanned(match e {
- Either::Left(l) => Field(acc, l),
- Either::Right(ls) => Projection(acc, ls),
- }))
+ rest.fold(
+ first,
+ |acc, e| {
+ spanned(
+ acc.span().unwrap().union(&e.1),
+ match e.0 {
+ Either::Left(l) => Field(acc, l),
+ Either::Right(ls) => Projection(acc, ls),
+ }
+ )
+ }
+ )
},
))
}
fn selector(
input: ParseInput<Rule>,
- ) -> ParseResult<Either<Label, DupTreeSet<Label>>> {
+ ) -> ParseResult<(Either<Label, DupTreeSet<Label>>, Span)> {
Ok(parse_children!(input;
- [label(l)] => Either::Left(l),
- [labels(ls)] => Either::Right(ls),
+ [label(l)] => (Either::Left(l), input.as_span()),
+ [labels(ls)] => (Either::Right(ls), input.as_span()),
// [expression(_e)] => unimplemented!("selection by expression"), // TODO
))
}