Lox In Rust — базовая структура проекта

Rust Принцип составления
Lox In Rust — базовая структура проекта

до начала

Прежде чем писать компилятор, давайте взглянем на базовую структуру проекта.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некоторые операции.