From a3591d19af3ae2a5d987d56755ae1ec06c664f55 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 9 Mar 2024 15:17:19 -0500 Subject: [PATCH] Clean up type parsing --- src/abstract_tree/if_else.rs | 36 ++++++------ src/parser.rs | 110 +++++++++++++++++++++-------------- 2 files changed, 85 insertions(+), 61 deletions(-) diff --git a/src/abstract_tree/if_else.rs b/src/abstract_tree/if_else.rs index 84270ff..45921a2 100644 --- a/src/abstract_tree/if_else.rs +++ b/src/abstract_tree/if_else.rs @@ -3,25 +3,21 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Expression, Statement, Type}; +use super::{AbstractTree, Action, Block, Expression, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct IfElse { if_expression: Expression, - if_statement: Box, - else_statement: Option>, + if_block: Block, + else_block: Option, } impl IfElse { - pub fn new( - if_expression: Expression, - if_statement: Statement, - else_statement: Option, - ) -> Self { + pub fn new(if_expression: Expression, if_block: Block, else_block: Option) -> Self { Self { if_expression, - if_statement: Box::new(if_statement), - else_statement: else_statement.map(|statement| Box::new(statement)), + if_block, + else_block, } } } @@ -47,8 +43,8 @@ impl AbstractTree for IfElse { .as_boolean()?; if if_boolean { - self.if_statement.run(_context) - } else if let Some(else_statement) = self.else_statement { + self.if_block.run(_context) + } else if let Some(else_statement) = self.else_block { else_statement.run(_context) } else { Ok(Action::None) @@ -59,7 +55,7 @@ impl AbstractTree for IfElse { #[cfg(test)] mod tests { use crate::{ - abstract_tree::{Action, ValueNode}, + abstract_tree::{Action, Statement, ValueNode}, context::Context, Value, }; @@ -71,7 +67,9 @@ mod tests { assert_eq!( IfElse::new( Expression::Value(ValueNode::Boolean(true)), - Statement::Expression(Expression::Value(ValueNode::String("foo".to_string()))), + Block::new(vec![Statement::Expression(Expression::Value( + ValueNode::String("foo".to_string()) + )),]), None ) .run(&Context::new()), @@ -84,10 +82,12 @@ mod tests { assert_eq!( IfElse::new( Expression::Value(ValueNode::Boolean(false)), - Statement::Expression(Expression::Value(ValueNode::String("foo".to_string()))), - Some(Statement::Expression(Expression::Value(ValueNode::String( - "bar".to_string() - )))) + Block::new(vec![Statement::Expression(Expression::Value( + ValueNode::String("foo".to_string()) + )),]), + Some(Block::new(vec![Statement::Expression(Expression::Value( + ValueNode::String("bar".to_string()) + ))])) ) .run(&Context::new()), Ok(Action::Return(Value::string("bar".to_string()))) diff --git a/src/parser.rs b/src/parser.rs index 7f9c7e1..1cca56f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -56,40 +56,60 @@ pub fn parser<'src>() -> DustParser<'src> { .map(|value| Expression::Value(value)) .boxed(); - let basic_type = choice(( - just(Token::Keyword("any")).to(Type::Any), - just(Token::Keyword("bool")).to(Type::Boolean), - just(Token::Keyword("float")).to(Type::Float), - just(Token::Keyword("int")).to(Type::Integer), - just(Token::Keyword("none")).to(Type::None), - just(Token::Keyword("range")).to(Type::Range), - just(Token::Keyword("str")).to(Type::String), - just(Token::Keyword("list")).to(Type::List), - )); + let type_specification = recursive(|type_specification| { + let r#type = recursive(|r#type| { + let function_type = type_specification + .clone() + .separated_by(just(Token::Control(Control::Comma))) + .collect() + .delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ) + .then_ignore(just(Token::Control(Control::Colon))) + .then(r#type.clone()) + .map(|(parameter_types, return_type)| Type::Function { + parameter_types, + return_type: Box::new(return_type), + }); - let type_arguments = basic_type.clone().delimited_by( - just(Token::Control(Control::ParenOpen)), - just(Token::Control(Control::ParenClose)), - ); + choice(( + function_type, + just(Token::Keyword("any")).to(Type::Any), + just(Token::Keyword("bool")).to(Type::Boolean), + just(Token::Keyword("float")).to(Type::Float), + just(Token::Keyword("int")).to(Type::Integer), + just(Token::Keyword("none")).to(Type::None), + just(Token::Keyword("range")).to(Type::Range), + just(Token::Keyword("str")).to(Type::String), + just(Token::Keyword("list")).to(Type::List), + )) + }); - let type_specification = just(Token::Control(Control::Colon)).ignore_then(choice(( - basic_type - .clone() - .separated_by(just(Token::Control(Control::Comma))) - .collect() - .delimited_by( - just(Token::Control(Control::SquareOpen)), - just(Token::Control(Control::SquareClose)), - ) - .map(|types| Type::ListExact(types)), - just(Token::Keyword("list")) - .then(type_arguments) - .map(|(_, item_type)| Type::ListOf(Box::new(item_type))), - basic_type.clone(), - identifier - .clone() - .map(|identifier| Type::Custom(identifier)), - ))); + let type_arguments = r#type.clone().delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ); + + just(Token::Control(Control::Colon)).ignore_then(choice(( + r#type + .clone() + .separated_by(just(Token::Control(Control::Comma))) + .collect() + .delimited_by( + just(Token::Control(Control::SquareOpen)), + just(Token::Control(Control::SquareClose)), + ) + .map(|types| Type::ListExact(types)), + just(Token::Keyword("list")) + .then(type_arguments) + .map(|(_, item_type)| Type::ListOf(Box::new(item_type))), + r#type.clone(), + identifier + .clone() + .map(|identifier| Type::Custom(identifier)), + ))) + }); let statement = recursive(|statement| { let block = statement @@ -318,14 +338,14 @@ pub fn parser<'src>() -> DustParser<'src> { let if_else = just(Token::Keyword("if")) .ignore_then(expression.clone()) - .then(statement.clone()) + .then(block.clone()) .then( just(Token::Keyword("else")) - .ignore_then(statement.clone()) + .ignore_then(block.clone()) .or_not(), ) - .map(|((if_expression, if_statement), else_statement)| { - Statement::IfElse(IfElse::new(if_expression, if_statement, else_statement)) + .map(|((if_expression, if_block), else_block)| { + Statement::IfElse(IfElse::new(if_expression, if_block, else_block)) }) .boxed(); @@ -390,10 +410,12 @@ mod tests { #[test] fn r#if() { assert_eq!( - parse(&lex("if true 'foo'").unwrap()).unwrap()[0].0, + parse(&lex("if true { 'foo' }").unwrap()).unwrap()[0].0, Statement::IfElse(IfElse::new( Expression::Value(ValueNode::Boolean(true)), - Statement::Expression(Expression::Value(ValueNode::String("foo".to_string()))), + Block::new(vec![Statement::Expression(Expression::Value( + ValueNode::String("foo".to_string()) + ))]), None )) ) @@ -402,13 +424,15 @@ mod tests { #[test] fn if_else() { assert_eq!( - parse(&lex("if true 'foo' else 'bar'").unwrap()).unwrap()[0].0, + parse(&lex("if true {'foo' } else { 'bar' }").unwrap()).unwrap()[0].0, Statement::IfElse(IfElse::new( Expression::Value(ValueNode::Boolean(true)), - Statement::Expression(Expression::Value(ValueNode::String("foo".to_string()))), - Some(Statement::Expression(Expression::Value(ValueNode::String( - "bar".to_string() - )))) + Block::new(vec![Statement::Expression(Expression::Value( + ValueNode::String("foo".to_string()) + ))]), + Some(Block::new(vec![Statement::Expression(Expression::Value( + ValueNode::String("bar".to_string()) + ))])) )) ) }