From a81219a232cbb74e00c42006fb619c345f58002d Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Thu, 7 Sep 2017 20:46:34 +0200
Subject: [PATCH] add support for type hinting in file statement

---
 alib2cli/src/ast/Option.h                     |  2 ++
 alib2cli/src/ast/options/CategoryOption.h     |  4 +++
 alib2cli/src/ast/options/HL3Option.h          |  4 +++
 alib2cli/src/ast/options/TypeOption.h         |  4 +++
 .../ast/statements/ContainerFileStatement.h   |  1 -
 .../src/ast/statements/ContainerStatement.cpp |  2 ++
 .../src/ast/statements/ContainerStatement.h   |  3 --
 alib2cli/src/ast/statements/FileStatement.cpp | 29 +++++++++++++++++++
 alib2cli/src/ast/statements/FileStatement.h   | 17 +++++------
 alib2cli/src/parser/Parser.cpp                | 13 ++++++++-
 alib2cli/test-src/cli/CliTest.cpp             |  3 ++
 .../src/abstraction/PrimitiveRegistrator.cpp  |  3 ++
 .../src/abstraction/XmlParserRegistry.hpp     |  8 +++--
 13 files changed, 77 insertions(+), 16 deletions(-)
 create mode 100644 alib2cli/src/ast/statements/FileStatement.cpp

diff --git a/alib2cli/src/ast/Option.h b/alib2cli/src/ast/Option.h
index 8e3febebbf..32b9916620 100644
--- a/alib2cli/src/ast/Option.h
+++ b/alib2cli/src/ast/Option.h
@@ -5,6 +5,7 @@
 #include <ast/statements/SingleStatement.h>
 #include <ast/statements/ContainerStatement.h>
 #include <ast/statements/ContainerFileStatement.h>
+#include <ast/statements/FileStatement.h>
 
 namespace cli {
 
@@ -16,6 +17,7 @@ public:
 	virtual void eval ( SingleStatement & statement ) const = 0;
 	virtual void eval ( ContainerStatement & statement ) const = 0;
 	virtual void eval ( ContainerFileStatement & statement ) const = 0;
+	virtual void eval ( FileStatement & statement ) const = 0;
 };
 
 } /* namespace cli */
diff --git a/alib2cli/src/ast/options/CategoryOption.h b/alib2cli/src/ast/options/CategoryOption.h
index defe21f658..85d8bf3dbe 100644
--- a/alib2cli/src/ast/options/CategoryOption.h
+++ b/alib2cli/src/ast/options/CategoryOption.h
@@ -25,6 +25,10 @@ public:
 	virtual void eval ( ContainerFileStatement & ) const override {
 		throw exception::CommonException ( "ContainerFileStatement cannot be categorized." );
 	}
+
+	virtual void eval ( FileStatement & ) const override {
+		throw exception::CommonException ( "FileStatement cannot be categorized." );
+	}
 };
 
 } /* namespace cli */
diff --git a/alib2cli/src/ast/options/HL3Option.h b/alib2cli/src/ast/options/HL3Option.h
index 405e63ba48..6dba5a8131 100644
--- a/alib2cli/src/ast/options/HL3Option.h
+++ b/alib2cli/src/ast/options/HL3Option.h
@@ -18,6 +18,10 @@ public:
 	virtual void eval ( ContainerFileStatement & ) const override {
 		std::cout << "The cake is a lie, as well as the release date of HL3. GLaDOS told me." << std::endl;
 	}
+
+	virtual void eval ( FileStatement & ) const override {
+		std::cout << "The cake is a lie, as well as the release date of HL3. GLaDOS told me." << std::endl;
+	}
 };
 
 } /* namespace cli */
diff --git a/alib2cli/src/ast/options/TypeOption.h b/alib2cli/src/ast/options/TypeOption.h
index f9f06d8cb9..f70d309500 100644
--- a/alib2cli/src/ast/options/TypeOption.h
+++ b/alib2cli/src/ast/options/TypeOption.h
@@ -24,6 +24,10 @@ public:
 	virtual void eval ( ContainerFileStatement & statement ) const override {
 		statement.setType ( m_type );
 	}
+
+	virtual void eval ( FileStatement & statement ) const override {
+		statement.setType ( m_type );
+	}
 };
 
 } /* namespace cli */
diff --git a/alib2cli/src/ast/statements/ContainerFileStatement.h b/alib2cli/src/ast/statements/ContainerFileStatement.h
index 962eec43b7..e2e2d88c31 100644
--- a/alib2cli/src/ast/statements/ContainerFileStatement.h
+++ b/alib2cli/src/ast/statements/ContainerFileStatement.h
@@ -2,7 +2,6 @@
 #define _CLI_CONTAINER_FILE_STATEMENT_H_
 
 #include <ast/Statement.h>
-#include <abstraction/Registry.h>
 
 namespace cli {
 
diff --git a/alib2cli/src/ast/statements/ContainerStatement.cpp b/alib2cli/src/ast/statements/ContainerStatement.cpp
index 4b14caf0d0..9751550f2a 100644
--- a/alib2cli/src/ast/statements/ContainerStatement.cpp
+++ b/alib2cli/src/ast/statements/ContainerStatement.cpp
@@ -3,6 +3,8 @@
 #include <ast/Param.h>
 #include <ast/Arg.h>
 #include <abstraction/common/CastHelper.h>
+#include <exception/CommonException.h>
+#include <iostream>
 
 namespace cli {
 
diff --git a/alib2cli/src/ast/statements/ContainerStatement.h b/alib2cli/src/ast/statements/ContainerStatement.h
index 83930e6aff..35b97849d3 100644
--- a/alib2cli/src/ast/statements/ContainerStatement.h
+++ b/alib2cli/src/ast/statements/ContainerStatement.h
@@ -2,9 +2,6 @@
 #define _CLI_CONTAINER_STATEMENT_H_
 
 #include <ast/Statement.h>
-#include <abstraction/Registry.h>
-#include <exception/CommonException.h>
-#include <iostream>
 
 namespace cli {
 
diff --git a/alib2cli/src/ast/statements/FileStatement.cpp b/alib2cli/src/ast/statements/FileStatement.cpp
new file mode 100644
index 0000000000..9b8768ab8d
--- /dev/null
+++ b/alib2cli/src/ast/statements/FileStatement.cpp
@@ -0,0 +1,29 @@
+#include <ast/statements/FileStatement.h>
+#include <ast/Statement.h>
+#include <ast/Option.h>
+#include <ast/Arg.h>
+#include <abstraction/Registry.h>
+
+namespace cli {
+
+FileStatement::FileStatement ( ext::vector < std::unique_ptr < Option > > options, std::unique_ptr < Arg > file ) : m_file ( std::move ( file ) ), m_options ( std::move ( options ) ) {
+	for ( const std::unique_ptr < Option > & option : m_options ) {
+		option->eval ( * this );
+	}
+}
+
+std::shared_ptr < abstraction::OperationAbstraction > FileStatement::translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & environment ) const {
+	ext::deque < sax::Token > tokens = sax::FromXMLParserHelper::parseInput ( m_file->eval ( environment ) );
+
+	std::string type = m_type;
+	if ( type == "" )
+		type = tokens [ 0 ].getData ( );
+
+	return abstraction::Registry::getXmlParserAbstraction ( type, tokens );
+}
+
+void FileStatement::setType ( std::string type ) {
+	m_type = std::move ( type );
+}
+
+} /* namespace cli */
diff --git a/alib2cli/src/ast/statements/FileStatement.h b/alib2cli/src/ast/statements/FileStatement.h
index a430175887..cc3828577e 100644
--- a/alib2cli/src/ast/statements/FileStatement.h
+++ b/alib2cli/src/ast/statements/FileStatement.h
@@ -2,22 +2,21 @@
 #define _CLI_FILE_STATEMENT_H_
 
 #include <ast/Statement.h>
-#include <abstraction/Registry.h>
 
 namespace cli {
 
 class FileStatement final : public Statement {
 	std::unique_ptr < cli::Arg > m_file;
+	ext::vector < std::unique_ptr < Option > > m_options;
+
+	std::string m_type;
 
 public:
-	FileStatement ( std::unique_ptr < Arg > file ) : m_file ( std::move ( file ) ) {
-	}
-
-	virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & environment ) const override {
-		ext::deque < sax::Token > tokens = sax::FromXMLParserHelper::parseInput ( m_file->eval ( environment ) );
-		std::string type = tokens [ 0 ].getData ( );
-		return abstraction::Registry::getXmlParserAbstraction ( type, tokens );
-	}
+	FileStatement ( ext::vector < std::unique_ptr < Option > > options, std::unique_ptr < Arg > file );
+
+	virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & environment ) const override;
+
+	void setType ( std::string type );
 };
 
 } /* namespace cli */
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index 69e808981c..b153b061ca 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -200,8 +200,19 @@ std::shared_ptr < Statement > Parser::in_redirect_statement ( ) {
 		std::unique_ptr < Arg > file = arg ( );
 		return std::make_shared < ContainerFileStatement > ( "Set", std::move ( options ), std::move ( file ) );
 	} else {
+		ext::vector < std::unique_ptr < Option > > options;
+		while ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) {
+			match ( cli::Lexer::TokenType::COLON_SIGN );
+			std::unique_ptr < Option > res = type_option ( );
+			if ( ! res )
+				res = option ( );
+			if ( ! res )
+				throw exception::CommonException ( "Option not recognised" );
+			options.emplace_back ( std::move ( res ) );
+		}
+
 		std::unique_ptr < Arg > file = arg ( );
-		return std::make_shared < FileStatement > ( std::move ( file ) );
+		return std::make_shared < FileStatement > ( std::move ( options ), std::move ( file ) );
 	}
 }
 
diff --git a/alib2cli/test-src/cli/CliTest.cpp b/alib2cli/test-src/cli/CliTest.cpp
index c7e34789d3..7aac735909 100644
--- a/alib2cli/test-src/cli/CliTest.cpp
+++ b/alib2cli/test-src/cli/CliTest.cpp
@@ -96,6 +96,9 @@ void CliTest::testCreateUnique ( ) {
 	parser = cli::Parser ( cli::Lexer ( "execute One | Add <( Add (int) <#2 <(One) ) - | Neg (double) - | Divide (double) - <(One | (double) Add <(One) - )" ) );
 	parser.parse ( )->run ( environment );
 
+	parser = cli::Parser ( cli::Lexer ( "execute <:type int #2" ) );
+	parser.parse ( )->run ( environment );
+
 	parser = cli::Parser ( cli::Lexer ( "execute One > $res" ) );
 	parser.parse ( )->run ( environment );
 
diff --git a/alib2common/src/abstraction/PrimitiveRegistrator.cpp b/alib2common/src/abstraction/PrimitiveRegistrator.cpp
index c02d2f8471..7752bd3166 100644
--- a/alib2common/src/abstraction/PrimitiveRegistrator.cpp
+++ b/alib2common/src/abstraction/PrimitiveRegistrator.cpp
@@ -7,6 +7,7 @@
 
 #include <abstraction/CastRegistry.hpp>
 #include <abstraction/XmlFileWriterRegistry.hpp>
+#include <abstraction/XmlParserRegistry.hpp>
 #include <abstraction/NormalizeRegistry.hpp>
 #include <abstraction/ValuePrinterRegistry.hpp>
 #include <abstraction/ImmediateRegistry.hpp>
@@ -44,6 +45,8 @@ public:
 
 		abstraction::ContainerRegistry::registerSet < int > ( );
 
+		abstraction::XmlParserRegistry::registerXmlParser < int > ( "int" );
+
 		abstraction::XmlFileWriterRegistry::registerXmlFileWriter < int > ( );
 		abstraction::XmlFileWriterRegistry::registerXmlFileWriter < double > ( );
 		abstraction::XmlFileWriterRegistry::registerXmlFileWriter < std::string > ( );
diff --git a/alib2common/src/abstraction/XmlParserRegistry.hpp b/alib2common/src/abstraction/XmlParserRegistry.hpp
index 7adf27a9d0..eef86abb62 100644
--- a/alib2common/src/abstraction/XmlParserRegistry.hpp
+++ b/alib2common/src/abstraction/XmlParserRegistry.hpp
@@ -38,11 +38,15 @@ class XmlParserRegistry {
 	}
 
 public:
+	template < class ReturnType >
+	static void registerXmlParser ( std::string result ) {
+		getEntries ( ).insert ( std::make_pair ( result, std::unique_ptr < Entry > ( new EntryImpl < ReturnType > ( ) ) ) );
+	}
+
 	template < class ReturnType >
 	static void registerXmlParser ( ) {
 		std::string ret = alib::xmlApi < ReturnType >::xmlTagName ( );
-
-		getEntries ( ).insert ( std::make_pair ( ret, std::unique_ptr < Entry > ( new EntryImpl < ReturnType > ( ) ) ) );
+		registerXmlParser < ReturnType > ( ret );
 	}
 
 	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & typeName, ext::deque < sax::Token > tokens );
-- 
GitLab