From 674f70a428f91c67e617249fc56b863403996b66 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 12 Jan 2016 01:58:12 -0800 Subject: [PATCH] Convert parsing to method-based --- src/parser.rs | 196 ++++++++++++++++++++++++++++---------------------- 1 file changed, 109 insertions(+), 87 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 8775437..fda2938 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -58,105 +58,127 @@ impl ParseError { op := '+', '-', etc. */ -pub fn parse(tokens: &[Token], parsed_tree: &[ASTNode]) -> ParseResult { - use tokenizer::Token::*; +struct Parser { + tokens: Vec, +} - let mut rest: Vec = tokens.to_vec(); - rest.reverse(); - - let mut ast = parsed_tree.to_vec(); - - loop { - let cur_tok = match rest.last() { - Some(t) => t.clone(), - None => break - }; - - let result: ParseResult = match cur_tok { - Newline | Semicolon => { rest.pop(); continue}, - _ => parse_statement(&mut rest) - }; - - match result { - Ok(node) => ast.push(node), - Err(err) => return Err(err) - } +impl Parser { + fn initialize(tokens: &[Token]) -> Parser { + let mut tokens = tokens.to_vec(); + tokens.reverse(); + Parser { tokens: tokens } } - Ok(ast) + fn peek(&mut self) -> Option { + self.tokens.last().map(|x| x.clone()) + } + + fn next(&mut self) { + self.tokens.pop(); + } } macro_rules! expect { - ($token:pat, $tokens:expr, $error:expr) => { - match $tokens.pop() { - Some($token) => (), + ($self_:expr, $token:pat, $error:expr) => { + match $self_.peek() { + Some($token) => {$self_.next();}, _ => return ParseError::result_from_str($error) - }; - } -} - -fn parse_statement(tokens: &mut Vec) -> ParseResult { - use tokenizer::Token::*; - let cur_tok: Token = tokens.last().unwrap().clone(); - let node: ASTNode = match cur_tok { - Keyword(Kw::Fn) => try!(parse_declaration(tokens)), - _ => try!(parse_expression(tokens)) - }; - - Ok(node) -} - -fn parse_declaration(tokens: &mut Vec) -> ParseResult { - use tokenizer::Token::*; - expect!(Fn, tokens, "Expected 'fn'"); - let prototype = try!(parse_prototype(tokens)); - let body = try!(parse_body(tokens)); - Ok(ASTNode::FuncNode(Function { prototype: prototype, body: body})) -} - -fn parse_prototype(tokens: &mut Vec) -> ParseResult { - use tokenizer::Token::*; - let name: String = match tokens.pop() { - Some(Identifier(name)) => name, - _ => return ParseError::result_from_str("Expected identifier") - }; - expect!(LParen, tokens, "Expected '('"); - let mut args: Vec = try!(parse_identlist(tokens)); - expect!(RParen, tokens, "Expected ')'"); - - Ok(Prototype {name: name, args: args}) -} - -fn parse_identlist(tokens: &mut Vec) -> ParseResult> { - use tokenizer::Token::*; - let mut args: Vec = Vec::new(); - loop { - match tokens.pop() { - Some(Identifier(name)) => { - args.push(name); - if let Some(&Comma) = tokens.last() { - tokens.pop(); - } else { - break; - } - }, - - _ => break } } - - Ok(args) } -fn parse_body(tokens: &mut Vec) -> ParseResult { - use tokenizer::Token::*; - tokens.pop(); - Ok(Expression::Number(101.01)) +impl Parser { + fn program(&mut self) -> ParseResult { + use tokenizer::Token::*; + let mut ast = Vec::new(); //TODO have this come from previously-parsed tree + loop { + let cur_tok = match self.peek() { + Some(t) => t.clone(), + None => break + }; + + let result: ParseResult = match cur_tok { + Newline | Semicolon => { self.next(); continue}, + _ => self.statement() + }; + + match result { + Ok(node) => ast.push(node), + Err(err) => return Err(err) + } + } + + Ok(ast) + } + + fn statement(&mut self) -> ParseResult { + use tokenizer::Token::*; + let cur_tok: Token = self.peek().unwrap().clone(); + let node: ASTNode = match cur_tok { + Keyword(Kw::Fn) => try!(self.declaration()), + _ => try!(self.expression()) + }; + + Ok(node) + } + + fn declaration(&mut self) -> ParseResult { + use tokenizer::Token::*; + expect!(self, Fn, "Expected 'fn'"); + let prototype = try!(self.prototype()); + let body = try!(self.body()); + Ok(ASTNode::FuncNode(Function { prototype: prototype, body: body})) + } + + fn prototype(&mut self) -> ParseResult { + use tokenizer::Token::*; + let name: String = match self.peek() { + Some(Identifier(name)) => {self.next(); name}, + _ => return ParseError::result_from_str("Expected identifier") + }; + expect!(self, LParen, "Expected '('"); + let mut args: Vec = try!(self.identlist()); + expect!(self, RParen, "Expected ')'"); + Ok(Prototype {name: name, args: args}) + } + + fn identlist(&mut self) -> ParseResult> { + use tokenizer::Token::*; + let mut args: Vec = Vec::new(); + loop { + match self.peek() { + Some(Identifier(name)) => { + args.push(name); + self.next(); + if let Some(Comma) = self.peek() { + self.next(); + } else { + break; + } + }, + + _ => break + } + } + + Ok(args) + } + + fn body(&mut self) -> ParseResult { + use tokenizer::Token::*; + self.next(); + Ok(Expression::Number(101.01)) + } + + fn expression(&mut self) -> ParseResult { + use tokenizer::Token::*; + self.next(); + Ok(ASTNode::ExprNode(Expression::StringLiteral("Expr".to_string()))) + } } -fn parse_expression(tokens: &mut Vec) -> ParseResult { - use tokenizer::Token::*; - tokens.pop(); - Ok(ASTNode::ExprNode(Expression::StringLiteral("Expr".to_string()))) +pub fn parse(tokens: &[Token], _parsed_tree: &[ASTNode]) -> ParseResult { + let mut parser = Parser::initialize(tokens); + parser.program() }