7 unstable releases
Uses old Rust 2015
0.3.3 | May 24, 2016 |
---|---|
0.3.2 | Feb 15, 2015 |
0.3.1 | Jan 27, 2015 |
0.2.0 | Jan 8, 2015 |
0.0.1 | Dec 27, 2014 |
#1 in #macro-use
1MB
1.5K
SLoC
Contains (ELF exe/lib, 2MB) examples/interpreter/main, (ELF exe/lib, 1MB) examples/calc/calc
topdown-rs
A top-down parsing library for Rust.
Example
#![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<Box<Fn(isize, isize) -> isize + 'a>> {
return run_parser!(
cs >> &re("\\+|-"), |o|
match o.as_slice() {
"+" => (Box::new(|&: a:isize, b:isize| a+b)) as Box<Fn(isize, isize) -> isize + 'a>,
"-" => (Box::new(|&: a:isize, b:isize| a-b)) as Box<Fn(isize, isize) -> isize + 'a>,
_ => panic!(o)
}
)
}
fn op2<'a>(cs: &mut CharSeq) -> ParserResult<Box<Fn(isize, isize) -> isize + 'a>> {
return run_parser!(
cs >> &re("\\*|/|%"), |o|
match o.as_slice() {
"*" => (Box::new(|&: a:isize, b:isize| a*b)) as Box<Fn(isize, isize) -> isize + 'a>,
"/" => (Box::new(|&: a:isize, b:isize| a/b)) as Box<Fn(isize, isize) -> isize + 'a>,
"%" => (Box::new(|&: a:isize, b:isize| a%b)) as Box<Fn(isize, isize) -> isize + 'a>,
_ => panic!(o)
}
)
}
fn digit(cs: &mut CharSeq) -> ParserResult<isize> {
run_parser!(cs >> &re("-?[1-9][0-9]*"), |x| x.as_slice().parse().unwrap())
}
#[allow(unused_variables)]
fn factor(cs: &mut CharSeq) -> ParserResult<isize> {
run_parser!(
cs >> &"(", |i|
&wrap(expr), |e|
&")", |i2| e
)
}
fn term(cs: &mut CharSeq) -> ParserResult<isize> {
let f = wrap(factor);
let d = wrap(digit);
let l = [&d as &Parser<isize>, &f as &Parser<isize>];
let c = choice(&l);
let o = wrap(op2);
let cl = chainl(&c, &o, false);
cs.accept(&cl)
}
fn expr(cs: &mut CharSeq) -> ParserResult<isize> {
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
Dependencies
~3.5MB
~76K SLoC