use std::{fmt::Display, hash::Hash, mem::discriminant, ops::Index};
use derive_more::Display;
#[derive(Debug, Clone, Eq, Display)]
pub enum TokenKind {
#[display("(")]
LParen,
#[display(")")]
RParen,
#[display("{{")]
LBracket,
#[display("}}")]
RBracket,
#[display("<")]
LT,
#[display(">")]
GT,
#[display("<=")]
LTEq,
#[display(">=")]
GTEq,
#[display(".")]
Period,
#[display(",")]
Comma,
#[display("FROM")]
From,
#[display("WHERE")]
Where,
#[display("INNER")]
Inner,
#[display("LEFT")]
Left,
#[display("JOIN")]
Join,
#[display("SELECT")]
Select,
#[display("ON")]
On,
#[display("IN")]
In,
#[display("CASE")]
Case,
#[display("WHEN")]
When,
#[display("THEN")]
Then,
#[display("ELSE")]
Else,
#[display("END")]
End,
#[display("AS")]
As,
#[display("AND")]
And,
#[display("OR")]
Or,
#[display("GROUP")]
Group,
#[display("BY")]
By,
#[display("IS")]
Is,
#[display("NULL")]
Null,
#[display("NOT")]
Not,
#[display("USING")]
Using,
#[display("LIKE")]
Like,
#[display("UNION")]
Union,
#[display("ALL")]
All,
#[display("DATE")]
Date,
#[display("BETWEEN")]
Between,
#[display("OUTER")]
Outer,
#[display("DISTINCT")]
Distinct,
#[display("FULL")]
Full,
#[display("=")]
Eq,
#[display("<>")]
UnEq,
#[display("!=")]
NotEq,
#[display("*")]
Asterisk,
#[display("+")]
Plus,
#[display("-")]
Sub,
#[display(";")]
Semicolon,
#[display("/")]
Slash,
#[display("@")]
At,
#[display("||")]
JoinStrings,
Ident(String),
String(String),
#[display("/*{_0}*/")]
Comment(String),
Unkown(char),
Whitespace(String),
Integer(String),
}
#[derive(derive_more::Debug, Clone, PartialEq)]
pub struct Token {
pub kind: TokenKind,
#[debug(skip)]
pub start: Loc,
#[debug(skip)]
pub end: Loc,
}
impl Display for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.kind.fmt(f)
}
}
pub trait GetKind {
fn get_kind(&self) -> Option<&TokenKind>;
}
impl GetKind for Option<Token> {
fn get_kind(&self) -> Option<&TokenKind> {
self.as_ref().map(|tok| &tok.kind)
}
}
impl GetKind for Option<&Token> {
fn get_kind(&self) -> Option<&TokenKind> {
self.as_ref().map(|tok| &tok.kind)
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Loc {
pub line: usize,
pub col: usize,
pub idx: usize,
}
impl<T> Index<Loc> for [T] {
type Output = T;
fn index(&self, idx: Loc) -> &Self::Output {
&self[idx.idx]
}
}
impl Hash for TokenKind {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let disc = discriminant(self);
Hash::hash(&disc, state);
}
}
impl PartialEq for TokenKind {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&discriminant(self), &discriminant(other))
}
}
impl TokenKind {
pub fn ident(s: &str) -> Self {
TokenKind::Ident(s.to_string())
}
pub fn string(s: &str) -> Self {
TokenKind::String(s.to_string())
}
}
pub fn ident_map(ident: String) -> TokenKind {
match ident.to_lowercase().as_str() {
"select" => TokenKind::Select,
"from" => TokenKind::From,
"where" => TokenKind::Where,
"inner" => TokenKind::Inner,
"join" => TokenKind::Join,
"on" => TokenKind::On,
"in" => TokenKind::In,
"case" => TokenKind::Case,
"when" => TokenKind::When,
"then" => TokenKind::Then,
"else" => TokenKind::Else,
"end" => TokenKind::End,
"as" => TokenKind::As,
"left" => TokenKind::Left,
"and" => TokenKind::And,
"or" => TokenKind::Or,
"group" => TokenKind::Group,
"by" => TokenKind::By,
"is" => TokenKind::Is,
"null" => TokenKind::Null,
"not" => TokenKind::Not,
"using" => TokenKind::Using,
"like" => TokenKind::Like,
"union" => TokenKind::Union,
"all" => TokenKind::All,
"date" => TokenKind::Date,
"between" => TokenKind::Between,
"outer" => TokenKind::Outer,
"distinct" => TokenKind::Distinct,
"full" => TokenKind::Full,
_ => TokenKind::Ident(ident),
}
}