1#[cfg(feature = "bincode")]
2use bincode::{Decode, Encode};
3use proc_macro2::TokenStream;
4use quote::{quote, ToTokens, TokenStreamExt};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
13pub struct Span {
14 start: usize,
15 end: usize,
16}
17
18impl Span {
19 pub fn new(start: usize, end: usize) -> Self {
25 if end < start {
26 panic!("Span starts ({}) after it ends ({})!", start, end);
27 }
28 Span { start, end }
29 }
30
31 pub fn start(&self) -> usize {
33 self.start
34 }
35
36 pub fn end(&self) -> usize {
38 self.end
39 }
40
41 pub fn len(&self) -> usize {
43 self.end - self.start
44 }
45
46 pub fn is_empty(&self) -> bool {
48 self.len() == 0
49 }
50}
51
52pub trait Spanned: std::fmt::Display {
54 fn spans(&self) -> &[Span];
59 fn spanskind(&self) -> crate::yacc::parser::SpansKind;
61}
62
63impl ToTokens for Span {
64 fn to_tokens(&self, tokens: &mut TokenStream) {
65 let Span { start, end } = self;
66 tokens.append_all(quote! {::cfgrammar::Span::new(#start, #end)});
67 }
68}
69
70#[derive(Clone, Debug, Eq, PartialEq)]
73pub enum Location {
74 Span(Span),
75 CommandLine,
76 Other(String),
77}
78
79impl From<Span> for Location {
80 fn from(span: Span) -> Location {
81 Location::Span(span)
82 }
83}