This commit is contained in:
2026-04-11 03:50:43 -04:00
parent 29316e6353
commit 229b026573
16 changed files with 266 additions and 136 deletions
+69 -37
View File
@@ -3,17 +3,26 @@ use std::{iter::Peekable, str::CharIndices};
def_tokens! {
symbol {
'=' => Equal,
':' => Colon,
';' => Semicolon,
'{' => OpenCurly,
'}' => CloseCurly,
'(' => OpenParen,
')' => CloseParen,
'-' => Dash,
'+' => Plus,
'*' => Asterisk,
'/' => Slash,
Equal: "=",
Colon: ":",
Semicolon: ";",
Plus: "+",
Dash: "-",
Asterisk: "*",
Slash: "/",
OpenParen: "(",
CloseParen: ")",
OpenSquare: "[",
CloseSquare: "]",
OpenCurly: "{",
CloseCurly: "}",
Arrow: "->",
DoubleArrow: "=>",
PlusEqual: "+=",
DashEqual: "-=",
AsteriskEqual: "*=",
SlashEqual: "/=",
DoubleColon: "::",
}
keyword {
Let: "let",
@@ -22,6 +31,7 @@ def_tokens! {
Loop: "loop",
While: "while",
For: "for",
Match: "match",
}
other {
Ident(String),
@@ -55,13 +65,53 @@ impl Iterator for Tokens<'_> {
end: i,
file: self.file,
};
if let Some(inner) = from_char(c) {
return Some(Spanned { inner, span });
}
if c.is_whitespace() {
return self.next();
}
macro_rules! then {
(_ => $def:expr, $($char:expr => $to:expr,)*) => {
match self.chars.peek() {
$(Some((_, $char)) => {
self.chars.next();
$to
},)*
_ => $def,
}
};
}
let inner = match c {
'(' => Token::OpenParen,
')' => Token::CloseParen,
'[' => Token::OpenSquare,
']' => Token::CloseSquare,
'{' => Token::OpenCurly,
'}' => Token::CloseCurly,
'+' => then! {
_ => Token::Plus,
'=' => Token::PlusEqual,
},
'-' => then! {
_ => Token::Dash,
'=' => Token::DashEqual,
'>' => Token::Arrow,
},
'*' => then! {
_ => Token::Asterisk,
'=' => Token::AsteriskEqual,
},
'/' => then! {
_ => Token::Slash,
'=' => Token::SlashEqual,
},
':' => then! {
_ => Token::Colon,
':' => Token::DoubleColon,
},
';' => Token::Semicolon,
'=' => then! {
_ => Token::Equal,
'>' => Token::DoubleArrow,
},
'0'..='9' => {
let mut s = c.to_string();
while let Some((i, c)) = self.chars.peek()
@@ -105,23 +155,11 @@ impl Iterator for Tokens<'_> {
}
}
macro_rules! expand_sym_names {
({
$($sym_char:expr => $sym_name:ident,)*
}) => {
$($sym_name,)*
};
({
$($sym_char:expr => $sym_res:tt,)*
}) => {
expand_sym_names!($sym_res)
};
}
use expand_sym_names;
macro_rules! def_tokens {
{
symbol $syms:tt
symbol {
$($sym_name:ident: $sym_str:expr,)*
}
keyword {
$($kw_name:ident: $kw_str:expr,)*
}
@@ -131,16 +169,10 @@ macro_rules! def_tokens {
} => {
#[derive(PartialEq)]
pub enum Token {
$($syms,)*
$($sym_name,)*
$($kw_name,)*
$($other_name($data),)*
}
fn from_char(c: char) -> Option<Token> {
match c {
$($sym_char => Some(Token::$sym_res),)*
_ => None,
}
}
fn from_str(s: String) -> Token {
match s.as_str() {
$($kw_str => Token::$kw_name,)*
@@ -150,7 +182,7 @@ macro_rules! def_tokens {
impl std::fmt::Display for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
$(Token::$sym_res => write!(f, "{}", $sym_char),)*
$(Token::$sym_name => write!(f, "{}", $sym_str),)*
$(Token::$kw_name => write!(f, $kw_str),)*
$(Token::$other_name(v) => write!(f, "{v}"),)*
}