crafting-interpreters/rust/rox/src/lib.rs

76 lines
1.7 KiB
Rust
Raw Normal View History

//! Interpret the Lox language. Either compile (interpret for now though) some source code or run a
//! REPL.
2025-02-06 18:55:54 +01:00
use std::{
fs::{self},
io::{self, Write},
path::Path,
};
2025-02-12 10:30:51 +01:00
use interpreter::Interpreter;
use tracing::error;
2025-02-06 11:34:46 +01:00
2025-02-13 12:29:31 +01:00
pub mod callable;
2025-02-06 11:34:46 +01:00
pub mod cli;
2025-02-12 10:30:51 +01:00
pub mod environment;
2025-02-10 14:36:55 +01:00
pub mod expression;
2025-02-13 12:29:31 +01:00
pub mod function;
2025-02-11 11:19:56 +01:00
pub mod interpreter;
2025-02-06 18:55:54 +01:00
pub mod keywords;
2025-02-13 12:29:31 +01:00
pub mod native_functions;
2025-02-10 14:36:55 +01:00
pub mod parser;
2025-02-06 18:55:54 +01:00
pub mod scanner;
2025-02-12 10:30:51 +01:00
pub mod statement;
2025-02-06 18:55:54 +01:00
pub mod token;
pub mod tokenizer {
pub mod comment;
pub mod identifier;
pub mod interface;
pub mod lookahead;
pub mod newline;
pub mod number;
pub mod single_char;
pub mod string;
pub mod whitespace;
}
pub mod value;
2025-02-06 18:55:54 +01:00
/// Read the source code in a file and scan it to tokens.
2025-02-06 18:55:54 +01:00
pub fn compile(source: &Path) -> Result<(), io::Error> {
let input = fs::read_to_string(source)?;
2025-02-12 10:30:51 +01:00
let mut interpreter = Interpreter::default();
run(&input, &mut interpreter);
2025-02-06 18:55:54 +01:00
Ok(())
}
/// Run a Lox REPL until SIGINT.
2025-02-06 18:55:54 +01:00
pub fn repl() {
2025-02-12 10:30:51 +01:00
let mut interpreter = Interpreter::default();
2025-02-06 18:55:54 +01:00
loop {
print!("> ");
let _ = io::stdout().flush();
2025-02-06 11:34:46 +01:00
2025-02-06 18:55:54 +01:00
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(_) => {}
Err(e) => error!("{}", e),
}
let input = input.trim().to_string();
2025-02-12 10:30:51 +01:00
run(&input, &mut interpreter);
2025-02-11 11:19:56 +01:00
}
}
/// Evaluate a Lox input string and print errors or output.
2025-02-12 10:30:51 +01:00
fn run(input: &str, interpreter: &mut Interpreter) {
2025-02-11 11:19:56 +01:00
let tokens = scanner::tokenize(input);
2025-02-12 10:30:51 +01:00
match parser::ast(tokens) {
Ok(ast) => match interpreter.run(ast) {
Ok(_) => {}
2025-02-10 14:36:55 +01:00
Err(e) => error!("{e}"),
2025-02-11 11:19:56 +01:00
},
Err(e) => error!("{e}"),
2025-02-06 18:55:54 +01:00
}
}