diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 4ecc505..40af64c 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -9,14 +9,28 @@ use super::{AbstractTree, Action, Identifier, Statement, Type}; pub struct Assignment<'src> { identifier: Identifier, r#type: Option, + operator: AssignmentOperator, statement: Box>, } +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub enum AssignmentOperator { + Assign, + AddAssign, + SubAssign, +} + impl<'src> Assignment<'src> { - pub fn new(identifier: Identifier, r#type: Option, statement: Statement<'src>) -> Self { + pub fn new( + identifier: Identifier, + r#type: Option, + operator: AssignmentOperator, + statement: Statement<'src>, + ) -> Self { Self { identifier, r#type, + operator, statement: Box::new(statement), } } @@ -71,6 +85,7 @@ mod tests { Assignment::new( Identifier::new("foobar"), None, + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::Integer(42))), ) .run(&context) @@ -87,6 +102,7 @@ mod tests { let validation = Assignment::new( Identifier::new("foobar"), Some(Type::Boolean), + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::Integer(42))), ) .validate(&Context::new()); diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index aebd480..b84b9db 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -11,8 +11,16 @@ pub mod r#type; pub mod value_node; pub use self::{ - assignment::Assignment, block::Block, expression::Expression, identifier::Identifier, - index::Index, logic::Logic, math::Math, r#loop::Loop, r#type::Type, statement::Statement, + assignment::{Assignment, AssignmentOperator}, + block::Block, + expression::Expression, + identifier::Identifier, + index::Index, + logic::Logic, + math::Math, + r#loop::Loop, + r#type::Type, + statement::Statement, value_node::ValueNode, }; diff --git a/src/parser.rs b/src/parser.rs index 9e548df..3cc4909 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -222,10 +222,14 @@ pub fn parser<'src>() -> DustParser<'src> { let assignment = identifier .then(type_specification.clone().or_not()) - .then_ignore(just(Token::Operator(Operator::Assign))) + .then(choice(( + just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign), + just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign), + just(Token::Operator(Operator::SubAssign)).to(AssignmentOperator::SubAssign), + ))) .then(statement.clone()) - .map(|((identifier, r#type), statement)| { - Statement::Assignment(Assignment::new(identifier, r#type, statement)) + .map(|(((identifier, r#type), operator), statement)| { + Statement::Assignment(Assignment::new(identifier, r#type, operator, statement)) }) .boxed(); @@ -406,6 +410,7 @@ mod tests { Statement::Assignment(Assignment::new( Identifier::new("foobar"), None, + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::Integer(1))) )), ); @@ -418,6 +423,7 @@ mod tests { Statement::Assignment(Assignment::new( Identifier::new("foobar"), Some(Type::Integer), + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::Integer(1))) )), ); @@ -430,6 +436,7 @@ mod tests { Statement::Assignment(Assignment::new( Identifier::new("foobar"), Some(Type::Custom(Identifier::new("Foo"))), + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::Enum( Identifier::new("Foo"), Identifier::new("Bar") @@ -445,6 +452,7 @@ mod tests { Statement::Assignment(Assignment::new( Identifier::new("foobar"), Some(Type::List), + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::List(vec![]))) )), ); @@ -454,6 +462,7 @@ mod tests { Statement::Assignment(Assignment::new( Identifier::new("foobar"), Some(Type::ListOf(Box::new(Type::Integer))), + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::List(vec![]))) )), ); @@ -463,6 +472,7 @@ mod tests { Statement::Assignment(Assignment::new( Identifier::new("foobar"), Some(Type::ListExact(vec![Type::Integer, Type::String])), + AssignmentOperator::Assign, Statement::Expression(Expression::Value(ValueNode::List(vec![ Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::String("foo"))