From 346d9ba878a42c31849999bb10bb6030495e9d27 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 11 Mar 2024 17:58:26 -0400 Subject: [PATCH] Add parsing for while loops --- src/abstract_tree/mod.rs | 2 ++ src/abstract_tree/statement.rs | 6 +++++- src/abstract_tree/while.rs | 32 ++++++++++++++++++++++++++++++++ src/lexer.rs | 3 ++- src/parser.rs | 22 ++++++++++++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/abstract_tree/while.rs diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index 0f69933..8d44df0 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -11,6 +11,7 @@ pub mod math; pub mod statement; pub mod r#type; pub mod value_node; +pub mod r#while; pub use self::{ assignment::{Assignment, AssignmentOperator}, @@ -24,6 +25,7 @@ pub use self::{ math::Math, r#loop::Loop, r#type::Type, + r#while::While, statement::Statement, value_node::ValueNode, }; diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index fee8fbd..af8afd6 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -3,7 +3,7 @@ use crate::{ 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)] pub enum Statement { @@ -13,6 +13,7 @@ pub enum Statement { Expression(Expression), IfElse(IfElse), Loop(Loop), + While(While), } impl AbstractTree for Statement { @@ -24,6 +25,7 @@ impl AbstractTree for Statement { Statement::Expression(expression) => expression.expected_type(_context), Statement::IfElse(if_else) => if_else.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::IfElse(if_else) => if_else.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::IfElse(if_else) => if_else.run(_context), Statement::Loop(r#loop) => r#loop.run(_context), + Statement::While(r#while) => r#while.run(_context), } } } diff --git a/src/abstract_tree/while.rs b/src/abstract_tree/while.rs new file mode 100644 index 0000000..918cac5 --- /dev/null +++ b/src/abstract_tree/while.rs @@ -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 { + todo!() + } + + fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + todo!() + } + + fn run(self, _context: &Context) -> Result { + todo!() + } +} diff --git a/src/lexer.rs b/src/lexer.rs index 6a96502..fab3bc2 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -92,8 +92,8 @@ impl Display for Control { Control::DoubleColon => write!(f, "::"), Control::Colon => write!(f, ":"), Control::Dot => write!(f, "."), - Control::DoubleDot => write!(f, ".."), Control::Semicolon => write!(f, ";"), + Control::DoubleDot => write!(f, ".."), } } } @@ -226,6 +226,7 @@ pub fn lexer<'src>() -> impl Parser< just("range").padded(), just("str").padded(), just("loop").padded(), + just("while").padded(), )) .map(Token::Keyword); diff --git a/src/parser.rs b/src/parser.rs index be29f53..16557cd 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -334,6 +334,11 @@ pub fn parser<'src>() -> DustParser<'src> { .map(|statements| Statement::Loop(Loop::new(statements))) .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")) .ignore_then(expression.clone()) .then(block.clone()) @@ -354,6 +359,7 @@ pub fn parser<'src>() -> DustParser<'src> { r#break, block_statement, r#loop, + r#while, )) .then_ignore(just(Token::Control(Control::Semicolon)).or_not()) .boxed() @@ -372,6 +378,22 @@ mod tests { 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] fn types() { assert_eq!(