use std::borrow::{Borrow, BorrowMut}; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::{Deref, DerefMut}; /// Original position of element in source code #[derive(PartialOrd, Ord, PartialEq, Eq, Clone, Copy, Default, Hash)] pub struct Pos { /// One-based line number pub line: usize, /// One-based column number pub column: usize, } impl fmt::Debug for Pos { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Pos({}:{})", self.line, self.column) } } impl fmt::Display for Pos { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}:{}", self.line, self.column) } } #[derive(Copy, Clone, Debug, Default)] pub struct Span { pub start: Pos, pub end: Pos, } /// Represents the location of a AST node #[derive(Clone, Debug, Copy, Default)] #[allow(missing_docs)] pub struct Spanned { pub span: Span, pub node: T, } impl fmt::Display for Spanned { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.node.fmt(f) } } impl Spanned { #[inline] #[allow(missing_docs)] pub fn clone_inner(&self) -> T { self.node.clone() } } impl PartialEq for Spanned { fn eq(&self, other: &Self) -> bool { self.node.eq(&other.node) } } impl PartialOrd for Spanned { fn partial_cmp(&self, other: &Self) -> Option { self.node.partial_cmp(&other.node) } } impl Ord for Spanned { fn cmp(&self, other: &Self) -> Ordering { self.node.cmp(&other.node) } } impl Eq for Spanned {} impl Deref for Spanned { type Target = T; fn deref(&self) -> &T { &self.node } } impl DerefMut for Spanned { fn deref_mut(&mut self) -> &mut T { &mut self.node } } impl Hash for Spanned { fn hash(&self, state: &mut H) { self.node.hash(state) } } impl Borrow for Spanned { fn borrow(&self) -> &str { self.node.as_str() } } impl BorrowMut for Spanned { fn borrow_mut(&mut self) -> &mut str { self.node.as_mut_str() } } impl Spanned { pub(crate) fn new(node: T, pair_span: pest::Span<'_>) -> Spanned { let ((start_line, start_column), (end_line, end_column)) = ( pair_span.start_pos().line_col(), pair_span.end_pos().line_col(), ); Spanned { node, span: Span { start: Pos { line: start_line, column: start_column, }, end: Pos { line: end_line, column: end_column, }, }, } } #[inline] pub(crate) fn into_inner(self) -> T { self.node } /// Get start position #[inline] pub fn position(&self) -> Pos { self.span.start } #[inline] pub(crate) fn pack R, R>(self, f: F) -> Spanned { Spanned { span: self.span, node: f(self), } } }