view src/old_manual_parsers.rs @ 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
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)
        }
    }
}