diff --git a/src/codegen/expression.rs b/src/codegen/expression.rs index c6d15f6..05b7242 100644 --- a/src/codegen/expression.rs +++ b/src/codegen/expression.rs @@ -17,6 +17,7 @@ impl Transpilable for Expression { } Expression::Boolean(value) => String::from(if *value { "true" } else { "false" }), Expression::Identifier(value) => format!("{}", *value), + Expression::FunctionCall(_) => todo!("FunctionCall codegen is not implemented yet"), } } } diff --git a/src/syntax/ast/mod.rs b/src/syntax/ast/mod.rs index 15f362a..cee691b 100644 --- a/src/syntax/ast/mod.rs +++ b/src/syntax/ast/mod.rs @@ -1,3 +1,5 @@ +use self::functions::FunctionCall; + pub mod functions; pub mod statement; pub mod var_binding; @@ -32,4 +34,5 @@ pub enum Expression { String(Box), Boolean(bool), Identifier(Box), + FunctionCall(FunctionCall), } diff --git a/src/syntax/binding.rs b/src/syntax/binding.rs index 760d7a0..a7dc6f3 100644 --- a/src/syntax/binding.rs +++ b/src/syntax/binding.rs @@ -1,5 +1,5 @@ use super::ast::var_binding::{Binding, ValBinding, VarBinding}; -use super::utils::{try_operator, parse_token_type}; +use super::utils::{parse_token_type, try_operator}; use super::{expression, ParseResult}; use crate::error_handling::SyntaxError; use crate::lexic::token::{Token, TokenType}; @@ -30,7 +30,8 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult (t, n), ParseResult::Mismatch(token) => { // The parser found a token, but it's not an identifier @@ -38,7 +39,7 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult { return ParseResult::Err(error); @@ -60,7 +61,7 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult t, Result3::Err(t) => { // The parser found a token, but it's not the `=` operator @@ -80,15 +81,16 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult (exp, next), + _ => { + return ParseResult::Err(SyntaxError { + reason: String::from("Expected an expression after the equal `=` operator"), + error_start: equal_operator.position, + error_end: equal_operator.get_end_position(), + }); + } + }; let binding = if is_val { Binding::Val(ValBinding { diff --git a/src/syntax/expression.rs b/src/syntax/expression.rs index 9e771a9..376a776 100644 --- a/src/syntax/expression.rs +++ b/src/syntax/expression.rs @@ -1,4 +1,4 @@ -use super::ast::Expression; +use super::{ast::Expression, ParseResult}; use crate::lexic::token::{Token, TokenType}; /// An expression can be: @@ -7,16 +7,36 @@ use crate::lexic::token::{Token, TokenType}; /// - A string /// - A boolean /// - An identifier -pub fn try_parse(tokens: &Vec, pos: usize) -> Option { - tokens.get(pos).and_then(|token| match token.token_type { - TokenType::Number => Some(Expression::Number(Box::new(token.value.clone()))), - TokenType::String => Some(Expression::String(Box::new(token.value.clone()))), - TokenType::Identifier if token.value == "true" || token.value == "false" => { - Some(Expression::Boolean(token.value == "true")) - } - TokenType::Identifier => Some(Expression::Identifier(Box::new(token.value.clone()))), - _ => None, - }) +/// - A function call +pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { + /* + match function_call::try_parse(tokens, pos) { + super::ParseResult::Ok(_, _) => todo!(), + super::ParseResult::Err(_) => todo!(), + super::ParseResult::Mismatch(_) => todo!(), + super::ParseResult::Unmatched => todo!(), + } + */ + + match tokens.get(pos) { + Some(token) => match token.token_type { + TokenType::Number => { + ParseResult::Ok(Expression::Number(Box::new(token.value.clone())), pos + 1) + } + TokenType::String => { + ParseResult::Ok(Expression::String(Box::new(token.value.clone())), pos + 1) + } + TokenType::Identifier if token.value == "true" || token.value == "false" => { + ParseResult::Ok(Expression::Boolean(token.value == "true"), pos + 1) + } + TokenType::Identifier => ParseResult::Ok( + Expression::Identifier(Box::new(token.value.clone())), + pos + 1, + ), + _ => ParseResult::Unmatched, + }, + None => ParseResult::Unmatched, + } } #[cfg(test)] @@ -27,10 +47,10 @@ mod tests { #[test] fn should_parse_a_number() { let tokens = get_tokens(&String::from("40")).unwrap(); - let expression = try_parse(&tokens, 0).unwrap(); + let expression = try_parse(&tokens, 0); match expression { - Expression::Number(value) => assert_eq!("40", format!("{}", value)), + ParseResult::Ok(Expression::Number(value), _) => assert_eq!("40", format!("{}", value)), _ => panic!(), } } @@ -38,10 +58,12 @@ mod tests { #[test] fn should_parse_a_string() { let tokens = get_tokens(&String::from("\"Hello\"")).unwrap(); - let expression = try_parse(&tokens, 0).unwrap(); + let expression = try_parse(&tokens, 0); match expression { - Expression::String(value) => assert_eq!("\"Hello\"", format!("{}", value)), + ParseResult::Ok(Expression::String(value), _) => { + assert_eq!("\"Hello\"", format!("{}", value)) + } _ => panic!(), } } @@ -49,10 +71,10 @@ mod tests { #[test] fn should_parse_a_boolean() { let tokens = get_tokens(&String::from("true")).unwrap(); - let expression = try_parse(&tokens, 0).unwrap(); + let expression = try_parse(&tokens, 0); match expression { - Expression::Boolean(value) => assert!(value), + ParseResult::Ok(Expression::Boolean(value), _) => assert!(value), _ => panic!(), } } @@ -60,10 +82,12 @@ mod tests { #[test] fn should_parse_an_identifier() { let tokens = get_tokens(&String::from("someIdentifier")).unwrap(); - let expression = try_parse(&tokens, 0).unwrap(); + let expression = try_parse(&tokens, 0); match expression { - Expression::Identifier(value) => assert_eq!("someIdentifier", format!("{}", value)), + ParseResult::Ok(Expression::Identifier(value), _) => { + assert_eq!("someIdentifier", format!("{}", value)) + } _ => panic!(), } } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index cd78397..c52406c 100755 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -17,16 +17,18 @@ use self::ast::TopLevelDeclaration; #[derive(Debug)] pub enum ParseResult { - /// The parsing was a success + /// The parsing was a success. The first element is the parsed construct, + /// the second element is the position of the next token to parse Ok(A, usize), /// The parsing failed past a point of no return. /// /// For example, when parsing a function declaration /// the `fun` token is found, but then no identifier Err(SyntaxError), - /// A construct different from the one expected was found + /// Some special value was expected, but something else was found. + /// The inside element is the something else found. Mismatch(B), - /// No construct was found + /// This parsing didn't succeed, but it's not a fatal error. Unmatched, } diff --git a/src/syntax/utils.rs b/src/syntax/utils.rs index 4f49710..df3fc96 100644 --- a/src/syntax/utils.rs +++ b/src/syntax/utils.rs @@ -28,7 +28,6 @@ pub fn try_operator(tokens: &Vec, pos: usize, operator: String) -> Result } } - /// Expects the token at `pos` to be of type `token_type` pub fn parse_token_type( tokens: &Vec, @@ -58,4 +57,3 @@ pub fn parse_token_type( None => ParseResult::Unmatched, } } -