diff --git a/alib2cli/src/ast/Option.h b/alib2cli/src/ast/Option.h index 2c9c896b2a295c4e585a356cb59710939d50eca5..d36660d3fc9c3c31d540d06dc2e2256649e7b64c 100644 --- a/alib2cli/src/ast/Option.h +++ b/alib2cli/src/ast/Option.h @@ -3,6 +3,7 @@ #include <ast/Ast.h> #include <ast/statements/SingleStatement.h> +#include <ast/statements/ContainerStatement.h> namespace cli { @@ -12,6 +13,7 @@ public: } virtual void eval ( SingleStatement & statement ) const = 0; + virtual void eval ( ContainerStatement & statement ) const = 0; }; } /* namespace cli */ diff --git a/alib2cli/src/ast/options/CategoryOption.h b/alib2cli/src/ast/options/CategoryOption.h index 594a587d6fa56883c195cb1e79fa79196a63a073..ed34c1752eefa524659c6406b8e29d7f80b72fe4 100644 --- a/alib2cli/src/ast/options/CategoryOption.h +++ b/alib2cli/src/ast/options/CategoryOption.h @@ -17,6 +17,10 @@ public: virtual void eval ( SingleStatement & statement ) const override { statement.setCategory ( abstraction::AlgorithmCategories::algorithmCategory ( m_key ) ); } + + virtual void eval ( ContainerStatement & ) const override { + throw exception::CommonException ( "ContainerStatement cannot be categorized." ); + } }; } /* namespace cli */ diff --git a/alib2cli/src/ast/options/HL3Option.h b/alib2cli/src/ast/options/HL3Option.h index 1a362e520f3c9527258a1411d64485914fbf5778..8cb993599526ee3d4f833f935bad335f9f3942e5 100644 --- a/alib2cli/src/ast/options/HL3Option.h +++ b/alib2cli/src/ast/options/HL3Option.h @@ -10,6 +10,10 @@ public: virtual void eval ( SingleStatement & ) 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 ( ContainerStatement & ) 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 new file mode 100644 index 0000000000000000000000000000000000000000..6b0835528d5d8504406781c89609659cfeaec15f --- /dev/null +++ b/alib2cli/src/ast/options/TypeOption.h @@ -0,0 +1,27 @@ +#ifndef _CLI_VALUE_OPTION_H_ +#define _CLI_VALUE_OPTION_H_ + +#include <ast/Option.h> +#include <exception/CommonException.h> + +namespace cli { + +class TypeOption final : public Option { + std::string m_type; + +public: + TypeOption ( std::string type ) : m_type ( std::move ( type ) ) { + } + + virtual void eval ( SingleStatement & ) const override { + throw exception::CommonException ( "Single statement cannot be parametrized with type." ); + } + + virtual void eval ( ContainerStatement & statement ) const override { + statement.setType ( m_type ); + } +}; + +} /* namespace cli */ + +#endif /* _CLI_VALUE_OPTION_H_ */ diff --git a/alib2cli/src/ast/statements/ContainerStatement.cpp b/alib2cli/src/ast/statements/ContainerStatement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b14caf0d0be12dde9e7e50c3f4de10824ef0066 --- /dev/null +++ b/alib2cli/src/ast/statements/ContainerStatement.cpp @@ -0,0 +1,57 @@ +#include <ast/statements/ContainerStatement.h> +#include <ast/Option.h> +#include <ast/Param.h> +#include <ast/Arg.h> +#include <abstraction/common/CastHelper.h> + +namespace cli { + +ContainerStatement::ContainerStatement ( std::string container, ext::vector < std::unique_ptr < Param > > params, ext::vector < std::unique_ptr < Option > > options ) : m_container ( std::move ( container ) ), m_params ( std::move ( params ) ), m_options ( std::move ( options ) ) { + for ( const std::unique_ptr < Option > & option : m_options ) { + option->eval ( * this ); + } +} + +std::shared_ptr < abstraction::OperationAbstraction > ContainerStatement::translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const { + ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > params; + for ( const std::unique_ptr < Param > & param : m_params ) { + params.push_back ( param->translateAndEval ( prev, environment ) ); + } + + std::vector < bool > moves; + for ( const std::unique_ptr < Param > & param : m_params ) { + moves.push_back ( param->getMove ( ) ); + } + + std::shared_ptr < abstraction::OperationAbstraction > algo = abstraction::Registry::getContainerAbstraction ( m_container, m_type ); + + unsigned i = 0; + ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > casted_params; + for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : params ) { + if ( abstraction::Registry::isCastNoOp ( algo->getParamType ( i ), param->getReturnType ( ) ) ) { + casted_params.push_back ( param ); + } else { + casted_params.push_back ( abstraction::CastHelper::eval ( param, algo->getParamType ( i ), moves [ i ] ) ); + moves [ i ] = true; + } + ++ i; + } + + i = 0; + for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : casted_params ) { + if ( ! algo->attachInput ( param, i, moves [ i ] ) ) + throw exception::CommonException ( "Can't connect param at " + ext::to_string ( i ) + " of algorithm " + m_container + " with result of type " + param->getReturnType ( ) + "." ); + ++ i; + } + + if ( ! algo->eval ( ) ) + throw exception::CommonException ( "Eval of algorithm " + m_container + " failed." ); + + return algo; +} + +void ContainerStatement::setType ( std::string type ) { + m_type = std::move ( type ); +} + +} /* namespace cli */ diff --git a/alib2cli/src/ast/statements/ContainerStatement.h b/alib2cli/src/ast/statements/ContainerStatement.h new file mode 100644 index 0000000000000000000000000000000000000000..83930e6affe9d2f7d846d563f284778a85de4646 --- /dev/null +++ b/alib2cli/src/ast/statements/ContainerStatement.h @@ -0,0 +1,28 @@ +#ifndef _CLI_CONTAINER_STATEMENT_H_ +#define _CLI_CONTAINER_STATEMENT_H_ + +#include <ast/Statement.h> +#include <abstraction/Registry.h> +#include <exception/CommonException.h> +#include <iostream> + +namespace cli { + +class ContainerStatement final : public Statement { + std::string m_container; + ext::vector < std::unique_ptr < Param > > m_params; + ext::vector < std::unique_ptr < Option > > m_options; + + std::string m_type; + +public: + ContainerStatement ( std::string container, ext::vector < std::unique_ptr < Param > > params, ext::vector < std::unique_ptr < Option > > options ); + + virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override; + + void setType ( std::string type ); +}; + +} /* namespace cli */ + +#endif /* _CLI_CONTAINER_STATEMENT_H_ */ diff --git a/alib2cli/src/lexer/Lexer.cpp b/alib2cli/src/lexer/Lexer.cpp index 2041b330c2f904e3529ce1d43865bc5714629cc5..ad591d4d06a0337217ca111a4e1254f824d866cc 100644 --- a/alib2cli/src/lexer/Lexer.cpp +++ b/alib2cli/src/lexer/Lexer.cpp @@ -35,6 +35,26 @@ q0: if ( m_index >= m_line.size ( ) ) { res.m_type = TokenType::RIGHT_PAREN; return res; } + if ( m_line [ m_index ] == '{' ) { + m_index ++; + res.m_type = TokenType::LEFT_BRACE; + return res; + } + if ( m_line [ m_index ] == '}' ) { + m_index ++; + res.m_type = TokenType::RIGHT_BRACE; + return res; + } + if ( m_line [ m_index ] == '[' ) { + m_index ++; + res.m_type = TokenType::LEFT_BRACKET; + return res; + } + if ( m_line [ m_index ] == ']' ) { + m_index ++; + res.m_type = TokenType::RIGHT_BRACKET; + return res; + } if ( m_line [ m_index ] == '$' ) { m_index ++; res.m_type = TokenType::DOLAR_SIGN; diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h index 7ed1d1676f03689dd4b07b2c23c3d1a5a731ed72..8e56b887ac2d4ca531899a01728ddadbd9754113 100644 --- a/alib2cli/src/lexer/Lexer.h +++ b/alib2cli/src/lexer/Lexer.h @@ -19,6 +19,10 @@ public: OUT_REDIRECT, LEFT_PAREN, RIGHT_PAREN, + LEFT_BRACE, + RIGHT_BRACE, + LEFT_BRACKET, + RIGHT_BRACKET, DOLAR_SIGN, AMPERSAND_SIGN, PIPE_SIGN, @@ -55,6 +59,14 @@ public: return out << "left_paren"; case TokenType::RIGHT_PAREN : return out << "right_paren"; + case TokenType::LEFT_BRACE : + return out << "left_brace"; + case TokenType::RIGHT_BRACE : + return out << "right_brace"; + case TokenType::LEFT_BRACKET : + return out << "left_bracket"; + case TokenType::RIGHT_BRACKET : + return out << "right_bracket"; case TokenType::DOLAR_SIGN : return out << "dolar_sign"; case TokenType::AMPERSAND_SIGN : diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp index bdce7cfa47178c8cbd7ead29b3b9b52ec566c5ea..a750241de9fc04e75ea9c591150d2c8d0c541e6b 100644 --- a/alib2cli/src/parser/Parser.cpp +++ b/alib2cli/src/parser/Parser.cpp @@ -2,6 +2,7 @@ #include <ast/statements/CastStatement.h> #include <ast/statements/SingleStatement.h> +#include <ast/statements/ContainerStatement.h> #include <ast/statements/ResultFileStatement.h> #include <ast/statements/ResultVariableStatement.h> #include <ast/statements/ResultPrintStatement.h> @@ -31,6 +32,7 @@ #include <command/SetCommand.h> #include <ast/options/HL3Option.h> +#include <ast/options/TypeOption.h> #include <ast/options/CategoryOption.h> #include <primitive/Integer.h> @@ -48,6 +50,17 @@ std::unique_ptr < Option > Parser::category_option ( ) { } } +std::unique_ptr < Option > Parser::type_option ( ) { + if ( check_nonreserved_kw ( "type" ) ) { + match_nonreserved_kw ( "type" ); + std::string value = getTokenValue ( ); + match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); + return std::make_unique < TypeOption > ( std::move ( value ) ); + } else { + return nullptr; + } +} + std::unique_ptr < Option > Parser::option ( ) { match ( cli::Lexer::TokenType::COLON_SIGN ); if ( check_nonreserved_kw ( "hl3" ) ) { @@ -203,6 +216,27 @@ std::shared_ptr < Statement > Parser::single_statement ( ) { } return std::make_shared < SingleStatement > ( std::move ( name ), std::move ( params ), std::move ( options ) ); + } else if ( check ( cli::Lexer::TokenType::LEFT_BRACE ) ) { + match ( cli::Lexer::TokenType::LEFT_BRACE ); + 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 ) ); + } + + ext::vector < std::unique_ptr < Param > > params; + while ( ! check ( cli::Lexer::TokenType::RIGHT_BRACE ) ) { + params.emplace_back ( param ( ) ); + } + + std::shared_ptr < Statement > res = std::make_shared < ContainerStatement > ( "Set", std::move ( params ), std::move ( options ) ); + match ( cli::Lexer::TokenType::RIGHT_BRACE ); + return res; } else if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { match ( cli::Lexer::TokenType::HASH_SIGN ); std::string value = getTokenValue ( ); diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h index 8d6a709b6d7ce9b9c0959d187bd11f9bb8af5b3e..124c88a85870706c1b960f7e45c0125e763fd29f 100644 --- a/alib2cli/src/parser/Parser.h +++ b/alib2cli/src/parser/Parser.h @@ -81,6 +81,7 @@ public: } std::unique_ptr < Option > category_option ( ); + std::unique_ptr < Option > type_option ( ); std::unique_ptr < Option > option ( ); std::unique_ptr < Arg > arg ( ); diff --git a/alib2cli/test-src/cli/CliTest.cpp b/alib2cli/test-src/cli/CliTest.cpp index e86f8daf2da24d7d41d849c0a4ec0489c1506b56..6b4904578129e55825af97b9f9011d1ba3232393 100644 --- a/alib2cli/test-src/cli/CliTest.cpp +++ b/alib2cli/test-src/cli/CliTest.cpp @@ -11,6 +11,7 @@ #include <abstraction/AlgorithmRegistry.hpp> #include <abstraction/XmlFileWriterRegistry.hpp> #include <abstraction/XmlParserRegistry.hpp> +#include <abstraction/ContainerRegistry.hpp> CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( CliTest, "common" ); CPPUNIT_TEST_SUITE_REGISTRATION ( CliTest ); @@ -237,3 +238,24 @@ void CliTest::testConstRvalueReferencePassing ( ) { cli::Parser parser ( cli::Lexer ( "execute ConstRvalueReferenceProvider | ConstRvalueReferenceAcceptor ^ - >" ) ); parser.parse ( )->run ( environment ); } + +class Print { +public: + static void print ( ext::set < int > theSet ) { + for ( int value : theSet ) + std::cout << value << ", "; + std::cout << std::endl; + } +}; + +void CliTest::testSetConstruction ( ) { + abstraction::ContainerRegistry::registerSet < int > ( ); + abstraction::AlgorithmRegistry::registerAlgorithm < Print > ( Print::print, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT, false, false, std::array < std::string, 1 > ( ) ); + + cli::Environment environment; + cli::Parser parser ( cli::Lexer ( "execute { :type int 1 2 3 } > $set" ) ); + parser.parse ( )->run ( environment ); + std::cout << environment.getVariable ( "set" )->getReturnType ( ) << std::endl; + parser = cli::Parser ( cli::Lexer ( "execute $set | Print -" ) ); + parser.parse ( )->run ( environment ); +} diff --git a/alib2cli/test-src/cli/CliTest.h b/alib2cli/test-src/cli/CliTest.h index 4f0f82bb3205c6641c0f2185c7aeef0a5fcca03c..d9f5c7af681fc1da6794c426c346bb779a016021 100644 --- a/alib2cli/test-src/cli/CliTest.h +++ b/alib2cli/test-src/cli/CliTest.h @@ -11,6 +11,7 @@ class CliTest : public CppUnit::TestFixture { CPPUNIT_TEST ( testConstReferencePassing ); CPPUNIT_TEST ( testReferencePassing ); CPPUNIT_TEST ( testConstRvalueReferencePassing ); + CPPUNIT_TEST ( testSetConstruction ); CPPUNIT_TEST_SUITE_END ( ); public: @@ -23,6 +24,7 @@ public: void testConstReferencePassing ( ); void testReferencePassing ( ); void testConstRvalueReferencePassing ( ); + void testSetConstruction ( ); }; #endif // CLI_TEST_H_