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},
|
io::{self, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
use scanner::Scanner;
|
|
||||||
use token::Token;
|
use token::Token;
|
||||||
|
|
||||||
mod scanner;
|
mod scanner;
|
||||||
@ -14,37 +13,24 @@ mod utils;
|
|||||||
pub fn run_file(path: &str) -> Result<(), Box<dyn Error>> {
|
pub fn run_file(path: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let file = fs::read_to_string(path)?;
|
let file = fs::read_to_string(path)?;
|
||||||
|
|
||||||
run(&file);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(src: &str) {
|
pub fn run(src: &str) {
|
||||||
let mut scanner = Scanner::new(src.to_string());
|
let tokens: Vec<Token> = Vec::new();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_prompt() -> Result<(), Box<dyn Error>> {
|
pub fn run_prompt() -> Result<(), Box<dyn Error>> {
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
let input = &mut String::new();
|
let input = &mut String::new();
|
||||||
loop {
|
|
||||||
input.clear();
|
|
||||||
print!("> ");
|
print!("> ");
|
||||||
io::stdout().flush()?;
|
io::stdout().flush()?;
|
||||||
stdin.read_line(input)?;
|
loop {
|
||||||
run(input);
|
input.clear();
|
||||||
|
let _ = stdin.read_line(input)?;
|
||||||
|
|
||||||
|
print!("> ");
|
||||||
|
io::stdout().flush()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +40,12 @@ pub struct RloxError {
|
|||||||
line: usize,
|
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}");
|
eprintln!("[line {line}] Error {location}: {message}");
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ pub struct Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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
|
// 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
|
// rust doesn't allow having both the iterator and iterable inside one
|
||||||
// structure(understandably so bcs of reference invalidation)
|
// 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
|
// this is so awful for me to write. This function needs to be not mutable in theory and it
|
||||||
// could be accomplished. TODO!
|
// 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();
|
let mut errors = Vec::new();
|
||||||
while self.peek().is_some() {
|
while self.peek().is_some() {
|
||||||
self.start = self.current;
|
self.start = self.current;
|
||||||
@ -94,11 +94,10 @@ impl Scanner {
|
|||||||
}
|
}
|
||||||
'/' => self.add_token(TokenType::Slash),
|
'/' => self.add_token(TokenType::Slash),
|
||||||
'"' => error = self.string(),
|
'"' => error = self.string(),
|
||||||
|
'0'..='9' => self.number(),
|
||||||
' ' | '\r' | '\t' => (),
|
' ' | '\r' | '\t' => (),
|
||||||
'\n' => self.line += 1,
|
'\n' => self.line += 1,
|
||||||
|
|
||||||
'0'..='9' => self.number(),
|
|
||||||
'a'..='z' | 'A'..='Z' | '_' => self.identifier(),
|
|
||||||
_ => {
|
_ => {
|
||||||
error = Err(RloxError {
|
error = Err(RloxError {
|
||||||
msg: "Unexpected character".to_string(),
|
msg: "Unexpected character".to_string(),
|
||||||
@ -201,45 +200,6 @@ impl Scanner {
|
|||||||
|
|
||||||
self.add_token_literal(TokenType::Number, Some(LiteralType::Number(number)));
|
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)]
|
#[cfg(test)]
|
||||||
@ -352,7 +312,7 @@ mod tests {
|
|||||||
fn correct_fractional_number_scan() {
|
fn correct_fractional_number_scan() {
|
||||||
let value = r#"
|
let value = r#"
|
||||||
// number test
|
// number test
|
||||||
123.aaa"#
|
123.456"#
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let mut scanner = Scanner::new(value);
|
let mut scanner = Scanner::new(value);
|
||||||
|
Loading…
Reference in New Issue
Block a user