use std::fmt::{Display, Formatter};
use std::ops::Range;
pub use parser::Parser;
#[cfg(feature = "serde")]
use serde::Serialize;
pub mod ast;
pub mod cst;
mod parser;
mod tokenizer;
#[derive(Default, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Span(pub Range<u32>);
impl From<logos::Span> for Span {
fn from(value: logos::Span) -> Self {
Self(value.start as u32..value.end as u32)
}
}
impl From<rowan::TextRange> for Span {
fn from(value: rowan::TextRange) -> Self {
Self(value.start().into()..value.end().into())
}
}
impl Display for Span {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}..{}]", self.start(), self.end())
}
}
impl Span {
const MAX: usize = u32::MAX as usize;
#[inline]
pub fn start(&self) -> usize {
self.0.start as usize
}
#[inline]
pub fn end(&self) -> usize {
self.0.end as usize
}
#[inline]
pub fn range(&self) -> Range<usize> {
self.0.start as usize..self.0.end as usize
}
#[inline]
pub fn len(&self) -> usize {
self.range().len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.range().is_empty()
}
pub fn combine(&self, other: &Self) -> Self {
Self(self.0.start..other.0.end)
}
pub fn contains(&self, other: &Self) -> bool {
self.0.contains(&other.0.start)
&& self.0.contains(&other.0.end.saturating_sub(1))
}
pub fn subspan(&self, start: usize, end: usize) -> Span {
assert!(start <= self.end() - self.start());
assert!(end <= self.end() - self.start());
Self(self.0.start + start as u32..self.0.start + end as u32)
}
pub fn offset(mut self, offset: isize) -> Self {
if offset.is_negative() {
let offset = offset.unsigned_abs() as u32;
self.0.start = self.0.start.checked_sub(offset).unwrap();
self.0.end = self.0.end.checked_sub(offset).unwrap();
} else {
let offset = offset as u32;
self.0.start = self.0.start.checked_add(offset).unwrap();
self.0.end = self.0.end.checked_add(offset).unwrap();
}
self
}
}