From 31f307cc6ba42d16a1d4c137a1db4f849f113759 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Tue, 5 Sep 2017 15:28:05 +0200 Subject: [PATCH] cli syntax for set construction --- 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 | 27 +++++++++ .../src/ast/statements/ContainerStatement.cpp | 57 +++++++++++++++++++ .../src/ast/statements/ContainerStatement.h | 28 +++++++++ alib2cli/src/lexer/Lexer.cpp | 20 +++++++ alib2cli/src/lexer/Lexer.h | 12 ++++ alib2cli/src/parser/Parser.cpp | 34 +++++++++++ alib2cli/src/parser/Parser.h | 1 + alib2cli/test-src/cli/CliTest.cpp | 22 +++++++ alib2cli/test-src/cli/CliTest.h | 2 + 12 files changed, 213 insertions(+) create mode 100644 alib2cli/src/ast/options/TypeOption.h create mode 100644 alib2cli/src/ast/statements/ContainerStatement.cpp create mode 100644 alib2cli/src/ast/statements/ContainerStatement.h diff --git a/alib2cli/src/ast/Option.h b/alib2cli/src/ast/Option.h index 2c9c896b2a..d36660d3fc 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 594a587d6f..ed34c1752e 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 1a362e520f..8cb9935995 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 0000000000..6b0835528d --- /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 0000000000..4b14caf0d0 --- /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 0000000000..83930e6aff --- /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 2041b330c2..ad591d4d06 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 7ed1d1676f..8e56b887ac 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 bdce7cfa47..a750241de9 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 8d6a709b6d..124c88a858 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 e86f8daf2d..6b49045781 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 4f0f82bb32..d9f5c7af68 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_ -- GitLab