lalrproc 0.0.2

Procedural macro built on LALRPOP
LALRPOP parser for procedural macro input
=========================================

[![Build Status](https://api.travis-ci.org/dtolnay/lalrproc.svg?branch=master)](https://travis-ci.org/dtolnay/lalrproc)

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

[LALRPOP]: https://github.com/nikomatsakis/lalrpop

## 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.

```rust
extern crate lalrproc;
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.

[Syn]: https://github.com/dtolnay/syn
[proc-macro2]: https://github.com/alexcrichton/proc-macro2

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))`.

```rust
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
```

<br>

#### License

<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>

<br>

<sub>
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.
</sub>