Parse minimal block of code

master
Araozu 2023-09-20 19:53:46 -05:00
parent bbd82b07c4
commit 8bf24e3f1a
5 changed files with 106 additions and 39 deletions

View File

@ -13,6 +13,9 @@ pub struct FunctionDeclaration {
pub identifier: Box<String>, pub identifier: Box<String>,
} }
#[derive(Debug)]
pub struct Block {}
#[derive(Debug)] #[derive(Debug)]
pub enum Binding { pub enum Binding {
Val(ValBinding), Val(ValBinding),

36
src/syntax/block.rs Normal file
View File

@ -0,0 +1,36 @@
use crate::{
lexic::token::{Token, TokenType},
syntax::{utils::expect_token_w, SyntaxResult},
};
use super::{ast::Block, utils::parse_token_type, ParseResult};
// Assumes that the token at `pos` is a {
pub fn parse_block<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Block, &Token> {
let mut current_pos = pos;
let (opening_brace, next_pos) =
match parse_token_type(tokens, current_pos, TokenType::LeftBrace) {
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 brace
let (_closing_brace, next_pos) = match expect_token_w(
tokens,
current_pos,
TokenType::RightBrace,
"Expected a closing brace after the block body.".into(),
opening_brace,
) {
Ok(t) => t,
Err(Some(SyntaxResult::Err(err))) => return ParseResult::Err(err),
_ => panic!("parse_block: invalid state"),
};
current_pos = next_pos;
ParseResult::Ok(Block {}, current_pos)
}

View File

@ -1,12 +1,14 @@
use crate::{ use crate::{
error_handling::SyntaxError,
lexic::token::{Token, TokenType}, lexic::token::{Token, TokenType},
utils::Result3, utils::Result3,
}; };
use super::{ use super::{
ast::{FunctionDeclaration, TopLevelDeclaration}, ast::{FunctionDeclaration, TopLevelDeclaration},
block::parse_block,
utils::{expect_token_w, try_token_type}, utils::{expect_token_w, try_token_type},
SyntaxResult, ParseResult, SyntaxResult,
}; };
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult> { pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult> {
@ -57,7 +59,6 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult>
}; };
current_pos = next_pos; current_pos = next_pos;
// Parse a closing paren // Parse a closing paren
let (closing_paren, next_pos) = match expect_token_w( let (closing_paren, next_pos) = match expect_token_w(
tokens, tokens,
@ -71,34 +72,28 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult>
}; };
current_pos = next_pos; current_pos = next_pos;
// TODO: Replace by block parsing let (_block, next_pos) = match parse_block(tokens, current_pos) {
// Parse opening brace ParseResult::Ok(block, next_pos) => (block, next_pos),
let (opening_brace, next_pos) = match expect_token_w( ParseResult::Err(error) => {
tokens, return Some(SyntaxResult::Err(error));
current_pos, }
TokenType::LeftBrace, ParseResult::Mismatch(wrong_token) => {
"Expected an opening brace afted the parameter list.".into(), return Some(SyntaxResult::Err(SyntaxError {
closing_paren, reason: String::from("Expected a block after the function declaration."),
) { error_start: wrong_token.position,
Ok(t) => t, error_end: wrong_token.get_end_position(),
Err(err) => return err, }));
}
ParseResult::Unmatched => {
return Some(SyntaxResult::Err(SyntaxError {
reason: String::from("Expected a block after the function declaration."),
error_start: closing_paren.position,
error_end: closing_paren.get_end_position(),
}));
}
}; };
current_pos = next_pos; current_pos = next_pos;
// Parse closing brace
let (_closing_brace, next_pos) = match expect_token_w(
tokens,
current_pos,
TokenType::RightBrace,
"Expected a closing brace after afted the function body.".into(),
opening_brace,
) {
Ok(t) => t,
Err(err) => return err,
};
current_pos = next_pos;
// Construct and return the function declaration // Construct and return the function declaration
Some(SyntaxResult::Ok( Some(SyntaxResult::Ok(
TopLevelDeclaration::FunctionDeclaration(FunctionDeclaration { TopLevelDeclaration::FunctionDeclaration(FunctionDeclaration {
@ -261,7 +256,7 @@ mod tests {
Some(SyntaxResult::Err(err)) => { Some(SyntaxResult::Err(err)) => {
assert_eq!( assert_eq!(
err.reason, err.reason,
"Expected an opening brace afted the parameter list." "Expected a block after the function declaration."
); );
assert_eq!(err.error_start, 9); assert_eq!(err.error_start, 9);
assert_eq!(err.error_end, 10); assert_eq!(err.error_end, 10);
@ -275,7 +270,7 @@ mod tests {
Some(SyntaxResult::Err(err)) => { Some(SyntaxResult::Err(err)) => {
assert_eq!( assert_eq!(
err.reason, err.reason,
"Expected an opening brace afted the parameter list." "Expected a block after the function declaration."
); );
assert_eq!(err.error_start, 7); assert_eq!(err.error_start, 7);
assert_eq!(err.error_end, 8); assert_eq!(err.error_end, 8);
@ -291,10 +286,7 @@ mod tests {
match fun_decl { match fun_decl {
Some(SyntaxResult::Err(err)) => { Some(SyntaxResult::Err(err)) => {
assert_eq!( assert_eq!(err.reason, "Expected a closing brace after the block body.");
err.reason,
"Expected a closing brace after afted the function body."
);
assert_eq!(err.error_start, 11); assert_eq!(err.error_start, 11);
assert_eq!(err.error_end, 13); assert_eq!(err.error_end, 13);
} }
@ -306,10 +298,7 @@ mod tests {
match fun_decl { match fun_decl {
Some(SyntaxResult::Err(err)) => { Some(SyntaxResult::Err(err)) => {
assert_eq!( assert_eq!(err.reason, "Expected a closing brace after the block body.");
err.reason,
"Expected a closing brace after afted the function body."
);
assert_eq!(err.error_start, 9); assert_eq!(err.error_start, 9);
assert_eq!(err.error_end, 10); assert_eq!(err.error_end, 10);
} }

View File

@ -1,6 +1,7 @@
use crate::error_handling::{MistiError, SyntaxError}; use crate::error_handling::{MistiError, SyntaxError};
mod binding; mod binding;
mod block;
mod expression; mod expression;
mod function_declaration; mod function_declaration;
mod utils; mod utils;
@ -25,6 +26,14 @@ pub enum SyntaxResult {
Err(SyntaxError), Err(SyntaxError),
} }
#[derive(Debug)]
pub enum ParseResult<A, B> {
Ok(A, usize),
Err(SyntaxError),
Mismatch(B),
Unmatched,
}
/// 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> {
let mut top_level_declarations = Vec::new(); let mut top_level_declarations = Vec::new();

View File

@ -4,7 +4,7 @@ use crate::{
utils::Result3, utils::Result3,
}; };
use super::SyntaxResult; use super::{ParseResult, SyntaxResult};
/// Expects the token at `pos` to be of type `token_type` /// 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> { pub fn try_token_type(tokens: &Vec<Token>, pos: usize, token_type: TokenType) -> Result3<&Token> {
@ -18,6 +18,36 @@ pub fn try_token_type(tokens: &Vec<Token>, pos: usize, token_type: TokenType) ->
} }
} }
/// Expects the token at `pos` to be of type `token_type`
pub fn parse_token_type(
tokens: &Vec<Token>,
pos: usize,
token_type: TokenType,
) -> ParseResult<&Token, &Token> {
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 => ParseResult::Ok(t, current_pos + 1),
Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => {
ParseResult::Unmatched
}
Some(t) => ParseResult::Mismatch(t),
None => ParseResult::Unmatched,
}
}
pub fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result3<&Token> { pub fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result3<&Token> {
match tokens.get(pos) { match tokens.get(pos) {
Some(t) if t.token_type == TokenType::Operator && t.value == operator => Result3::Ok(t), Some(t) if t.token_type == TokenType::Operator && t.value == operator => Result3::Ok(t),
@ -29,7 +59,7 @@ pub fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result
} }
} }
pub fn try_operator_w<'a>( pub fn _try_operator_w<'a>(
tokens: &'a Vec<Token>, tokens: &'a Vec<Token>,
pos: usize, pos: usize,
operator: String, operator: String,