Compare commits

..

No commits in common. "4df4107b776f262c96a7cde068842c6574966a94" and "2bac50ecbab3a99575cce0eec2e7b567f3ab4848" have entirely different histories.

2 changed files with 16 additions and 64 deletions

View File

@ -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}");
}

View File

@ -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);