use std::fmt;
use std::ops::{Deref, DerefMut};
use std::path::Path;
pub fn new_location() -> Span {
Span::default()
}
pub fn path_location<P: AsRef<Path>>(path: P) -> FileSource<P, Span> {
FileSource::new(Span::default(), path)
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Location {
byte: usize,
character: usize,
row: usize,
column: usize,
}
impl fmt::Display for Location {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.row, self.column)
}
}
impl Location {
pub fn character(&self) -> usize {
self.character
}
pub fn byte(&self) -> usize {
self.byte
}
pub fn row(&self) -> usize {
self.row
}
pub fn column(&self) -> usize {
self.column
}
pub fn after(&mut self, next_character: char) {
self.character += 1;
self.byte += next_character.len_utf8();
if next_character == '\n' {
self.row += 1;
self.column = 0;
} else {
self.column += 1;
}
}
pub fn span(self) -> Span {
Span {
start: self,
end: self,
}
}
pub fn bind<T>(self, object: T) -> Meta<T, Self> {
Meta {
inner: object,
location: self,
}
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct Span {
start: Location,
end: Location,
}
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
impl Span {
pub fn start(&self) -> &Location {
&self.start
}
pub fn end(&self) -> &Location {
&self.end
}
pub fn characters(&self) -> usize {
self.end().character() - self.start().character()
}
pub fn bytes(&self) -> usize {
self.end().byte() - self.start().byte()
}
pub fn move_start(&mut self, new_start: Location) {
self.start = new_start;
}
pub fn move_end(&mut self, new_end: Location) {
self.end = new_end;
}
pub fn following_span(&self) -> Self {
let mut span = self.clone();
span.move_start(span.end().clone());
span
}
pub fn take(&mut self) -> Self {
let span = self.clone();
self.move_start(self.end().clone());
span
}
pub fn after(&mut self, next_character: char) {
self.end.after(next_character);
}
pub fn bind<T>(self, object: T) -> Meta<T, Self> {
Meta {
inner: object,
location: self,
}
}
pub fn substr<'s>(&self, source: &'s str) -> &'s str {
let start = self.start().byte();
let end = self.end().byte();
&source[start..end]
}
pub(crate) fn subslice<'s>(&self, outer: &Self, source: &'s str) -> &'s str {
if outer.start().byte() > self.start.byte() {
panic!(
"Span::subslice cannot be used with {} which is after {}",
outer, self
);
}
let start = self.start().byte() - outer.start().byte();
let end = self.end().byte() - outer.start().byte();
&source[start..end]
}
pub(crate) fn join(self, next: Self) -> Self {
if self.end() != next.start() {
panic!(
"Span::concat cannot be used with {} and {} which are not adjacent",
self, next
);
}
Span {
start: *self.start(),
end: *next.end(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct FileSource<P, I> {
inner: I,
path: P,
}
impl<P: AsRef<Path>, I> FileSource<P, I> {
pub fn new(inner: I, path: P) -> Self {
FileSource { inner, path }
}
}
impl<P: AsRef<Path>, I: fmt::Display> fmt::Display for FileSource<P, I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}[{}]", self.path.as_ref().display(), self.inner)
}
}
impl<P> FileSource<P, Location> {
pub fn span(self) -> FileSource<P, Span> {
FileSource {
inner: self.inner.span(),
path: self.path,
}
}
}
impl<P: AsRef<Path>, I> AsRef<Path> for FileSource<P, I> {
fn as_ref(&self) -> &Path {
self.path.as_ref()
}
}
impl<P, I> Deref for FileSource<P, I> {
type Target = I;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<P, I> DerefMut for FileSource<P, I> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Meta<T, I> {
inner: T,
location: I,
}
impl<T, I> Meta<T, I> {
pub fn inner(self) -> T {
self.inner
}
pub fn inner_ref(&self) -> &T {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn split(self) -> (T, I) {
(self.inner, self.location)
}
pub fn map<A>(self, mut map: impl FnMut(T) -> A) -> Meta<A, I> {
let Meta { inner, location } = self;
let inner = map(inner);
Meta { inner, location }
}
}
impl<T, I: Clone> Meta<T, I> {
pub fn as_ref(&self) -> Meta<&T, I> {
Meta {
inner: &self.inner,
location: self.location.clone(),
}
}
pub fn as_mut(&mut self) -> Meta<&mut T, I> {
Meta {
inner: &mut self.inner,
location: self.location.clone(),
}
}
}
impl<T: fmt::Display, I: fmt::Display> fmt::Display for Meta<T, I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", self.location, self.inner)
}
}
impl<T, I> std::error::Error for Meta<T, I>
where
T: std::error::Error,
I: fmt::Display + fmt::Debug,
{
}
impl<T, I> Deref for Meta<T, I> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T, I> DerefMut for Meta<T, I> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<T> Meta<T, Location> {
pub fn span(self) -> Meta<T, Span> {
Meta {
location: self.location.span(),
inner: self.inner,
}
}
}