write expect

and also make the ParseResult type more general so it can be used for
more things.
This commit is contained in:
greg 2015-12-26 00:50:14 -08:00
parent 186c900920
commit 32a90b8103

View File

@ -4,7 +4,7 @@ use std::slice::Iter;
use tokenizer::Token; use tokenizer::Token;
#[derive(Debug)] #[derive(Debug)]
enum AST { pub enum AST {
BinOp(Box<AST>, Box<AST>, Box<AST>), BinOp(Box<AST>, Box<AST>, Box<AST>),
Number(f64), Number(f64),
Name(String), Name(String),
@ -15,7 +15,7 @@ pub struct ParseError {
err: String err: String
} }
pub type ParseResult = Result<AST, ParseError>; pub type ParseResult<T> = Result<T, ParseError>;
/* grammar /* grammar
@ -29,38 +29,36 @@ struct Parser<'a> {
tokens: Peekable<Iter<'a, Token>> tokens: Peekable<Iter<'a, Token>>
} }
macro_rules! expect { impl<'a> Parser<'a> {
($tok:expr, $self_:ident) => {
match $self_.tokens.next() { fn expect(&mut self, expected: Token) -> ParseResult<()> {
Some(next) if *next == $tok => (), match self.tokens.next() {
Some(next) if *next == expected => Ok(()),
Some(next) => { Some(next) => {
let err = format!("Expected {:?} but got {:?}", $tok, next); let err = format!("Expected {:?} but got {:?}", expected, next);
return Err(ParseError { err: err }); return Err(ParseError { err: err });
}, },
None => { None => {
let err = format!("Expected {:?} but got end of input", $tok); let err = format!("Expected {:?} but got end of input", expected);
return Err(ParseError { err: err }); return Err(ParseError { err: err });
} }
} }
} }
}
impl<'a> Parser<'a> { fn parse(&mut self) -> ParseResult<AST> {
fn parse(&mut self) -> ParseResult {
let r = self.expr(); let r = self.expr();
expect!(Token::Separator, self); try!(self.expect(Token::Separator));
expect!(Token::EOF, self); try!(self.expect(Token::EOF));
r r
} }
fn expr(&mut self) -> ParseResult { fn expr(&mut self) -> ParseResult<AST> {
self.tokens.next(); self.tokens.next();
return Ok(AST::Number(5.0)); return Ok(AST::Number(5.0));
} }
} }
pub fn parse(input: Vec<Token>) -> ParseResult { pub fn parse(input: Vec<Token>) -> ParseResult<AST> {
let mut iter = input.iter().peekable(); let mut iter = input.iter().peekable();
let mut parser = Parser { tokens: iter }; let mut parser = Parser { tokens: iter };
return parser.parse(); return parser.parse();