Proof of concept of procedural macro input parsed by LALRPOP
Rust
52
72 commits
updated Dec 19, 2022
This crate demostrates a proof of concept of using the LALRPOP parser generator framework to parse input tokens in a Rust procedural macro.
The procedural macros in this example are s_expr! and s_type! which expand
to a string literal S-expression representation of the Rust expression or type
given in the input.
use lalrproc::{s_expr, s_type};
fn main() {
// Expands to "(+ (* 1 2) (* 3 4))"
let e = s_expr!(1 * 2 + 3 * 4);
// Expands to "(Reference 'a mut (Path module T))"
let t = s_type!(&'a mut module::T);
}
The input parsing is handled entirely by LALRPOP. In particular, Syn and proc-macro2 are not involved.
All of the features of LALRPOP are available to the LALRPOP grammar. For example
here is a subset of the expression grammar illustrating the parsing of something
like 1 * 2 + 3 * 4 into the syntax tree (+ (* 1 2) (* 3 4)).
pub Expr: Box<Expr> = {
Expr ExprOp Factor => Box::new(Expr::Binary(<>)),
Factor,
};
ExprOp: BinOp = {
"+" => BinOp::Add,
"-" => BinOp::Sub,
};
Factor: Box<Expr> = {
Factor FactorOp Component => Box::new(Expr::Binary(<>)),
Component,
};
FactorOp: BinOp = {
"*" => BinOp::Mul,
"/" => BinOp::Div,
};
Component: Box<Expr> = {
Literal => Box::new(Expr::Lit(<>)),
Path => Box::new(Expr::Path(<>)),
"(" <Expr> ")",
};
If the input does not conform to the grammar expected by the procedural macro, the error from LALRPOP is rendered in a way that indicates the problematic token and gives the tokens that would have been accepted by the grammar in that position.
error: failed to parse macro input
--> tests/test.rs:17:25
|
17 | let e = s_expr!(1 + : / 2);
| ^
|
= note: unrecognized token `:`
= note: expected one of `(`, identifier, or literal
72 commits
Rust
100.0%
Proof of concept of procedural macro input parsed by LALRPOP
Rust
52
72 commits
updated Dec 19, 2022
This crate demostrates a proof of concept of using the LALRPOP parser generator framework to parse input tokens in a Rust procedural macro.
The procedural macros in this example are s_expr! and s_type! which expand
to a string literal S-expression representation of the Rust expression or type
given in the input.
use lalrproc::{s_expr, s_type};
fn main() {
// Expands to "(+ (* 1 2) (* 3 4))"
let e = s_expr!(1 * 2 + 3 * 4);
// Expands to "(Reference 'a mut (Path module T))"
let t = s_type!(&'a mut module::T);
}
The input parsing is handled entirely by LALRPOP. In particular, Syn and proc-macro2 are not involved.
All of the features of LALRPOP are available to the LALRPOP grammar. For example
here is a subset of the expression grammar illustrating the parsing of something
like 1 * 2 + 3 * 4 into the syntax tree (+ (* 1 2) (* 3 4)).
pub Expr: Box<Expr> = {
Expr ExprOp Factor => Box::new(Expr::Binary(<>)),
Factor,
};
ExprOp: BinOp = {
"+" => BinOp::Add,
"-" => BinOp::Sub,
};
Factor: Box<Expr> = {
Factor FactorOp Component => Box::new(Expr::Binary(<>)),
Component,
};
FactorOp: BinOp = {
"*" => BinOp::Mul,
"/" => BinOp::Div,
};
Component: Box<Expr> = {
Literal => Box::new(Expr::Lit(<>)),
Path => Box::new(Expr::Path(<>)),
"(" <Expr> ")",
};
If the input does not conform to the grammar expected by the procedural macro, the error from LALRPOP is rendered in a way that indicates the problematic token and gives the tokens that would have been accepted by the grammar in that position.
error: failed to parse macro input
--> tests/test.rs:17:25
|
17 | let e = s_expr!(1 + : / 2);
| ^
|
= note: unrecognized token `:`
= note: expected one of `(`, identifier, or literal
72 commits
Rust
100.0%