feat: parse while loops

master
Araozu 2024-08-28 09:45:58 -05:00
parent 86166c2105
commit 438802d011
9 changed files with 102 additions and 6 deletions

View File

@ -24,6 +24,7 @@
- [x] Parse conditionals
- [x] Parse arrays
- [x] Parse for loops
- [x] Parse while loops
## v0.1.1

View File

@ -12,7 +12,6 @@ fn str_is_keyword(s: &String) -> Option<TokenType> {
"for" => Some(TokenType::FOR),
"in" => Some(TokenType::IN),
"while" => Some(TokenType::WHILE),
"loop" => Some(TokenType::LOOP),
"match" => Some(TokenType::MATCH),
"case" => Some(TokenType::CASE),
_ => None,

View File

@ -29,7 +29,6 @@ pub enum TokenType {
FOR,
IN,
WHILE,
LOOP,
MATCH,
CASE,
}

View File

@ -23,7 +23,8 @@ impl SemanticCheck for Statement<'_> {
Statement::Binding(b) => b.check_semantics(scope),
Statement::FnDecl(f) => f.check_semantics(scope),
Statement::Conditional(_) => unimplemented!("check conditional"),
Statement::ForLoop(_) => unimplemented!("check for loop"),
Statement::ForLoop(_) => unimplemented!("check for for loop"),
Statement::WhileLoop(_) => unimplemented!("check for while loop"),
}
}
}

View File

@ -1,6 +1,6 @@
use crate::lexic::token::Token;
use super::Block;
use super::{Block, Expression};
#[derive(Debug)]
pub struct ForLoop<'a> {
@ -13,3 +13,15 @@ pub struct ForLoop<'a> {
pub value: &'a Token,
pub body: Block<'a>,
}
#[derive(Debug)]
pub struct WhileLoop<'a> {
/// the start position of the
/// `for` keyword
pub loop_start: usize,
/// the position of the closing bracket
pub loop_end: usize,
pub condition: Expression<'a>,
pub body: Block<'a>,
}

View File

@ -1,7 +1,7 @@
use crate::lexic::token::Token;
use self::functions::FunctionCall;
use loops::ForLoop;
use loops::{ForLoop, WhileLoop};
use var_binding::VariableBinding;
pub mod functions;
@ -36,6 +36,7 @@ pub enum Statement<'a> {
// TODO: Implement conditionals as expressions
Conditional(Conditional<'a>),
ForLoop(ForLoop<'a>),
WhileLoop(WhileLoop<'a>),
}
#[derive(Debug)]

View File

@ -6,3 +6,4 @@ pub mod for_loop;
pub mod function_declaration;
pub mod module;
pub mod statement;
pub mod while_loop;

View File

@ -2,7 +2,7 @@ use crate::{
lexic::token::Token,
syntax::{
ast::{
loops::ForLoop, var_binding::VariableBinding, Conditional, FunctionDeclaration,
loops::{ForLoop, WhileLoop}, var_binding::VariableBinding, Conditional, FunctionDeclaration,
Statement,
},
parseable::{Parseable, ParsingError, ParsingResult},
@ -51,6 +51,13 @@ impl<'a> Parseable<'a> for Statement<'a> {
_ => {}
}
// Try to parse a while loop
match WhileLoop::try_parse(tokens, current_pos) {
Ok((prod, next)) => return Ok((Statement::WhileLoop(prod), next)),
Err(ParsingError::Err(e)) => return Err(ParsingError::Err(e)),
_ => {}
}
// Here nothing was parsed.
Err(ParsingError::Unmatched)
}

View File

@ -0,0 +1,75 @@
use crate::{
error_handling::SyntaxError, lexic::token::{Token, TokenType}, syntax::{
ast::{loops::WhileLoop, Block, Expression, Positionable},
parseable::{Parseable, ParsingError, ParsingResult}, utils::parse_token_type,
}
};
impl<'a> Parseable<'a> for WhileLoop<'a> {
type Item = WhileLoop<'a>;
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
// while keyword
let (while_keyword, next) = match parse_token_type(tokens, current_pos, TokenType::WHILE) {
Ok(tuple) => tuple,
_ => return Err(ParsingError::Unmatched),
};
// condition expression
let (condition, next) = match Expression::try_parse(tokens, next) {
Ok(t) => t,
Err(ParsingError::Err(e)) => return Err(ParsingError::Err(e)),
Err(ParsingError::Mismatch(e)) => {
return Err(ParsingError::Err(SyntaxError {
error_start: e.position,
error_end: e.get_end_position(),
reason: format!(
"Expected an expression after the `while` keyword, found {}",
e.value
),
}))
}
Err(ParsingError::Unmatched) => {
return Err(ParsingError::Err(SyntaxError {
error_start: while_keyword.position,
error_end: while_keyword.get_end_position(),
reason: format!("Expected an identifier after the `while` keyword"),
}))
}
};
// body
let (body, next) = match Block::try_parse(tokens, next) {
Ok(t) => t,
Err(ParsingError::Err(e)) => return Err(ParsingError::Err(e)),
Err(ParsingError::Mismatch(e)) => {
return Err(ParsingError::Err(SyntaxError {
error_start: e.position,
error_end: e.get_end_position(),
reason: format!(
"Expected a block after the condition, found {}",
e.value
),
}))
}
Err(ParsingError::Unmatched) => {
return Err(ParsingError::Err(SyntaxError {
error_start: while_keyword.position,
error_end: while_keyword.get_end_position(),
reason: format!("Expected a block after the condition"),
}))
}
};
// return
let (_, loop_end) = body.get_position();
let while_loop = WhileLoop {
loop_start: while_keyword.position,
loop_end,
condition,
body,
};
Ok((while_loop, next))
}
}