#[cfg(feature = "bincode")]
use bincode::{Decode, Encode};
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt, quote};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
pub struct Span {
start: usize,
end: usize,
}
impl Span {
pub fn new(start: usize, end: usize) -> Self {
if end < start {
panic!("Span starts ({}) after it ends ({})!", start, end);
}
Span { start, end }
}
pub fn start(&self) -> usize {
self.start
}
pub fn end(&self) -> usize {
self.end
}
pub fn len(&self) -> usize {
self.end - self.start
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub trait Spanned: std::fmt::Display {
fn spans(&self) -> &[Span];
fn spanskind(&self) -> crate::yacc::parser::SpansKind;
}
impl ToTokens for Span {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Span { start, end } = self;
tokens.append_all(quote! {::cfgrammar::Span::new(#start, #end)});
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Location {
Span(Span),
CommandLine,
Other(String),
}
impl From<Span> for Location {
fn from(span: Span) -> Location {
Location::Span(span)
}
}