Mercurial > lbo > hg > arithmetal
view src/old_manual_parsers.rs @ 5:b02268b0d4b1 draft
Generalize two-hand expression parsing, and add parser for powers
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Wed, 23 Nov 2016 21:13:05 +0100 |
parents | |
children | ad77c2ad4853 |
line wrap: on
line source
fn expr<'a>(st: State<'a>) -> ParseResult { if st.len() == 0 { err("Empty", st) } else { // Test if addition or subtraction let mut paren_lvl = 0; let mut ix = 0; let mut op_pos: i32 = -1; for c in st.iter() { if c == '(' { paren_lvl += 1; } else if c == ')' { paren_lvl -= 1; } else if paren_lvl == 0 && (c == '+' || c == '-') { // yep! op_pos = ix; break; } ix += 1; } if op_pos > -1 { let left = pexpr(st.restrict(0, op_pos as usize)); let right = pexpr(st.restrict(op_pos as usize + 1, st.len())); if left.ok() && right.ok() { match (left, right) { (ParseResult::Ok(a1), ParseResult::Ok(a2)) => { if st.at(op_pos as usize) == '-' { ParseResult::Ok(Ast::Subtraction(Box::new(a1), Box::new(a2))) } else { ParseResult::Ok(Ast::Addition(Box::new(a1), Box::new(a2))) } } _ => panic!("Expected OK results"), } } else if !left.ok() { err("Left part of expr is bad", st) } else { err("Right or both parts of expr is|are bad", st) } } else { term(st) } } } fn term<'a>(st: State<'a>) -> ParseResult { if st.len() == 0 { err("Empty", st) } else { // Test if addition or subtraction let mut paren_lvl = 0; let mut ix = 0; let mut op_pos: i32 = -1; // Look for operator at top level for c in st.iter() { if c == '(' { paren_lvl += 1; } else if c == ')' { paren_lvl -= 1; } else if paren_lvl == 0 && (c == '*' || c == '/') { // yep! op_pos = ix; break; } ix += 1; } if op_pos > -1 { let left = pexpr(st.restrict(0, op_pos as usize)); let right = pexpr(st.restrict(op_pos as usize + 1, st.len())); if left.ok() && right.ok() { match (left, right) { (ParseResult::Ok(a1), ParseResult::Ok(a2)) => { if st.at(op_pos as usize) == '*' { ParseResult::Ok(Ast::Multiplication(Box::new(a1), Box::new(a2))) } else { ParseResult::Ok(Ast::Division(Box::new(a1), Box::new(a2))) } } _ => panic!("Expected OK results"), } } else if !left.ok() { err("Left part of term is bad", st) } else { err("Right or both parts of term is|are bad", st) } } else { sym(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) } }