use std::borrow::Cow;
use std::fmt::{self, Display};
use crate::span::{HasSpan, Span};
pub use crate::symbol::{Symbol, SymbolGroup};
#[derive(Clone, Debug, PartialEq)]
pub struct Token<'a> {
pub span: Span,
pub value: TokenValue<'a>,
}
impl HasSpan for Token<'_> {
fn span(&self) -> Span {
self.span
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum TokenValue<'a> {
Symbol(Symbol),
Number(NumberLiteral),
String {
value: Cow<'a, [u8]>,
kind: StringLiteralKind,
},
Comment {
value: &'a str,
kind: CommentKind,
},
Whitespace(&'a str),
Ident(&'a str),
Eof,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum NumberLiteral {
Float(f64),
Integer(i64),
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum StringLiteralKind {
Bracketed { level: usize },
SingleQuoted,
DoubleQuoted,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum CommentKind {
Bracketed { level: usize },
Unbracketed,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum TokenKind {
Symbol(Symbol),
Number,
String,
Comment,
Whitespace,
Ident,
Eof,
}
impl Token<'_> {
pub fn kind(&self) -> TokenKind {
self.value.kind()
}
}
impl TokenValue<'_> {
pub fn kind(&self) -> TokenKind {
match self {
TokenValue::Symbol(s) => TokenKind::Symbol(*s),
TokenValue::Number(_) => TokenKind::Number,
TokenValue::String { .. } => TokenKind::String,
TokenValue::Comment { .. } => TokenKind::Comment,
TokenValue::Whitespace(_) => TokenKind::Whitespace,
TokenValue::Ident(_) => TokenKind::Ident,
TokenValue::Eof => TokenKind::Eof,
}
}
}
impl TokenKind {
pub fn is_trivia(self) -> bool {
matches!(self, TokenKind::Whitespace | TokenKind::Comment)
}
}
impl From<Symbol> for TokenKind {
fn from(s: Symbol) -> TokenKind {
TokenKind::Symbol(s)
}
}
impl Display for TokenKind {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Symbol(s) => write!(formatter, "{}", s),
Self::Number => write!(formatter, "a number"),
Self::String => write!(formatter, "a string"),
Self::Comment => write!(formatter, "a comment"),
Self::Whitespace => write!(formatter, "whitespace"),
Self::Ident => write!(formatter, "an identifier"),
Self::Eof => write!(formatter, "end of file"),
}
}
}