Mercurial > lbo > hg > arithmetal
changeset 6:ad77c2ad4853 draft default tip
Fix build breakage; move generic expression parser into own function
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Wed, 23 Nov 2016 21:36:09 +0100 |
parents | b02268b0d4b1 |
children | |
files | src/lib.rs src/old_manual_parsers.rs |
diffstat | 2 files changed, 55 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib.rs Wed Nov 23 21:13:05 2016 +0100 +++ b/src/lib.rs Wed Nov 23 21:36:09 2016 +0100 @@ -172,23 +172,57 @@ // Paren is closed somewhere if good { - expr(st) + // old expression parser: + // expr(st) + new_expr(st) } else { err("Missing closing paren", st) } } } else { + // old expression parser: // expr(st) - parse_twohand_expr(expr_op_map(), - |st2| { - parse_twohand_expr(term_op_map(), - |st3| parse_twohand_expr(pow_op_map(), sym, st3), - st2) - }, - st) + new_expr(st) } } +/// Parses an expression based on the generic twohand expression parser. +fn new_expr<'a>(st: State<'a>) -> ParseResult { + parse_twohand_expr(expr_op_map(), + |st2| { + parse_twohand_expr(term_op_map(), + |st3| parse_twohand_expr(pow_op_map(), sym, st3), + st2) + }, + st) +} + +fn sym<'a>(st: State<'a>) -> ParseResult { + if st.len() == 0 { + err("Empty", st) + } else if st.at(0) == '-' { + match num(st.restrict(1, st.len())) { + ParseResult::Ok(Ast::Num(n)) => ParseResult::Ok(Ast::Num(-n)), + x => x, + } + } else { + num(st) + } +} + +fn num<'a>(st: State<'a>) -> ParseResult { + if st.len() == 0 { + err("Empty", st) + } else if st.iter().all(|c| c >= '0' && c <= '9') { + let s = String::from_iter(st.iter()); + match i64::from_str(&s) { + Ok(n) => ParseResult::Ok(Ast::Num(n)), + Err(e) => err(&format!("int parse err: {}", e), st), + } + } else { + err("Not a number", st) + } +} type TwoHandBuilder = fn(Box<Ast>, Box<Ast>) -> Ast; type OperatorMap = HashMap<char, TwoHandBuilder>; @@ -213,7 +247,8 @@ map } -/// Parse any expression that has two sides and an infix operator (e.g. '4*5' or '6+7'). +/// Parse any expression that has two sides and an infix operator (e.g. '4*5' or '6+7'). Both sides +/// of the expression are parsed using pexpr(). /// /// opmap is a map from operator character to a function building an Ast fragment. /// @@ -311,19 +346,19 @@ let v = super::str_to_vec("2+4"); let st = super::state(&v); - assert_eq!(super::expr(st), + assert_eq!(super::pexpr(st), ParseResult::Ok(Ast::Addition(Box::new(Ast::Num(2)), Box::new(Ast::Num(4))))); let v = super::str_to_vec("2-4"); let st = super::state(&v); - assert_eq!(super::expr(st), + assert_eq!(super::pexpr(st), ParseResult::Ok(Ast::Subtraction(Box::new(Ast::Num(2)), Box::new(Ast::Num(4))))); let v = super::str_to_vec("2+4+5"); let st = super::state(&v); - assert_eq!(super::expr(st), + assert_eq!(super::pexpr(st), ParseResult::Ok(Ast::Addition(Box::new(Ast::Num(2)), Box::new(Ast::Addition(Box::new(Ast::Num(4)), Box::new(Ast::Num(5))))))); @@ -355,6 +390,14 @@ ParseResult::Ok(Ast::Multiplication(Box::new(Ast::Num(3)), Box::new(Ast::Num(6))))); + let v = super::str_to_vec("(3*6"); + let st = super::state(&v); + + assert_eq!(super::pexpr(st), + ParseResult::Err("Missing closing paren".to_string(), + "at 0-4: [(3*6]".to_string())); + + let v = super::str_to_vec("((3+6)*2)"); let st = super::state(&v);
--- a/src/old_manual_parsers.rs Wed Nov 23 21:13:05 2016 +0100 +++ b/src/old_manual_parsers.rs Wed Nov 23 21:36:09 2016 +0100 @@ -94,29 +94,3 @@ } } } -fn sym<'a>(st: State<'a>) -> ParseResult { - if st.len() == 0 { - err("Empty", st) - } else if st.at(0) == '-' { - match num(st.restrict(1, st.len())) { - ParseResult::Ok(Ast::Num(n)) => ParseResult::Ok(Ast::Num(-n)), - x => x, - } - } else { - num(st) - } -} - -fn num<'a>(st: State<'a>) -> ParseResult { - if st.len() == 0 { - err("Empty", st) - } else if st.iter().all(|c| c >= '0' && c <= '9') { - let s = String::from_iter(st.iter()); - match i64::from_str(&s) { - Ok(n) => ParseResult::Ok(Ast::Num(n)), - Err(e) => err(&format!("int parse err: {}", e), st), - } - } else { - err("Not a number", st) - } -}