From fd93cba85c8cde67d85b8ff123aa63c3b2a8547f Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Fri, 30 Aug 2019 11:50:06 +0200 Subject: [PATCH] implement semicolon separation of commands --- alib2cli/src/command/CommandList.h | 34 ++++++++++++++++++++++++++++++ alib2cli/src/lexer/Lexer.cpp | 6 ++++++ alib2cli/src/lexer/Lexer.h | 3 +++ alib2cli/src/parser/Parser.cpp | 33 ++++++++++++++++------------- alib2cli/src/parser/Parser.h | 6 ++++-- 5 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 alib2cli/src/command/CommandList.h diff --git a/alib2cli/src/command/CommandList.h b/alib2cli/src/command/CommandList.h new file mode 100644 index 0000000000..ecfb42f0f8 --- /dev/null +++ b/alib2cli/src/command/CommandList.h @@ -0,0 +1,34 @@ +#ifndef _CLI_COMMAND_LIST_H_ +#define _CLI_COMMAND_LIST_H_ + +#include <command/Command.h> + +namespace cli { + +class CommandList final : public Command { + ext::vector < std::unique_ptr < Command > > m_commands; + +public: + CommandList ( ext::vector < std::unique_ptr < Command > > commands ) : m_commands ( std::move ( commands ) ) { + } + + Command::Result run ( Environment & environment ) const override { + if ( m_commands.empty ( ) ) + throw std::invalid_argument ( "Command list can't be empty" ); + + Command::Result res = Command::Result::OK; + for ( size_t i = 0; i < m_commands.size ( ) && res == Command::Result::OK; ++ i ) + res = m_commands [ i ]->run ( environment ); + + return res; + } + + void append ( std::unique_ptr < Command > command ) { + m_commands.emplace_back ( std::move ( command ) ); + } + +}; + +} /* namespace cli */ + +#endif /* _CLI_COMMAND_LIST_H_ */ diff --git a/alib2cli/src/lexer/Lexer.cpp b/alib2cli/src/lexer/Lexer.cpp index 48e23090c6..2c44d09b3c 100644 --- a/alib2cli/src/lexer/Lexer.cpp +++ b/alib2cli/src/lexer/Lexer.cpp @@ -113,6 +113,12 @@ q0: if ( m_source->isEndOfTransmition ( ) ) { res.m_type = TokenType::COLON_SIGN; return res; } + if ( m_source->getCharacter ( ) == ';' ) { + res.m_raw += m_source->getCharacter ( ); + m_source->advance ( readNextLine ); + res.m_type = TokenType::SEMICOLON_SIGN; + return res; + } if ( m_source->getCharacter ( ) == '=' ) { res.m_raw += m_source->getCharacter ( ); m_source->advance ( readNextLine ); diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h index ff23c37e27..9a6c9baf9f 100644 --- a/alib2cli/src/lexer/Lexer.h +++ b/alib2cli/src/lexer/Lexer.h @@ -44,6 +44,7 @@ public: PIPE_SIGN, CARET_SIGN, COLON_SIGN, + SEMICOLON_SIGN, DASH_SIGN, EQUAL_SIGN, HASH_SIGN, @@ -90,6 +91,8 @@ public: return "caret_sign"; case TokenType::COLON_SIGN : return "colon_sign"; + case TokenType::SEMICOLON_SIGN : + return "semicolon_sign"; case TokenType::DASH_SIGN : return "dash_sign"; case TokenType::EQUAL_SIGN : diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp index ca72b598bd..48e51675b2 100644 --- a/alib2cli/src/parser/Parser.cpp +++ b/alib2cli/src/parser/Parser.cpp @@ -240,7 +240,7 @@ std::shared_ptr < Statement > Parser::statement ( ) { std::unique_ptr < CategoryOption > category = category_option ( ); ext::vector < std::shared_ptr < Statement > > params; ext::vector < bool > moves; - while ( ! check ( cli::Lexer::TokenType::OUT_REDIRECT ) && ! check ( cli::Lexer::TokenType::PIPE_SIGN ) && ! check ( cli::Lexer::TokenType::EOS ) && ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) { + while ( ! check ( cli::Lexer::TokenType::OUT_REDIRECT ) && ! check ( cli::Lexer::TokenType::PIPE_SIGN ) && ! check ( cli::Lexer::TokenType::EOS ) && ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) && ! check ( cli::Lexer::TokenType::SEMICOLON_SIGN ) ) { moves.push_back ( move_arg ( ) ); params.emplace_back ( param ( ) ); } @@ -266,7 +266,7 @@ std::shared_ptr < StatementList > Parser::statement_list ( ) { match ( cli::Lexer::TokenType::PIPE_SIGN ); list.emplace_back ( statement ( ) ); } - return std::make_shared < StatementList > ( list ); + return std::make_shared < StatementList > ( std::move ( list ) ); } void Parser::out_redirect_file ( std::shared_ptr < StatementList > & list ) { @@ -286,7 +286,7 @@ void Parser::out_redirect ( std::shared_ptr < StatementList > & list ) { match ( cli::Lexer::TokenType::DOLAR_SIGN ); std::unique_ptr < Arg > name = arg ( ); list->append ( std::make_unique < ResultVariableStatement > ( std::move ( name ) ) ); - } else if ( check ( cli::Lexer::TokenType::EOS ) ) { + } else if ( check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) { return; } else { out_redirect_file ( list ); @@ -297,7 +297,7 @@ void Parser::result ( std::shared_ptr < StatementList > & list ) { if ( check ( cli::Lexer::TokenType::OUT_REDIRECT ) ) { match ( cli::Lexer::TokenType::OUT_REDIRECT ); out_redirect ( list ); - } else if ( check ( cli::Lexer::TokenType::EOS ) ) { + } else if ( check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) { list->append ( std::make_unique < ResultPrintStatement > ( ) ); } else { return; @@ -359,40 +359,46 @@ std::unique_ptr < Command > Parser::introspect_command ( ) { } } -std::unique_ptr < Command > Parser::parse ( ) { +std::unique_ptr < CommandList > Parser::parse ( ) { + ext::vector < std::unique_ptr < Command > > list; + list.emplace_back ( command ( ) ); + while ( check ( cli::Lexer::TokenType::SEMICOLON_SIGN ) ) { + match ( cli::Lexer::TokenType::SEMICOLON_SIGN ); + list.emplace_back ( command ( ) ); + } + match ( cli::Lexer::TokenType::EOS ); + return std::make_unique < CommandList > ( std::move ( list ) ); +} + +std::unique_ptr < Command > Parser::command ( ) { if ( check_nonreserved_kw ( "execute" ) ) { match_nonreserved_kw ( "execute" ); std::shared_ptr < StatementList > res = statement_list ( ); result ( res ); - match ( cli::Lexer::TokenType::EOS ); return std::make_unique < ExecuteCommand > ( res ); } else if ( check_nonreserved_kw ( "quit" ) ) { match_nonreserved_kw ( "quit" ); std::shared_ptr < StatementList > res; - if ( ! check ( cli::Lexer::TokenType::EOS ) ) + if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) res = statement_list ( ); - match ( cli::Lexer::TokenType::EOS ); return std::make_unique < QuitCommand > ( res ); } else if ( check_nonreserved_kw ( "exit" ) ) { match_nonreserved_kw ( "exit" ); std::shared_ptr < StatementList > res; - if ( ! check ( cli::Lexer::TokenType::EOS ) ) + if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) res = statement_list ( ); - match ( cli::Lexer::TokenType::EOS ); return std::make_unique < QuitCommand > ( res ); } else if ( check_nonreserved_kw ( "help" ) ) { match_nonreserved_kw ( "help" ); std::unique_ptr < cli::Arg > command = optional_arg ( ); - match ( cli::Lexer::TokenType::EOS ); return std::make_unique < HelpCommand > ( std::move ( command ) ); } else if ( check_nonreserved_kw ( "introspect" ) ) { match_nonreserved_kw ( "introspect" ); std::unique_ptr < Command > command = introspect_command ( ); - match ( cli::Lexer::TokenType::EOS ); return command; } else if ( check_nonreserved_kw ( "set" ) ) { match_nonreserved_kw ( "set" ); @@ -400,19 +406,16 @@ std::unique_ptr < Command > Parser::parse ( ) { match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); std::string value = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING ); - match ( cli::Lexer::TokenType::EOS ); return std::make_unique < SetCommand > ( std::move ( param ), std::move ( value ) ); } else if ( check_nonreserved_kw ( "load" ) ) { match_nonreserved_kw ( "load" ); std::string libraryName = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING ); - match ( cli::Lexer::TokenType::EOS ); return std::make_unique < LoadCommand > ( std::move ( libraryName ) ); } else if ( check_nonreserved_kw ( "unload" ) ) { match_nonreserved_kw ( "unload" ); std::string libraryName = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING ); - match ( cli::Lexer::TokenType::EOS ); return std::make_unique < UnloadCommand > ( std::move ( libraryName ) ); } else if ( check ( cli::Lexer::TokenType::EOT ) ) { return std::make_unique < QuitCommand > ( nullptr ); diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h index 3e5695c4b1..d0f63a0cb7 100644 --- a/alib2cli/src/parser/Parser.h +++ b/alib2cli/src/parser/Parser.h @@ -8,7 +8,7 @@ #include <ast/options/TypeOption.h> #include <ast/options/CategoryOption.h> -#include <command/Command.h> +#include <command/CommandList.h> #include <ast/statements/StatementList.h> @@ -152,7 +152,9 @@ public: std::unique_ptr < Command > introspect_command ( ); - std::unique_ptr < Command > parse ( ); + std::unique_ptr < Command > command ( ); + + std::unique_ptr < CommandList > parse ( ); }; -- GitLab