2015-09-11 06:50:39 -04:00
|
|
|
# LALRPOP
|
2015-06-24 06:03:57 -07:00
|
|
|
|
2015-09-16 06:03:36 -04:00
|
|
|

|
|
|
|
|
2015-09-11 06:50:39 -04:00
|
|
|
LALRPOP is a Rust parser generator framework with *usability* as its
|
|
|
|
primary goal. You should be able to write compact, DRY, readable
|
|
|
|
grammars. To this end, LALRPOP offers a number of nifty features:
|
2015-06-24 05:53:24 -07:00
|
|
|
|
2016-02-19 05:53:01 -05:00
|
|
|
0. Nice error messages in case parser constructor fails.
|
2015-06-24 05:53:24 -07:00
|
|
|
1. Macros that let you extract common parts of your grammar. This
|
|
|
|
means you can go beyond simple repetition like `Id*` and define
|
|
|
|
things like `Comma<Id>` for a comma-separated list of identifiers.
|
|
|
|
2. Macros can also create subsets, so that you easily do something
|
|
|
|
like `Expr<"all">` to represent the full range of expressions, but
|
|
|
|
`Expr<"if">` to represent the subset of expressions that can appear
|
|
|
|
in an `if` expression.
|
2015-09-11 06:50:39 -04:00
|
|
|
3. Builtin support for operators like `*` and `?`.
|
|
|
|
4. Compact defaults so that you can avoid writing action code much of the
|
2015-06-24 05:53:24 -07:00
|
|
|
time.
|
2015-09-11 06:50:39 -04:00
|
|
|
5. Type inference so you can often omit the types of nonterminals.
|
|
|
|
|
|
|
|
Despite its name, LALRPOP in fact uses LR(1) by default (though you
|
|
|
|
can opt for LALR(1)), and really I hope to eventually move to
|
|
|
|
something general that can handle all CFGs (like GLL, GLR, LL(\*),
|
|
|
|
etc).
|
|
|
|
|
|
|
|
### Documentation
|
|
|
|
|
|
|
|
There is a [tutorial available here](doc/tutorial.md) that covers a
|
|
|
|
fair bit of the features of LALRPOP. For the more advanced things are
|
|
|
|
not yet covered, it also points you to tests that may help give you
|
2015-09-11 06:53:09 -04:00
|
|
|
the idea. I plan eventually to build up a reference manual in the
|
|
|
|
Wiki, but that's not even started.
|
2015-09-11 06:50:39 -04:00
|
|
|
|
|
|
|
### Obligatory disclaimer
|
2015-07-26 07:49:45 -04:00
|
|
|
|
2015-09-11 06:50:39 -04:00
|
|
|
LALRPOP is still in its relatively early days. Not all the features I
|
|
|
|
want are there, and the error messages are sometimes a bit opaque. But
|
|
|
|
it's quite powerful already. It's also [self-hosting], which is fun.
|
2015-07-26 07:49:45 -04:00
|
|
|
|
2015-09-11 06:50:39 -04:00
|
|
|
[self-hosting]: https://github.com/nikomatsakis/lalrpop/blob/master/lalrpop/src/parser/lrgrammar.lalrpop
|
2015-07-26 07:49:45 -04:00
|
|
|
|
2016-02-01 05:24:11 -05:00
|
|
|
### Using LALRPOP
|
|
|
|
|
2016-08-05 05:32:04 -04:00
|
|
|
#### Configuring cargo
|
2016-02-01 05:24:11 -05:00
|
|
|
|
|
|
|
There are two ways to use LALRPOP. The recommended way is to
|
|
|
|
configure Cargo to automatically change all `.lalrpop` files
|
|
|
|
into `.rs` files by adding a `build.rs` file. Here is a "cheat sheet"
|
|
|
|
for how to do that.
|
2015-09-10 09:57:00 -04:00
|
|
|
|
|
|
|
This section is for if you already know what you're doing and just
|
|
|
|
want to copy-and-paste some code for adding LALRPOP to your Cargo
|
|
|
|
project. To enable LALRPOP, add the following lines to your
|
|
|
|
`Cargo.toml`:
|
2015-07-26 07:49:45 -04:00
|
|
|
|
|
|
|
```
|
|
|
|
[package]
|
|
|
|
...
|
|
|
|
build = "build.rs" # LALRPOP preprocessing
|
|
|
|
|
|
|
|
# Add a dependency on the LALRPOP runtime library:
|
|
|
|
[dependencies.lalrpop-util]
|
2016-08-05 05:32:04 -04:00
|
|
|
version = "0.12.0"
|
2015-07-26 07:49:45 -04:00
|
|
|
|
|
|
|
[build-dependencies.lalrpop]
|
2016-08-05 05:32:04 -04:00
|
|
|
version = "0.12.0"
|
2015-07-26 07:49:45 -04:00
|
|
|
```
|
|
|
|
|
|
|
|
And create a `build.rs` file that looks like:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
extern crate lalrpop;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
lalrpop::process_root().unwrap();
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
(If you already have a `build.rs` file, you should be able to just
|
|
|
|
call `process_root` in addition to whatever else that file is doing.)
|
|
|
|
|
|
|
|
That's it!
|
2016-02-01 05:24:11 -05:00
|
|
|
|
2016-08-05 05:32:04 -04:00
|
|
|
#### More advanced configuration
|
|
|
|
|
|
|
|
The `process_root` applies the default configuration: so it will
|
|
|
|
transform `.lalrpop` files into `.rs` files *in-place* (in your `src`
|
|
|
|
directory), and it will only do so if the `.lalrpop` file has actually
|
|
|
|
changed. But you can also use the [`Configuration`][config] struct to
|
|
|
|
get more detailed control.
|
|
|
|
|
|
|
|
[config]: https://github.com/nikomatsakis/lalrpop/blob/master/lalrpop/src/apimod.rs
|
|
|
|
|
2016-02-01 05:24:11 -05:00
|
|
|
#### Running manually
|
|
|
|
|
2016-02-19 05:53:01 -05:00
|
|
|
If you prefer, you can also run the `lalrpop` crate as an
|
|
|
|
executable. Simply run `cargo install lalrpop` and then you will get a
|
|
|
|
`lalrpop` binary you can execute, like so:
|
2016-02-01 05:24:11 -05:00
|
|
|
|
|
|
|
```
|
2016-02-19 05:53:01 -05:00
|
|
|
lalrpop file.lalrpop
|
2016-02-01 05:24:11 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
This will generate `file.rs` for you. Note that it only executes if
|
|
|
|
`file.lalrpop` is newer than `file.rs`; if you'd prefer to execute
|
|
|
|
unconditionally, pass `-f` (also try `--help` for other options).
|
|
|
|
|