diff --git a/CHANGELOG.md b/CHANGELOG.md index 4155b04..de45564 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ ## v0.0.10 +- [x] Parse function call parameters +- [ ] Codegen function call parameters +- [ ] Parse function declaration arguments - [ ] Begin work on semantic analysis - [ ] Symbol table - [ ] Typecheck bindings diff --git a/src/codegen/expression.rs b/src/codegen/expression.rs index db254e7..ef690c8 100644 --- a/src/codegen/expression.rs +++ b/src/codegen/expression.rs @@ -18,10 +18,6 @@ impl Transpilable for Expression { Expression::Boolean(value) => String::from(if *value { "true" } else { "false" }), Expression::Identifier(value) => format!("{}", *value), Expression::FunctionCall(f) => f.transpile(), -<<<<<<< HEAD - Expression::BinaryOperator(_, _, _) => { - todo!("BinaryOperator codegen is not implemented yet") -======= Expression::BinaryOperator(left_expr, right_expr, operator) => { format!( "{}{}{}", @@ -29,7 +25,6 @@ impl Transpilable for Expression { operator, right_expr.transpile() ) ->>>>>>> f71f9ab ((lazily) codegen parsed expressions. v0.0.9) } Expression::UnaryOperator(operator, expression) => { format!("{}{}", operator, expression.transpile()) diff --git a/src/codegen/function_call.rs b/src/codegen/function_call.rs index 591e706..ade02e2 100644 --- a/src/codegen/function_call.rs +++ b/src/codegen/function_call.rs @@ -4,10 +4,6 @@ use super::Transpilable; impl Transpilable for FunctionCall { fn transpile(&self) -> String { -<<<<<<< HEAD - format!("{}();", self.function.transpile()) -======= - format!("{}()", self.identifier) ->>>>>>> f71f9ab ((lazily) codegen parsed expressions. v0.0.9) + format!("{}()", self.function.transpile()) } } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index b375a40..86b47fc 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -5,7 +5,6 @@ mod block; mod expression; mod function_call; mod function_declaration; -mod function_call; mod module_ast; mod statement; mod top_level_construct; diff --git a/src/codegen/module_ast.rs b/src/codegen/module_ast.rs index 018efa8..d4c4067 100644 --- a/src/codegen/module_ast.rs +++ b/src/codegen/module_ast.rs @@ -37,10 +37,6 @@ mod tests { let result = module.transpile(); -<<<<<<< HEAD - assert_eq!(">>>>>> f71f9ab ((lazily) codegen parsed expressions. v0.0.9) } } diff --git a/src/codegen/statement.rs b/src/codegen/statement.rs index cbf72be..198b69c 100644 --- a/src/codegen/statement.rs +++ b/src/codegen/statement.rs @@ -4,18 +4,11 @@ use super::Transpilable; impl Transpilable for Statement { fn transpile(&self) -> String { -<<<<<<< HEAD - match self { - Statement::Binding(binding) => binding.transpile(), - Statement::FunctionCall(function_call) => function_call.transpile(), - } -======= let stmt = match self { Statement::FunctionCall(f) => f.transpile(), Statement::Binding(b) => b.transpile(), }; format!("{stmt};") ->>>>>>> f71f9ab ((lazily) codegen parsed expressions. v0.0.9) } } diff --git a/src/lexic/mod.rs b/src/lexic/mod.rs index 9a0639a..2ab9b07 100755 --- a/src/lexic/mod.rs +++ b/src/lexic/mod.rs @@ -116,6 +116,16 @@ fn next_token( .or_else(|| scanner::operator(next_char, chars, current_pos)) .or_else(|| scanner::grouping_sign(next_char, chars, current_pos)) .or_else(|| scanner::new_line(next_char, chars, current_pos)) + .or_else(|| { + if next_char == ',' { + Some(LexResult::Some( + Token::new(",".into(), current_pos, TokenType::Comma), + current_pos + 1, + )) + } else { + None + } + }) .unwrap_or_else(|| { let error = LexError { position: current_pos, diff --git a/src/lexic/token.rs b/src/lexic/token.rs index 1d479a3..d45fab5 100755 --- a/src/lexic/token.rs +++ b/src/lexic/token.rs @@ -13,6 +13,7 @@ pub enum TokenType { RightBrace, NewLine, Comment, + Comma, INDENT, DEDENT, LET, diff --git a/src/syntax/ast/functions.rs b/src/syntax/ast/functions.rs index 6932939..67fd85e 100644 --- a/src/syntax/ast/functions.rs +++ b/src/syntax/ast/functions.rs @@ -7,8 +7,6 @@ pub struct FunctionCall { #[derive(Debug)] pub struct ArgumentsList { - pub arguments: Vec>, + pub arguments: Vec, } -#[derive(Debug)] -pub enum Argument {} diff --git a/src/syntax/expression/mod.rs b/src/syntax/expression/mod.rs index 308f8fe..faecc77 100644 --- a/src/syntax/expression/mod.rs +++ b/src/syntax/expression/mod.rs @@ -13,3 +13,9 @@ mod unary; pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { return equality::try_parse(tokens, pos); } + + +#[cfg(test)] +mod tests { + +} diff --git a/src/syntax/expression/primary.rs b/src/syntax/expression/primary.rs index 5640c2d..1a359e9 100644 --- a/src/syntax/expression/primary.rs +++ b/src/syntax/expression/primary.rs @@ -98,4 +98,17 @@ mod tests { _ => panic!(), } } + + #[test] + fn should_parse_grouped_expression() { + let tokens = get_tokens(&String::from("(identifier)")).unwrap(); + let expression = try_parse(&tokens, 0); + + match expression { + ParseResult::Ok(Expression::Identifier(value), _) => { + assert_eq!("identifier", format!("{}", value)) + } + _ => panic!(), + } + } } diff --git a/src/syntax/expression/unary.rs b/src/syntax/expression/unary.rs index 6cb4470..2db44c8 100644 --- a/src/syntax/expression/unary.rs +++ b/src/syntax/expression/unary.rs @@ -25,3 +25,60 @@ pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult _ => function_call_expr::try_parse(tokens, pos), } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::lexic::get_tokens; + + #[test] + fn should_parse_single_expression() { + let tokens = get_tokens(&String::from("identifier")).unwrap(); + let expression = try_parse(&tokens, 0); + + match expression { + ParseResult::Ok(Expression::Identifier(value), _) => { + assert_eq!("identifier", format!("{}", value)) + } + _ => panic!(), + } + } + + #[test] + fn should_parse_unary_expression() { + let tokens = get_tokens(&String::from("-10")).unwrap(); + let expression = try_parse(&tokens, 0); + + match expression { + ParseResult::Ok(Expression::UnaryOperator(operator, expression), _) => { + match (operator, *expression) { + (op, Expression::Number(value)) => { + assert_eq!(*op, "-"); + assert_eq!(*value, "10"); + } + _ => panic!("unexpected values"), + } + } + _ => panic!(), + } + } + + #[test] + fn should_parse_grouped_unary_expression() { + let tokens = get_tokens(&String::from("-(25 + 30)")).unwrap(); + let expression = try_parse(&tokens, 0); + + match expression { + ParseResult::Ok(Expression::UnaryOperator(operator, expression), _) => { + assert_eq!(*operator, "-"); + match *expression { + Expression::BinaryOperator(_, _, _) => { + // :D + } + _ => panic!("unexpected values"), + } + } + _ => panic!(), + } + } +} diff --git a/src/syntax/functions/arguments_list.rs b/src/syntax/functions/arguments_list.rs index d498fd4..51d270b 100644 --- a/src/syntax/functions/arguments_list.rs +++ b/src/syntax/functions/arguments_list.rs @@ -1,7 +1,11 @@ use crate::{ error_handling::SyntaxError, lexic::token::{Token, TokenType}, - syntax::{ast::functions::ArgumentsList, utils::parse_token_type, ParseResult}, + syntax::{ + ast::{functions::ArgumentsList, Expression}, + utils::parse_token_type, + ParseResult, + }, }; pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult { @@ -16,6 +20,38 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult::new(); + loop { + let (next_expression, next_pos) = + match super::super::expression::try_parse(tokens, current_pos) { + ParseResult::Ok(expression, next_pos) => (expression, next_pos), + ParseResult::Err(error) => { + // TODO: Write a more detailed error + return ParseResult::Err(error); + } + _ => break, + }; + current_pos = next_pos; + + arguments.push(next_expression); + + // Parse comma. This also parses a trailing comma + match parse_token_type(tokens, current_pos, TokenType::Comma) { + ParseResult::Ok(_, next) => { + current_pos = next; + } + // This should never happen + ParseResult::Err(err) => return ParseResult::Err(err), + ParseResult::Mismatch(_) => { + // Something other than a comma was found. It must be a closing paren ) + // Still, break the loop, assume there are no more arguments + // TODO: This could be a good place to write a detailed error? + break; + } + ParseResult::Unmatched => break, + }; + } + // Parse closing paren let (_closing_paren, next_pos) = match parse_token_type(tokens, current_pos, TokenType::RightParen) { @@ -38,16 +74,13 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult