refactor: module constructions
This commit is contained in:
parent
5dafd6ca20
commit
1d4cec5548
@ -18,7 +18,7 @@ pub struct ModuleAST<'a> {
|
|||||||
pub enum ModuleMembers<'a> {
|
pub enum ModuleMembers<'a> {
|
||||||
// TODO: In the future implement module import
|
// TODO: In the future implement module import
|
||||||
Stmt(Statement<'a>),
|
Stmt(Statement<'a>),
|
||||||
Expression(Expression<'a>),
|
Expr(Expression<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -4,6 +4,8 @@ mod binding;
|
|||||||
mod block;
|
mod block;
|
||||||
mod expression;
|
mod expression;
|
||||||
mod functions;
|
mod functions;
|
||||||
|
mod parseable;
|
||||||
|
mod parsers;
|
||||||
mod statement;
|
mod statement;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
@ -13,21 +15,7 @@ use crate::lexic::token::{Token, TokenType};
|
|||||||
use ast::ModuleAST;
|
use ast::ModuleAST;
|
||||||
|
|
||||||
use self::ast::ModuleMembers;
|
use self::ast::ModuleMembers;
|
||||||
|
use self::parseable::{ParsingError, ParsingResult};
|
||||||
pub type ParsingResult<'a, A> = Result<(A, usize), ParsingError<'a>>;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
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 build_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
|
pub fn build_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
|
||||||
@ -66,10 +54,11 @@ pub fn build_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_construct<'a>(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<ModuleMembers> {
|
fn next_construct<'a>(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<ModuleMembers> {
|
||||||
|
todo!();
|
||||||
// Try to parse a function declaration
|
// Try to parse a function declaration
|
||||||
match functions::function_declaration::try_parse(tokens, current_pos) {
|
match functions::function_declaration::try_parse(tokens, current_pos) {
|
||||||
Ok((declaration, next_pos)) => {
|
Ok((declaration, next_pos)) => {
|
||||||
return Ok((ModuleMembers::FunctionDeclaration(declaration), next_pos))
|
return Ok((ModuleMembers::Stmt(FnDecl(declaration), next_pos)))
|
||||||
}
|
}
|
||||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -84,7 +73,7 @@ fn next_construct<'a>(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResu
|
|||||||
|
|
||||||
// Try to parse an expression
|
// Try to parse an expression
|
||||||
match expression::try_parse(tokens, current_pos) {
|
match expression::try_parse(tokens, current_pos) {
|
||||||
Ok((expression, next_pos)) => return Ok((ModuleMembers::Expression(expression), next_pos)),
|
Ok((expression, next_pos)) => return Ok((ModuleMembers::Expr(expression), next_pos)),
|
||||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
27
src/syntax/parseable.rs
Normal file
27
src/syntax/parseable.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use crate::{error_handling::SyntaxError, lexic::token::Token};
|
||||||
|
|
||||||
|
/// The result of a parsing operation.
|
||||||
|
/// On success, it contains the item and the position of the next token
|
||||||
|
/// On failure, it contains the error
|
||||||
|
pub type ParsingResult<'a, A> = Result<(A, usize), ParsingError<'a>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ParsingError<'a> {
|
||||||
|
/// The parsing didn't succeed, but it's not a fatal error
|
||||||
|
Unmatched,
|
||||||
|
/// Some other token was found than the expected one
|
||||||
|
Mismatch(&'a Token),
|
||||||
|
/// 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),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a type that can be parsed using Recursive Descent
|
||||||
|
pub trait Parseable<'a> {
|
||||||
|
type Item;
|
||||||
|
|
||||||
|
/// Try to parse the current production.
|
||||||
|
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item>;
|
||||||
|
}
|
15
src/syntax/parsers/expression.rs
Normal file
15
src/syntax/parsers/expression.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use crate::{
|
||||||
|
lexic::token::Token,
|
||||||
|
syntax::{
|
||||||
|
ast::Expression,
|
||||||
|
parseable::{Parseable, ParsingResult},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a> for Expression<'a> {
|
||||||
|
type Item = Expression<'a>;
|
||||||
|
|
||||||
|
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
3
src/syntax/parsers/mod.rs
Normal file
3
src/syntax/parsers/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod expression;
|
||||||
|
pub mod module;
|
||||||
|
pub mod statement;
|
67
src/syntax/parsers/module.rs
Normal file
67
src/syntax/parsers/module.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
use crate::{
|
||||||
|
error_handling::SyntaxError,
|
||||||
|
lexic::token::Token,
|
||||||
|
syntax::{
|
||||||
|
ast::{Expression, ModuleAST, ModuleMembers, Statement},
|
||||||
|
parseable::{Parseable, ParsingError, ParsingResult},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a> for ModuleAST<'a> {
|
||||||
|
type Item = ModuleAST<'a>;
|
||||||
|
|
||||||
|
/// Parses a THP module/source file
|
||||||
|
///
|
||||||
|
/// As this function parses the whole file, it ignores `current_pos` and
|
||||||
|
/// always starts from token 0.
|
||||||
|
///
|
||||||
|
/// Its grammar is defined it the spec, at the webpage
|
||||||
|
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
|
||||||
|
let mut productions = Vec::<ModuleMembers>::new();
|
||||||
|
let tokens_len = tokens.len();
|
||||||
|
let mut current_pos = 0;
|
||||||
|
|
||||||
|
// Minus one because last token is EOF
|
||||||
|
// TODO: Does that EOF do anything?
|
||||||
|
while current_pos < tokens_len - 1 {
|
||||||
|
// Attempt to parse an statement
|
||||||
|
match Statement::try_parse(tokens, current_pos) {
|
||||||
|
Ok((prod, next_pos)) => {
|
||||||
|
productions.push(ModuleMembers::Stmt(prod));
|
||||||
|
current_pos = next_pos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(ParsingError::Err(error)) => {
|
||||||
|
// TODO: Better error handling, write a better error message
|
||||||
|
return Err(ParsingError::Err(error));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Attempt to parse an expression
|
||||||
|
// If this fails the whole thing fails
|
||||||
|
match Expression::try_parse(tokens, current_pos) {
|
||||||
|
Ok((prod, next_pos)) => {
|
||||||
|
productions.push(ModuleMembers::Expr(prod));
|
||||||
|
current_pos = next_pos;
|
||||||
|
}
|
||||||
|
Err(ParsingError::Err(error)) => {
|
||||||
|
// TODO: Better error handling, write a better error message
|
||||||
|
return Err(ParsingError::Err(error));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reached this point we didn't match any productions and fail
|
||||||
|
let t = tokens[current_pos];
|
||||||
|
|
||||||
|
return Err(ParsingError::Err(SyntaxError {
|
||||||
|
error_start: t.position,
|
||||||
|
error_end: t.get_end_position(),
|
||||||
|
reason: "Expected an statement or an expresion at the top level.".into(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((ModuleAST { productions }, current_pos))
|
||||||
|
}
|
||||||
|
}
|
12
src/syntax/parsers/statement.rs
Normal file
12
src/syntax/parsers/statement.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::syntax::{ast::Statement, parseable::Parseable};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a> for Statement<'a> {
|
||||||
|
type Item = Statement<'a>;
|
||||||
|
|
||||||
|
fn try_parse(
|
||||||
|
tokens: &'a Vec<crate::lexic::token::Token>,
|
||||||
|
current_pos: usize,
|
||||||
|
) -> crate::syntax::parseable::ParsingResult<'a, Self::Item> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user