refactor: binding parsing

This commit is contained in:
Araozu 2024-06-02 19:29:25 -05:00
parent b650447e06
commit 778a1390a0
8 changed files with 148 additions and 154 deletions

View File

@ -29,12 +29,12 @@
## v0.0.13 ## v0.0.13
- [ ] Begin work on a formal grammar - [ ] Begin work on a formal grammar
- [ ] Simplify AST - [ ] Simplify/rewrite AST
- [ ] Define the top level constructs - [ ] Define the top level constructs
- [ ] Include the original tokens in the AST - [ ] Include the original tokens in the AST
- [ ] Implement a hello world until semantic analysis - [ ] Finish the workflow for a hello world
- [ ] Refactor code - [ ] Refactor code
- [ ] Remove `PARSER couldn't parse any construction` error & replace with an actual error message - [x] Remove `PARSER couldn't parse any construction` error & replace with an actual error message
## v0.0.12 ## v0.0.12

View File

@ -1,6 +1,5 @@
use crate::error_handling::MistiError; use crate::error_handling::MistiError;
mod binding;
mod block; mod block;
mod expression; mod expression;
mod functions; mod functions;
@ -36,7 +35,6 @@ mod tests {
use tests::ast::Statement; use tests::ast::Statement;
// TODO: Reenable when statement parsing is rewritten // TODO: Reenable when statement parsing is rewritten
/*
#[test] #[test]
fn should_parse_top_level_construct_with_trailing_newline() { fn should_parse_top_level_construct_with_trailing_newline() {
let input = String::from(" fun f1(){}\n"); let input = String::from(" fun f1(){}\n");
@ -52,7 +50,6 @@ mod tests {
_ => panic!("Expected a function declaration"), _ => panic!("Expected a function declaration"),
} }
} }
*/
#[test] #[test]
fn should_parse_2_top_level_construct() { fn should_parse_2_top_level_construct() {

View File

@ -1,27 +1,26 @@
use super::ast::var_binding::VariableBinding; use crate::{
use super::utils::{parse_token_type, try_operator}; error_handling::SyntaxError,
use super::{expression, ParsingError, ParsingResult}; lexic::token::{Token, TokenType},
use crate::error_handling::SyntaxError; syntax::{
use crate::lexic::token::{Token, TokenType}; ast::{var_binding::VariableBinding, Expression},
parseable::{Parseable, ParsingError, ParsingResult},
utils::{parse_token_type, try_operator},
},
};
/* impl<'a> Parseable<'a> for VariableBinding<'a> {
binding = val binding | var binding type Item = VariableBinding<'a>;
val binding = "val", datatype?, binding remainder
| datatype, binding remainder
var binding = "var", datatype?, binding remainder fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
let current_pos = current_pos;
binding remainder = identifier, "=", expression
*/
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<VariableBinding> {
let mut current_pos = pos;
/* /*
* val/var keyword * val/var keyword
*/ */
let (is_var, binding_token, next_pos) = 'token: { let (is_var, binding_token, next_pos) = 'token: {
// check for VAL // check for VAL
if let Ok((val_token, next_pos)) = parse_token_type(tokens, current_pos, TokenType::VAL) { if let Ok((val_token, next_pos)) = parse_token_type(tokens, current_pos, TokenType::VAL)
{
break 'token (false, Some(val_token), next_pos); break 'token (false, Some(val_token), next_pos);
}; };
@ -32,16 +31,15 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Variab
_ => (false, None, current_pos), _ => (false, None, current_pos),
} }
}; };
current_pos = next_pos;
/* /*
* datatype * datatype
*/ */
let (datatype, next_pos) = match parse_token_type(tokens, current_pos, TokenType::Datatype) { let (datatype, next_pos) = match parse_token_type(tokens, next_pos, TokenType::Datatype)
{
Ok((t, next)) => (Some(t), next), Ok((t, next)) => (Some(t), next),
_ => (None, current_pos), _ => (None, next_pos),
}; };
current_pos = next_pos;
// Here: // Here:
// If the binding is None and the datatype is None, then we didn't match a binding // If the binding is None and the datatype is None, then we didn't match a binding
@ -52,8 +50,8 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Variab
/* /*
* identifier * identifier
*/ */
let (identifier, next_pos) = match parse_token_type(tokens, current_pos, TokenType::Identifier) let (identifier, next_pos) =
{ match parse_token_type(tokens, next_pos, TokenType::Identifier) {
Ok((t, n)) => (t, n), Ok((t, n)) => (t, n),
Err(ParsingError::Mismatch(token)) => { Err(ParsingError::Mismatch(token)) => {
// The parser found a token, but it's not an identifier // The parser found a token, but it's not an identifier
@ -84,17 +82,18 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Variab
})); }));
} }
_ => { _ => {
unreachable!("Illegal parser state: binding_token and datatype are both None") unreachable!(
"Illegal parser state: binding_token and datatype are both None"
)
} }
}; };
} }
}; };
current_pos = next_pos;
/* /*
* Equal (=) operator * Equal (=) operator
*/ */
let equal_operator = match try_operator(tokens, current_pos, String::from("=")) { let equal_operator = match try_operator(tokens, next_pos, String::from("=")) {
Ok((t, _)) => t, Ok((t, _)) => t,
Err(ParsingError::Mismatch(t)) => { Err(ParsingError::Mismatch(t)) => {
// The parser found a token, but it's not the `=` operator // The parser found a token, but it's not the `=` operator
@ -113,12 +112,12 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Variab
})); }));
} }
}; };
current_pos += 1; let next_pos = next_pos + 1;
/* /*
* Expression of the binding * Expression of the binding
*/ */
let (expression, next_pos) = match expression::try_parse(tokens, current_pos) { let (expression, next_pos) = match Expression::try_parse(tokens, next_pos) {
Ok((exp, next)) => (exp, next), Ok((exp, next)) => (exp, next),
_ => { _ => {
return Err(ParsingError::Err(SyntaxError { return Err(ParsingError::Err(SyntaxError {
@ -128,7 +127,6 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Variab
})); }));
} }
}; };
current_pos = next_pos;
let binding = VariableBinding { let binding = VariableBinding {
datatype, datatype,
@ -137,7 +135,8 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Variab
is_mutable: is_var, is_mutable: is_var,
}; };
Ok((binding, current_pos)) Ok((binding, next_pos))
}
} }
#[cfg(test)] #[cfg(test)]
@ -148,7 +147,7 @@ mod tests {
#[test] #[test]
fn should_parse_val_binding() { fn should_parse_val_binding() {
let tokens = get_tokens(&String::from("val identifier = 20")).unwrap(); let tokens = get_tokens(&String::from("val identifier = 20")).unwrap();
let Ok((binding, _)) = try_parse(&tokens, 0) else { let Ok((binding, _)) = VariableBinding::try_parse(&tokens, 0) else {
panic!() panic!()
}; };
@ -183,7 +182,7 @@ mod tests {
#[test] #[test]
fn should_parse_val_binding_with_datatype() { fn should_parse_val_binding_with_datatype() {
let tokens = get_tokens(&String::from("val Int identifier = 20")).unwrap(); let tokens = get_tokens(&String::from("val Int identifier = 20")).unwrap();
let (binding, _) = try_parse(&tokens, 0).unwrap(); let (binding, _) = VariableBinding::try_parse(&tokens, 0).unwrap();
assert!(!binding.is_mutable); assert!(!binding.is_mutable);
assert_eq!("Int", binding.datatype.unwrap().value); assert_eq!("Int", binding.datatype.unwrap().value);
@ -193,7 +192,7 @@ mod tests {
#[test] #[test]
fn should_parse_var_binding_with_datatype() { fn should_parse_var_binding_with_datatype() {
let tokens = get_tokens(&String::from("var Int identifier = 20")).unwrap(); let tokens = get_tokens(&String::from("var Int identifier = 20")).unwrap();
let (binding, _) = try_parse(&tokens, 0).unwrap(); let (binding, _) = VariableBinding::try_parse(&tokens, 0).unwrap();
assert!(binding.is_mutable); assert!(binding.is_mutable);
assert!(binding.datatype.is_some()); assert!(binding.datatype.is_some());
@ -204,7 +203,7 @@ mod tests {
#[test] #[test]
fn should_parse_implicit_val_binding() { fn should_parse_implicit_val_binding() {
let tokens = get_tokens(&String::from("Int identifier = 20")).unwrap(); let tokens = get_tokens(&String::from("Int identifier = 20")).unwrap();
let (binding, _) = try_parse(&tokens, 0).unwrap(); let (binding, _) = VariableBinding::try_parse(&tokens, 0).unwrap();
assert!(!binding.is_mutable); assert!(!binding.is_mutable);
assert!(binding.datatype.is_some()); assert!(binding.datatype.is_some());
@ -215,7 +214,7 @@ mod tests {
#[test] #[test]
fn should_return_error_on_implicit_val_binding() { fn should_return_error_on_implicit_val_binding() {
let tokens = get_tokens(&String::from("Int => 20")).unwrap(); let tokens = get_tokens(&String::from("Int => 20")).unwrap();
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -231,7 +230,7 @@ mod tests {
let tokens = get_tokens(&String::from("val")).unwrap(); let tokens = get_tokens(&String::from("val")).unwrap();
assert_eq!(TokenType::VAL, tokens[0].token_type); assert_eq!(TokenType::VAL, tokens[0].token_type);
assert_eq!(0, tokens[0].position); assert_eq!(0, tokens[0].position);
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -247,7 +246,7 @@ mod tests {
let tokens = get_tokens(&String::from("val 322")).unwrap(); let tokens = get_tokens(&String::from("val 322")).unwrap();
assert_eq!(TokenType::VAL, tokens[0].token_type); assert_eq!(TokenType::VAL, tokens[0].token_type);
assert_eq!(0, tokens[0].position); assert_eq!(0, tokens[0].position);
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -258,7 +257,7 @@ mod tests {
} }
let tokens = get_tokens(&String::from("val \"hello\"")).unwrap(); let tokens = get_tokens(&String::from("val \"hello\"")).unwrap();
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -276,7 +275,7 @@ mod tests {
#[test] #[test]
fn should_return_error_when_equal_op_is_wrong() { fn should_return_error_when_equal_op_is_wrong() {
let tokens = get_tokens(&String::from("val id \"error\"")).unwrap(); let tokens = get_tokens(&String::from("val id \"error\"")).unwrap();
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -290,7 +289,7 @@ mod tests {
#[test] #[test]
fn should_return_error_when_identifier_is_empty() { fn should_return_error_when_identifier_is_empty() {
let tokens = get_tokens(&String::from("val String ")).unwrap(); let tokens = get_tokens(&String::from("val String ")).unwrap();
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -308,7 +307,7 @@ mod tests {
#[test] #[test]
fn should_return_error_when_identifier_is_empty_2() { fn should_return_error_when_identifier_is_empty_2() {
let tokens = get_tokens(&String::from("val ")).unwrap(); let tokens = get_tokens(&String::from("val ")).unwrap();
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -326,7 +325,7 @@ mod tests {
#[test] #[test]
fn should_error_when_equal_op_is_missing() { fn should_error_when_equal_op_is_missing() {
let tokens = get_tokens(&String::from("val identifier ")).unwrap(); let tokens = get_tokens(&String::from("val identifier ")).unwrap();
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {
@ -344,7 +343,7 @@ mod tests {
#[test] #[test]
fn should_error_when_exp_is_empty() { fn should_error_when_exp_is_empty() {
let tokens = get_tokens(&String::from("val identifier = ")).unwrap(); let tokens = get_tokens(&String::from("val identifier = ")).unwrap();
let binding = try_parse(&tokens, 0); let binding = VariableBinding::try_parse(&tokens, 0);
match binding { match binding {
Err(ParsingError::Err(error)) => { Err(ParsingError::Err(error)) => {

View File

@ -1,8 +1,7 @@
use crate::{ use crate::{
lexic::token::Token, lexic::token::Token,
syntax::{ syntax::{
ast::Expression, ast::Expression, expression, parseable::{Parseable, ParsingResult}
parseable::{Parseable, ParsingResult},
}, },
}; };
@ -10,6 +9,6 @@ impl<'a> Parseable<'a> for Expression<'a> {
type Item = Expression<'a>; type Item = Expression<'a>;
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> { fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
todo!() expression::try_parse(tokens, current_pos)
} }
} }

View File

@ -1,3 +1,4 @@
pub mod binding;
pub mod expression; pub mod expression;
pub mod module; pub mod module;
pub mod statement; pub mod statement;

View File

@ -24,10 +24,6 @@ impl<'a> Parseable<'a> for ModuleAST<'a> {
// Minus one because last token is EOF // Minus one because last token is EOF
// TODO: Does that EOF do anything? // TODO: Does that EOF do anything?
while current_pos < tokens_len - 1 { while current_pos < tokens_len - 1 {
println!(
"len: {} pos: {}, value: `{}`, type: {:?}",
tokens_len, current_pos, tokens[current_pos].value, tokens[current_pos].token_type
);
// Attempt to parse an statement // Attempt to parse an statement
match Statement::try_parse(tokens, current_pos) { match Statement::try_parse(tokens, current_pos) {
Ok((prod, next_pos)) => { Ok((prod, next_pos)) => {

View File

@ -1,6 +1,5 @@
use crate::syntax::{ use crate::syntax::{
ast::Statement, ast::{var_binding::VariableBinding, Statement},
binding,
functions::function_declaration, functions::function_declaration,
parseable::{Parseable, ParsingError}, parseable::{Parseable, ParsingError},
}; };
@ -13,8 +12,7 @@ impl<'a> Parseable<'a> for Statement<'a> {
current_pos: usize, current_pos: usize,
) -> crate::syntax::parseable::ParsingResult<'a, Self::Item> { ) -> crate::syntax::parseable::ParsingResult<'a, Self::Item> {
// Try to parse a variable binding // Try to parse a variable binding
// TODO: Rewrite function_declaration to use Parseable match VariableBinding::try_parse(tokens, current_pos) {
match binding::try_parse(tokens, current_pos) {
Ok((prod, next)) => { Ok((prod, next)) => {
return Ok((Statement::Binding(prod), next)); return Ok((Statement::Binding(prod), next));
} }

View File

@ -1,10 +1,14 @@
use crate::lexic::token::Token; use crate::lexic::token::Token;
use super::{ast::Statement, binding, ParsingError, ParsingResult}; use super::{
ast::{var_binding::VariableBinding, Statement},
parseable::Parseable,
ParsingError, ParsingResult,
};
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Statement> { pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParsingResult<Statement> {
// Try to parse a binding // Try to parse a binding
match binding::try_parse(tokens, pos) { match VariableBinding::try_parse(tokens, pos) {
Ok((b, next)) => return Ok((Statement::Binding(b), next)), Ok((b, next)) => return Ok((Statement::Binding(b), next)),
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
_ => {} _ => {}