#include <parser/Parser.h> #include <ast/statements/CastStatement.h> #include <ast/statements/SingleStatement.h> #include <ast/statements/ContainerStatement.h> #include <ast/statements/ContainerFileStatement.h> #include <ast/statements/ResultFileStatement.h> #include <ast/statements/ResultVariableStatement.h> #include <ast/statements/ResultPrintStatement.h> #include <ast/statements/VariableStatement.h> #include <ast/statements/ValueStatement.h> #include <ast/statements/FileStatement.h> #include <ast/statements/ImmediateStatement.h> #include <ast/statements/PreviousResultStatement.h> #include <ast/args/BindedArg.h> #include <ast/args/ImmediateArg.h> #include <command/ExecuteCommand.h> #include <command/QuitCommand.h> #include <command/HelpCommand.h> #include <command/AlgorithmsIntrospectionCommand.h> #include <command/OverloadsIntrospectionCommand.h> #include <command/DataTypesIntrospectionCommand.h> #include <command/CastsIntrospectionCommand.h> #include <command/SetCommand.h> #include <command/LoadCommand.h> #include <primitive/Integer.h> #include <primitive/String.h> namespace cli { std::unique_ptr < CategoryOption > Parser::category_option ( ) { if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { match ( cli::Lexer::TokenType::COLON_SIGN ); std::string value = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < CategoryOption > ( value ); } else { return nullptr; } } std::unique_ptr < TypeOption > Parser::type_option ( ) { if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { match ( cli::Lexer::TokenType::COLON_SIGN ); 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 < Arg > Parser::arg ( ) { if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { match ( cli::Lexer::TokenType::HASH_SIGN ); std::string value = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < BindedArg > ( std::move ( value ) ); } else { std::string value = matchIdentifier ( ); return std::make_unique < ImmediateArg > ( value ); } } std::unique_ptr < Arg > Parser::optional_arg ( ) { if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { match ( cli::Lexer::TokenType::HASH_SIGN ); std::string value = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < BindedArg > ( std::move ( value ) ); } else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) { std::string value = matchIdentifier ( ); return std::make_unique < ImmediateArg > ( value ); } else { return nullptr; } } bool Parser::move_arg ( ) { if ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) { match ( cli::Lexer::TokenType::CARET_SIGN ); return true; } else { return false; } } std::unique_ptr < Arg > Parser::template_arg ( ) { match ( cli::Lexer::TokenType::AT_SIGN ); return arg ( ); } std::shared_ptr < Statement > Parser::in_redirect ( ) { if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) { match ( cli::Lexer::TokenType::LEFT_PAREN ); std::shared_ptr < StatementList > res = statement_list ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); return res; } else if ( check ( cli::Lexer::TokenType::LEFT_BRACE ) ) { match ( cli::Lexer::TokenType::LEFT_BRACE ); std::unique_ptr < TypeOption > type = type_option ( ); match ( cli::Lexer::TokenType::RIGHT_BRACE ); std::unique_ptr < Arg > file = arg ( ); return std::make_shared < ContainerFileStatement > ( "Set", std::move ( type ), std::move ( file ) ); } else { ext::vector < std::unique_ptr < Option > > options; std::unique_ptr < TypeOption > type = type_option ( ); std::unique_ptr < Arg > file = arg ( ); return std::make_shared < FileStatement > ( std::move ( type ), std::move ( file ) ); } } std::shared_ptr < Statement > Parser::common ( ) { if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) { match ( cli::Lexer::TokenType::DOLAR_SIGN ); std::unique_ptr < Arg > name = arg ( ); return std::make_shared < VariableStatement > ( std::move ( name ) ); } else if ( check ( cli::Lexer::TokenType::IN_REDIRECT ) ) { match ( cli::Lexer::TokenType::IN_REDIRECT ); return in_redirect ( ); } else if ( check ( cli::Lexer::TokenType::STRING ) ) { std::string value = matchString ( ); return std::make_shared < ImmediateStatement < std::string > > ( value ); } else if ( check ( cli::Lexer::TokenType::INTEGER ) ) { int value = matchInteger ( ); return std::make_shared < ImmediateStatement < int > > ( value ); } else if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { match ( cli::Lexer::TokenType::HASH_SIGN ); std::string value = getTokenValue ( ); match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER ); return std::make_shared < ValueStatement > ( std::make_unique < BindedArg > ( std::move ( value ) ) ); } else { throw exception::CommonException ( "Mismatched set while expanding common rule." ); } } std::shared_ptr < Statement > Parser::param ( ) { if ( check ( cli::Lexer::TokenType::DOLAR_SIGN, cli::Lexer::TokenType::IN_REDIRECT, cli::Lexer::TokenType::STRING, cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::HASH_SIGN ) ) { return common ( ); } else if ( check ( cli::Lexer::TokenType::DASH_SIGN ) ) { match ( cli::Lexer::TokenType::DASH_SIGN ); return std::make_shared < PreviousResultStatement > ( ); } else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) { std::string value = matchIdentifier ( ); return std::make_shared < ImmediateStatement < std::string > > ( value ); } else if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) { match ( cli::Lexer::TokenType::LEFT_PAREN ); std::unique_ptr < Arg > type = arg ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); bool move = move_arg ( ); std::shared_ptr < Statement > castedParam = param ( ); return std::make_shared < CastStatement > ( std::move ( type ), castedParam, move ); } else { throw exception::CommonException ( "Mismatched set while expanding param rule." ); } } std::shared_ptr < Statement > Parser::statement ( ) { if ( check ( cli::Lexer::TokenType::DOLAR_SIGN, cli::Lexer::TokenType::IN_REDIRECT, cli::Lexer::TokenType::STRING, cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::HASH_SIGN ) ) { return common ( ); } else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) { std::unique_ptr < Arg > name = std::make_unique < ImmediateArg > ( matchIdentifier ( ) ); ext::vector < std::unique_ptr < cli::Arg > > templateArgs; while ( check ( cli::Lexer::TokenType::AT_SIGN ) ) { templateArgs.emplace_back ( template_arg ( ) ); } 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::END ) && ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) { moves.push_back ( move_arg ( ) ); params.emplace_back ( param ( ) ); } return std::make_shared < SingleStatement > ( std::move ( name ), std::move ( templateArgs ), std::move ( params ), std::move ( category ), std::move ( moves ) ); } else if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) { match ( cli::Lexer::TokenType::LEFT_PAREN ); std::unique_ptr < Arg > type = arg ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); bool move = move_arg ( ); std::shared_ptr < Statement > castedStatement = statement ( ); return std::make_shared < CastStatement > ( std::move ( type ), castedStatement, move ); } else if ( check ( cli::Lexer::TokenType::LEFT_BRACE ) ) { match ( cli::Lexer::TokenType::LEFT_BRACE ); std::unique_ptr < TypeOption > type = type_option ( ); ext::vector < std::shared_ptr < Statement > > params; ext::vector < bool > moves; while ( ! check ( cli::Lexer::TokenType::RIGHT_BRACE ) ) { moves.push_back ( move_arg ( ) ); params.emplace_back ( param ( ) ); } std::shared_ptr < Statement > res = std::make_shared < ContainerStatement > ( "Set", std::move ( params ), std::move ( type ), std::move ( moves ) ); match ( cli::Lexer::TokenType::RIGHT_BRACE ); return res; } else { // TODO builtin statement type to get string type throw exception::CommonException ( "Mismatched set while expanding param statement." ); } } std::shared_ptr < StatementList > Parser::statement_list ( ) { ext::vector < std::shared_ptr < Statement > > list; list.emplace_back ( statement ( ) ); while ( check ( cli::Lexer::TokenType::PIPE_SIGN ) ) { match ( cli::Lexer::TokenType::PIPE_SIGN ); list.emplace_back ( statement ( ) ); } return std::make_shared < StatementList > ( list ); } void Parser::out_redirect ( std::shared_ptr < StatementList > & list ) { if ( check ( cli::Lexer::TokenType::LEFT_BRACKET ) ) { match ( cli::Lexer::TokenType::LEFT_BRACKET ); std::unique_ptr < Arg > name = arg ( ); match ( cli::Lexer::TokenType::RIGHT_BRACKET ); } if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) { 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::END ) ) { return; } else { std::unique_ptr < Arg > file = arg ( ); list->append ( std::make_unique < ResultFileStatement > ( std::move ( file ) ) ); } } 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::END ) ) { list->append ( std::make_unique < ResultPrintStatement > ( ) ); } else { return; } } std::pair < bool, bool > Parser::introspect_cast_from_to ( ) { bool from = false; bool to = false; while ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) { match ( cli::Lexer::TokenType::COLON_SIGN ); if ( check_nonreserved_kw ( "from" ) ) { match_nonreserved_kw ( "from" ); from = true; } else if ( check_nonreserved_kw ( "to" ) ) { match_nonreserved_kw ( "to" ); to = true; } else { throw exception::CommonException ( "Mismatched set while expanding param introspect_cast_from_to." ); } } return std::make_pair ( from, to ); } std::unique_ptr < Command > Parser::introspect_command ( ) { if ( check_nonreserved_kw ( "algorithms" ) ) { match_nonreserved_kw ( "algorithms" ); std::unique_ptr < cli::Arg > param = optional_arg ( ); match ( cli::Lexer::TokenType::END ); return std::make_unique < AlgorithmsIntrospectionCommand > ( std::move ( param ) ); } else if ( check_nonreserved_kw ( "overloads" ) ) { match_nonreserved_kw ( "overloads" ); std::unique_ptr < cli::Arg > param = arg ( ); ext::vector < std::unique_ptr < cli::Arg > > templateArgs; while ( check ( cli::Lexer::TokenType::AT_SIGN ) ) { templateArgs.emplace_back ( template_arg ( ) ); } match ( cli::Lexer::TokenType::END ); return std::make_unique < OverloadsIntrospectionCommand > ( std::move ( param ), std::move ( templateArgs ) ); } else if ( check_nonreserved_kw ( "datatypes" ) ) { match_nonreserved_kw ( "datatypes" ); std::unique_ptr < cli::Arg > param = optional_arg ( ); match ( cli::Lexer::TokenType::END ); return std::make_unique < DataTypesIntrospectionCommand > ( std::move ( param ) ); } else if ( check_nonreserved_kw ( "casts" ) ) { match_nonreserved_kw ( "casts" ); std::pair < bool, bool > from_to = introspect_cast_from_to ( ); std::unique_ptr < cli::Arg > param = optional_arg ( ); match ( cli::Lexer::TokenType::END ); return std::make_unique < CastsIntrospectionCommand > ( std::move ( param ), from_to.first, from_to.second ); } else { throw exception::CommonException ( "Mismatched set while expanding param introspect_command." ); } } std::unique_ptr < Command > Parser::parse ( ) { if ( check_nonreserved_kw ( "execute" ) ) { match_nonreserved_kw ( "execute" ); std::shared_ptr < StatementList > res = statement_list ( ); result ( res ); match ( cli::Lexer::TokenType::END ); return std::make_unique < ExecuteCommand > ( res ); } else if ( check_nonreserved_kw ( "quit" ) ) { match_nonreserved_kw ( "quit" ); match ( cli::Lexer::TokenType::END ); return std::make_unique < QuitCommand > ( ); } else if ( check_nonreserved_kw ( "help" ) ) { match_nonreserved_kw ( "help" ); std::unique_ptr < cli::Arg > command = optional_arg ( ); match ( cli::Lexer::TokenType::END ); return std::make_unique < HelpCommand > ( std::move ( command ) ); } else if ( check_nonreserved_kw ( "introspect" ) ) { match_nonreserved_kw ( "introspect" ); return introspect_command ( ); } else if ( check_nonreserved_kw ( "set" ) ) { match_nonreserved_kw ( "set" ); std::string param = getTokenValue ( ); 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::END ); 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::END ); return std::make_unique < LoadCommand > ( std::move ( libraryName ) ); } else { throw exception::CommonException ( "Mismatched set while expanding parse rule." ); } } } /* namespace cli */