From b1b6672399f846edc322220e907c13c9816af752 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 12 Jan 2016 00:58:21 -0800 Subject: [PATCH] Implement function parsing With a lot of dummy code, especially around expression parsing --- src/parser.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 346911c..8775437 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -39,7 +39,7 @@ pub struct ParseError { } impl ParseError { - fn new(msg: &str) -> ParseResult { + fn result_from_str(msg: &str) -> ParseResult { 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 { 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) -> ParseResult { 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) -> 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(); - tokens.pop(); - Ok(ASTNode::ExprNode(Expression::StringLiteral("Declaration".to_string()))) + Ok(Expression::Number(101.01)) } fn parse_expression(tokens: &mut Vec) -> ParseResult {