ちょっと必要になったきがするのでparserをかくためのものを探したり
サンプルを書いてみたりした。
個人的なメモ
What is the difference between parser generators and parser combinators? - Quora
compiler construction - What is the difference between LALR and LR parsing? - Stack Overflow
専門と離れているので適当に下調べ。
nom - Rust
combine - Rust
pest. The Elegant Parser
LALRPOP -
syntax-cli - npm
最初はlex(情報がたくさん),bison(情報がたくさん)に似てると書いてある
syntax-cliがいいかもしれないと思ったけど、
パーサーを生成するコマンドがbuild.rsでうまく自動化できなかったのでやめた。
結局最初から生成もセットで提供されている
lalrpopを使うことにした。
とりあえず式をパースするサンプルを書いた。

use std::str::FromStr;
use crate::ast::Node;
grammar;
NUM_INTEGER: i32 = r"[0-9]+" => i32::from_str(<>).unwrap();
IDENTIFIER: String = r"[a-zA-Z_][a-zA-Z0-9_$]*" => <>.to_string();
pub Expr: Node = {
<e:Expr> "+" <f:Factor> => Node::Binary{
op: "+",
left: Box::new(e),
right: Box::new(f),
},
Factor,
};
pub Factor: Node = {
<f:Factor> "*" <t:Term> => Node::Binary{
op: "*",
left: Box::new(f),
right: Box::new(t),
},
Term,
};
pub Term: Node = {
<n:NUM_INTEGER> => Node::Literal(n),
<ident:IDENTIFIER> => Node::Ident(ident),
"(" <Expr> ")",
};#[derive(Debug)] pub enum Node { Literal(i32), Ident(String), Binary { op: &'static str, left: Box<Node>, right: Box<Node>, }, }
#[macro_use] extern crate lalrpop_util; pub mod ast; pub mod parser; fn main() { println!("Hello, world!"); println!("{:?}", parser::ExprParser::new().parse("((22))")); println!("{:?}", parser::ExprParser::new().parse("(a_A0)")); println!("{:?}", parser::ExprParser::new().parse("(2+a)*4")); println!("{:?}", parser::ExprParser::new().parse("2+a*4")); println!("{:?}", parser::ExprParser::new().parse("5*4+b")); println!("{:?}", parser::ExprParser::new().parse("5*(4+b)")); }
Finished dev [unoptimized + debuginfo] target(s) in 1.68s
Running `target/debug/calc3`
Hello, world!
Ok(Literal(22))
Ok(Ident("a_A0"))
Ok(Binary { op: "*", left: Binary { op: "+", left: Literal(2), right: Ident("a") }, right: Literal(4) })
Ok(Binary { op: "+", left: Literal(2), right: Binary { op: "*", left: Ident("a"), right: Literal(4) } })
Ok(Binary { op: "+", left: Binary { op: "*", left: Literal(5), right: Literal(4) }, right: Ident("b") })
Ok(Binary { op: "*", left: Literal(5), right: Binary { op: "+", left: Literal(4), right: Ident("b") } })うーんよさそう?
ある文法をパースしたかったら
既存のプロジェクトを参考にできる
GitHub - RustPython/RustPython: A Python Interpreter written in Rust
GitHub - tcr/rust-verilog: Verilog parsing and generator crate.