Extract params list parsing

master
Araozu 2023-09-21 20:52:55 -05:00
parent fec196d5aa
commit 1fbc353ebf
6 changed files with 102 additions and 115 deletions

View File

@ -11,11 +11,15 @@ pub enum TopLevelDeclaration {
#[derive(Debug)] #[derive(Debug)]
pub struct FunctionDeclaration { pub struct FunctionDeclaration {
pub identifier: Box<String>, pub identifier: Box<String>,
pub params_list: Box<ParamsList>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Block {} pub struct Block {}
#[derive(Debug)]
pub struct ParamsList {}
#[derive(Debug)] #[derive(Debug)]
pub enum Binding { pub enum Binding {
Val(ValBinding), Val(ValBinding),

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
error_handling::SyntaxError,
lexic::token::{Token, TokenType}, lexic::token::{Token, TokenType},
syntax::{utils::expect_token_w, SyntaxResult},
}; };
use super::{ast::Block, utils::parse_token_type, ParseResult}; use super::{ast::Block, utils::parse_token_type, ParseResult};
@ -19,16 +19,24 @@ pub fn parse_block<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Block,
current_pos = next_pos; current_pos = next_pos;
// Parse closing brace // Parse closing brace
let (_closing_brace, next_pos) = match expect_token_w( let (_closing_brace, next_pos) =
tokens, match parse_token_type(tokens, current_pos, TokenType::RightBrace) {
current_pos, ParseResult::Ok(t, next) => (t, next),
TokenType::RightBrace, ParseResult::Err(err) => return ParseResult::Err(err),
"Expected a closing brace after the block body.".into(), ParseResult::Mismatch(t) => {
opening_brace, return ParseResult::Err(SyntaxError {
) { reason: String::from("Expected a closing brace after the block body."),
Ok(t) => t, error_start: t.position,
Err(Some(SyntaxResult::Err(err))) => return ParseResult::Err(err), error_end: t.get_end_position(),
_ => panic!("parse_block: invalid state"), });
}
ParseResult::Unmatched => {
return ParseResult::Err(SyntaxError {
reason: String::from("Expected a closing brace after the block body."),
error_start: opening_brace.position,
error_end: opening_brace.get_end_position(),
});
}
}; };
current_pos = next_pos; current_pos = next_pos;

View File

@ -1,5 +1,3 @@
use std::thread::current;
use crate::{ use crate::{
error_handling::SyntaxError, error_handling::SyntaxError,
lexic::token::{Token, TokenType}, lexic::token::{Token, TokenType},
@ -7,10 +5,11 @@ use crate::{
}; };
use super::{ use super::{
ast::{FunctionDeclaration, TopLevelDeclaration}, ast::{FunctionDeclaration, ParamsList},
block::parse_block, block::parse_block,
utils::{expect_token_w, parse_token_type, try_token_type}, params_list::parse_params_list,
ParseResult, SyntaxResult, utils::{parse_token_type, try_token_type},
ParseResult,
}; };
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<FunctionDeclaration, ()> { pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<FunctionDeclaration, ()> {
@ -45,25 +44,19 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Function
}; };
current_pos = next_pos; current_pos = next_pos;
// TODO: Call function that parses a parameter list let (params_list, next_pos) = match parse_params_list(tokens, current_pos) {
let (opening_paren, next_pos) = ParseResult::Ok(params, next_pos) => (params, next_pos),
match parse_token_type(tokens, current_pos, TokenType::LeftParen) {
ParseResult::Ok(id, next) => (id, next),
ParseResult::Err(err) => return ParseResult::Err(err), ParseResult::Err(err) => return ParseResult::Err(err),
ParseResult::Mismatch(wrong_token) => { ParseResult::Mismatch(wrong_token) => {
return ParseResult::Err(SyntaxError { return ParseResult::Err(SyntaxError {
reason: String::from( reason: String::from("Expected an opening paren afted the function identifier."),
"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 => { ParseResult::Unmatched => {
return ParseResult::Err(SyntaxError { return ParseResult::Err(SyntaxError {
reason: String::from( reason: String::from("Expected an opening paren afted the function identifier."),
"Expected an opening paren afted the function identifier.",
),
error_start: identifier.position, error_start: identifier.position,
error_end: identifier.get_end_position(), error_end: identifier.get_end_position(),
}); });
@ -71,27 +64,6 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Function
}; };
current_pos = next_pos; current_pos = next_pos;
let (closing_paren, next_pos) =
match parse_token_type(tokens, current_pos, TokenType::RightParen) {
ParseResult::Ok(id, next) => (id, next),
ParseResult::Err(err) => return ParseResult::Err(err),
ParseResult::Mismatch(wrong_token) => {
return ParseResult::Err(SyntaxError {
reason: String::from("Expected a closing paren afted the function identifier."),
error_start: wrong_token.position,
error_end: wrong_token.get_end_position(),
});
}
ParseResult::Unmatched => {
return ParseResult::Err(SyntaxError {
reason: String::from("Expected a closing paren afted the function identifier."),
error_start: opening_paren.position,
error_end: opening_paren.get_end_position(),
});
}
};
current_pos = next_pos;
let (_block, next_pos) = match parse_block(tokens, current_pos) { let (_block, next_pos) = match parse_block(tokens, current_pos) {
ParseResult::Ok(block, next_pos) => (block, next_pos), ParseResult::Ok(block, next_pos) => (block, next_pos),
ParseResult::Err(error) => { ParseResult::Err(error) => {
@ -107,8 +79,8 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Function
ParseResult::Unmatched => { ParseResult::Unmatched => {
return ParseResult::Err(SyntaxError { return ParseResult::Err(SyntaxError {
reason: String::from("Expected a block after the function declaration."), reason: String::from("Expected a block after the function declaration."),
error_start: closing_paren.position, error_start: identifier.position,
error_end: closing_paren.get_end_position(), error_end: identifier.get_end_position(),
}); });
} }
}; };
@ -118,8 +90,9 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Function
ParseResult::Ok( ParseResult::Ok(
FunctionDeclaration { FunctionDeclaration {
identifier: Box::new(identifier.value.clone()), identifier: Box::new(identifier.value.clone()),
params_list: Box::new(params_list),
}, },
next_pos, current_pos,
) )
} }
@ -212,7 +185,7 @@ mod tests {
ParseResult::Err(err) => { ParseResult::Err(err) => {
assert_eq!( assert_eq!(
err.reason, err.reason,
"Expected a closing paren afted the function identifier." "Expected a closing paren after the function identifier."
); );
assert_eq!(err.error_start, 7); assert_eq!(err.error_start, 7);
assert_eq!(err.error_end, 8); assert_eq!(err.error_end, 8);
@ -226,7 +199,7 @@ mod tests {
ParseResult::Err(err) => { ParseResult::Err(err) => {
assert_eq!( assert_eq!(
err.reason, err.reason,
"Expected a closing paren afted the function identifier." "Expected a closing paren after the function identifier."
); );
assert_eq!(err.error_start, 6); assert_eq!(err.error_start, 6);
assert_eq!(err.error_end, 7); assert_eq!(err.error_end, 7);
@ -294,8 +267,8 @@ mod tests {
err.reason, err.reason,
"Expected a block after the function declaration." "Expected a block after the function declaration."
); );
assert_eq!(err.error_start, 7); assert_eq!(err.error_start, 4);
assert_eq!(err.error_end, 8); assert_eq!(err.error_end, 6);
} }
_ => panic!("Expected an error: {:?}", fun_decl), _ => panic!("Expected an error: {:?}", fun_decl),
} }

View File

@ -1,11 +1,10 @@
use std::f32::consts::E;
use crate::error_handling::{MistiError, SyntaxError}; use crate::error_handling::{MistiError, SyntaxError};
mod binding; mod binding;
mod block; mod block;
mod expression; mod expression;
mod function_declaration; mod function_declaration;
mod params_list;
mod utils; mod utils;
pub mod ast; pub mod ast;

47
src/syntax/params_list.rs Normal file
View File

@ -0,0 +1,47 @@
use crate::{
error_handling::SyntaxError,
lexic::token::{Token, TokenType},
syntax::utils::parse_token_type,
};
use super::{ast::ParamsList, ParseResult};
pub fn parse_params_list<'a>(
tokens: &'a Vec<Token>,
pos: usize,
) -> ParseResult<ParamsList, &Token> {
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,
};
current_pos = next_pos;
// Parse closing paren
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::Mismatch(t) => {
return ParseResult::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 {
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)
}

View File

@ -103,47 +103,3 @@ pub fn _try_operator_w<'a>(
}))), }))),
} }
} }
/// Ignores all whitespace and newlines
pub fn expect_token_w<'a>(
tokens: &'a Vec<Token>,
pos: usize,
token_type: TokenType,
error_message: String,
prev_token: &Token,
) -> Result<(&'a Token, usize), Option<SyntaxResult>> {
let mut current_pos = pos;
// Ignore all whitespace and newlines
while let Some(t) = tokens.get(current_pos) {
if t.token_type == TokenType::INDENT
|| t.token_type == TokenType::DEDENT
|| t.token_type == TokenType::NewLine
{
current_pos += 1;
} else {
break;
}
}
match tokens.get(current_pos) {
Some(t) if t.token_type == token_type => Ok((t, current_pos + 1)),
Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => {
Err(Some(SyntaxResult::Err(SyntaxError {
reason: error_message,
error_start: prev_token.position,
error_end: prev_token.get_end_position(),
})))
}
Some(t) => Err(Some(SyntaxResult::Err(SyntaxError {
reason: error_message,
error_start: t.position,
error_end: t.get_end_position(),
}))),
None => Err(Some(SyntaxResult::Err(SyntaxError {
reason: error_message,
error_start: prev_token.position,
error_end: prev_token.get_end_position(),
}))),
}
}