diff --git a/src/main.rs b/src/main.rs index 61535c1..b63f99b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use clap::Parser; mod ast; mod builtin; mod parser; +mod span; mod table; mod value; diff --git a/src/span.rs b/src/span.rs new file mode 100644 index 0000000..8df7bf0 --- /dev/null +++ b/src/span.rs @@ -0,0 +1,66 @@ +use std::fmt; +use std::ops::Range; + +#[derive(Clone, Copy)] +pub struct Span { + start: usize, + end: usize, +} + +impl Span { + pub fn new(start: usize, end: usize) -> Self { + assert!(start <= end, "start must be less than or equal to end"); + Self { start, end } + } + + pub fn range(self) -> Range { + self.start..self.end + } + + pub fn join(self, other: Self) -> Self { + let start = self.start.min(other.start); + let end = self.end.max(other.end); + Self::new(start, end) + } +} + +impl fmt::Debug for Span { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.range().fmt(f) + } +} + +impl From for Range { + fn from(span: Span) -> Self { + span.range() + } +} + +pub trait HasSpan { + fn span(&self) -> Span; +} + +impl HasSpan for (T, Span) { + fn span(&self) -> Span { + self.1 + } +} + +impl chumsky::Span for Span { + type Context = (); + type Offset = usize; + + fn new(_: Self::Context, range: Range) -> Self { + Self::new(range.start, range.end) + } + + fn context(&self) -> Self::Context {} + + fn start(&self) -> Self::Offset { + self.start + } + + fn end(&self) -> Self::Offset { + self.end + } +}