From 53eb8442f8599a0bc106d0919545ef80779b0918 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Fri, 11 Aug 2017 19:46:37 +0200 Subject: [PATCH] change cli syntax, pass options to singleStatement --- alib2cli/src/ast/Ast.h | 12 ++++ alib2cli/src/ast/Option.h | 19 ++++++ alib2cli/src/ast/Param.h | 1 + alib2cli/src/ast/Statement.h | 3 +- alib2cli/src/ast/options/HL3Option.h | 17 ++++++ .../src/ast/statements/SingleStatement.cpp | 58 +++++++++++++++++++ alib2cli/src/ast/statements/SingleStatement.h | 51 ++-------------- alib2cli/src/command/HelpCommand.h | 10 ++-- alib2cli/src/lexer/Lexer.cpp | 5 ++ alib2cli/src/lexer/Lexer.h | 3 + alib2cli/src/parser/Parser.cpp | 44 +++++++++----- alib2cli/src/parser/Parser.h | 7 ++- alib2cli/test-src/cli/CliTest.cpp | 4 +- 13 files changed, 165 insertions(+), 69 deletions(-) create mode 100644 alib2cli/src/ast/Ast.h create mode 100644 alib2cli/src/ast/Option.h create mode 100644 alib2cli/src/ast/options/HL3Option.h create mode 100644 alib2cli/src/ast/statements/SingleStatement.cpp diff --git a/alib2cli/src/ast/Ast.h b/alib2cli/src/ast/Ast.h new file mode 100644 index 0000000000..b79fc96bf4 --- /dev/null +++ b/alib2cli/src/ast/Ast.h @@ -0,0 +1,12 @@ +#ifndef _CLI_AST_H_ +#define _CLI_AST_H_ + +namespace cli { + +class Option; +class Statement; +class Param; + +} /* namespace cli */ + +#endif /* _CLI_AST_H_ */ diff --git a/alib2cli/src/ast/Option.h b/alib2cli/src/ast/Option.h new file mode 100644 index 0000000000..2c9c896b2a --- /dev/null +++ b/alib2cli/src/ast/Option.h @@ -0,0 +1,19 @@ +#ifndef _CLI_OPTION_H_ +#define _CLI_OPTION_H_ + +#include <ast/Ast.h> +#include <ast/statements/SingleStatement.h> + +namespace cli { + +class Option { +public: + virtual ~Option ( ) noexcept { + } + + virtual void eval ( SingleStatement & statement ) const = 0; +}; + +} /* namespace cli */ + +#endif /* _CLI_OPTION_H_ */ diff --git a/alib2cli/src/ast/Param.h b/alib2cli/src/ast/Param.h index 82bf87a669..4e2ef4a463 100644 --- a/alib2cli/src/ast/Param.h +++ b/alib2cli/src/ast/Param.h @@ -1,6 +1,7 @@ #ifndef _CLI_PARAM_H_ #define _CLI_PARAM_H_ +#include <ast/Ast.h> #include <abstraction/OperationAbstraction.hpp> #include <environment/Environment.h> diff --git a/alib2cli/src/ast/Statement.h b/alib2cli/src/ast/Statement.h index 2a23c5496f..5e026e7a0b 100644 --- a/alib2cli/src/ast/Statement.h +++ b/alib2cli/src/ast/Statement.h @@ -1,12 +1,13 @@ #ifndef _CLI_STATEMENT_H_ #define _CLI_STATEMENT_H_ +#include <ast/Ast.h> #include <abstraction/OperationAbstraction.hpp> #include <environment/Environment.h> namespace cli { -class Statement { +class Statement : public std::enable_shared_from_this < Statement > { public: virtual ~Statement ( ) noexcept { } diff --git a/alib2cli/src/ast/options/HL3Option.h b/alib2cli/src/ast/options/HL3Option.h new file mode 100644 index 0000000000..90b3bea7de --- /dev/null +++ b/alib2cli/src/ast/options/HL3Option.h @@ -0,0 +1,17 @@ +#ifndef _CLI_HL3_OPTION_H_ +#define _CLI_HL3_OPTION_H_ + +#include <ast/Option.h> + +namespace cli { + +class HL3Option final : public Option { +public: + virtual void eval ( SingleStatement & statement ) const override { + statement.setHL3 ( ); + } +}; + +} /* namespace cli */ + +#endif /* _CLI_HL3_OPTION_H_ */ diff --git a/alib2cli/src/ast/statements/SingleStatement.cpp b/alib2cli/src/ast/statements/SingleStatement.cpp new file mode 100644 index 0000000000..4804e8791e --- /dev/null +++ b/alib2cli/src/ast/statements/SingleStatement.cpp @@ -0,0 +1,58 @@ +#include <ast/statements/SingleStatement.h> +#include <ast/Option.h> +#include <ast/Param.h> + +namespace cli { + +SingleStatement::SingleStatement ( std::string name, ext::vector < std::unique_ptr < Param > > params, ext::vector < std::unique_ptr < Option > > options ) : m_name ( name ), 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 > SingleStatement::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 ) ); + } + + ext::vector < ext::type_index > paramTypes; + for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : params ) { + paramTypes.push_back ( param->type ( ) ); + } + + bool downcast = false; + bool normalize = false; + + std::shared_ptr < abstraction::OperationAbstraction > algo = abstraction::Registry::getAlgorithmAbstraction ( m_name, paramTypes, downcast, normalize ); + + unsigned i = 0; + for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : params ) { + if ( ! algo->attachInput ( param, i ) ) + throw exception::CommonException ( "Can't connect param at " + ext::to_string ( i ) + " of algorithm " + m_name + " with result of type " + ext::to_string ( param->type ( ) ) + "." ); + i++; + } + + if ( ! algo->eval ( ) ) + throw exception::CommonException ( "Eval of algorithm " + m_name + " failed." ); + + if ( downcast ) { + std::shared_ptr < abstraction::OperationAbstraction > downcaster = algo->getDowncastResult ( ); + downcaster->attachInput ( algo, 0 ); + downcaster->eval ( ); + + algo = downcaster; + } + + if ( normalize ) { + std::shared_ptr < abstraction::OperationAbstraction > normalized = algo->getNormalizeResult ( ); + normalized->attachInput ( algo, 0 ); + normalized->eval ( ); + + algo = normalized; + } + + return algo; +} + +} /* namespace cli */ diff --git a/alib2cli/src/ast/statements/SingleStatement.h b/alib2cli/src/ast/statements/SingleStatement.h index ef7d6b518c..f68f7aa484 100644 --- a/alib2cli/src/ast/statements/SingleStatement.h +++ b/alib2cli/src/ast/statements/SingleStatement.h @@ -4,62 +4,23 @@ #include <ast/Statement.h> #include <abstraction/Registry.h> #include <exception/CommonException.h> +#include <iostream> namespace cli { class SingleStatement final : public Statement { std::string m_name; ext::vector < std::unique_ptr < Param > > m_params; + ext::vector < std::unique_ptr < Option > > m_options; public: - SingleStatement ( std::string name, ext::vector < std::unique_ptr < Param > > params ) : m_name ( name ), m_params ( std::move ( params ) ) { - } - - virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override { - ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > params; - for ( const std::unique_ptr < Param > & param : m_params ) { - params.push_back ( param->translateAndEval ( prev, environment ) ); - } - - ext::vector < ext::type_index > paramTypes; - for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : params ) { - paramTypes.push_back ( param->type ( ) ); - } - - bool downcast = false; - bool normalize = false; - - std::shared_ptr < abstraction::OperationAbstraction > algo = abstraction::Registry::getAlgorithmAbstraction ( m_name, paramTypes, downcast, normalize ); - - unsigned i = 0; - for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : params ) { - if ( ! algo->attachInput ( param, i ) ) - throw exception::CommonException ( "Can't connect param at " + ext::to_string ( i ) + " of algorithm " + m_name + " with result of type " + ext::to_string ( param->type ( ) ) + "." ); - i++; - } + SingleStatement ( std::string name, ext::vector < std::unique_ptr < Param > > params, ext::vector < std::unique_ptr < Option > > options ); - if ( ! algo->eval ( ) ) - throw exception::CommonException ( "Eval of algorithm " + m_name + " failed." ); + virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override; - if ( downcast ) { - std::shared_ptr < abstraction::OperationAbstraction > downcaster = algo->getDowncastResult ( ); - downcaster->attachInput ( algo, 0 ); - downcaster->eval ( ); - - algo = downcaster; - } - - if ( normalize ) { - std::shared_ptr < abstraction::OperationAbstraction > normalized = algo->getNormalizeResult ( ); - normalized->attachInput ( algo, 0 ); - normalized->eval ( ); - - algo = normalized; - } - - return algo; + void setHL3 ( ) { + 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/command/HelpCommand.h b/alib2cli/src/command/HelpCommand.h index 222fb8f065..a78a6a46c1 100644 --- a/alib2cli/src/command/HelpCommand.h +++ b/alib2cli/src/command/HelpCommand.h @@ -26,25 +26,25 @@ public: std::cout << "" << std::endl; std::cout << "identifier - an immediate string param - the value is a std::string (ImmediateValueParam)" << std::endl; std::cout << "number - an immediate number param - the value is an int (ImmediateValueParam)" << std::endl; - std::cout << ":identifier - an immediate value from an environment - the value is a std::string (BindedValueParam)" << std::endl; + std::cout << "#identifier - an immediate value from an environment - the value is a std::string (BindedValueParam)" << std::endl; std::cout << "$identifier - a value from a variable (VariableValueParam)" << std::endl; std::cout << "" << std::endl; std::cout << "<identifier - a value from a xml file named (ImmediateFileParam)" << std::endl; - std::cout << "<:identifier - a value from a xml file with a name from an environment (BindedFileParam)" << std::endl; + std::cout << "<#identifier - a value from a xml file with a name from an environment (BindedFileParam)" << std::endl; std::cout << "" << std::endl; std::cout << "statement:" << std::endl; std::cout << "name ( param )* output_spec - a statement with params (SingleStatement)" << std::endl; std::cout << "( type ) statement - the result of a statement is casted (CastedStatement)" << std::endl; std::cout << "" << std::endl; - std::cout << ":identifier - an immediate value from an environment (BindedValueStatement)" << std::endl; + std::cout << "#identifier - an immediate value from an environment (BindedValueStatement)" << std::endl; std::cout << "$identifier - a value from a variable (VariableValueStatement)" << std::endl; std::cout << "" << std::endl; std::cout << "<identifier - a value from a xml file (ImmediateFileStatement)" << std::endl; - std::cout << "<:identifier - a value from a xml file with a name from an environment (BindedFileStatement)" << std::endl; + std::cout << "<#identifier - a value from a xml file with a name from an environment (BindedFileStatement)" << std::endl; std::cout << "" << std::endl; std::cout << "output_spec:" << std::endl; std::cout << ">identifier - a value to a xml file (ResultImmediateFileStatement)" << std::endl; - std::cout << ">:identifier - a value to a xml file with name from environment (ResultBindedFileStatement)" << std::endl; + std::cout << ">#identifier - a value to a xml file with name from environment (ResultBindedFileStatement)" << std::endl; std::cout << ">$identifier - a value to a variable (ResultVariableStatement)" << std::endl; std::cout << "> - a value is discarded" << std::endl; std::cout << " - an empty output specifier prints the result to the stdout (ResultPrintStatement)" << std::endl; diff --git a/alib2cli/src/lexer/Lexer.cpp b/alib2cli/src/lexer/Lexer.cpp index f6aba8a339..d70f22cc9d 100644 --- a/alib2cli/src/lexer/Lexer.cpp +++ b/alib2cli/src/lexer/Lexer.cpp @@ -60,6 +60,11 @@ q0: if ( m_index >= m_line.size ( ) ) { res.m_type = TokenType::EQUAL_SIGN; return res; } + if ( m_line [ m_index ] == '#' ) { + m_index ++; + res.m_type = TokenType::HASH_SIGN; + return res; + } if ( m_line [ m_index ] == '-' ) { res.m_value += m_line [ m_index ]; m_index ++; diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h index 64eb39d97c..7eb4d8a426 100644 --- a/alib2cli/src/lexer/Lexer.h +++ b/alib2cli/src/lexer/Lexer.h @@ -24,6 +24,7 @@ public: COLON_SIGN, DASH_SIGN, EQUAL_SIGN, + HASH_SIGN, ERROR, END }; @@ -62,6 +63,8 @@ public: return out << "dash_sign"; case TokenType::EQUAL_SIGN : return out << "equal_sign"; + case TokenType::HASH_SIGN : + return out << "hash_sign"; case TokenType::ERROR : return out << "error"; case TokenType::END : diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp index 46b0ae6b75..06749d3d5a 100644 --- a/alib2cli/src/parser/Parser.cpp +++ b/alib2cli/src/parser/Parser.cpp @@ -26,19 +26,31 @@ #include <command/IntrospectionCommand.h> #include <command/SetCommand.h> +#include <ast/options/HL3Option.h> + #include <primitive/Integer.h> #include <primitive/String.h> namespace cli { +std::unique_ptr < Option > Parser::option ( ) { + match ( cli::Lexer::TokenType::COLON_SIGN ); + if ( check_nonreserved_kw ( "hl3" ) ) { + match_nonreserved_kw ( "hl3" ); + return std::make_unique < HL3Option > ( ); + } else { + throw exception::CommonException ( "Mismatched set while expanding option rule." ); + } +} + std::unique_ptr < Param > Parser::in_redirect_param ( ) { if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) { match ( cli::Lexer::TokenType::LEFT_PAREN ); auto sub_statement = std::make_unique < StatementParam > ( statement_list ( ) ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); return sub_statement; - } else if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { - match ( cli::Lexer::TokenType::COLON_SIGN ); + } else if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { + match ( cli::Lexer::TokenType::HASH_SIGN ); std::string name = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < BindedFileParam > ( std::move ( name ) ); @@ -67,8 +79,8 @@ std::unique_ptr < Param > Parser::param ( ) { match ( cli::Lexer::TokenType::RIGHT_PAREN ); std::unique_ptr < Param > castedParam = param ( ); return std::make_unique < CastParam > ( std::move ( type ), std::move ( castedParam ) ); - } else if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { - match ( cli::Lexer::TokenType::COLON_SIGN ); + } else if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { + match ( cli::Lexer::TokenType::HASH_SIGN ); std::string name = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < BindedValueParam > ( std::move ( name ) ); @@ -83,8 +95,8 @@ std::unique_ptr < Param > Parser::param ( ) { } std::shared_ptr < Statement > Parser::in_redirect_statement ( ) { - if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { - match ( cli::Lexer::TokenType::COLON_SIGN ); + if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { + match ( cli::Lexer::TokenType::HASH_SIGN ); std::string name = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < BindedFileStatement > ( std::move ( name ) ); @@ -99,8 +111,8 @@ std::shared_ptr < Statement > Parser::single_statement ( ) { match ( cli::Lexer::TokenType::DOLAR_SIGN ); std::string name = matchIdentifier ( ); return std::make_shared < VariableValueStatement > ( std::move ( name ) ); - } else if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { - match ( cli::Lexer::TokenType::COLON_SIGN ); + } else if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { + match ( cli::Lexer::TokenType::HASH_SIGN ); std::string name = matchIdentifier ( ); return std::make_shared < BindedValueStatement > ( std::move ( name ) ); } else if ( check ( cli::Lexer::TokenType::IN_REDIRECT ) ) { @@ -114,14 +126,18 @@ std::shared_ptr < Statement > Parser::single_statement ( ) { return std::make_shared < CastStatement > ( std::move ( type ), casted_statement ); } else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) { std::string name = matchIdentifier ( ); + ext::vector < std::unique_ptr < Option > > options; + while ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { + options.emplace_back ( option ( ) ); + } ext::vector < std::unique_ptr < Param > > params; - while ( ! check ( cli::Lexer::TokenType::OUT_REDIRECT ) && ! check ( cli::Lexer::TokenType::COLON_SIGN ) && ! check ( cli::Lexer::TokenType::PIPE_SIGN ) && ! check ( cli::Lexer::TokenType::END ) && ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) { + while ( ! check ( cli::Lexer::TokenType::OUT_REDIRECT ) && ! check ( cli::Lexer::TokenType::HASH_SIGN ) && ! check ( cli::Lexer::TokenType::PIPE_SIGN ) && ! check ( cli::Lexer::TokenType::END ) && ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) { params.emplace_back ( param ( ) ); } - return std::make_shared < SingleStatement > ( name, std::move ( params ) ); + return std::make_shared < SingleStatement > ( name, std::move ( params ), std::move ( options ) ); } else { - throw exception::CommonException ( "Mismatched set while expanding param rule." ); + throw exception::CommonException ( "Mismatched set while expanding single_statement rule." ); } } @@ -141,8 +157,8 @@ std::shared_ptr < StatementList > Parser::statement_list_cont ( ) { } void Parser::out_redirect ( std::shared_ptr < StatementList > & list ) { - if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { - match ( cli::Lexer::TokenType::COLON_SIGN ); + if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { + match ( cli::Lexer::TokenType::HASH_SIGN ); std::string name = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); list->append ( std::make_unique < ResultBindedFileStatement > ( std::move ( name ) ) ); @@ -207,7 +223,7 @@ std::unique_ptr < Command > Parser::parse ( ) { match ( cli::Lexer::TokenType::END ); return std::make_unique < SetCommand > ( std::move ( param ), std::move ( value ) ); } else { - throw exception::CommonException ( "Mismatched set while expanding param rule." ); + throw exception::CommonException ( "Mismatched set while expanding parse rule." ); } } diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h index 1b50257903..063edc3b8a 100644 --- a/alib2cli/src/parser/Parser.h +++ b/alib2cli/src/parser/Parser.h @@ -3,10 +3,11 @@ #include <ast/Param.h> #include <ast/Statement.h> -#include <ast/statements/StatementList.h> - +#include <ast/Option.h> #include <command/Command.h> +#include <ast/statements/StatementList.h> + #include <lexer/Lexer.h> #include <exception/CommonException.h> @@ -68,6 +69,8 @@ public: return m_current.m_value; } + std::unique_ptr < Option > option ( ); + std::unique_ptr < Param > in_redirect_param ( ); std::unique_ptr < Param > param ( ); diff --git a/alib2cli/test-src/cli/CliTest.cpp b/alib2cli/test-src/cli/CliTest.cpp index 8b2ce29b5a..20799db7c5 100644 --- a/alib2cli/test-src/cli/CliTest.cpp +++ b/alib2cli/test-src/cli/CliTest.cpp @@ -84,11 +84,11 @@ void CliTest::testCreateUnique ( ) { try { cli::Environment environment; environment.setBinding ( "1", "1" ); - cli::Parser parser ( cli::Lexer ( "execute One | Add <( Add (int) :1 <(One) ) - | Neg - > local/xxx.xml" ) ); + cli::Parser parser ( cli::Lexer ( "execute One | Add <( Add (int) #1 <(One) ) - | Neg - > local/xxx.xml" ) ); parser.parse ( )->run ( environment ); environment.setBinding ( "2", "local/xxx.xml" ); - parser = cli::Parser ( cli::Lexer ( "execute One | Add <( Add (int) <:2 <(One) ) - | (double) Neg - | Divide - <(One | (double) Add <(One) - )" ) ); + parser = cli::Parser ( cli::Lexer ( "execute One | Add <( Add (int) <#2 <(One) ) - | (double) Neg - | Divide - <(One | (double) Add <(One) - )" ) ); parser.parse ( )->run ( environment ); parser = cli::Parser ( cli::Lexer ( "execute One > $res" ) ); -- GitLab