diff --git a/src/syntax/binding.rs b/src/syntax/binding.rs index 544a3ec..939c62a 100644 --- a/src/syntax/binding.rs +++ b/src/syntax/binding.rs @@ -108,7 +108,7 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult #[cfg(test)] mod tests { use super::*; - use crate::{lexic::get_tokens, syntax::utils::try_token_type}; + use crate::{lexic::get_tokens, syntax::utils::parse_immediate_token_type}; #[test] fn should_parse_val_binding() { @@ -123,7 +123,7 @@ mod tests { #[test] fn should_parse_val() { let tokens = get_tokens(&String::from("let")).unwrap(); - let token = *try_token_type(&tokens, 0, TokenType::LET).unwrap(); + let token = *parse_immediate_token_type(&tokens, 0, TokenType::LET).unwrap(); assert_eq!(TokenType::LET, token.token_type); assert_eq!("let", token.value); @@ -132,7 +132,7 @@ mod tests { #[test] fn should_parse_identifier() { let tokens = get_tokens(&String::from("identifier")).unwrap(); - let token = *try_token_type(&tokens, 0, TokenType::Identifier).unwrap(); + let token = *parse_immediate_token_type(&tokens, 0, TokenType::Identifier).unwrap(); assert_eq!("identifier", token.value); } diff --git a/src/syntax/expression/comparison.rs b/src/syntax/expression/comparison.rs index 1e6b6a0..91cf25e 100644 --- a/src/syntax/expression/comparison.rs +++ b/src/syntax/expression/comparison.rs @@ -21,7 +21,7 @@ fn parse_many<'a>( tokens: &'a Vec, pos: usize, prev_expr: Expression<'a>, -) -> ParseResult> { +) -> ParseResult<'a, Expression<'a>> { // comparison = term, ((">" | ">=" | "<" | "<="), term)*; match tokens.get(pos) { diff --git a/src/syntax/expression/equality.rs b/src/syntax/expression/equality.rs index 31ebb41..c88cb12 100644 --- a/src/syntax/expression/equality.rs +++ b/src/syntax/expression/equality.rs @@ -21,7 +21,7 @@ fn parse_many<'a>( tokens: &'a Vec, pos: usize, prev_expr: Expression<'a>, -) -> ParseResult> { +) -> ParseResult<'a, Expression<'a>> { // equality = comparison, (("==" | "!="), comparison )*; match tokens.get(pos) { diff --git a/src/syntax/expression/factor.rs b/src/syntax/expression/factor.rs index bddfc8b..e82eb03 100644 --- a/src/syntax/expression/factor.rs +++ b/src/syntax/expression/factor.rs @@ -21,7 +21,7 @@ fn parse_many<'a>( tokens: &'a Vec, pos: usize, prev_expr: Expression<'a>, -) -> ParseResult> { +) -> ParseResult<'a, Expression<'a>> { // (("/" | "*"), unary)* match tokens.get(pos) { diff --git a/src/syntax/expression/term.rs b/src/syntax/expression/term.rs index a6d1db5..8b4ca55 100644 --- a/src/syntax/expression/term.rs +++ b/src/syntax/expression/term.rs @@ -21,7 +21,7 @@ fn parse_many<'a>( tokens: &'a Vec, pos: usize, prev_expr: Expression<'a>, -) -> ParseResult> { +) -> ParseResult<'a, Expression<'a>> { // term = factor, (("-" | "+"), factor)*; match tokens.get(pos) { diff --git a/src/syntax/functions/function_declaration.rs b/src/syntax/functions/function_declaration.rs index 85a1dc4..35aec44 100644 --- a/src/syntax/functions/function_declaration.rs +++ b/src/syntax/functions/function_declaration.rs @@ -1,6 +1,7 @@ use crate::{ error_handling::SyntaxError, lexic::token::{Token, TokenType}, + syntax::ParsingError, utils::Result3, }; @@ -8,7 +9,7 @@ use super::{ super::{ ast::FunctionDeclaration, block::parse_block, - utils::{parse_token_type, try_token_type}, + utils::{parse_immediate_token_type, parse_token_type}, ParseResult, }, params_list::parse_params_list, @@ -18,7 +19,7 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult t, Result3::Err(_token) => return ParseResult::Unmatched, Result3::None => return ParseResult::Unmatched, @@ -47,16 +48,16 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult (params, next_pos), - ParseResult::Err(err) => return ParseResult::Err(err), - ParseResult::Mismatch(wrong_token) => { + Ok((params, next_pos)) => (params, next_pos), + Err(ParsingError::Err(err)) => return ParseResult::Err(err), + Err(ParsingError::Mismatch(wrong_token)) => { return ParseResult::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(), }); } - ParseResult::Unmatched => { + Err(ParsingError::Unmatched) => { return ParseResult::Err(SyntaxError { reason: String::from("Expected an opening paren afted the function identifier."), error_start: identifier.position, diff --git a/src/syntax/functions/params_list.rs b/src/syntax/functions/params_list.rs index f4619c9..91d0c53 100644 --- a/src/syntax/functions/params_list.rs +++ b/src/syntax/functions/params_list.rs @@ -1,7 +1,7 @@ use crate::{ error_handling::SyntaxError, lexic::token::{Token, TokenType}, - syntax::utils::parse_token_type, + syntax::{utils::parse_token_type, ParsingError, ParsingResult}, }; use super::super::{ @@ -9,15 +9,15 @@ use super::super::{ utils, ParseResult, }; -pub fn parse_params_list<'a>(tokens: &'a Vec, pos: usize) -> ParseResult { +pub fn parse_params_list<'a>(tokens: &'a Vec, pos: usize) -> ParsingResult { let mut current_pos = pos; let (opening_paren, next_pos) = match parse_token_type(tokens, current_pos, TokenType::LeftParen) { ParseResult::Ok(t, next) => (t, next), - ParseResult::Err(err) => return ParseResult::Err(err), - ParseResult::Mismatch(t) => return ParseResult::Mismatch(t), - ParseResult::Unmatched => return ParseResult::Unmatched, + ParseResult::Err(err) => return Err(ParsingError::Err(err)), + ParseResult::Mismatch(t) => return Err(ParsingError::Mismatch(&t)), + ParseResult::Unmatched => return Err(ParsingError::Unmatched), }; current_pos = next_pos; @@ -35,7 +35,7 @@ pub fn parse_params_list<'a>(tokens: &'a Vec, pos: usize) -> ParseResult< let (next_parameter, next_pos) = match parse_param_definition(tokens, current_pos) { ParseResult::Ok(parameter, next_pos) => (parameter, next_pos), ParseResult::Err(error) => { - return ParseResult::Err(error); + return Err(ParsingError::Err(error)); } _ => break, }; @@ -48,7 +48,7 @@ pub fn parse_params_list<'a>(tokens: &'a Vec, pos: usize) -> ParseResult< current_pos = next; } // This should never happen - ParseResult::Err(err) => return ParseResult::Err(err), + ParseResult::Err(err) => return Err(ParsingError::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 @@ -63,25 +63,25 @@ pub fn parse_params_list<'a>(tokens: &'a Vec, pos: usize) -> ParseResult< let (_closing_paren, next_pos) = match parse_token_type(tokens, current_pos, TokenType::RightParen) { ParseResult::Ok(t, next) => (t, next), - ParseResult::Err(err) => return ParseResult::Err(err), + ParseResult::Err(err) => return Err(ParsingError::Err(err)), ParseResult::Mismatch(t) => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected a closing paren after the function identifier."), error_start: t.position, error_end: t.get_end_position(), - }); + })); } ParseResult::Unmatched => { - return ParseResult::Err(SyntaxError { + return Err(ParsingError::Err(SyntaxError { reason: String::from("Expected a closing paren after the function identifier."), error_start: opening_paren.position, error_end: opening_paren.get_end_position(), - }); + })); } }; current_pos = next_pos; - ParseResult::Ok(ParamsList {}, current_pos) + Ok((ParamsList {}, current_pos)) } fn parse_param_definition<'a>(tokens: &'a Vec, pos: usize) -> ParseResult { diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 7b54a5a..784937c 100755 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -15,7 +15,7 @@ use ast::ModuleAST; use self::ast::TopLevelDeclaration; #[derive(Debug)] -pub enum ParseResult { +pub enum ParseResult<'a, A> { /// 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), @@ -26,18 +26,24 @@ pub enum ParseResult { Err(SyntaxError), /// Some special value was expected, but something else was found. /// The inside element is the something else found. - Mismatch(Token), + Mismatch(&'a Token), /// This parsing didn't succeed, but it's not a fatal error. Unmatched, } -enum ParsingError { - Mismatch(Token), - Unmatch, - Error(SyntaxError), -} +pub type ParsingResult<'a, A> = Result<(A, usize), ParsingError<'a>>; -type ParsingResult = Result<(A, usize), ParsingError>; +pub enum ParsingError<'a> { + /// Some other token was found than the expected one + Mismatch(&'a Token), + /// The parsing didn't succeed, but it's not a fatal error + Unmatched, + /// 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), +} /// Constructs the Misti AST from a vector of tokens pub fn construct_ast<'a>(tokens: &'a Vec) -> Result { diff --git a/src/syntax/utils.rs b/src/syntax/utils.rs index 7f685ca..8d6edcb 100644 --- a/src/syntax/utils.rs +++ b/src/syntax/utils.rs @@ -33,8 +33,14 @@ impl Tokenizer for Vec { } } -/// Expects the token at `pos` to be of type `token_type`. Doesn't ignore whitespace or newlines -pub fn try_token_type(tokens: &Vec, pos: usize, token_type: TokenType) -> Result3<&Token> { +/// Expects the token at `pos` to be of type `token_type`. +/// +/// **Doesn't ignore whitespace or newlines** +pub fn parse_immediate_token_type( + tokens: &Vec, + pos: usize, + token_type: TokenType, +) -> Result3<&Token> { match tokens.get(pos) { Some(t) if t.token_type == token_type => Result3::Ok(t), Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => { @@ -57,7 +63,9 @@ pub fn try_operator(tokens: &Vec, pos: usize, operator: String) -> Result } } -/// Expects the token at `pos` to be of type `token_type`, ignoring all whitespace & newlines +/// Expects the token at `pos` to be of type `token_type`, and returns the token and the next position. +/// +/// Ignores all whitespace and newlines pub fn parse_token_type( tokens: &Vec, pos: usize, @@ -82,7 +90,7 @@ pub fn parse_token_type( Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => { ParseResult::Unmatched } - Some(t) => ParseResult::Mismatch(t.clone()), + Some(t) => ParseResult::Mismatch(t), None => ParseResult::Unmatched, } }