Update lexer.rs

This commit is contained in:
2024-03-15 11:27:12 -03:00
parent 4dd77025c3
commit ee8e9424d9

View File

@ -2,26 +2,35 @@ use std::iter::Peekable;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::str::Chars; use std::str::Chars;
/// Represents a primitive syntax token. #[derive(Clone, Debug, PartialEq)]
#[derive(Debug, Clone)] pub enum Keyword {
pub enum Token {
Comma,
Comment,
Const, Const,
Else, Else,
EOF,
For, For,
Function, Function,
Ident(String),
If, If,
Import, Import,
LParen, Return,
Var,
}
#[derive(Clone, Debug, PartialEq)]
pub enum TokenKind {
CloseBrace, // "}"
CloseBracket, // "]"
CloseParen, // ")"
Comma, // ","
Eof,
Ident(String),
Keyword(Keyword),
LineComment,
Number(f64), Number(f64),
Op(char), Op(char),
Return, OpenBrace, // "{"
RParen, OpenBracket, // "["
OpenParen, // "("
Semi, // ";"
SemiColon, SemiColon,
Var,
} }
/// Defines an error encountered by the `Lexer`. /// Defines an error encountered by the `Lexer`.
@ -47,7 +56,7 @@ impl LexerError {
/// Defines the result of a lexing operation; namely a /// Defines the result of a lexing operation; namely a
/// `Token` on success, or a `LexerError` on failure. /// `Token` on success, or a `LexerError` on failure.
pub type LexerResult = Result<Token, LexerError>; pub type LexerResult = Result<TokenKind, LexerError>;
pub struct Lexer<'a> { pub struct Lexer<'a> {
input: &'a str, input: &'a str,
@ -83,7 +92,7 @@ impl<'a> Lexer<'a> {
if ch.is_none() { if ch.is_none() {
self.pos = pos; self.pos = pos;
return Ok(Token::EOF); return Ok(TokenKind::Eof);
} }
if !ch.unwrap().is_whitespace() { if !ch.unwrap().is_whitespace() {
@ -99,17 +108,21 @@ impl<'a> Lexer<'a> {
let next = chars.next(); let next = chars.next();
if next.is_none() { if next.is_none() {
return Ok(Token::EOF); return Ok(TokenKind::Eof);
} }
pos += 1; pos += 1;
// Actually get the next token. // Actually get the next token.
let result = match next.unwrap() { let result = match next.unwrap() {
'(' => Ok(Token::LParen), ';' => Ok(TokenKind::Semi),
')' => Ok(Token::RParen), ',' => Ok(TokenKind::Comma),
',' => Ok(Token::Comma), '(' => Ok(TokenKind::OpenParen),
';' => Ok(Token::SemiColon), ')' => Ok(TokenKind::CloseParen),
'{' => Ok(TokenKind::OpenBrace),
'}' => Ok(TokenKind::CloseBrace),
'[' => Ok(TokenKind::OpenBracket),
']' => Ok(TokenKind::CloseBracket),
'#' => { '#' => {
// Comment // Comment
@ -122,7 +135,7 @@ impl<'a> Lexer<'a> {
} }
} }
Ok(Token::Comment) Ok(TokenKind::LineComment)
} }
'.' | '0'..='9' => { '.' | '0'..='9' => {
@ -130,7 +143,7 @@ impl<'a> Lexer<'a> {
loop { loop {
let ch = match chars.peek() { let ch = match chars.peek() {
Some(ch) => *ch, Some(ch) => *ch,
None => return Ok(Token::EOF), None => return Ok(TokenKind::Eof),
}; };
// Parse float. // Parse float.
@ -142,7 +155,7 @@ impl<'a> Lexer<'a> {
pos += 1; pos += 1;
} }
Ok(Token::Number(src[start..pos].parse().unwrap())) Ok(TokenKind::Number(src[start..pos].parse().unwrap()))
} }
'a'..='z' | 'A'..='Z' | '_' => { 'a'..='z' | 'A'..='Z' | '_' => {
@ -150,7 +163,7 @@ impl<'a> Lexer<'a> {
loop { loop {
let ch = match chars.peek() { let ch = match chars.peek() {
Some(ch) => *ch, Some(ch) => *ch,
None => return Ok(Token::EOF), None => return Ok(TokenKind::Eof),
}; };
// A word-like identifier only contains underscores and alphanumeric characters. // A word-like identifier only contains underscores and alphanumeric characters.
@ -163,22 +176,21 @@ impl<'a> Lexer<'a> {
} }
match &src[start..pos] { match &src[start..pos] {
"function" => Ok(Token::Function), "const" => Ok(TokenKind::Keyword(Keyword::Const)),
"import" => Ok(Token::Import), "else" => Ok(TokenKind::Keyword(Keyword::Else)),
"if" => Ok(Token::If), "for" => Ok(TokenKind::Keyword(Keyword::For)),
"else" => Ok(Token::Else), "function" => Ok(TokenKind::Keyword(Keyword::Function)),
"for" => Ok(Token::For), "if" => Ok(TokenKind::Keyword(Keyword::If)),
"var" => Ok(Token::Var), "import" => Ok(TokenKind::Keyword(Keyword::Import)),
"return" => Ok(Token::Return), "return" => Ok(TokenKind::Keyword(Keyword::Return)),
"const" => Ok(Token::Const), "var" => Ok(TokenKind::Keyword(Keyword::Var)),
ident => Ok(TokenKind::Ident(ident.to_string())),
ident => Ok(Token::Ident(ident.to_string())),
} }
} }
op => { op => {
// Parse operator // Parse operator
Ok(Token::Op(op)) Ok(TokenKind::Op(op))
} }
}; };
@ -190,13 +202,13 @@ impl<'a> Lexer<'a> {
} }
impl<'a> Iterator for Lexer<'a> { impl<'a> Iterator for Lexer<'a> {
type Item = Token; type Item = TokenKind;
/// Lexes the next `Token` and returns it. /// Lexes the next `Token` and returns it.
/// On EOF or failure, `None` will be returned. /// On EOF or failure, `None` will be returned.
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
match self.lex() { match self.lex() {
Ok(Token::EOF) | Err(_) => None, Ok(TokenKind::Eof) | Err(_) => None,
Ok(token) => Some(token), Ok(token) => Some(token),
} }
} }