diff --git a/examples/main5.rs b/examples/main5.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ca37cd4133b59570e0c82785b3ca31b2e6dcb987
--- /dev/null
+++ b/examples/main5.rs
@@ -0,0 +1,332 @@
+extern crate nom;
+
+use nom::{
+    branch::alt,
+    bytes::complete::tag,
+    character::complete::char,
+    character::complete::{digit1, multispace0},
+    combinator::{cut, map, opt},
+    error::ParseError,
+    multi::{fold_many0, many0, separated_list},
+    sequence::{delimited, preceded, tuple},
+    IResult,
+};
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum Op {
+    Eq,
+    Neq,
+    Add,
+    Sub,
+    Mul,
+    Div,
+    Pow,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum UOp {
+    Minus,
+    Not,
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum Expr {
+    Num(i32),
+    BinOp(Op, Box<Expr>, Box<Expr>),
+    Unary(UOp, Box<Expr>),
+}
+
+pub fn parse_i32(i: &str) -> IResult<&str, Expr> {
+    map(digit1, |digit_str: &str| {
+        Expr::Num(digit_str.parse::<i32>().unwrap())
+    })(i)
+}
+
+fn parse_op(i: &str) -> IResult<&str, Op> {
+    alt((
+        map(tag("+"), |_| Op::Add),
+        map(tag("-"), |_| Op::Sub),
+        map(tag("*"), |_| Op::Mul),
+        map(tag("/"), |_| Op::Div),
+        map(tag("^"), |_| Op::Pow),
+    ))(i)
+}
+
+fn parse_uop(i: &str) -> IResult<&str, UOp> {
+    preceded(
+        multispace0,
+        alt((map(tag("-"), |_| UOp::Minus), map(tag("!"), |_| UOp::Not))),
+    )(i)
+}
+
+fn parse_mulop(i: &str) -> IResult<&str, Op> {
+    preceded(
+        multispace0,
+        alt((map(tag("*"), |_| Op::Mul), map(tag("/"), |_| Op::Div))),
+    )(i)
+}
+
+fn parse_addop(i: &str) -> IResult<&str, Op> {
+    preceded(
+        multispace0,
+        alt((map(tag("+"), |_| Op::Add), map(tag("-"), |_| Op::Sub))),
+    )(i)
+}
+
+//   expr       ::= eq-expr
+//   eq-expr    ::= add-expr ( ( '==' | '!=' ) add-expr ) *
+//   add-expr   ::= mul-expr ( ( '+' | '-' ) mul-expression ) *
+//   mul-expr   ::= primary ( ( '*' | '/' ) terminal ) *
+//   terminal   ::= '(' expr ')' | NUMBER | VARIABLE | '-' primary
+
+fn parse_expr(i: &str) -> IResult<&str, Expr> {
+    parse_additative(i)
+}
+
+fn parse_additative(i: &str) -> IResult<&str, Expr> {
+    //map(tuple((parse_terminal, opt(parse_rhs)), |((_,t), _)| t))(i)
+    map(
+        tuple((
+            parse_multiplicative,
+            many0(tuple((parse_addop, parse_multiplicative))),
+        )),
+        |(t, m)| {
+            println!("add: t {:?}, m {:?}", t, m);
+            let r = m.iter().fold(t, |l, (op, r)| {
+                println!("l {:?}, r {:?}", l, r);
+                Expr::BinOp(*op, Box::new(l), Box::new(r.clone()))
+            });
+            r
+        },
+    )(i)
+}
+
+fn parse_multiplicative(i: &str) -> IResult<&str, Expr> {
+    //map(tuple((parse_terminal, opt(parse_rhs)), |((_,t), _)| t))(i)
+    map(
+        tuple((
+            parse_terminal,
+            many0(tuple((parse_mulop, parse_multiplicative))),
+        )),
+        |(t, m)| {
+            println!("mul: t {:?}, m {:?}", t, m);
+            let r = m.iter().fold(t, |l, (op, r)| {
+                println!("l {:?}, r {:?}", l, r);
+                Expr::BinOp(*op, Box::new(l), Box::new(r.clone()))
+            });
+            r
+        },
+    )(i)
+}
+
+fn parse_terminal(i: &str) -> IResult<&str, Expr> {
+    preceded(
+        multispace0,
+        alt((
+            parse_i32,
+            map(tuple((parse_uop, parse_terminal)), |(uop, e)| {
+                Expr::Unary(uop, Box::new(e))
+            }),
+            parse_parenthesis(parse_expr),
+        )),
+    )(i)
+}
+
+// helpers
+fn parse_parenthesis<'a, O, F, E>(
+    inner: F,
+) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
+where
+    F: Fn(&'a str) -> IResult<&'a str, O, E>,
+    E: ParseError<&'a str>,
+{
+    // delimited allows us to split up the input
+    // cut allwos us to consume the input (and prevent backtracking)
+    delimited(char('('), preceded(multispace0, inner), cut(char(')')))
+}
+
+fn main() {
+    let p = parse_additative("(1+2)*(5-1-1)").unwrap().1;
+    println!("{:?} {} {}", p, math_eval(&p), (1 + 2) * (5 - 1 - 1));
+
+    let p = parse_additative("5*(20+2)/4").unwrap().1;
+    println!("{:?} {} {}", p, math_eval(&p), 5 * (20 + 2) / 4);
+}
+
+fn math_expr(e: &Expr) -> String {
+    match e {
+        Expr::Num(i) => format!("{}", i),
+        Expr::BinOp(op, l, r) => {
+            format!("({:?}, {}, {})", op, math_expr(l), math_expr(r))
+        }
+        Expr::Unary(op, e) => format!("({:?}, {})", op, math_expr(e)),
+    }
+}
+
+fn math_eval(e: &Expr) -> i32 {
+    match e {
+        Expr::Num(i) => *i,
+        Expr::BinOp(op, l, r) => {
+            let lv = math_eval(l);
+            let rv = math_eval(r);
+            match op {
+                Op::Add => lv + rv,
+                Op::Sub => lv - rv,
+                Op::Mul => lv * rv,
+                Op::Div => lv / rv,
+                Op::Pow => lv.pow(rv as u32),
+                _ => unimplemented!(),
+            }
+        }
+        _ => unimplemented!(),
+    }
+}
+
+// #[derive(Debug, Copy, Clone, PartialEq)]
+// enum Ass {
+//     Left,
+//     Right,
+// }
+
+// fn climb_op(op: &Op) -> (u8, Ass) {
+//     match op {
+//         Op::Add => (1, Ass::Left),
+//         Op::Sub => (1, Ass::Left),
+//         Op::Mul => (2, Ass::Left),
+//         Op::Div => (2, Ass::Left),
+//         Op::Pow => (3, Ass::Right),
+//     }
+// }
+
+// operator precedence parser
+// https://en.wikipedia.org/wiki/Operator-precedence_parser
+// parse_expression ()
+//     return parse_expression_1 (parse_primary (), 0)
+
+// parse_expression_1 (lhs, min_precedence)
+//     lookahead := peek next token
+//     while lookahead is a binary operator whose precedence is >= min_precedence
+//         op := lookahead
+//         advance to next token
+//         rhs := parse_primary ()
+//         lookahead := peek next token
+//         while lookahead is a binary operator whose precedence is greater
+//                  than op's, or a right-associative operator
+//                  whose precedence is equal to op's
+//             rhs := parse_expression_1 (rhs, lookahead's precedence)
+//             lookahead := peek next token
+//         lhs := the result of applying op with operands lhs and rhs
+//     return lhs
+
+// fn token_to_expr(t: Token) -> Expr {
+//     match t {
+//         Token::Num(i) => Expr::Num(i),
+//         _ => panic!(),
+//     }
+// }
+
+// fn climb(mut v: Vec<Token>, min_prec: u8) -> (Expr, Vec<Token>) {
+//     println!("in climb {:?}, {}", v, min_prec);
+//     let t = v.last().unwrap();
+//     let mut result = token_to_expr(*t);
+//     // loop {
+//     //     match v.pop() {
+//     //         Some(Token::Num(_)) => {
+//     //             println!("break num");
+//     //             break;
+//     //         }
+//     //         Some(Token::Op(op)) => {
+//     //             println!("result {:?}, op {:?}, v:{:?}", result, op, v);
+//     //             let (prec, assoc) = climb_op(&op);
+//     //             if prec < min_prec {
+//     //                 println!("break prec");
+//     //                 break;
+//     //             } else {
+//     //                 println!("push");
+//     //                 let next_min_prec =
+//     //                     if assoc == Ass::Left { 1 + prec } else { prec };
+//     //                 let (rhs, v_rest) = climb(v.clone(), next_min_prec);
+//     //                 v = v_rest;
+//     //                 println!("return from call, rhs {:?}, v {:?}", rhs, v);
+//     //                 println!("current result {:?}", result);
+//     //                 result = Expr::BinOp(Box::new(result), op, Box::new(rhs));
+//     //                 println!("new result {:?}", result);
+//     //             }
+//     //         }
+
+//     //         _ => {
+//     //             println!("reaced end");
+//     //             break;
+//     //         } // reached end
+//     //     }
+//     // }
+//     (result, v)
+// }
+
+// fn test_eq(s: &str, v: i32) {
+//     let mut p = parse_expr(s).unwrap().1;
+//     println!("{:?}", p);
+//     p.reverse();
+//     let e = climb(p, 0);
+//     println!("{:?}", e);
+
+//     println!("e = {}, v = {}", math_eval(&e.0), v);
+// }
+
+// fn main() {
+//     test_eq("1 + 2", 1 + 2);
+//     // test_eq("1 + 2 * 3", 1 + 2 * 3);
+//     // test_eq("3 * 4 + 5", 3 * 4 + 5);
+
+//     //     // 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);
+// }
+
+// // // #[test]
+// // // fn climb1() {
+// // //     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 climb4() {
+// // //     test_eq("2^5", 2i32.pow(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 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 {}\n", math_expr(&p));
+// //     let r = climb(p, 0);
+// //     println!("r {:?}", &r);
+// //     println!("math r {}", math_expr(&r));
+// //     println!("eval r {} = {} ", math_eval(&r), v);
+// // }