Add parsing for while loops
This commit is contained in:
parent
565fd450a9
commit
346d9ba878
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
src/abstract_tree/while.rs
Normal file
32
src/abstract_tree/while.rs
Normal 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!()
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
|
||||||
|
@ -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!(
|
||||||
|
Loading…
Reference in New Issue
Block a user