From 98f67bd0978381014253c7b5f806892a42ff7c5a Mon Sep 17 00:00:00 2001 From: Araozu Date: Fri, 15 Mar 2024 16:44:29 -0500 Subject: [PATCH] refactor syntax result pt2 --- src/syntax/functions/function_declaration.rs | 105 ++++++++----------- src/syntax/mod.rs | 39 +++---- src/syntax/utils.rs | 4 +- 3 files changed, 63 insertions(+), 85 deletions(-) diff --git a/src/syntax/functions/function_declaration.rs b/src/syntax/functions/function_declaration.rs index 35aec44..adaaeeb 100644 --- a/src/syntax/functions/function_declaration.rs +++ b/src/syntax/functions/function_declaration.rs @@ -1,68 +1,61 @@ use crate::{ error_handling::SyntaxError, lexic::token::{Token, TokenType}, - syntax::ParsingError, - utils::Result3, + syntax::{ParsingError, ParsingResult}, }; use super::{ - super::{ - ast::FunctionDeclaration, - block::parse_block, - utils::{parse_immediate_token_type, parse_token_type}, - ParseResult, - }, + super::{ast::FunctionDeclaration, block::parse_block, utils::parse_token_type, ParseResult}, params_list::parse_params_list, }; -pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult { +pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParsingResult { let mut current_pos = pos; // `fun` keyword - let fun_keyword = match parse_immediate_token_type(tokens, current_pos, TokenType::FUN) { - Result3::Ok(t) => t, - Result3::Err(_token) => return ParseResult::Unmatched, - Result3::None => return ParseResult::Unmatched, + let (fun_keyword, next_pos) = match parse_token_type(tokens, current_pos, TokenType::FUN) { + ParseResult::Ok(t, next) => (t, next), + _ => return Err(ParsingError::Unmatched), }; - current_pos += 1; + current_pos = next_pos; let (identifier, next_pos) = match parse_token_type(tokens, current_pos, TokenType::Identifier) { ParseResult::Ok(id, next) => (id, next), - ParseResult::Err(err) => return ParseResult::Err(err), + ParseResult::Err(err) => return Err(ParsingError::Err(err)), ParseResult::Mismatch(wrong_token) => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected an identifier after the `fun` keyword."), error_start: wrong_token.position, error_end: wrong_token.get_end_position(), - }); + })); } ParseResult::Unmatched => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected an identifier after the `fun` keyword."), error_start: fun_keyword.position, error_end: fun_keyword.get_end_position(), - }); + })); } }; current_pos = next_pos; let (params_list, next_pos) = match parse_params_list(tokens, current_pos) { Ok((params, next_pos)) => (params, next_pos), - Err(ParsingError::Err(err)) => return ParseResult::Err(err), + Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), Err(ParsingError::Mismatch(wrong_token)) => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected an opening paren afted the function identifier."), error_start: wrong_token.position, error_end: wrong_token.get_end_position(), - }); + })); } Err(ParsingError::Unmatched) => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected an opening paren afted the function identifier."), error_start: identifier.position, error_end: identifier.get_end_position(), - }); + })); } }; current_pos = next_pos; @@ -70,34 +63,34 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult (block, next_pos), ParseResult::Err(error) => { - return ParseResult::Err(error); + return Err(ParsingError::Err(error)); } ParseResult::Mismatch(wrong_token) => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected a block after the function declaration."), error_start: wrong_token.position, error_end: wrong_token.get_end_position(), - }); + })); } ParseResult::Unmatched => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected a block after the function declaration."), error_start: identifier.position, error_end: identifier.get_end_position(), - }); + })); } }; current_pos = next_pos; // Construct and return the function declaration - ParseResult::Ok( + Ok(( FunctionDeclaration { identifier: &identifier, params_list: Box::new(params_list), block: Box::new(block), }, current_pos, - ) + )) } #[cfg(test)] @@ -111,7 +104,7 @@ mod tests { let tokens = get_tokens(&String::from("val identifier = 20")).unwrap(); let fun_decl = try_parse(&tokens, 0); - let ParseResult::Unmatched = fun_decl else { + let Err(ParsingError::Unmatched) = fun_decl else { panic!("Expected an unmatched result: {:?}", fun_decl); }; } @@ -122,7 +115,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected an identifier after the `fun` keyword." @@ -136,7 +129,7 @@ mod tests { let tokens = get_tokens(&String::from("fun")).unwrap(); let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected an identifier after the `fun` keyword." @@ -154,7 +147,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected an opening paren afted the function identifier." @@ -168,7 +161,7 @@ mod tests { let tokens = get_tokens(&String::from("fun id")).unwrap(); let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected an opening paren afted the function identifier." @@ -186,7 +179,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected a closing paren after the function identifier." @@ -200,7 +193,7 @@ mod tests { let tokens = get_tokens(&String::from("fun id(")).unwrap(); let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected a closing paren after the function identifier." @@ -218,7 +211,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected an identifier after the `fun` keyword." @@ -234,7 +227,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected an identifier after the `fun` keyword." @@ -252,7 +245,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected a block after the function declaration." @@ -266,7 +259,7 @@ mod tests { let tokens = get_tokens(&String::from("fun id()")).unwrap(); let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!( err.reason, "Expected a block after the function declaration." @@ -284,7 +277,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!(err.reason, "Expected a closing brace after the block body."); assert_eq!(err.error_start, 11); assert_eq!(err.error_end, 13); @@ -296,7 +289,7 @@ mod tests { let fun_decl = try_parse(&tokens, 0); match fun_decl { - ParseResult::Err(err) => { + Err(ParsingError::Err(err)) => { assert_eq!(err.reason, "Expected a closing brace after the block body."); assert_eq!(err.error_start, 9); assert_eq!(err.error_end, 10); @@ -308,9 +301,7 @@ mod tests { #[test] fn should_parse_simple_function_declaration() { let tokens = get_tokens(&String::from("fun id() {}")).unwrap(); - let ParseResult::Ok(function_declaration, _) = try_parse(&tokens, 0) else { - panic!("Expected a function declaration.") - }; + let (function_declaration, _) = try_parse(&tokens, 0).unwrap(); assert_eq!(function_declaration.identifier.value, String::from("id")); } @@ -325,9 +316,7 @@ mod whitespace_test { #[test] fn should_ignore_whitespace_1() { let tokens = get_tokens(&String::from("fun\nid() {}")).unwrap(); - let ParseResult::Ok(declaration, _) = try_parse(&tokens, 0) else { - panic!("Expected a function declaration.") - }; + let (declaration, _) = try_parse(&tokens, 0).unwrap(); assert_eq!(declaration.identifier.value, (String::from("id"))); } @@ -335,9 +324,7 @@ mod whitespace_test { #[test] fn should_ignore_whitespace_2() { let tokens = get_tokens(&String::from("fun\nid\n() {}")).unwrap(); - let ParseResult::Ok(declaration, _) = try_parse(&tokens, 0) else { - panic!("Expected a function declaration.") - }; + let (declaration, _) = try_parse(&tokens, 0).unwrap(); assert_eq!(declaration.identifier.value, (String::from("id"))); } @@ -345,9 +332,7 @@ mod whitespace_test { #[test] fn should_ignore_whitespace_3() { let tokens = get_tokens(&String::from("fun\nid\n(\n) {}")).unwrap(); - let ParseResult::Ok(declaration, _) = try_parse(&tokens, 0) else { - panic!("Expected a function declaration.") - }; + let (declaration, _) = try_parse(&tokens, 0).unwrap(); assert_eq!(declaration.identifier.value, (String::from("id"))); } @@ -355,18 +340,14 @@ mod whitespace_test { #[test] fn should_ignore_whitespace_4() { let tokens = get_tokens(&String::from("fun id\n(\n)\n{}")).unwrap(); - let ParseResult::Ok(declaration, _) = try_parse(&tokens, 0) else { - panic!("Expected a function declaration.") - }; + let (declaration, _) = try_parse(&tokens, 0).unwrap(); assert_eq!(declaration.identifier.value, (String::from("id"))); } #[test] fn should_ignore_whitespace_5() { let tokens = get_tokens(&String::from("fun\nid() \n{\n}")).unwrap(); - let ParseResult::Ok(declaration, _) = try_parse(&tokens, 0) else { - panic!("Expected a function declaration.") - }; + let (declaration, _) = try_parse(&tokens, 0).unwrap(); assert_eq!(declaration.identifier.value, (String::from("id"))); } } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 784937c..2c1b966 100755 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -33,6 +33,7 @@ pub enum ParseResult<'a, A> { pub type ParsingResult<'a, A> = Result<(A, usize), ParsingError<'a>>; +#[derive(Debug)] pub enum ParsingError<'a> { /// Some other token was found than the expected one Mismatch(&'a Token), @@ -60,11 +61,11 @@ pub fn construct_ast<'a>(tokens: &'a Vec) -> Result { + Ok((module, next_pos)) => { top_level_declarations.push(module); current_pos = next_pos; } - ParseResult::Err(err) => return Err(MistiError::Syntax(err)), + Err(ParsingError::Err(err)) => return Err(MistiError::Syntax(err)), _ => { return Err(MistiError::Syntax(SyntaxError { reason: String::from("PARSER couldn't parse any construction"), @@ -84,27 +85,21 @@ pub fn construct_ast<'a>(tokens: &'a Vec) -> Result( tokens: &'a Vec, current_pos: usize, -) -> ParseResult { - None.or_else( - || match functions::function_declaration::try_parse(tokens, current_pos) { - ParseResult::Ok(declaration, next_pos) => Some(ParseResult::Ok( +) -> ParsingResult { + // Try to parse a function declaration + match functions::function_declaration::try_parse(tokens, current_pos) { + Ok((declaration, next_pos)) => { + return Ok(( TopLevelDeclaration::FunctionDeclaration(declaration), next_pos, - )), - ParseResult::Err(err) => Some(ParseResult::Err(err)), - _ => None, - }, - ) - .or_else(|| match expression::try_parse(tokens, current_pos) { - ParseResult::Ok(expression, next_pos) => Some(ParseResult::Ok( - TopLevelDeclaration::Expression(expression), - next_pos, - )), - ParseResult::Err(_) => todo!(), - ParseResult::Mismatch(_) => todo!(), - ParseResult::Unmatched => todo!(), - }) - .unwrap_or_else(|| ParseResult::Unmatched) + )) + } + Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), + _ => {} + } + + // No top level construct was found, return unmatched + Err(ParsingError::Unmatched) } #[cfg(test)] @@ -113,7 +108,7 @@ mod tests { #[test] fn should_parse_top_level_construct_with_trailing_newline() { - let input = String::from("fun f1(){}\n"); + let input = String::from(" fun f1(){}\n"); let tokens = crate::lexic::get_tokens(&input).unwrap(); let declarations = construct_ast(&tokens).unwrap().declarations; diff --git a/src/syntax/utils.rs b/src/syntax/utils.rs index 8d6edcb..0b4460e 100644 --- a/src/syntax/utils.rs +++ b/src/syntax/utils.rs @@ -65,7 +65,9 @@ pub fn try_operator(tokens: &Vec, pos: usize, operator: String) -> Result /// Expects the token at `pos` to be of type `token_type`, and returns the token and the next position. /// -/// Ignores all whitespace and newlines +/// Ignores all whitespace and newlines. +/// +/// Only returns: Ok, Unmatched, Mismatched pub fn parse_token_type( tokens: &Vec, pos: usize,