thp/src/syntax/mod.rs

150 lines
4.7 KiB
Rust
Raw Normal View History

use crate::error_handling::{MistiError, SyntaxError};
mod binding;
2023-09-21 00:53:46 +00:00
mod block;
mod expression;
2023-10-01 22:43:59 +00:00
mod functions;
2023-10-05 11:56:21 +00:00
mod statement;
2023-10-06 01:26:47 +00:00
mod utils;
2023-09-09 01:17:46 +00:00
2023-09-08 01:50:51 +00:00
pub mod ast;
2023-09-08 01:46:11 +00:00
2023-09-17 22:58:56 +00:00
use crate::lexic::token::{Token, TokenType};
2023-09-09 01:28:53 +00:00
use ast::ModuleAST;
2023-01-05 23:20:58 +00:00
2023-09-17 22:58:56 +00:00
use self::ast::TopLevelDeclaration;
2023-01-08 23:09:06 +00:00
2024-03-15 21:07:28 +00:00
pub type ParsingResult<'a, A> = Result<(A, usize), ParsingError<'a>>;
2024-03-15 20:49:02 +00:00
2024-03-15 21:44:29 +00:00
#[derive(Debug)]
2024-03-15 21:07:28 +00:00
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),
}
2024-03-15 20:49:02 +00:00
2022-11-28 23:33:34 +00:00
/// Constructs the Misti AST from a vector of tokens
2023-09-08 01:32:59 +00:00
pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
2023-09-17 22:58:56 +00:00
let mut top_level_declarations = Vec::new();
let token_amount = tokens.len();
let mut current_pos = 0;
// Minus one because the last token is always EOF
while current_pos < token_amount - 1 {
// Ignore newlines
if tokens[current_pos].token_type == TokenType::NewLine {
current_pos += 1;
continue;
}
match next_construct(tokens, current_pos) {
2024-03-15 21:44:29 +00:00
Ok((module, next_pos)) => {
2023-09-17 22:58:56 +00:00
top_level_declarations.push(module);
current_pos = next_pos;
}
2024-03-15 21:44:29 +00:00
Err(ParsingError::Err(err)) => return Err(MistiError::Syntax(err)),
2023-09-22 01:34:51 +00:00
_ => {
2023-09-17 22:58:56 +00:00
return Err(MistiError::Syntax(SyntaxError {
reason: String::from("PARSER couldn't parse any construction"),
// FIXME: This should get the position of the _token_ that current_pos points to
error_start: current_pos,
error_end: current_pos,
}));
}
}
2023-01-17 13:04:11 +00:00
}
2023-09-17 22:58:56 +00:00
Ok(ModuleAST {
declarations: top_level_declarations,
})
2022-11-21 21:58:51 +00:00
}
2023-01-05 23:20:58 +00:00
2023-09-22 01:34:51 +00:00
fn next_construct<'a>(
tokens: &'a Vec<Token>,
current_pos: usize,
2024-03-15 21:44:29 +00:00
) -> ParsingResult<TopLevelDeclaration> {
// Try to parse a function declaration
match functions::function_declaration::try_parse(tokens, current_pos) {
Ok((declaration, next_pos)) => {
return Ok((
2023-09-22 01:34:51 +00:00
TopLevelDeclaration::FunctionDeclaration(declaration),
next_pos,
2024-03-15 21:44:29 +00:00
))
}
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
_ => {}
}
2024-03-18 13:57:28 +00:00
// Try to parse a binding
match binding::try_parse(tokens, current_pos) {
Ok((binding, next_pos)) => return Ok((TopLevelDeclaration::Binding(binding), next_pos)),
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
_ => {}
}
// Try to parse an expression
match expression::try_parse(tokens, current_pos) {
Ok((expression, next_pos)) => {
return Ok((TopLevelDeclaration::Expression(expression), next_pos))
}
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
_ => {}
}
2024-03-15 21:44:29 +00:00
// No top level construct was found, return unmatched
Err(ParsingError::Unmatched)
}
2023-09-17 22:58:56 +00:00
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_parse_top_level_construct_with_trailing_newline() {
2024-03-15 21:44:29 +00:00
let input = String::from(" fun f1(){}\n");
2023-09-17 22:58:56 +00:00
let tokens = crate::lexic::get_tokens(&input).unwrap();
let declarations = construct_ast(&tokens).unwrap().declarations;
assert_eq!(declarations.len(), 1);
match declarations.get(0).unwrap() {
TopLevelDeclaration::Binding(_) => panic!("Expected a function declaration"),
TopLevelDeclaration::FunctionDeclaration(_f) => {
assert!(true)
}
2024-03-15 20:49:02 +00:00
_ => panic!("Not implemented: Expression at top level"),
2023-09-17 22:58:56 +00:00
}
}
#[test]
fn should_parse_2_top_level_construct() {
let input = String::from("fun f1(){} fun f2() {}");
let tokens = crate::lexic::get_tokens(&input).unwrap();
let declarations = construct_ast(&tokens).unwrap().declarations;
assert_eq!(declarations.len(), 2);
match declarations.get(0).unwrap() {
TopLevelDeclaration::Binding(_) => panic!("Expected a function declaration"),
TopLevelDeclaration::FunctionDeclaration(_f) => {
assert!(true)
}
2024-03-15 20:49:02 +00:00
_ => panic!("Not implemented: Expression at top level"),
2023-09-17 22:58:56 +00:00
}
match declarations.get(1).unwrap() {
TopLevelDeclaration::Binding(_) => panic!("Expected a function declaration"),
TopLevelDeclaration::FunctionDeclaration(_f) => {
assert!(true)
}
2024-03-15 20:49:02 +00:00
_ => panic!("Not implemented: Expression at top level"),
2023-09-17 22:58:56 +00:00
}
}
}