use std::{
fmt::{ Display, Debug, Formatter, Result as FMTResult, },
ops::{ Deref, },
};
use crate::{
source::{ SourceLocation, SourceRegion, },
ansi,
common::{ Identifier, Number, Keyword, Operator, },
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[allow(missing_docs)]
pub enum TokenKind {
Invalid,
Identifier,
Number,
String,
Keyword,
Operator
}
#[derive(Debug, Clone, PartialEq)]
#[allow(missing_docs)]
pub enum TokenData {
Invalid,
Identifier(Identifier),
Number(Number),
String(String),
Keyword(Keyword),
Operator(Operator),
}
impl TokenData {
pub fn kind (&self) -> TokenKind {
match self {
TokenData::Invalid => TokenKind::Invalid,
TokenData::Identifier(_) => TokenKind::Identifier,
TokenData::Number(_) => TokenKind::Number,
TokenData::String(_) => TokenKind::String,
TokenData::Keyword(_) => TokenKind::Keyword,
TokenData::Operator(_) => TokenKind::Operator,
}
}
pub fn is_operator (&self, operator: Operator) -> bool {
*self == TokenData::Operator(operator)
}
pub fn is_keyword (&self, keyword: Keyword) -> bool {
*self == TokenData::Keyword(keyword)
}
pub fn is_any_operator_of (&self, operators: &[Operator]) -> Option<Operator> {
if let TokenData::Operator(operator) = self {
for matched_operator in operators.iter() {
if matched_operator == operator {
return Some(*operator)
}
}
}
None
}
pub fn is_any_keyword_of (&self, keywords: &[Keyword]) -> Option<Keyword> {
if let TokenData::Keyword(keyword) = self {
for matched_keyword in keywords.iter() {
if matched_keyword == keyword {
return Some(*keyword)
}
}
}
None
}
}
#[derive(Clone)]
#[allow(missing_docs)]
pub struct Token {
pub data: TokenData,
pub origin: SourceRegion,
}
impl PartialEq for Token {
#[inline] fn eq (&self, other: &Self) -> bool { self.data == other.data }
}
impl Token {
pub fn new (data: TokenData, origin: SourceRegion) -> Self {
Self { data, origin }
}
pub fn no_src (data: TokenData) -> Self {
Self { data, origin: SourceLocation::ZERO.to_region(None) }
}
}
impl Deref for Token {
type Target = TokenData;
#[inline] fn deref (&self) -> &Self::Target { &self.data }
}
impl Debug for Token {
fn fmt (&self, f: &mut Formatter) -> FMTResult {
write!(f, "[{}]: {:?}",
self.origin,
self.data
)
}
}
impl Display for Token {
fn fmt (&self, f: &mut Formatter) -> FMTResult {
write!(f, "[{}{}{}]: {:?}",
ansi::Foreground::Cyan,
self.origin,
ansi::Foreground::Reset,
self.data
)
}
}