use std::iter::Peekable; use std::vec::IntoIter; use std::fmt; use tokenizer::Token; #[derive(Debug)] pub enum AST { BinOp(Box, Box, Box), Number(f64), Name(String), } impl fmt::Display for AST { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { &AST::Number(ref n) => write!(f, "{}", n), &AST::Name(ref s) => write!(f, "{}", s), astnode => write!(f, "UNEXPANDED AST NODE: {:?}", astnode) } } } #[derive(Debug)] pub struct ParseError { err: String } pub type ParseResult = Result; /* grammar expr : term ((PLUS|MIMUS) term)* term : factor ((MUL | DIV) factor)* factor : NUM | LPAREN expr RPAREN */ struct Parser { tokens: Peekable> } macro_rules! parse_error { ($($text:tt)*) => { Err(ParseError { err: format!($($text)*) }) } } impl Parser { fn next(&mut self) -> Option { self.tokens.next() } //TODO see if I can get rid of the need for this move fn lookahead(&mut self) -> Option { self.tokens.peek().map(|x| x.clone()) } } impl Parser { fn expect(&mut self, expected: Token) -> ParseResult<()> { match self.next() { Some(ref next) if *next == expected => Ok(()), Some(next) => { return parse_error!("Expected {:?} but got {:?}", expected, next); }, None => { return parse_error!("Expected {:?} but got end of input", expected); } } } fn expect_identifier(&mut self, identifier_str: &str) -> ParseResult<()> { use tokenizer::Token::*; match self.next() { Some(Identifier(ref s)) if s == identifier_str => Ok(()), Some(next) => { return parse_error!("Expected identifier `{}` but got {:?}", identifier_str, next); } None => { return parse_error!("Expected identifier `{}` but got end of input", identifier_str); } } } fn expect_num_literal(&mut self) -> ParseResult { use tokenizer::Token::*; match self.next() { Some(NumLiteral(f)) => Ok(f), Some(t) => { return parse_error!("Expected NumLiteral, but got {:?}", t); }, None => { return parse_error!("Expected NumLiteral but got end of input"); } } } fn parse(&mut self) -> ParseResult { let r = self.expr(); try!(self.expect(Token::Newline)); try!(self.expect(Token::EOF)); r } fn expr(&mut self) -> ParseResult { use tokenizer::Token::*; let mut lhs = try!(self.term()); loop { match self.lookahead() { Some(Identifier(ref s)) if s == "+" || s == "-" => { let op_token = self.next().unwrap(); let op = AST::Name(match op_token { Identifier(s) => s, _ => panic!("lol") }); let rhs = try!(self.term()); lhs = AST::BinOp( Box::new(lhs), Box::new(op), Box::new(rhs)); }, _ => break } } Ok(lhs) } fn term(&mut self) -> ParseResult { use tokenizer::Token::*; let mut lhs = try!(self.factor()); loop { match self.lookahead() { Some(Identifier(ref s)) if s == "*" || s == "/" => { let op_token = self.next().unwrap(); let op = AST::Name(match op_token { Identifier(s) => s, _ => panic!("lol") }); let rhs = try!(self.factor()); lhs = AST::BinOp( Box::new(lhs), Box::new(op), Box::new(rhs)); }, _ => break } } Ok(lhs) } fn factor(&mut self) -> ParseResult { use tokenizer::Token::*; match self.lookahead() { Some(LParen) => { self.next(); let expr = try!(self.expr()); try!(self.expect(RParen)); Ok(expr) }, Some(NumLiteral(n)) => { self.next(); Ok(AST::Number(n)) }, _ => parse_error!("Expected LParen or NumLiteral") } } } pub fn parse(input: Vec) -> ParseResult { let iter = input.into_iter().peekable(); let mut parser = Parser { tokens: iter }; return parser.parse(); }