Parse minimal block of code
This commit is contained in:
parent
bbd82b07c4
commit
8bf24e3f1a
@ -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
36
src/syntax/block.rs
Normal 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)
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user