Refactor parsing return values
This commit is contained in:
parent
1348020cd7
commit
e43eb9e137
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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,
|
||||||
|
@ -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> {
|
||||||
|
@ -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> {
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user