From 1e5765192b7568a63ec4ebc4373b065e38970413 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Mon, 2 Dec 2019 18:21:40 +0100
Subject: [PATCH] unify batch and expressions

---
 alib2cli/src/ast/command/ExecuteCommand.h     |  8 +--
 alib2cli/src/ast/command/PrintCommand.h       |  8 +--
 alib2cli/src/ast/command/QuitCommand.h        | 10 +--
 alib2cli/src/ast/command/ReturnCommand.h      |  8 +--
 alib2cli/src/ast/expression/BatchExpression.h | 24 +++++++
 alib2cli/src/parser/Parser.cpp                | 68 ++++++++++++++-----
 alib2cli/src/parser/Parser.h                  |  8 +++
 7 files changed, 99 insertions(+), 35 deletions(-)
 create mode 100644 alib2cli/src/ast/expression/BatchExpression.h

diff --git a/alib2cli/src/ast/command/ExecuteCommand.h b/alib2cli/src/ast/command/ExecuteCommand.h
index 1145eac138..338bc9c2ac 100644
--- a/alib2cli/src/ast/command/ExecuteCommand.h
+++ b/alib2cli/src/ast/command/ExecuteCommand.h
@@ -3,19 +3,19 @@
 
 #include <ast/Command.h>
 #include <environment/Environment.h>
-#include <ast/Statement.h>
+#include <ast/Expression.h>
 
 namespace cli {
 
 class ExecuteCommand : public Command {
-	std::shared_ptr < Statement > m_command;
+	std::unique_ptr < Expression > m_expr;
 
 public:
-	ExecuteCommand ( std::shared_ptr < StatementList > command ) : m_command ( std::move ( command ) ) {
+	ExecuteCommand ( std::unique_ptr < Expression > expr ) : m_expr ( std::move ( expr ) ) {
 	}
 
 	CommandResult run ( Environment & environment ) const override {
-		m_command->translateAndEval ( nullptr, environment );
+		m_expr->translateAndEval ( environment );
 		return CommandResult::OK;
 	}
 };
diff --git a/alib2cli/src/ast/command/PrintCommand.h b/alib2cli/src/ast/command/PrintCommand.h
index 9f785fceff..3266f095af 100644
--- a/alib2cli/src/ast/command/PrintCommand.h
+++ b/alib2cli/src/ast/command/PrintCommand.h
@@ -3,7 +3,7 @@
 
 #include <ast/Command.h>
 #include <environment/Environment.h>
-#include <ast/Statement.h>
+#include <ast/Expression.h>
 
 #include <global/GlobalData.h>
 #include <registry/Registry.h>
@@ -11,14 +11,14 @@
 namespace cli {
 
 class PrintCommand : public Command {
-	std::shared_ptr < Statement > m_command;
+	std::unique_ptr < Expression > m_expr;
 
 public:
-	PrintCommand ( std::shared_ptr < Statement > command ) : m_command ( std::move ( command ) ) {
+	PrintCommand ( std::unique_ptr < Expression > expr ) : m_expr ( std::move ( expr ) ) {
 	}
 
 	CommandResult run ( Environment & environment ) const override {
-		std::shared_ptr < abstraction::Value > value = m_command->translateAndEval ( nullptr, environment );
+		std::shared_ptr < abstraction::Value > value = m_expr->translateAndEval ( environment );
 
 		std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getValuePrinterAbstraction ( value->getType ( ) );
 
diff --git a/alib2cli/src/ast/command/QuitCommand.h b/alib2cli/src/ast/command/QuitCommand.h
index e8aa5655b8..476a30fb16 100644
--- a/alib2cli/src/ast/command/QuitCommand.h
+++ b/alib2cli/src/ast/command/QuitCommand.h
@@ -3,20 +3,20 @@
 
 #include <ast/Command.h>
 #include <environment/Environment.h>
-#include <ast/Statement.h>
+#include <ast/Expression.h>
 
 namespace cli {
 
 class QuitCommand : public Command {
-	std::shared_ptr < Statement > m_command;
+	std::unique_ptr < Expression > m_expr;
 
 public:
-	QuitCommand ( std::shared_ptr < Statement > command ) : m_command ( std::move ( command ) ) {
+	QuitCommand ( std::unique_ptr < Expression > expr ) : m_expr ( std::move ( expr ) ) {
 	}
 
 	CommandResult run ( Environment & environment ) const override {
-		if ( m_command )
-			environment.setResult ( m_command->translateAndEval ( nullptr, environment ) );
+		if ( m_expr )
+			environment.setResult ( m_expr->translateAndEval ( environment ) );
 
 		return CommandResult::QUIT;
 	}
diff --git a/alib2cli/src/ast/command/ReturnCommand.h b/alib2cli/src/ast/command/ReturnCommand.h
index 9b9de6bceb..dd3b062b04 100644
--- a/alib2cli/src/ast/command/ReturnCommand.h
+++ b/alib2cli/src/ast/command/ReturnCommand.h
@@ -3,20 +3,20 @@
 
 #include <ast/Command.h>
 #include <environment/Environment.h>
-#include <ast/Statement.h>
+#include <ast/Expression.h>
 
 namespace cli {
 
 class ReturnCommand : public Command {
-	std::shared_ptr < Statement > m_command;
+	std::unique_ptr < Expression > m_command;
 
 public:
-	ReturnCommand ( std::shared_ptr < Statement > command ) : m_command ( std::move ( command ) ) {
+	ReturnCommand ( std::unique_ptr < Expression > command ) : m_command ( std::move ( command ) ) {
 	}
 
 	CommandResult run ( Environment & environment ) const override {
 		if ( m_command )
-			environment.setResult ( m_command->translateAndEval ( nullptr, environment ) );
+			environment.setResult ( m_command->translateAndEval ( environment ) );
 
 		return CommandResult::RETURN;
 	}
diff --git a/alib2cli/src/ast/expression/BatchExpression.h b/alib2cli/src/ast/expression/BatchExpression.h
new file mode 100644
index 0000000000..53e5f55267
--- /dev/null
+++ b/alib2cli/src/ast/expression/BatchExpression.h
@@ -0,0 +1,24 @@
+#ifndef _CLI_BATCH_EXPRESSION_H_
+#define _CLI_BATCH_EXPRESSION_H_
+
+#include <ast/Expression.h>
+#include <ast/Statement.h>
+
+namespace cli {
+
+class BatchExpression final : public Expression {
+	std::shared_ptr < Statement > m_statement;
+
+public:
+	BatchExpression ( std::shared_ptr < Statement > statement ) : m_statement ( std::move ( statement ) ) {
+	}
+
+	std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override {
+		return m_statement->translateAndEval ( nullptr, environment );
+	}
+
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_BATCH_EXPRESSION_H_ */
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index cdb6a08063..39ac763c9f 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -36,6 +36,7 @@
 #include <ast/command/IfCommand.h>
 #include <ast/command/ReturnCommand.h>
 
+#include <ast/expression/BatchExpression.h>
 #include <ast/expression/BinaryExpression.h>
 #include <ast/expression/PrefixExpression.h>
 #include <ast/expression/PostfixExpression.h>
@@ -375,40 +376,71 @@ std::unique_ptr < Command > Parser::semicolon_command ( ) {
 	return res;
 }
 
+std::unique_ptr < Expression > Parser::expression ( ) {
+	return assign_expression ( );
+}
+
+std::unique_ptr < Expression > Parser::batch ( ) {
+	std::shared_ptr < StatementList > res = statement_list ( );
+	return std::make_unique < BatchExpression > ( std::move ( res ) );
+}
+
+std::unique_ptr < Expression > Parser::expression_or_batch ( ) {
+	if ( check_nonreserved_kw ( "batch" ) ) {
+		match_nonreserved_kw ( "batch" );
+		return batch ( );
+	} else {
+		if ( check_nonreserved_kw ( "expression" ) )
+			match_nonreserved_kw ( "expression" );
+		return expression ( );
+	}
+}
+
+std::unique_ptr < Expression > Parser::batch_or_expression ( ) {
+	if ( check_nonreserved_kw ( "expression" ) ) {
+		match_nonreserved_kw ( "expression" );
+		return expression ( );
+	} else {
+		if ( check_nonreserved_kw ( "batch" ) )
+			match_nonreserved_kw ( "batch" );
+		return batch ( );
+	}
+}
+
 std::unique_ptr < Command > Parser::command ( ) {
 	clearCheckOptions ( );
 	if ( check_nonreserved_kw ( "execute" ) ) {
 		match_nonreserved_kw ( "execute" );
-		std::shared_ptr < StatementList > res = statement_list ( );
-		return std::make_unique < ExecuteCommand > ( std::move ( res ) );
+		std::unique_ptr < Expression > expr = batch_or_expression ( );
+		return std::make_unique < ExecuteCommand > ( std::move ( expr ) );
 	} else if ( check_nonreserved_kw ( "print" ) ) {
 		match_nonreserved_kw ( "print" );
-		std::shared_ptr < StatementList > res = statement_list ( );
-		return std::make_unique < PrintCommand > ( std::move ( res ) );
+		std::unique_ptr < Expression > expr = batch_or_expression ( );
+		return std::make_unique < PrintCommand > ( std::move ( expr ) );
 	} else if ( check_nonreserved_kw ( "quit" ) ) {
 		match_nonreserved_kw ( "quit" );
 
-		std::shared_ptr < StatementList > res;
+		std::unique_ptr < Expression > expr;
 		if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) )
-			res = statement_list ( );
+			expr = batch_or_expression ( );
 
-		return std::make_unique < QuitCommand > ( res );
+		return std::make_unique < QuitCommand > ( std::move ( expr ) );
 	} else if ( check_nonreserved_kw ( "exit" ) ) {
 		match_nonreserved_kw ( "exit" );
 
-		std::shared_ptr < StatementList > res;
+		std::unique_ptr < Expression > expr;
 		if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) )
-			res = statement_list ( );
+			expr = batch_or_expression ( );
 
-		return std::make_unique < QuitCommand > ( res );
+		return std::make_unique < QuitCommand > ( std::move ( expr ) );
 	} else if ( check_nonreserved_kw ( "return" ) ) {
 		match_nonreserved_kw ( "return" );
 
-		std::shared_ptr < StatementList > res;
+		std::unique_ptr < Expression > expr;
 		if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) )
-			res = statement_list ( );
+			expr = expression ( );
 
-		return std::make_unique < ReturnCommand > ( res );
+		return std::make_unique < ReturnCommand > ( std::move ( expr ) );
 	} else if ( check_nonreserved_kw ( "help" ) ) {
 		match_nonreserved_kw ( "help" );
 		std::unique_ptr < cli::Arg > command = optional_arg ( );
@@ -443,7 +475,7 @@ std::unique_ptr < Command > Parser::command ( ) {
 	} else if ( check_nonreserved_kw ( "calc" ) ) {
 		match_nonreserved_kw ( "calc" );
 
-		std::unique_ptr < Expression > expr = assign_expression ( );
+		std::unique_ptr < Expression > expr = expression ( );
 		return std::make_unique < CalcCommand > ( std::move ( expr ) );
 	} else if ( check_nonreserved_kw ( "begin" ) ) {
 		return std::make_unique < BlockCommand > ( block ( ) );
@@ -465,7 +497,7 @@ std::unique_ptr < Command > Parser::command ( ) {
 			throw exception::CommonException ( "Statement not available in global scope." );
 		match_nonreserved_kw ( "if" );
 		match ( cli::Lexer::TokenType::LEFT_PAREN );
-		std::unique_ptr < Expression > condition = assign_expression ( );
+		std::unique_ptr < Expression > condition = expression_or_batch ( );
 		match ( cli::Lexer::TokenType::RIGHT_PAREN );
 
 		match_nonreserved_kw ( "then" );
@@ -739,7 +771,7 @@ std::unique_ptr < Expression > Parser::atom ( ) {
 		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 ( );
+		std::unique_ptr < Expression > expr = expression ( );
 		match ( cli::Lexer::TokenType::RIGHT_PAREN );
 		return expr;
 	} else if ( check ( cli::Lexer::TokenType::STRING ) ) {
@@ -757,10 +789,10 @@ 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 ( ) );
+		res.push_back ( expression ( ) );
 		while ( check ( cli::Lexer::TokenType::COMMA ) ) {
 			match ( cli::Lexer::TokenType::COMMA );
-			res.push_back ( assign_expression ( ) );
+			res.push_back ( expression ( ) );
 		}
 	}
 	match ( cli::Lexer::TokenType::RIGHT_PAREN );
diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h
index d5770d3a10..f40642b172 100644
--- a/alib2cli/src/parser/Parser.h
+++ b/alib2cli/src/parser/Parser.h
@@ -221,6 +221,14 @@ public:
 
 	std::unique_ptr < CommandList > block ( );
 
+	std::unique_ptr < Expression > expression ( );
+
+	std::unique_ptr < Expression > batch ( );
+
+	std::unique_ptr < Expression > expression_or_batch ( );
+
+	std::unique_ptr < Expression > batch_or_expression ( );
+
 	std::unique_ptr < Command > command ( );
 
 	std::unique_ptr < Command > semicolon_command ( );
-- 
GitLab