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 {
|
||||
fn new<T>(msg: &str) -> ParseResult<T> {
|
||||
fn result_from_str<T>(msg: &str) -> ParseResult<T> {
|
||||
Err(ParseError { msg: msg.to_string() })
|
||||
}
|
||||
}
|
||||
@ -49,11 +49,12 @@ impl ParseError {
|
||||
delimiter := Newline | Semicolon
|
||||
statement := declaration | 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)*
|
||||
primary_expression := Variable | Number | String | call_expr | paren_expr
|
||||
paren_expr := LParen expression RParen
|
||||
call_expr := identifier LParen (expression Comma ?)* RParen
|
||||
call_expr := identifier LParen identlist RParen
|
||||
op := '+', '-', etc.
|
||||
*/
|
||||
|
||||
@ -85,22 +86,72 @@ pub fn parse(tokens: &[Token], parsed_tree: &[ASTNode]) -> ParseResult<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> {
|
||||
use tokenizer::Token::*;
|
||||
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)),
|
||||
_ => try!(parse_expression(tokens))
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
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();
|
||||
tokens.pop();
|
||||
Ok(ASTNode::ExprNode(Expression::StringLiteral("Declaration".to_string())))
|
||||
Ok(Expression::Number(101.01))
|
||||
}
|
||||
|
||||
fn parse_expression(tokens: &mut Vec<Token>) -> ParseResult<ASTNode> {
|
||||
|
Loading…
Reference in New Issue
Block a user