Implement function parsing
With a lot of dummy code, especially around expression parsing
This commit is contained in:
parent
bd1c455dc8
commit
b1b6672399
@ -39,7 +39,7 @@ pub struct ParseError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ParseError {
|
impl ParseError {
|
||||||
fn new<T>(msg: &str) -> ParseResult<T> {
|
fn result_from_str<T>(msg: &str) -> ParseResult<T> {
|
||||||
Err(ParseError { msg: msg.to_string() })
|
Err(ParseError { msg: msg.to_string() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,11 +49,12 @@ impl ParseError {
|
|||||||
delimiter := Newline | Semicolon
|
delimiter := Newline | Semicolon
|
||||||
statement := declaration | expression
|
statement := declaration | expression
|
||||||
declaraion := Fn prototype expression
|
declaraion := Fn prototype expression
|
||||||
prototype := identifier LParen (Ident Comma?)* RParen
|
prototype := identifier LParen identlist RParen
|
||||||
|
identlist := Ident (Comma Ident)*
|
||||||
expression := primary_expression (op primary_expression)*
|
expression := primary_expression (op primary_expression)*
|
||||||
primary_expression := Variable | Number | String | call_expr | paren_expr
|
primary_expression := Variable | Number | String | call_expr | paren_expr
|
||||||
paren_expr := LParen expression RParen
|
paren_expr := LParen expression RParen
|
||||||
call_expr := identifier LParen (expression Comma ?)* RParen
|
call_expr := identifier LParen identlist RParen
|
||||||
op := '+', '-', etc.
|
op := '+', '-', etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -85,22 +86,72 @@ pub fn parse(tokens: &[Token], parsed_tree: &[ASTNode]) -> ParseResult<AST> {
|
|||||||
Ok(ast)
|
Ok(ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! expect {
|
||||||
|
($token:pat, $tokens:expr, $error:expr) => {
|
||||||
|
match $tokens.pop() {
|
||||||
|
Some($token) => (),
|
||||||
|
_ => return ParseError::result_from_str($error)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_statement(tokens: &mut Vec<Token>) -> ParseResult<ASTNode> {
|
fn parse_statement(tokens: &mut Vec<Token>) -> ParseResult<ASTNode> {
|
||||||
use tokenizer::Token::*;
|
use tokenizer::Token::*;
|
||||||
let cur_tok: Token = tokens.last().unwrap().clone();
|
let cur_tok: Token = tokens.last().unwrap().clone();
|
||||||
let result: ASTNode = match cur_tok {
|
let node: ASTNode = match cur_tok {
|
||||||
Keyword(Kw::Fn) => try!(parse_declaration(tokens)),
|
Keyword(Kw::Fn) => try!(parse_declaration(tokens)),
|
||||||
_ => try!(parse_expression(tokens))
|
_ => try!(parse_expression(tokens))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(result)
|
Ok(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_declaration(tokens: &mut Vec<Token>) -> ParseResult<ASTNode> {
|
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::*;
|
use tokenizer::Token::*;
|
||||||
tokens.pop();
|
tokens.pop();
|
||||||
tokens.pop();
|
Ok(Expression::Number(101.01))
|
||||||
Ok(ASTNode::ExprNode(Expression::StringLiteral("Declaration".to_string())))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expression(tokens: &mut Vec<Token>) -> ParseResult<ASTNode> {
|
fn parse_expression(tokens: &mut Vec<Token>) -> ParseResult<ASTNode> {
|
||||||
|
Loading…
Reference in New Issue
Block a user