до начала
Прежде чем писать компилятор, давайте взглянем на базовую структуру проекта.RustСоздание проектов действительно очень удобно, если
$ cargo new lox-rs --bin
создатьbin
проект, то я напрямую использую последнююnightlyверсияRustКомпилятор, потому что при написании такого рода приложений практически не встречается ни один компилятор.bug, так что вы можете использовать его с уверенностьюnightlyВерсия.
Чтобы унифицировать стиль кода, сначала создайтеrustfmt.toml, контента не так много, а остальные сохраняются по умолчанию, эти должны быть специально стандартизированы.
max_width = 120
fn_call_width = 100
tab_spaces = 2
Когда вам нужно отправить, используйтеrustfmtФорматировать код.
Cargo.toml добавляет несколько сторонних зависимостей, а также текущий локальныйcoreПакет содержит исходный код компилятора, который нам нужно реализовать.
[package]
name = "lox-rs"
version = "0.1.0"
edition = "2021"
authors = ["Limit Liu <limitliu@qq.com>"]
[workspace]
[dependencies]
core = { path = "core" }
ansi_term = "0.12"
rustyline = "9.0.0"
getopts = "0.2"
В итоге структура нашего проекта выглядит так
$ tree ./
├── Cargo.lock
├── Cargo.toml
├── README.md
├── core
│ ├── Cargo.toml
│ └── src
│ ├── common
│ │ └── mod.rs
│ ├── lexer
│ │ └── mod.rs
│ ├── lib.rs
│ └── parser
│ └── mod.rs
├── pbcopy
├── rustfmt.toml
└── src
├── lib.rs
├── main.rs
├── repl.rs
└── run.rs
6 directories, 14 files
ansi_termПакеты используются для отображения цветов в терминале, а также языка реализацииREPL, использоватьrustylineЭто будет относительно просто, иначе вам придется вручную реализовывать такие операции, как клавиши со стрелками, что очень хлопотно.getopts — это пакет, связанный с программой управления терминалом и параметрами. На самом деле сейчасRustВскоре я хочу отказаться от Edition 2021, Nightly смог напрямую использовать Edition 2021.
Лично я стараюсь не использовать сторонние библиотеки для реализации некоторых функций, а некоторые терминальные, слишком много деталей влияет на изучение темы проекта. картинаGCЭтот контент также доступен в готовых пакетах, его действительно легко использовать напрямую, но тогда вы не сможете изучить его реализацию, интереснее делать это вручную.
Затем заливаем контент в main.rs, а теперь основная реализация просто взаимодействовать с терминалом
use getopts::Options;
use std::env;
use lox_rs::repl;
use lox_rs::run;
fn print_usage(program: &str, opts: Options) {
let brief = format!(
"Usage: {} [OPTIONS] COMMAND [PARAMS]
Commands:
repl\t\tlaunch repl
run INPUT\t\tlaunch a script file",
program
);
print!("{}", opts.usage(&brief));
}
fn main() {
let args: Vec<String> = env::args().collect();
let program = args.first().unwrap();
let mut opts = Options::new();
opts.optflag("h", "help", "print this help menu");
let matches = opts.parse(&args[1..]).unwrap();
if matches.opt_present("h") || matches.free.is_empty() {
print_usage(program, opts);
return;
}
let command = matches.free[0].as_str();
match command {
"repl" => repl::main(),
"run" => match matches.free.get(1) {
Some(p) => run::main(p),
_ => print_usage(program, opts),
},
_ => print_usage(program, opts),
}
}
Сделайте это временно в repl.rs и run.rs
// repl
pub fn main() {
println!("The Lox programming language REPL");
}
// run
pub fn main(p: &str) {}
Теперь используйте команду cargo run для запуска проекта.После компиляции проигнорируйте предупреждение, зафиксируйте и отправьте на платформу хостинга git.
следовать заcoreПосле того, как контент наполнится, его нужно снова улучшить.cliнекоторые операции.