This commit is contained in:
2026-04-08 17:54:42 -04:00
parent 11ab9285f1
commit edabc22431
127 changed files with 382 additions and 10885 deletions
+161
View File
@@ -0,0 +1,161 @@
use super::{Span, Spanned};
use std::{iter::Peekable, str::CharIndices};
#[derive(PartialEq)]
pub enum Token {
// symbols
Equal,
Colon,
Semicolon,
OpenCurly,
CloseCurly,
OpenParen,
CloseParen,
Dash,
Plus,
Asterisk,
Slash,
// keywords
Let,
Fn,
// other
Ident(String),
Lit(Lit),
}
#[derive(PartialEq)]
pub enum Lit {
Number(String),
Bool(bool),
String(String),
}
impl From<Lit> for Token {
fn from(value: Lit) -> Self {
Self::Lit(value)
}
}
pub type TokenInst = Spanned<Token>;
pub struct Tokens<'a> {
text: Peekable<CharIndices<'a>>,
}
impl<'a> Tokens<'a> {
pub fn new(code: &'a str) -> Self {
Self {
text: code.char_indices().peekable(),
}
}
}
impl Iterator for Tokens<'_> {
type Item = Spanned<Token>;
fn next(&mut self) -> Option<Self::Item> {
let (i, c) = self.text.next()?;
let mut span = Span { first: i, last: i };
Some(Spanned {
inner: match c {
'=' => Token::Equal,
'{' => Token::OpenCurly,
'}' => Token::CloseCurly,
'(' => Token::OpenParen,
')' => Token::CloseParen,
':' => Token::Colon,
';' => Token::Semicolon,
'-' => Token::Dash,
'+' => Token::Plus,
'*' => Token::Asterisk,
'/' => Token::Slash,
'\n' | ' ' => {
return self.next();
}
'0'..='9' => {
let mut s = c.to_string();
while let Some((i, c)) = self.text.peek()
&& c.is_alphanumeric()
{
s.push(*c);
span.last = *i;
self.text.next();
}
Lit::Number(s).into()
}
'"' => {
let mut s = c.to_string();
while let Some((i, c)) = self.text.peek()
&& !matches!(c, '"')
{
s.push(*c);
span.last = *i;
self.text.next();
}
self.text.next();
Lit::String(s).into()
}
_ => {
let mut s = c.to_string();
while let Some((i, c)) = self.text.peek()
&& !matches!(
c,
'=' | '{' | '}' | '(' | ')' | ':' | ';' | '\n' | '"' | ' '
)
{
s.push(*c);
span.last = *i;
self.text.next();
}
match s.as_str() {
"let" => Token::Let,
"fn" => Token::Fn,
"true" => Lit::Bool(true).into(),
"false" => Lit::Bool(false).into(),
_ => Token::Ident(s),
}
}
},
span,
})
}
}
impl std::fmt::Display for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Token::Equal => write!(f, "="),
Token::Colon => write!(f, ":"),
Token::Plus => write!(f, "+"),
Token::Dash => write!(f, "-"),
Token::Asterisk => write!(f, "*"),
Token::Slash => write!(f, "/"),
Token::Semicolon => write!(f, ";"),
Token::OpenCurly => write!(f, "{{"),
Token::CloseCurly => write!(f, "}}"),
Token::OpenParen => write!(f, "("),
Token::CloseParen => write!(f, ")"),
Token::Let => write!(f, "let"),
Token::Fn => write!(f, "fn"),
Token::Ident(s) => write!(f, "{s}"),
Token::Lit(lit) => write!(f, "{lit}"),
}?;
Ok(())
}
}
impl std::fmt::Display for Lit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Lit::Number(n) => write!(f, "{n}"),
Lit::Bool(b) => write!(f, "{b}"),
Lit::String(s) => write!(f, "{s}"),
}
}
}
impl std::fmt::Debug for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "'{self}'")
}
}