From 2f6f21c52e60c560eb4c5fff9441b7d20c8c1d9a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 3 Sep 2019 23:01:55 +0200 Subject: Store Spans at every node when parsing --- dhall_syntax/src/core/expr.rs | 18 ++++++++++++---- dhall_syntax/src/parser.rs | 50 ++++++++++++++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 17 deletions(-) (limited to 'dhall_syntax') 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 Expr { pub fn as_mut(&mut self) -> &mut RawExpr { &mut self.0.as_mut().0 } + pub fn span(&self) -> Option<&Span> { + self.0.as_ref().1.as_ref() + } - pub fn new(x: RawExpr, n: Span) -> Self { + pub(crate) fn new(x: RawExpr, n: Span) -> Self { Expr(Box::new((x, Some(n)))) } @@ -387,9 +400,6 @@ pub fn rc(x: RawExpr) -> Expr { pub(crate) fn spanned(span: Span, x: RawExpr) -> Expr { Expr::new(x, span) } -pub(crate) fn unspanned(x: RawExpr) -> Expr { - 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( input: ParseInput, - ) -> ParseResult<(Label, Option>, Expr)> { + ) -> ParseResult<(Label, Option>, Expr, 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) -> 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, - ) -> ParseResult>> { + ) -> ParseResult<(Either>, 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 )) } -- cgit v1.2.3