diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index 9d3ab07..bd145bb 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -19,8 +19,8 @@ impl<'src> Index<'src> { } impl<'src> AbstractTree for Index<'src> { - fn expected_type(&self, context: &Context) -> Result { - let left_type = self.left.expected_type(context)?; + fn expected_type(&self, _context: &Context) -> Result { + let left_type = self.left.expected_type(_context)?; if let ( Expression::Value(ValueNode::List(expression_list)), @@ -33,7 +33,7 @@ impl<'src> AbstractTree for Index<'src> { return Ok(Type::None); }; - expression.expected_type(context) + expression.expected_type(_context) } else { Err(ValidationError::CannotIndex(left_type)) } diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index b6fef36..67ebd41 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -48,11 +48,11 @@ impl<'src> AbstractTree for Math<'src> { } } - fn run(self, context: &Context) -> Result { + fn run(self, _context: &Context) -> Result { match self { Math::Add(left, right) => { - let left_value = left.run(context)?; - let right_value = right.run(context)?; + let left_value = left.run(_context)?; + let right_value = right.run(_context)?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) @@ -65,8 +65,8 @@ impl<'src> AbstractTree for Math<'src> { } } Math::Subtract(left, right) => { - let left_value = left.run(context)?; - let right_value = right.run(context)?; + let left_value = left.run(_context)?; + let right_value = right.run(_context)?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) @@ -79,8 +79,8 @@ impl<'src> AbstractTree for Math<'src> { } } Math::Multiply(left, right) => { - let left_value = left.run(context)?; - let right_value = right.run(context)?; + let left_value = left.run(_context)?; + let right_value = right.run(_context)?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) @@ -93,8 +93,8 @@ impl<'src> AbstractTree for Math<'src> { } } Math::Divide(left, right) => { - let left_value = left.run(context)?; - let right_value = right.run(context)?; + let left_value = left.run(_context)?; + let right_value = right.run(_context)?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) @@ -107,8 +107,8 @@ impl<'src> AbstractTree for Math<'src> { } } Math::Modulo(left, right) => { - let left_value = left.run(context)?; - let right_value = right.run(context)?; + let left_value = left.run(_context)?; + let right_value = right.run(_context)?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 478a34d..567c071 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -14,7 +14,7 @@ pub enum ValueNode<'src> { Float(f64), Integer(i64), List(Vec>), - Map(Vec<(Identifier, Expression<'src>)>), + Map(Vec<(Identifier, Option, Expression<'src>)>), Range(Range), String(&'src str), Enum(Identifier, Identifier), @@ -67,7 +67,7 @@ impl<'src> AbstractTree for ValueNode<'src> { ValueNode::Map(property_list) => { let mut property_map = BTreeMap::new(); - for (identifier, expression) in property_list { + for (identifier, _type, expression) in property_list { let value = expression.run(_context)?; property_map.insert(identifier, value); diff --git a/src/parser.rs b/src/parser.rs index 33d4412..31803e2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -47,6 +47,39 @@ pub fn parser<'src>() -> DustParser<'src> { } }; + let basic_type = choice(( + just(Token::Keyword("bool")).to(Type::Boolean), + just(Token::Keyword("float")).to(Type::Float), + just(Token::Keyword("int")).to(Type::Integer), + just(Token::Keyword("range")).to(Type::Range), + just(Token::Keyword("str")).to(Type::String), + just(Token::Keyword("list")).to(Type::List), + )); + + let type_arguments = basic_type.clone().delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ); + + 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 expression = recursive(|expression| { let basic_value = select! { Token::Boolean(boolean) => ValueNode::Boolean(boolean), @@ -74,6 +107,23 @@ pub fn parser<'src>() -> DustParser<'src> { .map(|list| Expression::Value(ValueNode::List(list))) .boxed(); + let map_assignment = identifier + .clone() + .then(type_specification.clone().or_not()) + .then_ignore(just(Token::Operator(Operator::Assign))) + .then(expression.clone()) + .map(|((identifier, r#type), expression)| (identifier, r#type, expression)); + + let map = map_assignment + .separated_by(just(Token::Control(Control::Comma)).or_not()) + .allow_trailing() + .collect() + .delimited_by( + just(Token::Control(Control::CurlyOpen)), + just(Token::Control(Control::CurlyClose)), + ) + .map(|map_assigment_list| Expression::Value(ValueNode::Map(map_assigment_list))); + let r#enum = identifier .clone() .then_ignore(just(Token::Control(Control::DoubleColon))) @@ -94,7 +144,7 @@ pub fn parser<'src>() -> DustParser<'src> { use Operator::*; - let logic_and_math = atom + let logic_math_and_index = atom .pratt(( prefix(2, just(Token::Operator(Not)), |expression| { Expression::Logic(Box::new(Logic::Not(expression))) @@ -152,9 +202,10 @@ pub fn parser<'src>() -> DustParser<'src> { choice(( r#enum, - logic_and_math, + logic_math_and_index, identifier_expression, list, + map, basic_value, )) }); @@ -164,39 +215,6 @@ pub fn parser<'src>() -> DustParser<'src> { .map(|expression| Statement::Expression(expression)) .boxed(); - let basic_type = choice(( - just(Token::Keyword("bool")).to(Type::Boolean), - just(Token::Keyword("float")).to(Type::Float), - just(Token::Keyword("int")).to(Type::Integer), - just(Token::Keyword("range")).to(Type::Range), - just(Token::Keyword("str")).to(Type::String), - just(Token::Keyword("list")).to(Type::List), - )); - - let type_arguments = basic_type.clone().delimited_by( - just(Token::Control(Control::ParenOpen)), - just(Token::Control(Control::ParenClose)), - ); - - 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 assignment = identifier .then(type_specification.clone().or_not()) .then_ignore(just(Token::Operator(Operator::Assign))) @@ -245,6 +263,48 @@ mod tests { use super::*; + #[test] + fn map() { + assert_eq!( + parse(&lex("{ foo = 'bar' }").unwrap()).unwrap()[0].0, + Statement::Expression(Expression::Value(ValueNode::Map(vec![( + Identifier::new("foo"), + None, + Expression::Value(ValueNode::String("bar")) + )]))) + ); + assert_eq!( + parse(&lex("{ x = 1, y = 2, }").unwrap()).unwrap()[0].0, + Statement::Expression(Expression::Value(ValueNode::Map(vec![ + ( + Identifier::new("x"), + None, + Expression::Value(ValueNode::Integer(1)) + ), + ( + Identifier::new("y"), + None, + Expression::Value(ValueNode::Integer(2)) + ), + ]))) + ); + assert_eq!( + parse(&lex("{ x = 1 y = 2 }").unwrap()).unwrap()[0].0, + Statement::Expression(Expression::Value(ValueNode::Map(vec![ + ( + Identifier::new("x"), + None, + Expression::Value(ValueNode::Integer(1)) + ), + ( + Identifier::new("y"), + None, + Expression::Value(ValueNode::Integer(2)) + ), + ]))) + ); + } + #[test] fn math() { assert_eq!(