Add parsing for while loops

This commit is contained in:
Jeff 2024-03-11 17:58:26 -04:00
parent 565fd450a9
commit 346d9ba878
5 changed files with 63 additions and 2 deletions

View File

@ -11,6 +11,7 @@ pub mod math;
pub mod statement; pub mod statement;
pub mod r#type; pub mod r#type;
pub mod value_node; pub mod value_node;
pub mod r#while;
pub use self::{ pub use self::{
assignment::{Assignment, AssignmentOperator}, assignment::{Assignment, AssignmentOperator},
@ -24,6 +25,7 @@ pub use self::{
math::Math, math::Math,
r#loop::Loop, r#loop::Loop,
r#type::Type, r#type::Type,
r#while::While,
statement::Statement, statement::Statement,
value_node::ValueNode, value_node::ValueNode,
}; };

View File

@ -3,7 +3,7 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Type}; use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Type, While};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Statement { pub enum Statement {
@ -13,6 +13,7 @@ pub enum Statement {
Expression(Expression), Expression(Expression),
IfElse(IfElse), IfElse(IfElse),
Loop(Loop), Loop(Loop),
While(While),
} }
impl AbstractTree for Statement { impl AbstractTree for Statement {
@ -24,6 +25,7 @@ impl AbstractTree for Statement {
Statement::Expression(expression) => expression.expected_type(_context), Statement::Expression(expression) => expression.expected_type(_context),
Statement::IfElse(if_else) => if_else.expected_type(_context), Statement::IfElse(if_else) => if_else.expected_type(_context),
Statement::Loop(r#loop) => r#loop.expected_type(_context), Statement::Loop(r#loop) => r#loop.expected_type(_context),
Statement::While(r#while) => r#while.expected_type(_context),
} }
} }
@ -35,6 +37,7 @@ impl AbstractTree for Statement {
Statement::Expression(expression) => expression.validate(_context), Statement::Expression(expression) => expression.validate(_context),
Statement::IfElse(if_else) => if_else.validate(_context), Statement::IfElse(if_else) => if_else.validate(_context),
Statement::Loop(r#loop) => r#loop.validate(_context), Statement::Loop(r#loop) => r#loop.validate(_context),
Statement::While(r#while) => r#while.validate(_context),
} }
} }
@ -46,6 +49,7 @@ impl AbstractTree for Statement {
Statement::Expression(expression) => expression.run(_context), Statement::Expression(expression) => expression.run(_context),
Statement::IfElse(if_else) => if_else.run(_context), Statement::IfElse(if_else) => if_else.run(_context),
Statement::Loop(r#loop) => r#loop.run(_context), Statement::Loop(r#loop) => r#loop.run(_context),
Statement::While(r#while) => r#while.run(_context),
} }
} }
} }

View File

@ -0,0 +1,32 @@
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
};
use super::{AbstractTree, Action, Block, Expression, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct While {
expression: Expression,
block: Block,
}
impl While {
pub fn new(expression: Expression, block: Block) -> Self {
Self { expression, block }
}
}
impl AbstractTree for While {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
todo!()
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
todo!()
}
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
todo!()
}
}

View File

@ -92,8 +92,8 @@ impl Display for Control {
Control::DoubleColon => write!(f, "::"), Control::DoubleColon => write!(f, "::"),
Control::Colon => write!(f, ":"), Control::Colon => write!(f, ":"),
Control::Dot => write!(f, "."), Control::Dot => write!(f, "."),
Control::DoubleDot => write!(f, ".."),
Control::Semicolon => write!(f, ";"), Control::Semicolon => write!(f, ";"),
Control::DoubleDot => write!(f, ".."),
} }
} }
} }
@ -226,6 +226,7 @@ pub fn lexer<'src>() -> impl Parser<
just("range").padded(), just("range").padded(),
just("str").padded(), just("str").padded(),
just("loop").padded(), just("loop").padded(),
just("while").padded(),
)) ))
.map(Token::Keyword); .map(Token::Keyword);

View File

@ -334,6 +334,11 @@ pub fn parser<'src>() -> DustParser<'src> {
.map(|statements| Statement::Loop(Loop::new(statements))) .map(|statements| Statement::Loop(Loop::new(statements)))
.boxed(); .boxed();
let r#while = just(Token::Keyword("while"))
.ignore_then(expression.clone())
.then(block.clone())
.map(|(expression, block)| Statement::While(While::new(expression, block)));
let if_else = just(Token::Keyword("if")) let if_else = just(Token::Keyword("if"))
.ignore_then(expression.clone()) .ignore_then(expression.clone())
.then(block.clone()) .then(block.clone())
@ -354,6 +359,7 @@ pub fn parser<'src>() -> DustParser<'src> {
r#break, r#break,
block_statement, block_statement,
r#loop, r#loop,
r#while,
)) ))
.then_ignore(just(Token::Control(Control::Semicolon)).or_not()) .then_ignore(just(Token::Control(Control::Semicolon)).or_not())
.boxed() .boxed()
@ -372,6 +378,22 @@ mod tests {
use super::*; use super::*;
#[test]
fn r#while() {
assert_eq!(
parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0].0,
Statement::While(While::new(
Expression::Value(ValueNode::Boolean(true)),
Block::new(vec![Statement::Expression(Expression::FunctionCall(
FunctionCall::new(
Expression::Identifier(Identifier::new("output")),
vec![Expression::Value(ValueNode::String("hi".to_string()))]
)
))])
))
)
}
#[test] #[test]
fn types() { fn types() {
assert_eq!( assert_eq!(