Crates.io | lalrproc |
lib.rs | lalrproc |
version | 0.0.8 |
source | src |
created_at | 2018-01-12 19:03:36.070131 |
updated_at | 2022-12-19 17:40:30.363009 |
description | Procedural macro built on LALRPOP |
homepage | |
repository | https://github.com/dtolnay/lalrproc |
max_upload_size | |
id | 46562 |
size | 37,588 |
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