todown-rs

A top-down parsing library for Rust.

Usage

```

![allow(unused_variables)]

![feature(phase)]

extern crate topdown;

[phase(plugin)]

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<|int, int|:'a->int> { return runparser!( cs >> &re("\+|-") -> |o| match o.asslice() { "+" => |a:int, b:int| a+b, "-" => |a:int, b:int| a-b, _ => panic!(o) } ) }

fn op2<'a>(cs: &mut CharSeq) -> ParserResult<|int, int|:'a->int> { return runparser!( cs >> &re("\*|/|%") -> |o| match o.asslice() { "" => |a:int, b:int| ab, "/" => |a:int, b:int| a/b, "%" => |a:int, b:int| a%b, _ => 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