feat: parse while loops
This commit is contained in:
parent
86166c2105
commit
438802d011
@ -24,6 +24,7 @@
|
||||
- [x] Parse conditionals
|
||||
- [x] Parse arrays
|
||||
- [x] Parse for loops
|
||||
- [x] Parse while loops
|
||||
|
||||
|
||||
## v0.1.1
|
||||
|
@ -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,
|
||||
|
@ -29,7 +29,6 @@ pub enum TokenType {
|
||||
FOR,
|
||||
IN,
|
||||
WHILE,
|
||||
LOOP,
|
||||
MATCH,
|
||||
CASE,
|
||||
}
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -6,3 +6,4 @@ pub mod for_loop;
|
||||
pub mod function_declaration;
|
||||
pub mod module;
|
||||
pub mod statement;
|
||||
pub mod while_loop;
|
||||
|
@ -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)
|
||||
}
|
||||
|
75
src/syntax/parsers/while_loop.rs
Normal file
75
src/syntax/parsers/while_loop.rs
Normal 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))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user