Convert parsing to method-based
This commit is contained in:
parent
b1b6672399
commit
674f70a428
196
src/parser.rs
196
src/parser.rs
@ -58,105 +58,127 @@ impl ParseError {
|
||||
op := '+', '-', etc.
|
||||
*/
|
||||
|
||||
pub fn parse(tokens: &[Token], parsed_tree: &[ASTNode]) -> ParseResult<AST> {
|
||||
use tokenizer::Token::*;
|
||||
struct Parser {
|
||||
tokens: Vec<Token>,
|
||||
}
|
||||
|
||||
let mut rest: Vec<Token> = 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<ASTNode> = 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<Token> {
|
||||
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<Token>) -> ParseResult<ASTNode> {
|
||||
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<Token>) -> ParseResult<ASTNode> {
|
||||
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<Token>) -> ParseResult<Prototype> {
|
||||
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<String> = try!(parse_identlist(tokens));
|
||||
expect!(RParen, tokens, "Expected ')'");
|
||||
|
||||
Ok(Prototype {name: name, args: args})
|
||||
}
|
||||
|
||||
fn parse_identlist(tokens: &mut Vec<Token>) -> ParseResult<Vec<String>> {
|
||||
use tokenizer::Token::*;
|
||||
let mut args: Vec<String> = 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<Token>) -> ParseResult<Expression> {
|
||||
use tokenizer::Token::*;
|
||||
tokens.pop();
|
||||
Ok(Expression::Number(101.01))
|
||||
impl Parser {
|
||||
fn program(&mut self) -> ParseResult<AST> {
|
||||
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<ASTNode> = 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<ASTNode> {
|
||||
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<ASTNode> {
|
||||
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<Prototype> {
|
||||
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<String> = try!(self.identlist());
|
||||
expect!(self, RParen, "Expected ')'");
|
||||
Ok(Prototype {name: name, args: args})
|
||||
}
|
||||
|
||||
fn identlist(&mut self) -> ParseResult<Vec<String>> {
|
||||
use tokenizer::Token::*;
|
||||
let mut args: Vec<String> = 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<Expression> {
|
||||
use tokenizer::Token::*;
|
||||
self.next();
|
||||
Ok(Expression::Number(101.01))
|
||||
}
|
||||
|
||||
fn expression(&mut self) -> ParseResult<ASTNode> {
|
||||
use tokenizer::Token::*;
|
||||
self.next();
|
||||
Ok(ASTNode::ExprNode(Expression::StringLiteral("Expr".to_string())))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_expression(tokens: &mut Vec<Token>) -> ParseResult<ASTNode> {
|
||||
use tokenizer::Token::*;
|
||||
tokens.pop();
|
||||
Ok(ASTNode::ExprNode(Expression::StringLiteral("Expr".to_string())))
|
||||
pub fn parse(tokens: &[Token], _parsed_tree: &[ASTNode]) -> ParseResult<AST> {
|
||||
let mut parser = Parser::initialize(tokens);
|
||||
parser.program()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user