ちょっと必要になったきがするので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.