diff options
Diffstat (limited to 'src/syntax/span.rs')
| -rw-r--r-- | src/syntax/span.rs | 178 |
1 files changed, 96 insertions, 82 deletions
diff --git a/src/syntax/span.rs b/src/syntax/span.rs index 9eb80d92..c8e2cddb 100644 --- a/src/syntax/span.rs +++ b/src/syntax/span.rs @@ -4,65 +4,63 @@ use std::fmt::{self, Debug, Formatter}; use std::ops::{Add, Sub}; use serde::Serialize; +/// A vector of spanned values of type `T`. +pub type SpanVec<T> = Vec<Spanned<T>>; -/// Zero-indexed line-column position in source code. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] -pub struct Position { - /// The zero-indexed line. - pub line: usize, - /// The zero-indexed column. - pub column: usize, +/// [Offset](Span::offset) all spans in a vector of spanned things by a start +/// position. +pub fn offset_spans<T>( + vec: SpanVec<T>, + start: Position, +) -> impl Iterator<Item=Spanned<T>> { + vec.into_iter().map(move |s| s.map_span(|span| span.offset(start))) } -impl Position { - /// The line 0, column 0 position. - pub const ZERO: Position = Position { line: 0, column: 0 }; +/// A value with the span it corresponds to in the source code. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] +pub struct Spanned<T> { + /// The value. + pub v: T, + /// The corresponding span. + pub span: Span, +} - /// Crete a new instance from line and column. - pub fn new(line: usize, column: usize) -> Position { - Position { line, column } +impl<T> Spanned<T> { + /// Create a new instance from a value and its span. + pub fn new(v: T, span: Span) -> Spanned<T> { + Spanned { v, span } } -} -impl Add for Position { - type Output = Position; + /// Create a new instance from a value with the zero span. + pub fn zero(v: T) -> Spanned<T> { + Spanned { v, span: Span::ZERO } + } - fn add(self, rhs: Position) -> Position { - if rhs.line == 0 { - Position { - line: self.line, - column: self.column + rhs.column - } - } else { - Position { - line: self.line + rhs.line, - column: rhs.column, - } - } + /// Access the value. + pub fn value(self) -> T { + self.v } -} -impl Sub for Position { - type Output = Position; + /// Map the value using a function while keeping the span. + pub fn map<V, F>(self, f: F) -> Spanned<V> where F: FnOnce(T) -> V { + Spanned { v: f(self.v), span: self.span } + } - fn sub(self, rhs: Position) -> Position { - if self.line == rhs.line { - Position { - line: 0, - column: self.column - rhs.column - } - } else { - Position { - line: self.line - rhs.line, - column: self.column, - } - } + /// Maps the span while keeping the value. + pub fn map_span<F>(mut self, f: F) -> Spanned<T> where F: FnOnce(Span) -> Span { + self.span = f(self.span); + self } } -impl Debug for Position { +impl<T: Debug> Debug for Spanned<T> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}:{}", self.line, self.column) + self.v.fmt(f)?; + if f.alternate() { + f.write_str(" ")?; + self.span.fmt(f)?; + } + Ok(()) } } @@ -97,6 +95,11 @@ impl Span { Span { start: pos, end: pos } } + /// Expand a span by merging it with another span. + pub fn expand(&mut self, other: Span) { + *self = Span::merge(*self, other) + } + /// Offset a span by a start position. /// /// This is, for example, used to translate error spans from function local @@ -111,56 +114,67 @@ impl Span { impl Debug for Span { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "({:?} -> {:?})", self.start, self.end) + write!(f, "<{:?}-{:?}>", self.start, self.end) } } -/// A value with the span it corresponds to in the source code. -#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] -pub struct Spanned<T> { - /// The value. - pub v: T, - /// The corresponding span. - pub span: Span, +/// Zero-indexed line-column position in source code. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] +pub struct Position { + /// The zero-indexed line. + pub line: usize, + /// The zero-indexed column. + pub column: usize, } -impl<T> Spanned<T> { - /// Create a new instance from a value and its span. - pub fn new(v: T, span: Span) -> Spanned<T> { - Spanned { v, span } - } +impl Position { + /// The line 0, column 0 position. + pub const ZERO: Position = Position { line: 0, column: 0 }; - /// Access the value. - pub fn value(self) -> T { - self.v + /// Create a new position from line and column. + pub fn new(line: usize, column: usize) -> Position { + Position { line, column } } +} - /// Map the value using a function while keeping the span. - pub fn map<V, F>(self, f: F) -> Spanned<V> where F: FnOnce(T) -> V { - Spanned { v: f(self.v), span: self.span } - } +impl Add for Position { + type Output = Position; - /// Maps the span while keeping the value. - pub fn map_span<F>(mut self, f: F) -> Spanned<T> where F: FnOnce(Span) -> Span { - self.span = f(self.span); - self + fn add(self, rhs: Position) -> Position { + if rhs.line == 0 { + Position { + line: self.line, + column: self.column + rhs.column + } + } else { + Position { + line: self.line + rhs.line, + column: rhs.column, + } + } } } -impl<T: Debug> Debug for Spanned<T> { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.v.fmt(f)?; - f.write_str(" ")?; - self.span.fmt(f) +impl Sub for Position { + type Output = Position; + + fn sub(self, rhs: Position) -> Position { + if self.line == rhs.line { + Position { + line: 0, + column: self.column - rhs.column + } + } else { + Position { + line: self.line - rhs.line, + column: self.column, + } + } } } -/// A vector of spanned things. -pub type SpanVec<T> = Vec<Spanned<T>>; - -/// [Offset](Span::offset) all spans in a vector of spanned things by a start -/// position. -pub fn offset_spans<T>(start: Position, vec: SpanVec<T>) -> impl Iterator<Item=Spanned<T>> { - vec.into_iter() - .map(move |s| s.map_span(|span| span.offset(start))) +impl Debug for Position { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}:{}", self.line, self.column) + } } |
