diff --git a/examples/main3.rs b/aron.rs similarity index 100% rename from examples/main3.rs rename to aron.rs diff --git a/examples/climb.rs b/examples/climb.rs index 49ecb09f2ed83266a7ec46cd92cde3e2ee1226d0..de59ff6fba7b5f650c968f978f08ad31074a1750 100644 --- a/examples/climb.rs +++ b/examples/climb.rs @@ -144,6 +144,7 @@ fn main() { test("2+3**2**3*5+1", 2 + 3i32.pow(2u32.pow(3)) * 5 + 1); test("(12*2)/3-4", (12 * 2) / 3 - 4); test("1*2+3", 1 * 2 + 3); + // just to check that we get a parse error test("1*2+3+3*21-a12+2", 1 * 2 + 3 + 3 * 21 - 12 + 2); } diff --git a/examples/main2.rs b/examples/main2.rs deleted file mode 100644 index 787cd45d4ac1a10d5340c6963d77362dc4b389f5..0000000000000000000000000000000000000000 --- a/examples/main2.rs +++ /dev/null @@ -1,198 +0,0 @@ -extern crate nom; - -use nom::combinator::map_res; -use nom::{ - branch::alt, - bytes::complete::tag, - character::complete::{digit1, multispace0}, - combinator::map, - error::{context, VerboseError, VerboseErrorKind}, - sequence::{preceded, tuple}, - IResult, -}; - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Pow, -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Expr { - Num(i32), - 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()) - })(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_expr(i: &str) -> IResult<&str, Expr> { - preceded( - multispace0, - alt(( - map( - tuple((parse_i32, preceded(multispace0, parse_op), parse_expr)), - |(l, op, r)| Expr::BinOp(Box::new(l), op, Box::new(r)), - ), - parse_i32, - )), - )(i) -} - -fn math_expr(e: &Expr) -> String { - match e { - Expr::Num(i) => format!("{}", i), - Expr::BinOp(l, op, r) => { - format!("({:?}, {}, {})", op, math_expr(l), math_expr(r)) - } - } -} - -fn math_eval(e: &Expr) -> i32 { - match e { - Expr::Num(i) => *i, - Expr::BinOp(l, op, 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), - } - } - } -} - -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), - } -} - -// 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 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), 0), v); -// } - -// #[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 {}", math_expr(&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); - // climb_test("1+2*3-4+5", 1 + 2 * 3 - 4 + 5); - climb_test("1", 1); - climb_test("1+2", 1 + 2); -} diff --git a/examples/main4.rs b/examples/main4.rs deleted file mode 100644 index b5d0653b78812b98b8eb9296a5d503206b93cd4a..0000000000000000000000000000000000000000 --- a/examples/main4.rs +++ /dev/null @@ -1,240 +0,0 @@ -extern crate nom; - -use nom::{ - branch::alt, - bytes::complete::tag, - character::complete::{digit1, multispace0}, - combinator::map, - sequence::{preceded, tuple}, - IResult, -}; - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Pow, -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Expr { - Num(i32), - BinOp(Box<Expr>, Op, Box<Expr>), -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Token { - Num(i32), - Op(Op), -} - -pub fn parse_i32(i: &str) -> IResult<&str, Token> { - map(digit1, |digit_str: &str| { - Token::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_expr(i: &str) -> IResult<&str, Vec<Token>> { - preceded( - multispace0, - alt(( - map( - tuple((parse_i32, preceded(multispace0, parse_op), parse_expr)), - |(l, op, r)| { - let mut v = Vec::new(); - v.push(l); - v.push(Token::Op(op)); - v.extend(r); - v - }, - ), - map(parse_i32, |i| { - let mut v = Vec::new(); - v.push(i); - v - }), - )), - )(i) -} - -fn math_expr(e: &Expr) -> String { - match e { - Expr::Num(i) => format!("{}", i), - Expr::BinOp(l, op, r) => { - format!("({:?}, {}, {})", op, math_expr(l), math_expr(r)) - } - } -} - -fn math_eval(e: &Expr) -> i32 { - match e { - Expr::Num(i) => *i, - Expr::BinOp(l, op, 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), - } - } - } -} - -#[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), - } -} - -// boilerplate -// compute_expr(min_prec): -// result = compute_atom() - -// while cur token is a binary operator with precedence >= min_prec: -// prec, assoc = precedence and associativity of current token -// if assoc is left: -// next_min_prec = prec + 1 -// else: -// next_min_prec = prec -// rhs = compute_expr(next_min_prec) -// result = compute operator(result, rhs) - -// return result - -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.pop().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); -// } diff --git a/examples/main5.rs b/examples/main5.rs deleted file mode 100644 index 7b41a4bbcd6b96c32c53a8f79f1cb25bbe21306c..0000000000000000000000000000000000000000 --- a/examples/main5.rs +++ /dev/null @@ -1,217 +0,0 @@ -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, - Minus, - Not, - Par -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Expr { - Atom(Atom), - BinOp(Op, Box<Expr>, Box<Expr>), - Unary(Op, Box<Expr>), -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Atom { - Num(i32), - // Identifier - // Function application -} - - -pub fn parse_i32(i: &str) -> IResult<&str, Expr> { - map(digit1, |digit_str: &str| { - Expr::Atom(Atom::Num(digit_str.parse::<i32>().unwrap())) - })(i) -} - -fn parse_uop(i: &str) -> IResult<&str, Op> { - preceded( - multispace0, - alt((map(tag("-"), |_| Op::Minus), map(tag("!"), |_| Op::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)| { - m.iter() - .fold(t, |l, (op, r)| climb(l, op.clone(), r.clone())) - }, - )(i) -} - -fn binop(op: Op, l: Expr, r: Expr) -> Expr { - Expr::BinOp(op, Box::new(l), Box::new(r)) -} - -fn climb(l: Expr, op: Op, r: Expr) -> Expr { - match r.clone() { - Expr::BinOp(r_op, r_l, r_r) => { - let (prec, ass) = climb_op(&op); - let (r_prec, _) = climb_op(&r_op); - if r_prec - < prec - + match ass { - Ass::Left => 1, - _ => 0, - } - { - binop(r_op, binop(op, l, *r_l), *r_r) - } else { - binop(op, l, r) - } - } - _ => binop(op, l, r), - } -} - -fn parse_multiplicative(i: &str) -> IResult<&str, Expr> { - map( - tuple(( - parse_terminal, - many0(tuple((parse_mulop, parse_multiplicative))), - )), - |(t, m)| { - m.iter() - .fold(t, |l, (op, r)| climb(l, op.clone(), r.clone())) - }, - )(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)) - }), - map(parse_parenthesis(parse_expr), |e| Expr::Unary(Op::Par, Box::new(e))) - )), - )(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-(1+1)-1)").unwrap().1; - println!("{:?} {} {}", p, math_eval(&p), 1-(1+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::Atom(Atom::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::Atom(Atom::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!(), - } - }, - Expr::Unary(op, e) => { - let e = math_eval(e); - match op { - Op::Par => e, - Op::Mul => -e, - _ => 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), - _ => unimplemented!(), - } -} -