Skip to content
Snippets Groups Projects
Parser.cpp 7.13 KiB
Newer Older
#include <parser/Parser.h>

#include <ast/CastStatement.h>
#include <ast/SingleStatement.h>
#include <ast/FileResultStatement.h>
#include <ast/BindedFileResultStatement.h>
#include <ast/PrintResultStatement.h>
#include <ast/PreviousResultStatement.h>

#include <ast/StatementParam.h>
#include <ast/ImmediateFileParam.h>
#include <ast/BindedFileParam.h>
#include <ast/PreviousResultParam.h>
#include <ast/ImmediateParam.h>
#include <ast/BindedParam.h>
#include <ast/BindedVariable.h>
#include <ast/CastParam.h>

#include <command/ExecuteCommand.h>
#include <command/ExportCommand.h>
#include <command/QuitCommand.h>

#include <primitive/Integer.h>
#include <primitive/String.h>

namespace cli {

std::shared_ptr < StatementList > Parser::statement_list ( ) {
	std::shared_ptr < Statement > statement = single_statement ( );
	return std::make_shared < StatementList > ( statement, statement_list_cont ( ) );
}

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 );
		std::string name = getTokenValue ( );
		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
		return std::make_unique < BindedFileParam > ( std::move ( name ) );
	} else {
		std::string filename = matchIdentifier ( );
		return std::make_unique < ImmediateFileParam > ( filename );
	}
}

std::unique_ptr < Param > Parser::param ( ) {
	if ( check ( cli::Lexer::TokenType::DASH_SIGN ) ) {
		match ( cli::Lexer::TokenType::DASH_SIGN );
		return std::make_unique < PreviousResultParam > ( );
	} 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::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::string type = matchIdentifier ( );
		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 );
		std::string name = getTokenValue ( );
		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
		return std::make_unique < BindedParam > ( std::move ( name ) );
	} else if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) {
		match ( cli::Lexer::TokenType::DOLAR_SIGN );
		std::string name = getTokenValue ( );
		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
		return std::make_unique < BindedVariable > ( std::move ( name ) );
	} else {
		throw exception::CommonException ( "Mismatched set while expanding param rule." );
	}
}

std::shared_ptr < Statement > Parser::first_statement ( ) {
	if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) {
		match ( cli::Lexer::TokenType::DOLAR_SIGN );
		std::string name = matchIdentifier ( );
		return std::make_shared < PreviousResultStatement > ( std::move ( name ) );
	} else {
		return single_statement ( );
	}
}

std::shared_ptr < Statement > Parser::single_statement ( ) {
	if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) {
		match ( cli::Lexer::TokenType::LEFT_PAREN );
		std::string type = matchIdentifier ( );
		match ( cli::Lexer::TokenType::RIGHT_PAREN );
		std::shared_ptr < Statement > casted_statement = single_statement ( );
		return std::make_shared < CastStatement > ( std::move ( type ), casted_statement );
	} else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) {
		std::string name = matchIdentifier ( );
		std::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 ) ) {
			params.emplace_back ( param ( ) );
		}

		return std::make_shared < SingleStatement > ( name, std::move ( params ) );
	} else {
		throw exception::CommonException ( "Mismatched set while expanding param rule." );
	}
}

std::unique_ptr < Statement > Parser::out_redirect ( ) {
	if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) {
		match ( cli::Lexer::TokenType::COLON_SIGN );
		std::string name = getTokenValue ( );
		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
		return std::make_unique < BindedFileResultStatement > ( std::move ( name ) );
	} else {
		std::string filename = matchIdentifier ( );
		return std::make_unique < FileResultStatement > ( std::move ( filename ) );
	}
}

std::shared_ptr < StatementList > Parser::statement_list_cont ( ) {
	if ( check ( cli::Lexer::TokenType::OUT_REDIRECT ) ) {
		match ( cli::Lexer::TokenType::OUT_REDIRECT );
		return std::make_shared < StatementList > ( out_redirect ( ), nullptr );
	} else if ( check ( cli::Lexer::TokenType::END ) ) {
		return std::make_shared < StatementList > ( std::make_shared < PrintResultStatement > ( ), nullptr );
	} else {
		return statement_list_cont_no_print ( );
	}
}

std::shared_ptr < StatementList > Parser::statement_list_cont_no_print ( ) {
	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 ( ) );
std::unique_ptr < Command > Parser::parse ( ) {
	if ( check_nonreserved_kw ( "execute" ) ) {
		match_nonreserved_kw ( "execute" );
		std::shared_ptr < Statement > statement = first_statement ( );
		std::shared_ptr < StatementList > res = std::make_shared < StatementList > ( statement, statement_list_cont ( ) );
		match ( cli::Lexer::TokenType::END );
		return std::make_unique < ExecuteCommand > ( res );
	} else if ( check_nonreserved_kw ( "export" ) ) {
		match_nonreserved_kw ( "export" );
		std::string name = getTokenValue ( );
		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
		match ( cli::Lexer::TokenType::EQUAL_SIGN );
		std::shared_ptr < Statement > statement = first_statement ( );
		std::shared_ptr < StatementList > res = std::make_shared < StatementList > ( statement, statement_list_cont_no_print ( ) );
		match ( cli::Lexer::TokenType::END );
		return std::make_unique < ExportCommand > ( std::move ( name ), res );
	} else if ( check_nonreserved_kw ( "quit" ) ) {
		match_nonreserved_kw ( "quit" );
		match ( cli::Lexer::TokenType::END );
		return std::make_unique < QuitCommand > ( );
	} else {
		throw exception::CommonException ( "Mismatched set while expanding param rule." );
	}