2015-12-25 02:03:11 -08:00
|
|
|
use std::iter::Peekable;
|
|
|
|
use std::slice::Iter;
|
2015-12-28 22:27:26 -08:00
|
|
|
use std::vec::IntoIter;
|
2015-12-24 22:01:59 -08:00
|
|
|
|
2015-12-25 02:03:11 -08:00
|
|
|
use tokenizer::Token;
|
2015-12-24 22:01:59 -08:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
2015-12-26 00:50:14 -08:00
|
|
|
pub enum AST {
|
2015-12-24 22:01:59 -08:00
|
|
|
BinOp(Box<AST>, Box<AST>, Box<AST>),
|
|
|
|
Number(f64),
|
|
|
|
Name(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ParseError {
|
|
|
|
err: String
|
|
|
|
}
|
|
|
|
|
2015-12-26 00:50:14 -08:00
|
|
|
pub type ParseResult<T> = Result<T, ParseError>;
|
2015-12-24 22:01:59 -08:00
|
|
|
|
2015-12-25 02:03:11 -08:00
|
|
|
/* grammar
|
2015-12-24 22:01:59 -08:00
|
|
|
|
2015-12-25 02:03:11 -08:00
|
|
|
expr : term ((PLUS|MIMUS) term)*
|
|
|
|
term : factor ((MUL | DIV) factor)*
|
|
|
|
factor : NUM | LPAREN expr RPAREN
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2015-12-28 22:27:26 -08:00
|
|
|
struct Parser {
|
|
|
|
tokens: Peekable<IntoIter<Token>>
|
2015-12-25 02:03:11 -08:00
|
|
|
}
|
|
|
|
|
2015-12-28 22:27:26 -08:00
|
|
|
impl Parser {
|
|
|
|
fn next(&mut self) -> Option<Token> {
|
|
|
|
self.tokens.next()
|
|
|
|
}
|
|
|
|
|
2015-12-29 03:32:08 -08:00
|
|
|
//TODO see if I can get rid of the need for this move
|
|
|
|
fn lookahead(&mut self) -> Option<Token> {
|
|
|
|
self.tokens.peek().map(|x| x.clone())
|
2015-12-28 22:27:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Parser {
|
2015-12-26 00:50:14 -08:00
|
|
|
|
|
|
|
fn expect(&mut self, expected: Token) -> ParseResult<()> {
|
2015-12-28 22:27:26 -08:00
|
|
|
match self.next() {
|
|
|
|
Some(ref next) if *next == expected => Ok(()),
|
2015-12-25 03:22:36 -08:00
|
|
|
Some(next) => {
|
2015-12-26 00:50:14 -08:00
|
|
|
let err = format!("Expected {:?} but got {:?}", expected, next);
|
2015-12-25 03:22:36 -08:00
|
|
|
return Err(ParseError { err: err });
|
|
|
|
},
|
|
|
|
None => {
|
2015-12-26 00:50:14 -08:00
|
|
|
let err = format!("Expected {:?} but got end of input", expected);
|
2015-12-25 03:22:36 -08:00
|
|
|
return Err(ParseError { err: err });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-12-25 02:03:11 -08:00
|
|
|
|
2015-12-28 23:11:26 -08:00
|
|
|
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) => {
|
|
|
|
let err = format!("Expected identifier `{}` but got {:?}", identifier_str, next);
|
|
|
|
Err(ParseError { err: err })
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
let err = format!("Expected identifier `{}` but got end of input", identifier_str);
|
|
|
|
Err(ParseError { err: err })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-29 03:32:08 -08:00
|
|
|
fn expect_num_literal(&mut self) -> ParseResult<f64> {
|
|
|
|
use tokenizer::Token::*;
|
|
|
|
match self.next() {
|
|
|
|
Some(NumLiteral(f)) => Ok(f),
|
|
|
|
Some(t) => {
|
|
|
|
let err = format!("Expected NumLiteral, but got {:?}", t);
|
|
|
|
Err(ParseError { err: err })
|
|
|
|
},
|
|
|
|
Nome => {
|
|
|
|
let err = format!("Expected NumLiteral but got end of input");
|
|
|
|
Err(ParseError { err: err })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-26 00:50:14 -08:00
|
|
|
fn parse(&mut self) -> ParseResult<AST> {
|
2015-12-25 02:03:11 -08:00
|
|
|
let r = self.expr();
|
2015-12-26 00:50:14 -08:00
|
|
|
try!(self.expect(Token::Separator));
|
|
|
|
try!(self.expect(Token::EOF));
|
2015-12-25 02:03:11 -08:00
|
|
|
r
|
|
|
|
}
|
|
|
|
|
2015-12-26 00:50:14 -08:00
|
|
|
fn expr(&mut self) -> ParseResult<AST> {
|
2015-12-29 03:32:08 -08:00
|
|
|
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<AST> {
|
|
|
|
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<AST> {
|
|
|
|
let n = try!(self.expect_num_literal());
|
|
|
|
Ok(AST::Number(n))
|
2015-12-25 02:03:11 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-26 00:50:14 -08:00
|
|
|
pub fn parse(input: Vec<Token>) -> ParseResult<AST> {
|
2015-12-28 22:27:26 -08:00
|
|
|
let mut iter = input.into_iter().peekable();
|
2015-12-25 02:03:11 -08:00
|
|
|
let mut parser = Parser { tokens: iter };
|
|
|
|
return parser.parse();
|
2015-12-24 22:01:59 -08:00
|
|
|
}
|
|
|
|
|