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.
|
op := '+', '-', etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn parse(tokens: &[Token], parsed_tree: &[ASTNode]) -> ParseResult<AST> {
|
struct Parser {
|
||||||
use tokenizer::Token::*;
|
tokens: Vec<Token>,
|
||||||
|
}
|
||||||
|
|
||||||
let mut rest: Vec<Token> = tokens.to_vec();
|
impl Parser {
|
||||||
rest.reverse();
|
fn initialize(tokens: &[Token]) -> Parser {
|
||||||
|
let mut tokens = tokens.to_vec();
|
||||||
let mut ast = parsed_tree.to_vec();
|
tokens.reverse();
|
||||||
|
Parser { tokens: tokens }
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
macro_rules! expect {
|
||||||
($token:pat, $tokens:expr, $error:expr) => {
|
($self_:expr, $token:pat, $error:expr) => {
|
||||||
match $tokens.pop() {
|
match $self_.peek() {
|
||||||
Some($token) => (),
|
Some($token) => {$self_.next();},
|
||||||
_ => return ParseError::result_from_str($error)
|
_ => 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> {
|
impl Parser {
|
||||||
use tokenizer::Token::*;
|
fn program(&mut self) -> ParseResult<AST> {
|
||||||
tokens.pop();
|
use tokenizer::Token::*;
|
||||||
Ok(Expression::Number(101.01))
|
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> {
|
pub fn parse(tokens: &[Token], _parsed_tree: &[ASTNode]) -> ParseResult<AST> {
|
||||||
use tokenizer::Token::*;
|
let mut parser = Parser::initialize(tokens);
|
||||||
tokens.pop();
|
parser.program()
|
||||||
Ok(ASTNode::ExprNode(Expression::StringLiteral("Expr".to_string())))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user