extern crate gobble;
use gobble::*;
#[derive(Debug)]
pub enum Op {
Add,
Sub,
Div,
Mul,
}
enum_parser! { (OP,op,Op) =>
((ADD->Op::Add) '+'),
((SUB->Op::Sub) '-'),
((DIV->Op::Div) '/'),
((MUL->Op::Mul) '*'),
}
#[derive(Debug)]
pub enum Expr {
Val(isize),
Parenth(Box<Expr>),
Oper(Op, Box<Expr>, Box<Expr>),
}
parser! {
(LtExpr->Expr)
or(
common::Int.map(|i| Expr::Val(i)),
middle("(", RtExpr, ")").map(|e| Expr::Parenth(Box::new(e)))
)
}
parser! {
(RtExpr->Expr)
(LtExpr, maybe((OP, RtExpr))).map(|(l, opt)| match opt {
Some((oper, r)) => Expr::Oper(oper, Box::new(l), Box::new(r)),
None => l,
})
}
fn main() -> Result<(), std::io::Error> {
let stdin = std::io::stdin();
loop {
let mut s = String::new();
match stdin.read_line(&mut s) {
Ok(0) => return Ok(()),
Err(e) => return Err(e),
_ => {}
}
match first(RtExpr, ("\n", eoi)).parse_s(&s) {
Ok(v) => println!("{:?}", v),
Err(e) => println!("{}", e),
}
}
}