diff options
author | Nadrieril | 2019-09-03 23:01:55 +0200 |
---|---|---|
committer | Nadrieril | 2019-09-06 11:42:37 +0200 |
commit | 2f6f21c52e60c560eb4c5fff9441b7d20c8c1d9a (patch) | |
tree | b8b4af2ddd052b2c37d7b34ef46588141305daf3 /dhall_syntax/src | |
parent | bcaeab3b7b114d8782be9589ad673ab9ab8c59fd (diff) |
Store Spans at every node when parsing
Diffstat (limited to 'dhall_syntax/src')
-rw-r--r-- | dhall_syntax/src/core/expr.rs | 18 | ||||
-rw-r--r-- | dhall_syntax/src/parser.rs | 50 |
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 )) } |