remove strum
This commit is contained in:
parent
564d90d061
commit
bbc6c276a8
|
@ -2,78 +2,6 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "leaf"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"strum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
|
|
@ -4,4 +4,3 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
strum = { version = "0.27", features = ["derive"] }
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
pub trait Kind {
|
||||
type Kinds;
|
||||
|
||||
fn kind(&self) -> Self::Kinds;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! kinds {
|
||||
($b:ident, $k:ident, $( $v:ident $( ( $($vty:ty = $vval:expr),* ) )?),* $(,)?) => {
|
||||
#[derive(Debug)]
|
||||
pub enum $b {
|
||||
$( $v $( ( $($vty),* ) )?, )*
|
||||
}
|
||||
impl $crate::kind::Kind for $b {
|
||||
type Kinds = $k;
|
||||
|
||||
fn kind(&self) -> $k {
|
||||
$k (std::mem::discriminant(self))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub struct $k(std::mem::Discriminant<$b>);
|
||||
|
||||
impl $k {
|
||||
$(
|
||||
#[allow(non_upper_case_globals, dead_code)]
|
||||
pub const $v: Self = $k (
|
||||
std::mem::discriminant(
|
||||
&( $b::$v $( ( $($vval),* ) )? )
|
||||
)
|
||||
);
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
58
src/lexer.rs
58
src/lexer.rs
|
@ -1,6 +1,6 @@
|
|||
use std::{fmt, iter::Peekable};
|
||||
use std::{fmt, iter::Peekable, num::ParseIntError};
|
||||
|
||||
use strum::EnumDiscriminants;
|
||||
use crate::kinds;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Ident(String);
|
||||
|
@ -30,47 +30,38 @@ impl fmt::Display for Literal {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumDiscriminants)]
|
||||
#[strum_discriminants(name(TokenKind))]
|
||||
pub enum Token {
|
||||
kinds!(
|
||||
Token,
|
||||
TokenKind,
|
||||
Equals,
|
||||
|
||||
Plus,
|
||||
Minus,
|
||||
Star,
|
||||
Slash,
|
||||
Percent,
|
||||
Caret,
|
||||
|
||||
CurlyOpen,
|
||||
CurlyClose,
|
||||
|
||||
ParenOpen,
|
||||
ParenClose,
|
||||
|
||||
Comma,
|
||||
Semicolon,
|
||||
|
||||
Eol,
|
||||
Func,
|
||||
If,
|
||||
Else,
|
||||
Return,
|
||||
|
||||
Not,
|
||||
|
||||
EqualTo,
|
||||
NotEqualTo,
|
||||
|
||||
And,
|
||||
Or,
|
||||
|
||||
LessThan,
|
||||
LessThanOrEqualTo,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqualTo,
|
||||
|
||||
Literal(Literal),
|
||||
}
|
||||
Literal(Literal = Literal::Nil),
|
||||
);
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||
pub enum Precedence {
|
||||
Min,
|
||||
|
@ -116,6 +107,7 @@ impl Token {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum LexError {
|
||||
InvalidInteger(ParseIntError),
|
||||
InvalidEscape(char),
|
||||
UnexpectedCharacter(char),
|
||||
UnexpectedEnd,
|
||||
|
@ -123,12 +115,18 @@ pub enum LexError {
|
|||
impl fmt::Display for LexError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::InvalidInteger(err) => write!(f, "invalid integer: {err}"),
|
||||
Self::UnexpectedEnd => write!(f, "unexpected end of source"),
|
||||
Self::UnexpectedCharacter(c) => write!(f, "unexpected char '{c}'"),
|
||||
Self::InvalidEscape(c) => write!(f, "\"\\{c}\" is not a valid string escape"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<ParseIntError> for LexError {
|
||||
fn from(err: ParseIntError) -> Self {
|
||||
Self::InvalidInteger(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, LexError>;
|
||||
|
||||
|
@ -139,6 +137,10 @@ where
|
|||
chars: Peekable<I>,
|
||||
}
|
||||
|
||||
fn t(tk: Token) -> Option<Result<Token>> {
|
||||
Some(Ok(tk))
|
||||
}
|
||||
|
||||
impl<I> Lexer<I>
|
||||
where
|
||||
I: Iterator<Item = char>,
|
||||
|
@ -209,7 +211,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn lex_integer(&mut self) -> Token {
|
||||
fn lex_integer(&mut self) -> Result<Token> {
|
||||
let mut n_str = String::new();
|
||||
|
||||
// we don't lex negatives. the impl for that is
|
||||
|
@ -221,9 +223,9 @@ where
|
|||
|
||||
// we can only read digits 0 to 9 so this should not fail
|
||||
// .. unless we overflow
|
||||
let n = n_str.parse().unwrap();
|
||||
let n = n_str.parse()?;
|
||||
|
||||
Token::Literal(Literal::Integer(n))
|
||||
Ok(Token::Literal(Literal::Integer(n)))
|
||||
}
|
||||
|
||||
fn lex_string(&mut self) -> Result<Token> {
|
||||
|
@ -283,18 +285,21 @@ where
|
|||
// , comma
|
||||
',' => self.eat_to(Token::Comma),
|
||||
|
||||
// ; semicolon
|
||||
';' => self.eat_to(Token::Semicolon),
|
||||
|
||||
// = equals
|
||||
// or == equal to
|
||||
'=' => match self.eat_peek() {
|
||||
Some('=') => self.eat_to(Token::EqualTo),
|
||||
_ => Some(Ok(Token::Equals)),
|
||||
_ => t(Token::Equals),
|
||||
},
|
||||
|
||||
// ! not
|
||||
// or != not equal to
|
||||
'!' => match self.eat_peek() {
|
||||
Some('=') => self.eat_to(Token::NotEqualTo),
|
||||
_ => Some(Ok(Token::Not)),
|
||||
_ => t(Token::Not),
|
||||
},
|
||||
|
||||
// && and
|
||||
|
@ -307,21 +312,21 @@ where
|
|||
// or >= greater than/equal to
|
||||
'>' => match self.eat_peek() {
|
||||
Some('=') => self.eat_to(Token::GreaterThanOrEqualTo),
|
||||
_ => Some(Ok(Token::GreaterThan)),
|
||||
_ => t(Token::GreaterThan),
|
||||
},
|
||||
|
||||
// < less than
|
||||
// or <= less than/equal to
|
||||
'<' => match self.eat_peek() {
|
||||
Some('=') => self.eat_to(Token::LessThanOrEqualTo),
|
||||
_ => Some(Ok(Token::LessThan)),
|
||||
_ => t(Token::LessThan),
|
||||
},
|
||||
|
||||
// a-zA-Z_ start of word
|
||||
'a'..='z' | 'A'..='Z' | '_' => Some(Ok(self.lex_word())),
|
||||
|
||||
// 0-9 integer
|
||||
'0'..='9' => Some(Ok(self.lex_integer())),
|
||||
'0'..='9' => Some(self.lex_integer()),
|
||||
|
||||
// " strings
|
||||
'"' => Some(self.lex_string()),
|
||||
|
@ -336,9 +341,6 @@ where
|
|||
continue;
|
||||
}
|
||||
|
||||
// ; semicolon
|
||||
';' => self.eat_to(Token::Semicolon),
|
||||
|
||||
// unexpected character
|
||||
c => Some(Err(LexError::UnexpectedCharacter(c))),
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::time::Instant;
|
|||
|
||||
use crate::{lexer::Lexer, parser::Parser};
|
||||
|
||||
mod kind;
|
||||
mod lexer;
|
||||
mod parser;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::{fmt, iter::Peekable};
|
||||
|
||||
use strum::IntoDiscriminant;
|
||||
|
||||
use crate::lexer::{Associativity, LexError, Literal, Precedence, Token, TokenKind};
|
||||
use crate::{
|
||||
kind::Kind,
|
||||
lexer::{Associativity, LexError, Literal, Precedence, Token, TokenKind},
|
||||
};
|
||||
|
||||
pub mod util;
|
||||
|
||||
|
@ -96,7 +97,7 @@ where
|
|||
fn expect_next(&mut self, kind: TokenKind) -> Result<()> {
|
||||
let t = self.try_next()?;
|
||||
|
||||
if t.discriminant() != kind {
|
||||
if t.kind() != kind {
|
||||
return Err(ParseError::UnexpectedToken(t));
|
||||
}
|
||||
|
||||
|
@ -104,7 +105,7 @@ where
|
|||
}
|
||||
fn is_next(&mut self, kind: Option<TokenKind>) -> bool {
|
||||
match self.try_peek() {
|
||||
Ok(t) if Some(t.discriminant()) == kind => true,
|
||||
Ok(t) if Some(t.kind()) == kind => true,
|
||||
Ok(_) => false,
|
||||
|
||||
Err(ParseError::UnexpectedEnd) if kind.is_none() => true,
|
||||
|
|
Loading…
Reference in New Issue