Fully fixed binop parsing

This commit is contained in:
greg 2015-08-05 01:21:16 -07:00
parent 19a344fa77
commit 0da7f7e3a1

View File

@ -201,29 +201,36 @@ fn while_expression(tokens: &mut Tokens) -> ParseResult {
fn binop_expression(precedence: i32, tokens: &mut Tokens) -> ParseResult { fn binop_expression(precedence: i32, tokens: &mut Tokens) -> ParseResult {
//TODO left needs to match on an identifiers vs. a prefix operator and return *that* AST //TODO left needs to match on an identifiers vs. a prefix operator and return *that* AST
let left: AST = match simple_expression(tokens) { let mut left: AST = match simple_expression(tokens) {
err@ParseResult::Err(_) => return err, err@ParseResult::Err(_) => return err,
ParseResult::Ok(ast) => ast ParseResult::Ok(ast) => ast
}; };
let lookahead: Option<&Token> = tokens.peek().map(|i| i.clone()); loop {
let precedence = lookahead.and_then(|t| get_binop_precedence(t)); let lookahead: Option<&Token> = tokens.peek().map(|i| i.clone());
let next_precedence = lookahead.and_then(|t| get_binop_precedence(t));
if let None = precedence { match next_precedence {
return ParseResult::Ok(left); Some(next) if precedence < next => {
left = match binop_rhs(next, left, tokens) {
err@ParseResult::Err(_) => return err,
ParseResult::Ok(ast) => ast
};
},
_ => return ParseResult::Ok(left),
}
} }
binop_rhs(left, tokens)
} }
fn binop_rhs(lhs: AST, tokens: &mut Tokens) -> ParseResult { fn binop_rhs(precedence: i32, lhs: AST, tokens: &mut Tokens) -> ParseResult {
let op: AST = match simple_expression(tokens) { let op: AST = match simple_expression(tokens) {
err@ParseResult::Err(_) => return err, err@ParseResult::Err(_) => return err,
ParseResult::Ok(ast) => ast ParseResult::Ok(ast) => ast
}; };
let rhs: AST = match binop_expression(0, tokens) { let rhs: AST = match binop_expression(precedence, tokens) {
err@ParseResult::Err(_) => return err, err@ParseResult::Err(_) => return err,
ParseResult::Ok(ast) => ast ParseResult::Ok(ast) => ast
}; };
@ -244,8 +251,8 @@ fn get_binop_precedence(token: &Token) -> Option<i32> {
match &identifier_str[..] { match &identifier_str[..] {
"+" => Some(20), "+" => Some(20),
"-" => Some(20), "-" => Some(20),
"*" => Some(20), "*" => Some(40),
"/" => Some(20), "/" => Some(40),
_ => None _ => None
} }
} }