feat: parse while loops
This commit is contained in:
parent
86166c2105
commit
438802d011
@ -24,6 +24,7 @@
|
|||||||
- [x] Parse conditionals
|
- [x] Parse conditionals
|
||||||
- [x] Parse arrays
|
- [x] Parse arrays
|
||||||
- [x] Parse for loops
|
- [x] Parse for loops
|
||||||
|
- [x] Parse while loops
|
||||||
|
|
||||||
|
|
||||||
## v0.1.1
|
## v0.1.1
|
||||||
|
@ -12,7 +12,6 @@ fn str_is_keyword(s: &String) -> Option<TokenType> {
|
|||||||
"for" => Some(TokenType::FOR),
|
"for" => Some(TokenType::FOR),
|
||||||
"in" => Some(TokenType::IN),
|
"in" => Some(TokenType::IN),
|
||||||
"while" => Some(TokenType::WHILE),
|
"while" => Some(TokenType::WHILE),
|
||||||
"loop" => Some(TokenType::LOOP),
|
|
||||||
"match" => Some(TokenType::MATCH),
|
"match" => Some(TokenType::MATCH),
|
||||||
"case" => Some(TokenType::CASE),
|
"case" => Some(TokenType::CASE),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -29,7 +29,6 @@ pub enum TokenType {
|
|||||||
FOR,
|
FOR,
|
||||||
IN,
|
IN,
|
||||||
WHILE,
|
WHILE,
|
||||||
LOOP,
|
|
||||||
MATCH,
|
MATCH,
|
||||||
CASE,
|
CASE,
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ impl SemanticCheck for Statement<'_> {
|
|||||||
Statement::Binding(b) => b.check_semantics(scope),
|
Statement::Binding(b) => b.check_semantics(scope),
|
||||||
Statement::FnDecl(f) => f.check_semantics(scope),
|
Statement::FnDecl(f) => f.check_semantics(scope),
|
||||||
Statement::Conditional(_) => unimplemented!("check conditional"),
|
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 crate::lexic::token::Token;
|
||||||
|
|
||||||
use super::Block;
|
use super::{Block, Expression};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ForLoop<'a> {
|
pub struct ForLoop<'a> {
|
||||||
@ -13,3 +13,15 @@ pub struct ForLoop<'a> {
|
|||||||
pub value: &'a Token,
|
pub value: &'a Token,
|
||||||
pub body: Block<'a>,
|
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 crate::lexic::token::Token;
|
||||||
|
|
||||||
use self::functions::FunctionCall;
|
use self::functions::FunctionCall;
|
||||||
use loops::ForLoop;
|
use loops::{ForLoop, WhileLoop};
|
||||||
use var_binding::VariableBinding;
|
use var_binding::VariableBinding;
|
||||||
|
|
||||||
pub mod functions;
|
pub mod functions;
|
||||||
@ -36,6 +36,7 @@ pub enum Statement<'a> {
|
|||||||
// TODO: Implement conditionals as expressions
|
// TODO: Implement conditionals as expressions
|
||||||
Conditional(Conditional<'a>),
|
Conditional(Conditional<'a>),
|
||||||
ForLoop(ForLoop<'a>),
|
ForLoop(ForLoop<'a>),
|
||||||
|
WhileLoop(WhileLoop<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -6,3 +6,4 @@ pub mod for_loop;
|
|||||||
pub mod function_declaration;
|
pub mod function_declaration;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
|
pub mod while_loop;
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
lexic::token::Token,
|
lexic::token::Token,
|
||||||
syntax::{
|
syntax::{
|
||||||
ast::{
|
ast::{
|
||||||
loops::ForLoop, var_binding::VariableBinding, Conditional, FunctionDeclaration,
|
loops::{ForLoop, WhileLoop}, var_binding::VariableBinding, Conditional, FunctionDeclaration,
|
||||||
Statement,
|
Statement,
|
||||||
},
|
},
|
||||||
parseable::{Parseable, ParsingError, ParsingResult},
|
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.
|
// Here nothing was parsed.
|
||||||
Err(ParsingError::Unmatched)
|
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