mirror of
https://github.com/TheM1Stery/izanami.git
synced 2025-04-20 08:51:12 +00:00
Compare commits
No commits in common. "4df4107b776f262c96a7cde068842c6574966a94" and "2bac50ecbab3a99575cce0eec2e7b567f3ab4848" have entirely different histories.
4df4107b77
...
2bac50ecba
36
src/lib.rs
36
src/lib.rs
@ -4,7 +4,6 @@ use std::{
|
||||
io::{self, Write},
|
||||
};
|
||||
|
||||
use scanner::Scanner;
|
||||
use token::Token;
|
||||
|
||||
mod scanner;
|
||||
@ -14,37 +13,24 @@ mod utils;
|
||||
pub fn run_file(path: &str) -> Result<(), Box<dyn Error>> {
|
||||
let file = fs::read_to_string(path)?;
|
||||
|
||||
run(&file);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(src: &str) {
|
||||
let mut scanner = Scanner::new(src.to_string());
|
||||
let tokens = scanner.scan_tokens();
|
||||
|
||||
match tokens {
|
||||
Err(ref errors) => {
|
||||
for err in errors {
|
||||
report(err.line, "", &err.msg);
|
||||
}
|
||||
}
|
||||
Ok(tokens) => {
|
||||
for token in tokens {
|
||||
println!("{}", token);
|
||||
}
|
||||
}
|
||||
}
|
||||
let tokens: Vec<Token> = Vec::new();
|
||||
}
|
||||
|
||||
pub fn run_prompt() -> Result<(), Box<dyn Error>> {
|
||||
let stdin = io::stdin();
|
||||
let input = &mut String::new();
|
||||
loop {
|
||||
input.clear();
|
||||
print!("> ");
|
||||
io::stdout().flush()?;
|
||||
stdin.read_line(input)?;
|
||||
run(input);
|
||||
loop {
|
||||
input.clear();
|
||||
let _ = stdin.read_line(input)?;
|
||||
|
||||
print!("> ");
|
||||
io::stdout().flush()?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +40,12 @@ pub struct RloxError {
|
||||
line: usize,
|
||||
}
|
||||
|
||||
pub fn report(line: usize, location: &str, message: &str) {
|
||||
impl RloxError {
|
||||
pub fn error(line: i32, message: &str) {
|
||||
report(line, "", message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report(line: i32, location: &str, message: &str) {
|
||||
eprintln!("[line {line}] Error {location}: {message}");
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub struct Scanner {
|
||||
}
|
||||
|
||||
impl Scanner {
|
||||
pub fn new(source: String) -> Self {
|
||||
fn new(source: String) -> Self {
|
||||
// the reason for using unsafe here is to have the ability to use utf-8 symbols
|
||||
// rust doesn't allow having both the iterator and iterable inside one
|
||||
// structure(understandably so bcs of reference invalidation)
|
||||
@ -35,7 +35,7 @@ impl Scanner {
|
||||
|
||||
// this is so awful for me to write. This function needs to be not mutable in theory and it
|
||||
// could be accomplished. TODO!
|
||||
pub fn scan_tokens(&mut self) -> Result<&Vec<Token>, Vec<RloxError>> {
|
||||
fn scan_tokens(&mut self) -> Result<&Vec<Token>, Vec<RloxError>> {
|
||||
let mut errors = Vec::new();
|
||||
while self.peek().is_some() {
|
||||
self.start = self.current;
|
||||
@ -94,11 +94,10 @@ impl Scanner {
|
||||
}
|
||||
'/' => self.add_token(TokenType::Slash),
|
||||
'"' => error = self.string(),
|
||||
'0'..='9' => self.number(),
|
||||
' ' | '\r' | '\t' => (),
|
||||
'\n' => self.line += 1,
|
||||
|
||||
'0'..='9' => self.number(),
|
||||
'a'..='z' | 'A'..='Z' | '_' => self.identifier(),
|
||||
_ => {
|
||||
error = Err(RloxError {
|
||||
msg: "Unexpected character".to_string(),
|
||||
@ -201,45 +200,6 @@ impl Scanner {
|
||||
|
||||
self.add_token_literal(TokenType::Number, Some(LiteralType::Number(number)));
|
||||
}
|
||||
|
||||
fn identifier(&mut self) {
|
||||
while self.peek().is_some_and(is_alpha_numeric) {
|
||||
self.advance();
|
||||
}
|
||||
|
||||
let text_value = self.source.slice(self.start..self.current);
|
||||
if let Some(identified_token) = get_identified_keyword(text_value) {
|
||||
return self.add_token(identified_token);
|
||||
}
|
||||
|
||||
self.add_token(TokenType::Identifier);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_alpha_numeric(chr: char) -> bool {
|
||||
matches!(chr ,'0'..='9'| '_' | 'a'..='z'|'A'..='Z')
|
||||
}
|
||||
|
||||
fn get_identified_keyword(identifier: &str) -> Option<TokenType> {
|
||||
match identifier {
|
||||
"and" => Some(TokenType::And),
|
||||
"class" => Some(TokenType::Class),
|
||||
"else" => Some(TokenType::Else),
|
||||
"false" => Some(TokenType::False),
|
||||
"for" => Some(TokenType::For),
|
||||
"fun" => Some(TokenType::Fun),
|
||||
"if" => Some(TokenType::If),
|
||||
"nil" => Some(TokenType::Nil),
|
||||
"or" => Some(TokenType::OR),
|
||||
"print" => Some(TokenType::Print),
|
||||
"return" => Some(TokenType::Return),
|
||||
"super" => Some(TokenType::Super),
|
||||
"this" => Some(TokenType::This),
|
||||
"true" => Some(TokenType::True),
|
||||
"var" => Some(TokenType::Var),
|
||||
"while" => Some(TokenType::While),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -352,7 +312,7 @@ mod tests {
|
||||
fn correct_fractional_number_scan() {
|
||||
let value = r#"
|
||||
// number test
|
||||
123.aaa"#
|
||||
123.456"#
|
||||
.to_string();
|
||||
|
||||
let mut scanner = Scanner::new(value);
|
||||
|
Loading…
Reference in New Issue
Block a user