use std::cmp::Ordering;
use std::fmt::{self, Write};
use std::rc::Rc;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
pub enum Token {
Ident(String),
String(Rc<Vec<u8>>, StringType),
Integer(i64, String),
Float(f64, String),
And,
Break,
Do,
Else,
Elseif,
End,
False,
For,
Function,
Goto,
If,
In,
Local,
Nil,
Not,
Or,
Repeat,
Return,
Then,
True,
Until,
While,
Add,
Sub,
Mul,
Div,
Mod,
Pow,
Hash,
Amp,
Tilde,
Bar,
Shl,
Shr,
FlDiv,
Eq,
Neq,
Leq,
Geq,
Lt,
Gt,
Is,
ParO,
ParC,
CurlO,
CurlC,
SqrO,
SqrC,
Ass,
Semi,
Colon,
Comma,
Point,
Conc,
Dots,
}
impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Token::Ident(ident) => f.write_str(ident),
Token::String(str, typ) => match typ {
StringType::Double => write!(f, "\"{}\"", String::from_utf8_lossy(str).as_ref()),
StringType::Single => write!(f, "'{}'", String::from_utf8_lossy(str).as_ref()),
StringType::Long(len) => {
write!(
f,
"[{1}[{}]{1}]",
String::from_utf8_lossy(str).as_ref(),
"=".repeat(*len)
)
}
},
Token::Integer(_, orig) => f.write_str(orig),
Token::Float(_, orig) => f.write_str(orig),
Token::And => f.write_str("and"),
Token::Break => f.write_str("break"),
Token::Do => f.write_str("do"),
Token::Else => f.write_str("else"),
Token::Elseif => f.write_str("elseif"),
Token::End => f.write_str("end"),
Token::False => f.write_str("false"),
Token::For => f.write_str("for"),
Token::Function => f.write_str("function"),
Token::Goto => f.write_str("goto"),
Token::If => f.write_str("if"),
Token::In => f.write_str("in"),
Token::Local => f.write_str("local"),
Token::Nil => f.write_str("nil"),
Token::Not => f.write_str("not"),
Token::Or => f.write_str("or"),
Token::Repeat => f.write_str("repeat"),
Token::Return => f.write_str("return"),
Token::Then => f.write_str("then"),
Token::True => f.write_str("true"),
Token::Until => f.write_str("until"),
Token::While => f.write_str("while"),
Token::Add => f.write_char('+'),
Token::Sub => f.write_char('-'),
Token::Mul => f.write_char('*'),
Token::Div => f.write_char('/'),
Token::Mod => f.write_char('%'),
Token::Pow => f.write_char('^'),
Token::Hash => f.write_char('#'),
Token::Amp => f.write_char('&'),
Token::Tilde => f.write_char('~'),
Token::Bar => f.write_char('|'),
Token::Shl => f.write_str("<<"),
Token::Shr => f.write_str(">>"),
Token::FlDiv => f.write_str("//"),
Token::Eq => f.write_str("=="),
Token::Neq => f.write_str("~="),
Token::Leq => f.write_str("<="),
Token::Geq => f.write_str(">="),
Token::Lt => f.write_char('<'),
Token::Gt => f.write_char('>'),
Token::Is => f.write_char('='),
Token::ParO => f.write_char('('),
Token::ParC => f.write_char(')'),
Token::CurlO => f.write_char('{'),
Token::CurlC => f.write_char('}'),
Token::SqrO => f.write_char('['),
Token::SqrC => f.write_char(']'),
Token::Ass => f.write_str("::"),
Token::Semi => f.write_char(';'),
Token::Colon => f.write_char(':'),
Token::Comma => f.write_char(','),
Token::Point => f.write_char('.'),
Token::Conc => f.write_str(".."),
Token::Dots => f.write_str("..."),
}
}
}
#[derive(Clone, Debug)]
pub enum StringType {
Single,
Double,
Long(usize),
}
pub struct Spanned<T> {
pub(super) inner: T,
pub(super) pos: Pos,
}
impl<T> Spanned<T> {
pub fn inner(&self) -> &T {
&self.inner
}
pub fn pos(&self) -> Pos {
self.pos
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Pos(pub(super) i64, pub(super) i64);
impl Pos {
pub fn line(&self) -> i64 {
self.0
}
pub fn col(&self) -> i64 {
self.1
}
}
impl Default for Pos {
fn default() -> Self {
Self(-1, -1)
}
}
impl Ord for Pos {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0).then(self.1.cmp(&other.1))
}
}
impl PartialOrd for Pos {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl From<Spanned<Token>> for (Pos, Token) {
fn from(value: Spanned<Token>) -> Self {
(value.pos, value.inner)
}
}
impl<'a> From<&'a Spanned<Token>> for (Pos, &'a Token) {
fn from(value: &'a Spanned<Token>) -> Self {
(value.pos, &value.inner)
}
}