Refactor parsing return values

master
Araozu 2024-03-15 16:07:28 -05:00
parent 1348020cd7
commit e43eb9e137
9 changed files with 53 additions and 38 deletions

View File

@ -108,7 +108,7 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Binding>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{lexic::get_tokens, syntax::utils::try_token_type}; use crate::{lexic::get_tokens, syntax::utils::parse_immediate_token_type};
#[test] #[test]
fn should_parse_val_binding() { fn should_parse_val_binding() {
@ -123,7 +123,7 @@ mod tests {
#[test] #[test]
fn should_parse_val() { fn should_parse_val() {
let tokens = get_tokens(&String::from("let")).unwrap(); 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!(TokenType::LET, token.token_type);
assert_eq!("let", token.value); assert_eq!("let", token.value);
@ -132,7 +132,7 @@ mod tests {
#[test] #[test]
fn should_parse_identifier() { fn should_parse_identifier() {
let tokens = get_tokens(&String::from("identifier")).unwrap(); 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); assert_eq!("identifier", token.value);
} }

View File

@ -21,7 +21,7 @@ fn parse_many<'a>(
tokens: &'a Vec<Token>, tokens: &'a Vec<Token>,
pos: usize, pos: usize,
prev_expr: Expression<'a>, prev_expr: Expression<'a>,
) -> ParseResult<Expression<'a>> { ) -> ParseResult<'a, Expression<'a>> {
// comparison = term, ((">" | ">=" | "<" | "<="), term)*; // comparison = term, ((">" | ">=" | "<" | "<="), term)*;
match tokens.get(pos) { match tokens.get(pos) {

View File

@ -21,7 +21,7 @@ fn parse_many<'a>(
tokens: &'a Vec<Token>, tokens: &'a Vec<Token>,
pos: usize, pos: usize,
prev_expr: Expression<'a>, prev_expr: Expression<'a>,
) -> ParseResult<Expression<'a>> { ) -> ParseResult<'a, Expression<'a>> {
// equality = comparison, (("==" | "!="), comparison )*; // equality = comparison, (("==" | "!="), comparison )*;
match tokens.get(pos) { match tokens.get(pos) {

View File

@ -21,7 +21,7 @@ fn parse_many<'a>(
tokens: &'a Vec<Token>, tokens: &'a Vec<Token>,
pos: usize, pos: usize,
prev_expr: Expression<'a>, prev_expr: Expression<'a>,
) -> ParseResult<Expression<'a>> { ) -> ParseResult<'a, Expression<'a>> {
// (("/" | "*"), unary)* // (("/" | "*"), unary)*
match tokens.get(pos) { match tokens.get(pos) {

View File

@ -21,7 +21,7 @@ fn parse_many<'a>(
tokens: &'a Vec<Token>, tokens: &'a Vec<Token>,
pos: usize, pos: usize,
prev_expr: Expression<'a>, prev_expr: Expression<'a>,
) -> ParseResult<Expression<'a>> { ) -> ParseResult<'a, Expression<'a>> {
// term = factor, (("-" | "+"), factor)*; // term = factor, (("-" | "+"), factor)*;
match tokens.get(pos) { match tokens.get(pos) {

View File

@ -1,6 +1,7 @@
use crate::{ use crate::{
error_handling::SyntaxError, error_handling::SyntaxError,
lexic::token::{Token, TokenType}, lexic::token::{Token, TokenType},
syntax::ParsingError,
utils::Result3, utils::Result3,
}; };
@ -8,7 +9,7 @@ use super::{
super::{ super::{
ast::FunctionDeclaration, ast::FunctionDeclaration,
block::parse_block, block::parse_block,
utils::{parse_token_type, try_token_type}, utils::{parse_immediate_token_type, parse_token_type},
ParseResult, ParseResult,
}, },
params_list::parse_params_list, params_list::parse_params_list,
@ -18,7 +19,7 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Function
let mut current_pos = pos; let mut current_pos = pos;
// `fun` keyword // `fun` keyword
let fun_keyword = match try_token_type(tokens, current_pos, TokenType::FUN) { let fun_keyword = match parse_immediate_token_type(tokens, current_pos, TokenType::FUN) {
Result3::Ok(t) => t, Result3::Ok(t) => t,
Result3::Err(_token) => return ParseResult::Unmatched, Result3::Err(_token) => return ParseResult::Unmatched,
Result3::None => return ParseResult::Unmatched, Result3::None => return ParseResult::Unmatched,
@ -47,16 +48,16 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Function
current_pos = next_pos; current_pos = next_pos;
let (params_list, next_pos) = match parse_params_list(tokens, current_pos) { let (params_list, next_pos) = match parse_params_list(tokens, current_pos) {
ParseResult::Ok(params, next_pos) => (params, next_pos), Ok((params, next_pos)) => (params, next_pos),
ParseResult::Err(err) => return ParseResult::Err(err), Err(ParsingError::Err(err)) => return ParseResult::Err(err),
ParseResult::Mismatch(wrong_token) => { Err(ParsingError::Mismatch(wrong_token)) => {
return ParseResult::Err(SyntaxError { return ParseResult::Err(SyntaxError {
reason: String::from("Expected an opening paren afted the function identifier."), reason: String::from("Expected an opening paren afted the function identifier."),
error_start: wrong_token.position, error_start: wrong_token.position,
error_end: wrong_token.get_end_position(), error_end: wrong_token.get_end_position(),
}); });
} }
ParseResult::Unmatched => { Err(ParsingError::Unmatched) => {
return ParseResult::Err(SyntaxError { return ParseResult::Err(SyntaxError {
reason: String::from("Expected an opening paren afted the function identifier."), reason: String::from("Expected an opening paren afted the function identifier."),
error_start: identifier.position, error_start: identifier.position,

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
error_handling::SyntaxError, error_handling::SyntaxError,
lexic::token::{Token, TokenType}, lexic::token::{Token, TokenType},
syntax::utils::parse_token_type, syntax::{utils::parse_token_type, ParsingError, ParsingResult},
}; };
use super::super::{ use super::super::{
@ -9,15 +9,15 @@ use super::super::{
utils, ParseResult, utils, ParseResult,
}; };
pub fn parse_params_list<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<ParamsList> { pub fn parse_params_list<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<ParamsList> {
let mut current_pos = pos; let mut current_pos = pos;
let (opening_paren, next_pos) = let (opening_paren, next_pos) =
match parse_token_type(tokens, current_pos, TokenType::LeftParen) { match parse_token_type(tokens, current_pos, TokenType::LeftParen) {
ParseResult::Ok(t, next) => (t, next), 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::Mismatch(t), ParseResult::Mismatch(t) => return Err(ParsingError::Mismatch(&t)),
ParseResult::Unmatched => return ParseResult::Unmatched, ParseResult::Unmatched => return Err(ParsingError::Unmatched),
}; };
current_pos = next_pos; current_pos = next_pos;
@ -35,7 +35,7 @@ pub fn parse_params_list<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<
let (next_parameter, next_pos) = match parse_param_definition(tokens, current_pos) { let (next_parameter, next_pos) = match parse_param_definition(tokens, current_pos) {
ParseResult::Ok(parameter, next_pos) => (parameter, next_pos), ParseResult::Ok(parameter, next_pos) => (parameter, next_pos),
ParseResult::Err(error) => { ParseResult::Err(error) => {
return ParseResult::Err(error); return Err(ParsingError::Err(error));
} }
_ => break, _ => break,
}; };
@ -48,7 +48,7 @@ pub fn parse_params_list<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<
current_pos = next; current_pos = next;
} }
// This should never happen // This should never happen
ParseResult::Err(err) => return ParseResult::Err(err), ParseResult::Err(err) => return Err(ParsingError::Err(err)),
ParseResult::Mismatch(_) => { ParseResult::Mismatch(_) => {
// Something other than a comma was found. It must be a closing paren ) // Something other than a comma was found. It must be a closing paren )
// Still, break the loop, assume there are no more arguments // Still, break the loop, assume there are no more arguments
@ -63,25 +63,25 @@ pub fn parse_params_list<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<
let (_closing_paren, next_pos) = let (_closing_paren, next_pos) =
match parse_token_type(tokens, current_pos, TokenType::RightParen) { match parse_token_type(tokens, current_pos, TokenType::RightParen) {
ParseResult::Ok(t, next) => (t, next), ParseResult::Ok(t, next) => (t, next),
ParseResult::Err(err) => return ParseResult::Err(err), ParseResult::Err(err) => return Err(ParsingError::Err(err)),
ParseResult::Mismatch(t) => { ParseResult::Mismatch(t) => {
return ParseResult::Err(SyntaxError { return Err(ParsingError::Err(SyntaxError {
reason: String::from("Expected a closing paren after the function identifier."), reason: String::from("Expected a closing paren after the function identifier."),
error_start: t.position, error_start: t.position,
error_end: t.get_end_position(), error_end: t.get_end_position(),
}); }));
} }
ParseResult::Unmatched => { ParseResult::Unmatched => {
return ParseResult::Err(SyntaxError { return Err(ParsingError::Err(SyntaxError {
reason: String::from("Expected a closing paren after the function identifier."), reason: String::from("Expected a closing paren after the function identifier."),
error_start: opening_paren.position, error_start: opening_paren.position,
error_end: opening_paren.get_end_position(), error_end: opening_paren.get_end_position(),
}); }));
} }
}; };
current_pos = next_pos; current_pos = next_pos;
ParseResult::Ok(ParamsList {}, current_pos) Ok((ParamsList {}, current_pos))
} }
fn parse_param_definition<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Parameter> { fn parse_param_definition<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Parameter> {

View File

@ -15,7 +15,7 @@ use ast::ModuleAST;
use self::ast::TopLevelDeclaration; use self::ast::TopLevelDeclaration;
#[derive(Debug)] #[derive(Debug)]
pub enum ParseResult<A> { pub enum ParseResult<'a, A> {
/// The parsing was a success. The first element is the parsed construct, /// The parsing was a success. The first element is the parsed construct,
/// the second element is the position of the next token to parse /// the second element is the position of the next token to parse
Ok(A, usize), Ok(A, usize),
@ -26,18 +26,24 @@ pub enum ParseResult<A> {
Err(SyntaxError), Err(SyntaxError),
/// Some special value was expected, but something else was found. /// Some special value was expected, but something else was found.
/// The inside element is the something else 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. /// This parsing didn't succeed, but it's not a fatal error.
Unmatched, Unmatched,
} }
enum ParsingError { pub type ParsingResult<'a, A> = Result<(A, usize), ParsingError<'a>>;
Mismatch(Token),
Unmatch,
Error(SyntaxError),
}
type ParsingResult<A> = 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 /// Constructs the Misti AST from a vector of tokens
pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> { pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {

View File

@ -33,8 +33,14 @@ impl Tokenizer for Vec<Token> {
} }
} }
/// Expects the token at `pos` to be of type `token_type`. Doesn't ignore whitespace or newlines /// Expects the token at `pos` to be of type `token_type`.
pub fn try_token_type(tokens: &Vec<Token>, pos: usize, token_type: TokenType) -> Result3<&Token> { ///
/// **Doesn't ignore whitespace or newlines**
pub fn parse_immediate_token_type(
tokens: &Vec<Token>,
pos: usize,
token_type: TokenType,
) -> Result3<&Token> {
match tokens.get(pos) { match tokens.get(pos) {
Some(t) if t.token_type == token_type => Result3::Ok(t), Some(t) if t.token_type == token_type => Result3::Ok(t),
Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => { Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => {
@ -57,7 +63,9 @@ pub fn try_operator(tokens: &Vec<Token>, 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( pub fn parse_token_type(
tokens: &Vec<Token>, tokens: &Vec<Token>,
pos: usize, pos: usize,
@ -82,7 +90,7 @@ pub fn parse_token_type(
Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => { Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => {
ParseResult::Unmatched ParseResult::Unmatched
} }
Some(t) => ParseResult::Mismatch(t.clone()), Some(t) => ParseResult::Mismatch(t),
None => ParseResult::Unmatched, None => ParseResult::Unmatched,
} }
} }