diff --git a/examples/main2.rs b/examples/main2.rs index 7270d7a6e95c025aa76234d3e04a5291f68eb608..787cd45d4ac1a10d5340c6963d77362dc4b389f5 100644 --- a/examples/main2.rs +++ b/examples/main2.rs @@ -26,6 +26,18 @@ pub enum Expr { BinOp(Box<Expr>, Op, Box<Expr>), } +// // deep cloning (is it necessary) +// impl Clone for Expr { +// fn clone(&self) -> Expr { +// match self { +// Expr::BinOp(l, op, r) => Expr::BinOp ( +// l.clone(), *op, r.clone() +// ), +// Expr::Num(i) => Expr::Num(*i) +// } +// } +// } + pub fn parse_i32(i: &str) -> IResult<&str, Expr> { map(digit1, |digit_str: &str| { Expr::Num(digit_str.parse::<i32>().unwrap()) @@ -58,7 +70,9 @@ fn parse_expr(i: &str) -> IResult<&str, Expr> { fn math_expr(e: &Expr) -> String { match e { Expr::Num(i) => format!("{}", i), - Expr::BinOp(l, op, r) => format!("({} {:?} {})", math_expr(l), op, math_expr(r)), + Expr::BinOp(l, op, r) => { + format!("({:?}, {}, {})", op, math_expr(l), math_expr(r)) + } } } @@ -94,148 +108,91 @@ fn climb_op(op: &Op) -> (u8, Ass) { } } -fn climb(e: Expr) -> Expr { - println!("climb {:?}", &e); +// fn build_expr(l:&Expr, op:&Op, r:&Expr) -> Expr { +// Expr::BinOp(Box::new(*l), *op, Box::new(*r)) +// } + +fn climb(e: Expr, min_prec: u8) -> Expr { + println!("in climb {}, {}", math_expr(&e), min_prec); match e.clone() { Expr::Num(_) => e, Expr::BinOp(l, op, r) => { let (prec, ass) = climb_op(&op); - let new_r = *r; - match new_r.clone() { - Expr::Num(_) => e, - Expr::BinOp(r_l, r_op, r_r) => { - let (r_prec, r_ass) = climb_op(&r_op); - if r_prec - < prec - + match ass { - Ass::Left => 1, - Ass::Right => 0, - } - { - // push upwards - println!("push upwards {:?} {:?}", op, r_op); - let new_l = Expr::BinOp(Box::new(*l), op, Box::new(*r_l)); - let new_top = Expr::BinOp(Box::new(new_l), r_op, Box::new(climb(*r_r))); - new_top - } else { - Expr::BinOp(l, op, Box::new(climb(new_r))) - } - } + + let mut res = e.clone(); + let mut cur = e.clone(); + while let Expr::BinOp(l, op, r) = cur { + cur = *r.clone(); + let rhs = climb( + cur.clone(), + prec + match ass { + Ass::Left => 1, + Ass::Right => 0, + }, + ); + println!("rhs {}", math_expr(&rhs)); + res = Expr::BinOp(Box::new(res), op, Box::new(rhs)) } + + res } } } -fn test_eq(s: &str, v: i32) { - assert_eq!(math_eval(&climb(parse_expr(s).unwrap().1)), v); -} +// fn test_eq(s: &str, v: i32) { +// assert_eq!(math_eval(&climb(parse_expr(s).unwrap().1), 0), v); +// } -#[test] -fn climb1() { - test_eq("1-2+3", 1 - 2 + 3); -} +// #[test] +// fn climb1() { +// test_eq("1-2+3", 1 - 2 + 3); +// } -#[test] -fn climb2() { - test_eq("1*2+3", 1 * 2 + 3); -} +// #[test] +// fn climb2() { +// test_eq("1*2+3", 1 * 2 + 3); +// } -#[test] -fn climb3() { - test_eq("1*2+3*4-5", 1 * 2 + 3 * 4 - 5); -} +// #[test] +// fn climb3() { +// test_eq("1*2+3*4-5", 1 * 2 + 3 * 4 - 5); +// } -#[test] -fn climb4() { - test_eq("2^5", 2i32.pow(5)); -} +// #[test] +// fn climb4() { +// test_eq("2^5", 2i32.pow(5)); +// } -#[test] -fn climb5() { - test_eq("2*3+4+5", 2 * 3 + 4 + 5); -} +// #[test] +// fn climb5() { +// test_eq("2*3+4+5", 2 * 3 + 4 + 5); +// } -#[test] -fn climb6() { - test_eq("2*3-4*5-2", 2 * 3 - 4 * 5 - 2); -} +// #[test] +// fn climb6() { +// test_eq("2*3-4*5-2", 2 * 3 - 4 * 5 - 2); +// } -#[test] -fn climb_err() { - test_eq("2 + 2 ^ 5 -3", 2 + 2i32.pow(5 - 3)); -} +// #[test] +// fn climb_err() { +// test_eq("2 + 2 ^ 5 -3", 2 + 2i32.pow(5 - 3)); +// } fn climb_test(s: &str, v: i32) { let p = parse_expr(s).unwrap().1; println!("{:?}", &p); println!("math {}", math_expr(&p)); - let r = climb(p); + let r = climb(p, 0); println!("r {:?}", &r); println!("math r {}", math_expr(&r)); println!("eval r {} = {} ", math_eval(&r), v); } fn main() { - climb_test("2*5+10+10", 2*5+10+10); - climb_test("2*5+10*11-1", 2*5+10*11-1); - climb_test("2*5+10*11-2+12", 2*5+10*11-1+12); - // println!(); - // let p = parse_expr("3+2*5+27").unwrap().1; - // println!("{:?}", &p); - // println!("math {}", math_expr(&p)); - // let r = climb(p); - // println!("r {:?}", &r); - // println!("math r {}", math_expr(&r)); - // println!("eval r {} = {} ", math_eval(&r), 3 + 2 * 5 + 27); - - // println!(); - // let p = parse_expr("2*5+11*27+13").unwrap().1; - // println!("{:?}", &p); - // println!("math {}", math_expr(&p)); - // let r = climb(p); - // println!("r {:?}", &r); - // println!("math r {}", math_expr(&r)); - // println!("eval r {} = {} ", math_eval(&r), 2 * 5 + 11 * 27 + 13); - - // println!(); - // let p = parse_expr("1-2-3").unwrap().1; - // println!("{:?}", &p); - // println!("math {}", math_expr(&p)); - // let r = climb(p); - // println!("r {:?}", &r); - // println!("math r {}", math_expr(&r)); - // println!("eval r {} = {} ", math_eval(&r), 1 - 2 - 3); - - // let i = "1-2-3-4"; - // println!("\n{}", i); - // let p = parse_expr(i).unwrap().1; - // println!("{:?}", &p); - // println!("math {}", math_expr(&p)); - // println!("eval r {} = {} ", math_eval(&p), 1 - 2 - 3 - 4); - // let r = climb(p); - // println!("r {:?}", &r); - // println!("math r {}", math_expr(&r)); - // println!("eval r {} = {} ", math_eval(&r), ((1 - 2) - 3) - 4); - - // let i = "2*3-4*5-2"; - // println!("\n{}", i); - // let p = parse_expr(i).unwrap().1; - // println!("{:?}", &p); - // println!("math {}", math_expr(&p)); - // println!("eval r {} = {} ", math_eval(&p), 2 * 3 - 4 * 5 - 2); - // let r = climb(p); - // println!("r {:?}", &r); - // println!("math r {}", math_expr(&r)); - // println!("eval r {} = {} ", math_eval(&r), (2 * 3) - (4 * 5) - 2); - - // let i = "2^5-1"; - // println!("\n{}", i); - // let p = parse_expr(i).unwrap().1; - // println!("{:?}", &p); - // println!("math {}", math_expr(&p)); - // println!("eval r {} = {} ", math_eval(&p), 1 - 2 - 3 - 4); - // let r = climb(p); - // println!("r {:?}", &r); - // println!("math r {}", math_expr(&r)); - // println!("eval r {} = {} ", math_eval(&r), ((1 - 2) - 3) - 4); + // climb_test("2*5+10+10", 2*5+10+10); + // climb_test("2*5+10*11-1", 2*5+10*11-1); + // climb_test("2*5+10*11-2+12", 2*5+10*11-1+12); + // climb_test("1+2*3-4+5", 1 + 2 * 3 - 4 + 5); + climb_test("1", 1); + climb_test("1+2", 1 + 2); }