8 releases

0.0.8 Dec 19, 2022
0.0.7 Dec 27, 2020
0.0.6 Jun 14, 2020
0.0.5 Apr 30, 2019
0.0.1 Jan 12, 2018

#8 in #lalrpop

MIT/Apache

23KB
473 lines

LALRPOP parser for procedural macro input

github build status

This crate demostrates a proof of concept of using the LALRPOP parser generator framework to parse input tokens in a Rust procedural macro.

Macros

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);
}

Parser

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> ")",
};

Error reporting

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

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~0–1.9MB
~26K SLoC