use std::fmt::Debug;
use super::{Lexicon, Span, ToSpan};
#[derive(Clone, Copy, PartialEq, Eq, Hash, ToSpan)]
pub struct Token<L: Lexicon> {
pub span: Span,
pub ty: L,
}
impl<L: Lexicon> Debug for Token<L> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "token {:?}({:?})", self.ty, self.span)
}
}
impl<L: Lexicon> Token<L> {
pub fn new<TSpan: Into<Span>>(span: TSpan, ty: L) -> Self {
Self {
span: span.into(),
ty,
}
}
#[inline]
pub fn src<'s>(&self, input: &'s str) -> &'s str {
self.span.get(input)
}
#[inline]
pub fn to_src<'s>(&self, input: &'s str) -> TokenSrc<'s, L> {
TokenSrc {
ty: self.ty,
src: self.src(input),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TokenSrc<'s, L: Lexicon> {
pub ty: L,
pub src: &'s str,
}
impl<'s, L: Lexicon> TokenSrc<'s, L> {
#[inline]
pub fn new(ty: L, src: &'s str) -> Self {
Self { ty, src }
}
}
impl<'s, L: Lexicon> From<(L, &'s str)> for TokenSrc<'s, L> {
#[inline]
fn from((ty, src): (L, &'s str)) -> Self {
Self { ty, src }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::TestTokenType as T;
#[test]
fn test_src() {
let token = Token::new((0, 1), T::A);
assert_eq!(token.src("abc"), "a");
}
#[test]
fn test_src_empty() {
let token = Token::new((0, 0), T::A);
assert_eq!(token.src("abc"), "");
let token = Token::new((1, 1), T::A);
assert_eq!(token.src("abc"), "");
let token = Token::new((1, 0), T::A);
assert_eq!(token.src("abc"), "");
}
#[test]
fn test_overflows() {
let token = Token::new(0..100, T::A);
assert_eq!(token.src("abc"), "abc");
}
}