From a172d7718572b0618ce6a61fd6cf572a3b492671 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 27 Nov 2019 14:01:18 +0100
Subject: [PATCH] expression parsing in cli

---
 alib2cli/src/ast/Expression.h                 |  36 +++
 alib2cli/src/ast/command/CalcCommand.h        |  26 ++
 .../src/ast/expression/BinaryExpression.h     |  34 +++
 alib2cli/src/ast/expression/CastExpression.h  |  29 +++
 .../ast/expression/FunctionCallExpression.h   |  41 +++
 .../src/ast/expression/ImmediateExpression.h  |  27 ++
 .../src/ast/expression/MethodCallExpression.h |  43 ++++
 .../src/ast/expression/PostfixExpression.h    |  29 +++
 .../src/ast/expression/PrefixExpression.h     |  29 +++
 .../src/ast/expression/VariableExpression.h   |  24 ++
 alib2cli/src/parser/Parser.cpp                | 235 ++++++++++++++++++
 alib2cli/src/parser/Parser.h                  |  31 +++
 12 files changed, 584 insertions(+)
 create mode 100644 alib2cli/src/ast/Expression.h
 create mode 100644 alib2cli/src/ast/command/CalcCommand.h
 create mode 100644 alib2cli/src/ast/expression/BinaryExpression.h
 create mode 100644 alib2cli/src/ast/expression/CastExpression.h
 create mode 100644 alib2cli/src/ast/expression/FunctionCallExpression.h
 create mode 100644 alib2cli/src/ast/expression/ImmediateExpression.h
 create mode 100644 alib2cli/src/ast/expression/MethodCallExpression.h
 create mode 100644 alib2cli/src/ast/expression/PostfixExpression.h
 create mode 100644 alib2cli/src/ast/expression/PrefixExpression.h
 create mode 100644 alib2cli/src/ast/expression/VariableExpression.h

diff --git a/alib2cli/src/ast/Expression.h b/alib2cli/src/ast/Expression.h
new file mode 100644
index 0000000000..47599d420e
--- /dev/null
+++ b/alib2cli/src/ast/Expression.h
@@ -0,0 +1,36 @@
+#ifndef _CLI_EXPRESSION_H_
+#define _CLI_EXPRESSION_H_
+
+#include <ast/Ast.h>
+#include <abstraction/OperationAbstraction.hpp>
+#include <environment/Environment.h>
+
+namespace cli {
+
+class Expression {
+public:
+	enum class Operation {
+		LOGICAL_OR,
+		LOGICAL_AND,
+		COMPARE_EQUALITY,
+		COMPARE_INEQUALITY,
+		COMPARE_LESS_OR_EQUAL,
+		COMPARE_LESS,
+		COMPARE_MORE_OR_EQUAL,
+		COMPARE_MORE,
+		ADD,
+		SUB,
+		MUL,
+		MOD,
+		DIV,
+		NOT
+	};
+
+	virtual ~Expression ( ) noexcept = default;
+
+	virtual std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const = 0;
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/command/CalcCommand.h b/alib2cli/src/ast/command/CalcCommand.h
new file mode 100644
index 0000000000..050a84bde4
--- /dev/null
+++ b/alib2cli/src/ast/command/CalcCommand.h
@@ -0,0 +1,26 @@
+#ifndef _CLI_CALC_COMMAND_H_
+#define _CLI_CALC_COMMAND_H_
+
+#include <ast/Command.h>
+#include <environment/Environment.h>
+#include <ast/Expression.h>
+
+namespace cli {
+
+class CalcCommand : public Command {
+	std::unique_ptr < cli::Expression > m_expr;
+
+public:
+	CalcCommand ( std::unique_ptr < cli::Expression > expr ) : m_expr ( std::move ( expr ) ) {
+	}
+
+	CommandResult run ( Environment & environment ) const override {
+		m_expr->translateAndEval ( environment );
+
+		return cli::CommandResult::OK;
+	}
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_CALC_COMMAND_H_ */
diff --git a/alib2cli/src/ast/expression/BinaryExpression.h b/alib2cli/src/ast/expression/BinaryExpression.h
new file mode 100644
index 0000000000..3cc02c96c9
--- /dev/null
+++ b/alib2cli/src/ast/expression/BinaryExpression.h
@@ -0,0 +1,34 @@
+#ifndef _CLI_BINARY_EXPRESSION_H_
+#define _CLI_BINARY_EXPRESSION_H_
+
+#include <ast/Expression.h>
+
+#include <common/Operators.hpp>
+#include <common/EvalHelper.h>
+
+namespace cli {
+
+class BinaryExpression final : public Expression {
+	abstraction::Operators::BinaryOperators m_operation;
+	std::unique_ptr < Expression > m_left;
+	std::unique_ptr < Expression > m_right;
+
+public:
+	BinaryExpression ( abstraction::Operators::BinaryOperators operation, std::unique_ptr < Expression > left, std::unique_ptr < Expression > right ) : m_operation ( operation ), m_left ( std::move ( left ) ), m_right ( std::move ( right ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		ext::vector < std::shared_ptr < abstraction::Value > > params;
+		params.push_back ( m_left->translateAndEval ( environment ) );
+		params.push_back ( m_right->translateAndEval ( environment ) );
+
+		abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE;
+
+		return abstraction::EvalHelper::evalOperator ( environment, m_operation, params, category );
+	}
+
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_BINARY_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/expression/CastExpression.h b/alib2cli/src/ast/expression/CastExpression.h
new file mode 100644
index 0000000000..62bec1dc30
--- /dev/null
+++ b/alib2cli/src/ast/expression/CastExpression.h
@@ -0,0 +1,29 @@
+#ifndef _CLI_CAST_EXPRESSION_H_
+#define _CLI_CAST_EXPRESSION_H_
+
+#include <ast/Expression.h>
+#include <common/CastHelper.h>
+
+namespace cli {
+
+class CastExpression final : public Expression {
+	std::unique_ptr < cli::Arg > m_type;
+	std::unique_ptr < Expression > m_expression;
+
+public:
+	CastExpression ( std::unique_ptr < cli::Arg > type, std::unique_ptr < Expression > expression ) : m_type ( std::move ( type ) ), m_expression ( std::move ( expression ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		std::string type = m_type->eval ( environment );
+
+		std::shared_ptr < abstraction::Value > translatedExpression = m_expression->translateAndEval ( environment );
+
+		return abstraction::CastHelper::eval ( environment, translatedExpression, type );
+	}
+
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_CAST_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/expression/FunctionCallExpression.h b/alib2cli/src/ast/expression/FunctionCallExpression.h
new file mode 100644
index 0000000000..ed52a3f1af
--- /dev/null
+++ b/alib2cli/src/ast/expression/FunctionCallExpression.h
@@ -0,0 +1,41 @@
+#ifndef _CLI_FUNCTION_CALL_EXPRESSION_H_
+#define _CLI_FUNCTION_CALL_EXPRESSION_H_
+
+#include <alib/foreach>
+
+#include <ast/Expression.h>
+#include <environment/Environment.h>
+
+namespace cli {
+
+class FunctionCallExpression : public Expression {
+	std::string m_name;
+	std::vector < std::unique_ptr < Expression > > m_params;
+
+public:
+	FunctionCallExpression ( std::string name, std::vector < std::unique_ptr < Expression > > params ) : m_name ( std::move ( name ) ), m_params ( std::move ( params ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		ext::vector < std::shared_ptr < abstraction::Value > > params;
+		for ( const std::unique_ptr < Expression > & param : m_params ) {
+			params.push_back ( param->translateAndEval ( environment ) );
+		}
+
+		std::string name = m_name;
+
+		ext::vector < std::string > templateParams;
+/*			for ( const std::unique_ptr < cli::Arg > & templateParam : m_templateParams )
+			templateParams.push_back ( templateParam->eval ( environment ) );*/
+
+		abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE;
+/*			if ( m_category )
+			category = m_category->getCategory ( );*/
+
+		return abstraction::EvalHelper::evalAlgorithm ( environment, name, templateParams, params, category );
+	}
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_FUNCTION_CALL_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/expression/ImmediateExpression.h b/alib2cli/src/ast/expression/ImmediateExpression.h
new file mode 100644
index 0000000000..49a4305c36
--- /dev/null
+++ b/alib2cli/src/ast/expression/ImmediateExpression.h
@@ -0,0 +1,27 @@
+#ifndef _IMMEDIATE_EXPRESSION_H_
+#define _IMMEDIATE_EXPRESSION_H_
+
+#include <ast/Expression.h>
+
+namespace cli {
+
+template < class Type >
+class ImmediateExpression final : public Expression {
+	Type m_value;
+
+public:
+	ImmediateExpression ( Type value ) : m_value ( std::move ( value ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		Type copy = m_value;
+		std::shared_ptr < abstraction::ValueHolder < Type > > value = std::make_shared < abstraction::ValueHolder < Type > > ( std::move ( copy ), true );
+		environment.holdTemporary ( value );
+		return value;
+	}
+
+};
+
+} /* namespace cli */
+
+#endif /* _IMMEDIATE_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/expression/MethodCallExpression.h b/alib2cli/src/ast/expression/MethodCallExpression.h
new file mode 100644
index 0000000000..2e48abff0f
--- /dev/null
+++ b/alib2cli/src/ast/expression/MethodCallExpression.h
@@ -0,0 +1,43 @@
+#ifndef _CLI_METHOD_CALL_EXPRESSION_H_
+#define _CLI_METHOD_CALL_EXPRESSION_H_
+
+#include <alib/foreach>
+
+#include <ast/Expression.h>
+#include <environment/Environment.h>
+
+namespace cli {
+
+class MethodCallExpression : public Expression {
+	std::unique_ptr < Expression > m_object;
+	std::string m_name;
+	std::vector < std::unique_ptr < Expression > > m_params;
+
+public:
+	MethodCallExpression ( std::unique_ptr < Expression > object, std::string name, std::vector < std::unique_ptr < Expression > > params ) : m_object ( std::move ( object ) ), m_name ( std::move ( name ) ), m_params ( std::move ( params ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		ext::vector < std::shared_ptr < abstraction::Value > > params;
+		params.push_back ( m_object->translateAndEval ( environment ) );
+		for ( const std::unique_ptr < Expression > & param : m_params ) {
+			params.push_back ( param->translateAndEval ( environment ) );
+		}
+
+		std::string name = m_name;
+
+		ext::vector < std::string > templateParams;
+/*		for ( const std::unique_ptr < cli::Arg > & templateParam : m_templateParams )
+			templateParams.push_back ( templateParam->eval ( environment ) );*/
+
+		abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE;
+/*		if ( m_category )
+			category = m_category->getCategory ( );*/
+
+		return abstraction::EvalHelper::evalAlgorithm ( environment, name, templateParams, params, category );
+	}
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_METHOD_CALL_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/expression/PostfixExpression.h b/alib2cli/src/ast/expression/PostfixExpression.h
new file mode 100644
index 0000000000..d915e1425d
--- /dev/null
+++ b/alib2cli/src/ast/expression/PostfixExpression.h
@@ -0,0 +1,29 @@
+#ifndef _CLI_POSTFIX_EXPRESSION_H_
+#define _CLI_POSTFIX_EXPRESSION_H_
+
+#include <ast/Expression.h>
+
+namespace cli {
+
+class PostfixExpression final : public Expression {
+	abstraction::Operators::PostfixOperators m_operation;
+	std::unique_ptr < Expression > m_expr;
+
+public:
+	PostfixExpression ( abstraction::Operators::PostfixOperators operation, std::unique_ptr < Expression > expr ) : m_operation ( operation ), m_expr ( std::move ( expr ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		ext::vector < std::shared_ptr < abstraction::Value > > params;
+		params.push_back ( m_expr->translateAndEval ( environment ) );
+
+		abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE;
+
+		return abstraction::EvalHelper::evalOperator ( environment, m_operation, params, category );
+	}
+
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_POSTFIX_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/expression/PrefixExpression.h b/alib2cli/src/ast/expression/PrefixExpression.h
new file mode 100644
index 0000000000..97f55ef70a
--- /dev/null
+++ b/alib2cli/src/ast/expression/PrefixExpression.h
@@ -0,0 +1,29 @@
+#ifndef _CLI_PREFIX_EXPRESSION_H_
+#define _CLI_PREFIX_EXPRESSION_H_
+
+#include <ast/Expression.h>
+
+namespace cli {
+
+class PrefixExpression final : public Expression {
+	abstraction::Operators::PrefixOperators m_operation;
+	std::unique_ptr < Expression > m_expr;
+
+public:
+	PrefixExpression ( abstraction::Operators::PrefixOperators operation, std::unique_ptr < Expression > expr ) : m_operation ( operation ), m_expr ( std::move ( expr ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		ext::vector < std::shared_ptr < abstraction::Value > > params;
+		params.push_back ( m_expr->translateAndEval ( environment ) );
+
+		abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE;
+
+		return abstraction::EvalHelper::evalOperator ( environment, m_operation, params, category );
+	}
+
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_PREFIX_EXPRESSION_H_ */
diff --git a/alib2cli/src/ast/expression/VariableExpression.h b/alib2cli/src/ast/expression/VariableExpression.h
new file mode 100644
index 0000000000..c8b27e51ab
--- /dev/null
+++ b/alib2cli/src/ast/expression/VariableExpression.h
@@ -0,0 +1,24 @@
+#ifndef _CLI_VARIABLE_EXPRESSION_H_
+#define _CLI_VARIABLE_EXPRESSION_H_
+
+#include <alib/string>
+#include <ast/Expression.h>
+
+namespace cli {
+
+class VariableExpression final : public Expression {
+	std::unique_ptr < cli::Arg > m_name;
+
+public:
+	VariableExpression ( std::unique_ptr < cli::Arg > name ) : m_name ( std::move ( name ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		return environment.getVariable ( m_name->eval ( environment ) );
+	}
+
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_VARIABLE_EXPRESSION_H_ */
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index a18e1aabf1..203f70d820 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -29,6 +29,16 @@
 #include <ast/command/SetCommand.h>
 #include <ast/command/LoadCommand.h>
 #include <ast/command/UnloadCommand.h>
+#include <ast/command/CalcCommand.h>
+
+#include <ast/expression/BinaryExpression.h>
+#include <ast/expression/PrefixExpression.h>
+#include <ast/expression/PostfixExpression.h>
+#include <ast/expression/CastExpression.h>
+#include <ast/expression/FunctionCallExpression.h>
+#include <ast/expression/MethodCallExpression.h>
+#include <ast/expression/VariableExpression.h>
+#include <ast/expression/ImmediateExpression.h>
 
 namespace cli {
 
@@ -412,9 +422,234 @@ std::unique_ptr < Command > Parser::command ( ) {
 		match ( cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING );
 
 		return std::make_unique < UnloadCommand > ( std::move ( libraryName ) );
+	} else if ( check_nonreserved_kw ( "calc" ) ) {
+		match_nonreserved_kw ( "calc" );
+
+		std::unique_ptr < Expression > expr = assign_expression ( );
+		return std::make_unique < CalcCommand > ( std::move ( expr ) );
 	} else {
 		throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding parse rule. Token is " + ( ( std::string ) m_current ) + "." );
 	}
 }
 
+std::unique_ptr < Expression > Parser::assign_expression ( ) {
+	std::unique_ptr < Expression > res = or_expression ( );
+	if ( check ( cli::Lexer::TokenType::ASSIGN_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::ASSIGN_OPERATOR );
+
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::ASSIGN, std::move ( res ), assign_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::or_expression ( ) {
+	std::unique_ptr < Expression > res = and_expression ( );
+	while ( check ( cli::Lexer::TokenType::OR_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::OR_OPERATOR );
+
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LOGICAL_OR, std::move ( res ), and_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::and_expression ( ) {
+	std::unique_ptr < Expression > res = bitwise_or_expression ( );
+	while ( check ( cli::Lexer::TokenType::AND_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::AND_OPERATOR );
+
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LOGICAL_AND, std::move ( res ), bitwise_or_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::bitwise_or_expression ( ) {
+	std::unique_ptr < Expression > res = bitwise_and_expression ( );
+	while ( check ( cli::Lexer::TokenType::PIPE_SIGN ) ) {
+		match ( cli::Lexer::TokenType::PIPE_SIGN );
+
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_OR, std::move ( res ), bitwise_and_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::bitwise_and_expression ( ) {
+	std::unique_ptr < Expression > res = bitwise_xor_expression ( );
+	while ( check ( cli::Lexer::TokenType::AMPERSAND_SIGN ) ) {
+		match ( cli::Lexer::TokenType::AMPERSAND_SIGN );
+
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_AND, std::move ( res ), bitwise_xor_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::bitwise_xor_expression ( ) {
+	std::unique_ptr < Expression > res = equality_expression ( );
+	while ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) {
+		match ( cli::Lexer::TokenType::CARET_SIGN );
+
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_XOR, std::move ( res ), equality_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::equality_expression ( ) {
+	std::unique_ptr < Expression > res = relational_expression ( );
+	if ( check ( cli::Lexer::TokenType::EQUAL_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::EQUAL_OPERATOR );
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::EQUALS, std::move ( res ), relational_expression ( ) );
+	} else if ( check ( cli::Lexer::TokenType::NOT_EQUAL_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::NOT_EQUAL_OPERATOR );
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::NOT_EQUALS, std::move ( res ), relational_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::relational_expression ( ) {
+	std::unique_ptr < Expression > res = add_expression ( );
+	if ( check ( cli::Lexer::TokenType::LESS_SIGN ) ) {
+		match ( cli::Lexer::TokenType::LESS_SIGN );
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LESS, std::move ( res ), add_expression ( ) );
+	} else if ( check ( cli::Lexer::TokenType::LESS_OR_EQUAL_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::LESS_OR_EQUAL_OPERATOR );
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LESS_OR_EQUAL, std::move ( res ), add_expression ( ) );
+	} else if ( check ( cli::Lexer::TokenType::MORE_SIGN ) ) {
+		match ( cli::Lexer::TokenType::MORE_SIGN );
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MORE, std::move ( res ), add_expression ( ) );
+	} else if ( check ( cli::Lexer::TokenType::MORE_OR_EQUAL_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::MORE_OR_EQUAL_OPERATOR );
+		res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MORE_OR_EQUAL, std::move ( res ), add_expression ( ) );
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::add_expression ( ) {
+	std::unique_ptr < Expression > res = mul_expression ( );
+	while ( check ( cli::Lexer::TokenType::PLUS_SIGN, cli::Lexer::TokenType::MINUS_SIGN ) ) {
+		if ( check ( cli::Lexer::TokenType::PLUS_SIGN ) ) {
+			match ( cli::Lexer::TokenType::PLUS_SIGN );
+			res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::ADD, std::move ( res ), mul_expression ( ) );
+		} else {
+			match ( cli::Lexer::TokenType::MINUS_SIGN );
+			res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::SUB, std::move ( res ), mul_expression ( ) );
+		}
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::mul_expression ( ) {
+	std::unique_ptr < Expression > res = prefix_expression ( );
+	while ( check ( cli::Lexer::TokenType::STAR_SIGN, cli::Lexer::TokenType::PERCENTAGE_SIGN, cli::Lexer::TokenType::SLASH_SIGN ) ) {
+		if ( check ( cli::Lexer::TokenType::STAR_SIGN ) ) {
+			match ( cli::Lexer::TokenType::STAR_SIGN );
+			res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MUL, std::move ( res ), prefix_expression ( ) );
+		} else if ( check ( cli::Lexer::TokenType::PERCENTAGE_SIGN ) ) {
+			match ( cli::Lexer::TokenType::PERCENTAGE_SIGN );
+			res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MOD, std::move ( res ), prefix_expression ( ) );
+		} else {
+			match ( cli::Lexer::TokenType::SLASH_SIGN );
+			res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::DIV, std::move ( res ), prefix_expression ( ) );
+		}
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::prefix_expression ( ) {
+	if ( check_nonreserved_kw ( "cast"  ) ) {
+		match_nonreserved_kw ( "cast" );
+		match ( cli::Lexer::TokenType::LEFT_PAREN );
+		std::unique_ptr < Arg > result_type = type ( );
+		match ( cli::Lexer::TokenType::RIGHT_PAREN );
+		std::unique_ptr < Expression > expression = prefix_expression ( );
+		return std::make_unique < CastExpression > ( std::move ( result_type ), std::move ( expression ) );
+	} else if ( check ( cli::Lexer::TokenType::PLUS_SIGN ) ) {
+		match ( cli::Lexer::TokenType::PLUS_SIGN );
+		std::unique_ptr < Expression > expression = prefix_expression ( );
+		return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::PLUS, std::move ( expression ) );
+	} else if ( check ( cli::Lexer::TokenType::MINUS_SIGN ) ) {
+		match ( cli::Lexer::TokenType::MINUS_SIGN );
+		std::unique_ptr < Expression > expression = prefix_expression ( );
+		return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::MINUS, std::move ( expression ) );
+	} else if ( check ( cli::Lexer::TokenType::EXCLAMATION_SIGN ) ) {
+		match ( cli::Lexer::TokenType::EXCLAMATION_SIGN );
+		std::unique_ptr < Expression > expression = prefix_expression ( );
+		return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::LOGICAL_NOT, std::move ( expression ) );
+	} else if ( check ( cli::Lexer::TokenType::TYLDE_SIGN ) ) {
+		match ( cli::Lexer::TokenType::TYLDE_SIGN );
+		std::unique_ptr < Expression > expression = prefix_expression ( );
+		return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::BINARY_NEG, std::move ( expression ) );
+	} else if ( check ( cli::Lexer::TokenType::INC_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::INC_OPERATOR );
+		std::unique_ptr < Expression > expression = prefix_expression ( );
+		return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::INCREMENT, std::move ( expression ) );
+	} else if ( check ( cli::Lexer::TokenType::DEC_OPERATOR ) ) {
+		match ( cli::Lexer::TokenType::DEC_OPERATOR );
+		std::unique_ptr < Expression > expression = prefix_expression ( );
+		return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::DECREMENT, std::move ( expression ) );
+	} else {
+		return suffix_expression ( );
+	}
+}
+
+std::unique_ptr < Expression > Parser::suffix_expression ( ) {
+	std::unique_ptr < Expression > res = atom ( );
+	while ( check ( cli::Lexer::TokenType::DOT, cli::Lexer::TokenType::INC_OPERATOR, cli::Lexer::TokenType::DEC_OPERATOR ) ) {
+		if ( check ( cli::Lexer::TokenType::DOT ) ) {
+			match ( cli::Lexer::TokenType::DOT );
+			std::string memberName = getTokenValue ( );
+			match ( cli::Lexer::TokenType::IDENTIFIER );
+			std::vector < std::unique_ptr < Expression > > params = bracketed_expression_list ( );
+			res = std::make_unique < MethodCallExpression > ( std::move ( res ), std::move ( memberName ), std::move ( params ) );
+		} else if ( check ( cli::Lexer::TokenType::INC_OPERATOR ) ){
+			match ( cli::Lexer::TokenType::INC_OPERATOR );
+			res = std::make_unique < PostfixExpression > ( abstraction::Operators::PostfixOperators::INCREMENT, std::move ( res ) );
+		} else if ( check ( cli::Lexer::TokenType::DEC_OPERATOR ) ){
+			match ( cli::Lexer::TokenType::DEC_OPERATOR );
+			res = std::make_unique < PostfixExpression > ( abstraction::Operators::PostfixOperators::DECREMENT, std::move ( res ) );
+		} else {
+			throw exception::CommonException ( "Mismatched set while expanding suffix expression rule. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );
+		}
+	}
+	return res;
+}
+
+std::unique_ptr < Expression > Parser::atom ( ) {
+	if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) {
+		std::string routineName = getTokenValue ( );
+		match ( cli::Lexer::TokenType::IDENTIFIER );
+		std::vector < std::unique_ptr < Expression > > params = bracketed_expression_list ( );
+		return std::make_unique < FunctionCallExpression > ( routineName, std::move ( params ) );
+	} else if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) {
+		match ( cli::Lexer::TokenType::DOLAR_SIGN );
+		std::unique_ptr < Arg > name = arg ( );
+		return std::make_unique < VariableExpression > ( std::move ( name ) );
+	} else if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) {
+		match ( cli::Lexer::TokenType::LEFT_PAREN );
+		std::unique_ptr < Expression > expr = assign_expression ( );
+		match ( cli::Lexer::TokenType::RIGHT_PAREN );
+		return expr;
+	} else if ( check ( cli::Lexer::TokenType::STRING ) ) {
+		std::string value = matchString ( );
+		return std::make_unique < ImmediateExpression < std::string > > ( value );
+	} else if ( check ( cli::Lexer::TokenType::UNSIGNED ) ) {
+		int value = matchInteger ( );
+		return std::make_unique < ImmediateExpression < int > > ( value );
+	} else {
+		throw exception::CommonException ( "Mismatched set while expanding parse rule. Token is " + ( ( std::string ) m_current ) + "." );
+	}
+}
+
+std::vector < std::unique_ptr < Expression > > Parser::bracketed_expression_list ( ) {
+	std::vector < std::unique_ptr < Expression > > res;
+	match ( cli::Lexer::TokenType::LEFT_PAREN );
+	if ( ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) {
+		res.push_back ( assign_expression ( ) );
+		while ( check ( cli::Lexer::TokenType::COMMA ) ) {
+			match ( cli::Lexer::TokenType::COMMA );
+			res.push_back ( assign_expression ( ) );
+		}
+	}
+	match ( cli::Lexer::TokenType::RIGHT_PAREN );
+	return res;
+}
+
 } /* namespace cli */
diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h
index bacd165f24..2461141cd1 100644
--- a/alib2cli/src/parser/Parser.h
+++ b/alib2cli/src/parser/Parser.h
@@ -4,6 +4,7 @@
 #include <ast/Statement.h>
 #include <ast/Option.h>
 #include <ast/Arg.h>
+#include <ast/Expression.h>
 
 #include <ast/options/TypeOption.h>
 #include <ast/options/CategoryOption.h>
@@ -139,6 +140,36 @@ public:
 		return m_current.m_value;
 	}
 
+	std::unique_ptr < Expression > assign_expression ( );
+
+	std::unique_ptr < Expression > or_expression ( );
+
+	std::unique_ptr < Expression > and_expression ( );
+
+	std::unique_ptr < Expression > bitwise_or_expression ( );
+
+	std::unique_ptr < Expression > bitwise_and_expression ( );
+
+	std::unique_ptr < Expression > bitwise_xor_expression ( );
+
+	std::unique_ptr < Expression > equality_expression ( );
+
+	std::unique_ptr < Expression > relational_expression ( );
+
+	std::unique_ptr < Expression > add_expression ( );
+
+	std::unique_ptr < Expression > mul_expression ( );
+
+	std::unique_ptr < Expression > cast_expression ( );
+
+	std::unique_ptr < Expression > prefix_expression ( );
+
+	std::unique_ptr < Expression > suffix_expression ( );
+
+	std::unique_ptr < Expression > atom ( );
+
+	std::vector < std::unique_ptr < Expression > > bracketed_expression_list ( );
+
 	std::unique_ptr < CategoryOption > category_option ( );
 
 	std::unique_ptr < TypeOption > type_option ( );
-- 
GitLab