summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-08-13 12:21:14 +0200
committerLaurenz <laurmaedje@gmail.com>2021-08-13 14:33:58 +0200
commit144f20882136ef81b79d77bd8a68f42b76c66676 (patch)
tree7a452ab2a092f674d93cd994d80b88cc6808e540 /src/syntax
parentd002cdf451e1c6efbf7cd7f2303264526b6f8a92 (diff)
Add file information to spans
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/span.rs104
1 files changed, 70 insertions, 34 deletions
diff --git a/src/syntax/span.rs b/src/syntax/span.rs
index 800cca19..cad9c5d5 100644
--- a/src/syntax/span.rs
+++ b/src/syntax/span.rs
@@ -3,8 +3,10 @@ use std::ops::{Add, Range};
use serde::{Deserialize, Serialize};
+use crate::source::SourceId;
+
/// A value with the span it corresponds to in the source code.
-#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[derive(Serialize, Deserialize)]
pub struct Spanned<T> {
/// The spanned value.
@@ -19,11 +21,6 @@ impl<T> Spanned<T> {
Self { v, span: span.into() }
}
- /// Create a new instance from a value with the zero span.
- pub fn zero(v: T) -> Self {
- Self { v, span: Span::ZERO }
- }
-
/// Convert from `&Spanned<T>` to `Spanned<&T>`
pub fn as_ref(&self) -> Spanned<&T> {
Spanned { v: &self.v, span: self.span }
@@ -51,9 +48,11 @@ impl<T: Debug> Debug for Spanned<T> {
}
/// Bounds of a slice of source code.
-#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[derive(Serialize, Deserialize)]
pub struct Span {
+ /// The id of the source file.
+ pub source: SourceId,
/// The inclusive start position.
pub start: Pos,
/// The inclusive end position.
@@ -61,22 +60,46 @@ pub struct Span {
}
impl Span {
- /// The zero span.
- pub const ZERO: Self = Self { start: Pos::ZERO, end: Pos::ZERO };
-
/// Create a new span from start and end positions.
- pub fn new(start: impl Into<Pos>, end: impl Into<Pos>) -> Self {
- Self { start: start.into(), end: end.into() }
+ pub fn new(source: SourceId, start: impl Into<Pos>, end: impl Into<Pos>) -> Self {
+ Self {
+ source,
+ start: start.into(),
+ end: end.into(),
+ }
}
/// Create a span including just a single position.
- pub fn at(pos: impl Into<Pos> + Copy) -> Self {
- Self::new(pos, pos)
+ pub fn at(source: SourceId, pos: impl Into<Pos> + Copy) -> Self {
+ Self::new(source, pos, pos)
+ }
+
+ /// Create a span without real location information, usually for testing.
+ pub fn detached() -> Self {
+ Self {
+ source: SourceId::from_raw(0),
+ start: Pos::ZERO,
+ end: Pos::ZERO,
+ }
+ }
+
+ /// Create a span with a different start position.
+ pub fn with_start(self, start: impl Into<Pos>) -> Self {
+ Self { start: start.into(), ..self }
+ }
+
+ /// Create a span with a different end position.
+ pub fn with_end(self, end: impl Into<Pos>) -> Self {
+ Self { end: end.into(), ..self }
}
/// Create a new span with the earlier start and later end position.
+ ///
+ /// This panics if the spans come from different files.
pub fn join(self, other: Self) -> Self {
+ debug_assert_eq!(self.source, other.source);
Self {
+ source: self.source,
start: self.start.min(other.start),
end: self.end.max(other.end),
}
@@ -89,33 +112,15 @@ impl Span {
/// Test whether one span complete contains the other span.
pub fn contains(self, other: Self) -> bool {
- self.start <= other.start && self.end >= other.end
+ self.source == other.source && self.start <= other.start && self.end >= other.end
}
- /// Convert to a `Range<usize>` for indexing.
+ /// Convert to a `Range<Pos>` for indexing.
pub fn to_range(self) -> Range<usize> {
self.start.to_usize() .. self.end.to_usize()
}
}
-impl<T> From<T> for Span
-where
- T: Into<Pos> + Copy,
-{
- fn from(pos: T) -> Self {
- Self::at(pos)
- }
-}
-
-impl<T> From<Range<T>> for Span
-where
- T: Into<Pos>,
-{
- fn from(range: Range<T>) -> Self {
- Self::new(range.start, range.end)
- }
-}
-
impl Debug for Span {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}-{:?}", self.start, self.end)
@@ -165,3 +170,34 @@ where
Pos(self.0 + rhs.into().0)
}
}
+
+/// Convert a position or range into a span.
+pub trait IntoSpan {
+ /// Convert into a span by providing the source id.
+ fn into_span(self, source: SourceId) -> Span;
+}
+
+impl IntoSpan for Span {
+ fn into_span(self, source: SourceId) -> Span {
+ debug_assert_eq!(self.source, source);
+ self
+ }
+}
+
+impl IntoSpan for Pos {
+ fn into_span(self, source: SourceId) -> Span {
+ Span::new(source, self, self)
+ }
+}
+
+impl IntoSpan for usize {
+ fn into_span(self, source: SourceId) -> Span {
+ Span::new(source, self, self)
+ }
+}
+
+impl IntoSpan for Range<usize> {
+ fn into_span(self, source: SourceId) -> Span {
+ Span::new(source, self.start, self.end)
+ }
+}