#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Position {
line: u32,
column: u32,
offset: u32,
}
impl Position {
#[must_use]
pub fn new(line: u32, column: u32, offset: u32) -> Self {
Self {
line,
column,
offset,
}
}
#[must_use]
pub fn synthetic() -> Self {
Self {
line: 0,
column: 0,
offset: 0,
}
}
#[must_use]
pub fn line(&self) -> u32 {
self.line
}
#[must_use]
pub fn column(&self) -> u32 {
self.column
}
#[must_use]
pub fn offset(&self) -> u32 {
self.offset
}
}
impl std::fmt::Display for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.line, self.column)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Span {
start: Position,
end: Position,
}
impl Span {
#[must_use]
pub fn new(start: Position, end: Position) -> Self {
Self { start, end }
}
#[must_use]
pub fn synthetic() -> Self {
Self {
start: Position::synthetic(),
end: Position::synthetic(),
}
}
#[must_use]
pub fn start(&self) -> Position {
self.start
}
#[must_use]
pub fn end(&self) -> Position {
self.end
}
#[must_use]
pub fn contains(&self, other: Span) -> bool {
self.start.offset() <= other.start.offset() && other.end.offset() <= self.end.offset()
}
}
impl std::fmt::Display for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Spanned<T> {
value: T,
span: Span,
}
impl<T> Spanned<T> {
pub fn new(value: T, span: Span) -> Self {
Self { value, span }
}
pub fn value(&self) -> &T {
&self.value
}
#[must_use]
pub fn span(&self) -> Span {
self.span
}
pub fn into_parts(self) -> (T, Span) {
(self.value, self.span)
}
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Spanned<U> {
Spanned {
value: f(self.value),
span: self.span,
}
}
}
impl<T: std::fmt::Display> std::fmt::Display for Spanned<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.value.fmt(f)
}
}