diff --git a/src/parser.rs b/src/parser.rs index 2e5941b..4735fb8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -71,7 +71,7 @@ impl Parser { Parser { tokens: tokens } } - fn peek(&mut self) -> Option { + fn peek(&self) -> Option { self.tokens.last().map(|x| x.clone()) } @@ -79,7 +79,7 @@ impl Parser { self.tokens.pop() } - fn get_precedence(op: Op) -> Precedence { + fn get_precedence(&self, op: &Op) -> Precedence { match &op.repr[..] { "+" => 10, "-" => 10, @@ -208,8 +208,28 @@ impl Parser { self.precedence_expr(lhs, 0) } - fn precedence_expr(&mut self, lhs: Expression, min_precedence: u8) -> ParseResult { + fn precedence_expr(&mut self, mut lhs: Expression, min_precedence: u8) -> ParseResult { use tokenizer::Token::*; + while let Some(Operator(op)) = self.peek() { + let precedence = self.get_precedence(&op); + if precedence < min_precedence { + break; + } + self.next(); + let mut rhs = try!(self.primary_expression()); + while let Some(Operator(ref op)) = self.peek() { + if self.get_precedence(op) > precedence { + let new_prec = self.get_precedence(op); + rhs = try!(self.precedence_expr(rhs, new_prec)); + + } else { + break; + } + } + + lhs = Expression::BinExp(op.repr, Box::new(lhs), Box::new(rhs)); + } + Ok(lhs) } @@ -221,11 +241,11 @@ impl Parser { Some(Identifier(var)) => { self.next(); match self.peek() { - Some(LParen) => try!(self.call_expr()), + Some(Token::LParen) => try!(self.call_expr()), _ => Expression::Variable(var) } }, - Some(LParen) => { try!(self.paren_expr()) } + Some(Token::LParen) => { try!(self.paren_expr()) } Some(x) => return ParseError::result_from_str("Expected primary expression"), None => return ParseError::result_from_str("Expected primary expression received EoI") }; @@ -238,9 +258,9 @@ impl Parser { } fn paren_expr(&mut self) -> ParseResult { - expect!(self, LParen, "Expected LParen"); + expect!(self, Token::LParen, "Expected LParen"); let expr = try!(self.expression()); - expect!(self, RParen, "Expected LParen"); + expect!(self, Token::RParen, "Expected LParen"); Ok(expr) } } @@ -249,3 +269,28 @@ pub fn parse(tokens: &[Token], _parsed_tree: &[ASTNode]) -> ParseResult { let mut parser = Parser::initialize(tokens); parser.program() } + +#[cfg(test)] +mod tests { + use tokenizer; + use super::*; + + macro_rules! parsetest { + ($input:expr, $output:pat) => { + { + let tokens = tokenizer::tokenize($input).unwrap(); + let ast = parse(&tokens, &[]).unwrap(); + match &ast[..] { + $output => (), + x => panic!("Error in parse test, got {:?} instead", x) + } + } + } + } + + #[test] + fn parse_test() { + parsetest!("a", [ASTNode::ExprNode(Expression::Variable("a"))]); + } + +}