use logos::Logos;
#[derive(Default, Debug, PartialEq, Clone)]
pub enum LexingError {
#[default]
UnexpectedToken,
InvalidInteger(String),
}
impl From<std::num::ParseIntError> for LexingError {
fn from(err: std::num::ParseIntError) -> Self {
use std::num::IntErrorKind::*;
match err.kind() {
PosOverflow | NegOverflow => {
LexingError::InvalidInteger("Integer overflow".to_string())
}
_ => LexingError::InvalidInteger("Other error".to_string()),
}
}
}
#[derive(Logos, Debug, PartialEq, Clone)]
#[logos(error = LexingError)]
#[logos(skip r"[ \t\n\f\r]+")]
pub enum Token {
#[regex("//[^\n]*|/\\*([^*]|\\*[^/])*\\*/", logos::skip)]
Comment,
#[token("/*", logos::skip)]
MultiLineCommentStart,
#[token("*/", logos::skip)]
MultiLineCommentEnd,
#[token("let")]
Let,
#[token("fn")]
Fn,
#[token("if")]
If,
#[token("else")]
Else,
#[token("while")]
While,
#[token("for")]
For,
#[token("true")]
True,
#[token("false")]
False,
#[token("null")]
Null,
#[token("return")]
Return,
#[token("==")]
EqEq,
#[token("!=")]
BangEq,
#[token(">")]
Gt,
#[token("<")]
Lt,
#[token(">=")]
GtEq,
#[token("<=")]
LtEq,
#[token("=")]
Assign,
#[token("+")]
Plus,
#[token("-")]
Minus,
#[token("*")]
Star,
#[token("/")]
Slash,
#[token("%")]
Percent,
#[token("..")]
Range,
#[token("(")]
LParen,
#[token(")")]
RParen,
#[token("{")]
LBrace,
#[token("}")]
RBrace,
#[token(",")]
Comma,
#[token(";")]
Semicolon,
#[regex("[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice().to_string())]
Identifier(String),
#[regex(r#""([^"\\]|\\.)*"|'([^'\\]|\\.)*'"#, |lex| {
let s = lex.slice();
s[1..s.len()-1].to_string()
})]
StringLiteral(String),
#[regex(r"[0-9][0-9_]*(\.[0-9_]+)?", |lex| {
let s = lex.slice().replace('_', "");
s.parse::<f64>().unwrap()
})]
NumberLiteral(f64),
#[allow(dead_code)]
Error, }