topdown-rs
A top-down parsing library for Rust.
Example
```rust
![allow(unused_variables)]
![allow(unstable)]
[macro_use]
extern crate topdown;
use topdown::{CharSeq, skip, Parser, wrap, choice, ParserResult, re, chainl};
use topdown::ParserResult::{Succ, Error, Fail};
fn op1<'a>(cs: &mut CharSeq) -> ParserResult isize + 'a>> {
return runparser!(
cs >> &re("\+|-"), |o|
match o.asslice() {
"+" => (Box::new(|&: a:isize, b:isize| a+b)) as Box isize + 'a>,
"-" => (Box::new(|&: a:isize, b:isize| a-b)) as Box isize + 'a>,
_ => panic!(o)
}
)
}
fn op2<'a>(cs: &mut CharSeq) -> ParserResult isize + 'a>> {
return runparser!(
cs >> &re("\*|/|%"), |o|
match o.asslice() {
"" => (Box::new(|&: a:isize, b:isize| ab)) as Box isize + 'a>,
"/" => (Box::new(|&: a:isize, b:isize| a/b)) as Box isize + 'a>,
"%" => (Box::new(|&: a:isize, b:isize| a%b)) as Box isize + 'a>,
_ => panic!(o)
}
)
}
fn digit(cs: &mut CharSeq) -> ParserResult {
runparser!(cs >> &re("-?[1-9][0-9]*"), |x| x.asslice().parse().unwrap())
}
[allow(unused_variables)]
fn factor(cs: &mut CharSeq) -> ParserResult {
run_parser!(
cs >> &"(", |i|
&wrap(expr), |e|
&")", |i2| e
)
}
fn term(cs: &mut CharSeq) -> ParserResult {
let f = wrap(factor);
let d = wrap(digit);
let l = [&d as &Parser, &f as &Parser];
let c = choice(&l);
let o = wrap(op2);
let cl = chainl(&c, &o, false);
cs.accept(&cl)
}
fn expr(cs: &mut CharSeq) -> ParserResult {
let t = wrap(term);
let o = wrap(op1);
let cl = chainl(&t, &o, false);
return cs.accept(&cl);
}
fn calc(e: &str) {
let mut cs = CharSeq::new(e, "");
let skip = skip(" ");
cs.add_hook(&skip);
match cs.accept(&wrap(expr)) {
Succ(x) => {
if !cs.eof() {
println!("error: {}", e);
} else {
println!("{}={}", e, x)
}
},
Fail(m, l) => println!("error: {}", e),
Error(m, l) => println!("error: {}", e)
}
}
fn main() {
calc("1 + 2 - 3 * 4");
calc("1 + (2 - 3) * 4");
calc("1 + (2 - 3)) * 4");
calc("1 + (2 - 3 * 4");
}
```
License
MIT