Skip to content
Snippets Groups Projects
Parser.cpp 14.1 KiB
Newer Older
#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/params/StatementParam.h>
#include <ast/params/FileParam.h>
#include <ast/params/ImmediateParam.h>
#include <ast/params/PreviousResultParam.h>
#include <ast/params/ValueParam.h>
#include <ast/params/VariableParam.h>
#include <ast/params/CastParam.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 <primitive/Integer.h>
#include <primitive/String.h>

namespace cli {

Jan Trávníček's avatar
Jan Trávníček committed
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;
	}
}

Jan Trávníček's avatar
Jan Trávníček committed
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 < 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 ( ), false );
		match ( cli::Lexer::TokenType::RIGHT_PAREN );
		return sub_statement;
	} else {
		std::unique_ptr < Arg > file = arg ( );
		return std::make_unique < FileParam > ( std::move ( file ) );
	}
}

std::unique_ptr < Param > Parser::param ( ) {
	if ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) {
		match ( cli::Lexer::TokenType::CARET_SIGN );
		return move_param ( );
	} else {
		return value_param ( );
	}
}

std::unique_ptr < Param > Parser::move_param ( ) {
	if ( check ( cli::Lexer::TokenType::DASH_SIGN ) ) {
		match ( cli::Lexer::TokenType::DASH_SIGN );
		return std::make_unique < PreviousResultParam > ( true );
	} else if ( check ( cli::Lexer::TokenType::IN_REDIRECT ) ) {
		match ( cli::Lexer::TokenType::IN_REDIRECT );
		match ( cli::Lexer::TokenType::LEFT_PAREN );
		auto sub_statement = std::make_unique < StatementParam > ( statement_list ( ), true );
		match ( cli::Lexer::TokenType::RIGHT_PAREN );
		return sub_statement;
	} else if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) {
		match ( cli::Lexer::TokenType::DOLAR_SIGN );
		std::unique_ptr < Arg > name = arg ( );
		return std::make_unique < VariableParam > ( std::move ( name ), true );
	} else {
		throw exception::CommonException ( "Mismatched set while expanding move_param rule." );
	}
}

std::unique_ptr < Param > Parser::value_param ( ) {
	if ( check ( cli::Lexer::TokenType::DASH_SIGN ) ) {
		match ( cli::Lexer::TokenType::DASH_SIGN );
		return std::make_unique < PreviousResultParam > ( false );
	} else if ( check ( cli::Lexer::TokenType::IN_REDIRECT ) ) {
		match ( cli::Lexer::TokenType::IN_REDIRECT );
		return in_redirect_param ( );
	} else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) {
		std::string value = matchIdentifier ( );
		return std::make_unique < ImmediateParam < std::string > > ( value );
	} else if ( check ( cli::Lexer::TokenType::STRING ) ) {
		std::string value = matchString ( );
		return std::make_unique < ImmediateParam < std::string > > ( value );
	} else if ( check ( cli::Lexer::TokenType::INTEGER ) ) {
		int value = matchInteger ( );
		return std::make_unique < ImmediateParam < int > > ( 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 );
		std::unique_ptr < Param > castedParam = param ( );
		return std::make_unique < CastParam > ( std::move ( type ), std::move ( castedParam ) );
	} else if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) {
		match ( cli::Lexer::TokenType::DOLAR_SIGN );
		std::unique_ptr < Arg > name = arg ( );
		return std::make_unique < VariableParam > ( std::move ( name ), false );
	} 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_unique < ValueParam > ( std::make_unique < BindedArg > ( std::move ( value ) ) );
		throw exception::CommonException ( "Mismatched set while expanding param rule." );
std::shared_ptr < Statement > Parser::in_redirect_statement ( ) {
	if ( check ( cli::Lexer::TokenType::LEFT_BRACE ) ) {
		match ( cli::Lexer::TokenType::LEFT_BRACE );
Jan Trávníček's avatar
Jan Trávníček committed
		std::unique_ptr < TypeOption > type = type_option ( );
		match ( cli::Lexer::TokenType::RIGHT_BRACE );
		std::unique_ptr < Arg > file = arg ( );
Jan Trávníček's avatar
Jan Trávníček committed
		return std::make_shared < ContainerFileStatement > ( "Set", std::move ( type ), std::move ( file ) );
		ext::vector < std::unique_ptr < Option > > options;
Jan Trávníček's avatar
Jan Trávníček committed
		std::unique_ptr < TypeOption > type = type_option ( );
		std::unique_ptr < Arg > file = arg ( );
Jan Trávníček's avatar
Jan Trávníček committed
		return std::make_shared < FileStatement > ( std::move ( type ), std::move ( file ) );
std::shared_ptr < Statement > Parser::single_statement ( ) {
	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_statement ( );
	} 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 > casted_statement = single_statement ( );
		return std::make_shared < CastStatement > ( std::move ( type ), casted_statement, move );
	// TODO builtin statement type to get string type
	} else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) {
		std::unique_ptr < Arg > name = std::make_unique < ImmediateArg > ( matchIdentifier ( ) );
Jan Trávníček's avatar
Jan Trávníček committed
		std::unique_ptr < CategoryOption > category = category_option ( );
		ext::vector < std::unique_ptr < Param > > params;
		while ( ! check ( cli::Lexer::TokenType::OUT_REDIRECT ) && ! check ( cli::Lexer::TokenType::PIPE_SIGN ) && ! check ( cli::Lexer::TokenType::END ) && ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) {
			params.emplace_back ( param ( ) );
		}

Jan Trávníček's avatar
Jan Trávníček committed
		return std::make_shared < SingleStatement > ( std::move ( name ), std::move ( params ), std::move ( category ) );
	} else if ( check ( cli::Lexer::TokenType::LEFT_BRACE ) ) {
		match ( cli::Lexer::TokenType::LEFT_BRACE );
Jan Trávníček's avatar
Jan Trávníček committed
		std::unique_ptr < TypeOption > type = type_option ( );

		ext::vector < std::unique_ptr < Param > > params;
		while ( ! check ( cli::Lexer::TokenType::RIGHT_BRACE ) ) {
			params.emplace_back ( param ( ) );
		}

Jan Trávníček's avatar
Jan Trávníček committed
		std::shared_ptr < Statement > res = std::make_shared < ContainerStatement > ( "Set", std::move ( params ), std::move ( type ) );
		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 ( );
		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
		return std::make_shared < ValueStatement > ( std::make_unique < BindedArg > ( std::move ( value ) ) );
		throw exception::CommonException ( "Mismatched set while expanding param single_statement." );
Jan Trávníček's avatar
Jan Trávníček committed
std::shared_ptr < StatementList > Parser::statement_list ( ) {
	std::shared_ptr < Statement > statement = single_statement ( );
Jan Trávníček's avatar
Jan Trávníček committed
	return std::make_shared < StatementList > ( statement, statement_list_cont ( ) );
}

std::shared_ptr < StatementList > Parser::statement_list_cont ( ) {
	if ( check ( cli::Lexer::TokenType::PIPE_SIGN ) ) {
		match ( cli::Lexer::TokenType::PIPE_SIGN );
		std::shared_ptr < Statement > statement = single_statement ( );
		return std::make_shared < StatementList > ( statement, statement_list_cont ( ) );
	} else {
		return nullptr;
	}
}

void Parser::out_redirect ( std::shared_ptr < StatementList > & list ) {
	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 ) ) {
	} else {
		std::unique_ptr < Arg > file = arg ( );
		list->append ( std::make_unique < ResultFileStatement > ( std::move ( file ) ) );
Jan Trávníček's avatar
Jan Trávníček committed
void Parser::result ( std::shared_ptr < StatementList > & list ) {
	if ( check ( cli::Lexer::TokenType::OUT_REDIRECT ) ) {
		match ( cli::Lexer::TokenType::OUT_REDIRECT );
Jan Trávníček's avatar
Jan Trávníček committed
		out_redirect ( list );
	} else if ( check ( cli::Lexer::TokenType::END ) ) {
		list->append ( std::make_unique < ResultPrintStatement > ( ) );
Jan Trávníček's avatar
Jan Trávníček committed
		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 ( );
		match ( cli::Lexer::TokenType::END );
		return std::make_unique < OverloadsIntrospectionCommand > ( std::move ( param ) );
	} 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" );
Jan Trávníček's avatar
Jan Trávníček committed
		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 ) );
Jan Trávníček's avatar
Jan Trávníček committed
	} 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 ) );
		throw exception::CommonException ( "Mismatched set while expanding parse rule." );