Skip to content
Snippets Groups Projects
Parser.cpp 17.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <parser/Parser.h>
    
    
    #include <ast/statements/CastStatement.h>
    #include <ast/statements/SingleStatement.h>
    
    #include <ast/statements/ContainerStatement.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/EOTCommand.h>
    
    #include <command/HelpCommand.h>
    
    #include <command/AlgorithmsIntrospectionCommand.h>
    
    #include <command/OverloadsIntrospectionCommand.h>
    
    #include <command/DataTypesIntrospectionCommand.h>
    #include <command/CastsIntrospectionCommand.h>
    
    #include <command/BindingsIntrospectionCommand.h>
    #include <command/VariablesIntrospectionCommand.h>
    
    #include <command/SetCommand.h>
    
    #include <command/LoadCommand.h>
    
    #include <command/UnloadCommand.h>
    
    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 ) );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    	} else {
    
    		throw exception::CommonException ( "Mismatched colon sign while expanding type_option rule. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    	}
    }
    
    std::unique_ptr < TypeOption > Parser::optional_type_option ( ) {
    	if ( check ( cli::Lexer::TokenType::COLON_SIGN ) ) {
    		return type_option ( );
    
    	} else {
    		return nullptr;
    	}
    }
    
    
    std::unique_ptr < Arg > Parser::file ( ) {
    	setHint ( Lexer::Hint::FILE );
    	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::STRING ) ) {
    		return std::make_unique < ImmediateArg > ( matchString ( ) );
    	} else {
    		return std::make_unique < ImmediateArg > ( matchFile ( ) );
    	}
    }
    
    std::unique_ptr < Arg > Parser::type ( ) {
    	setHint ( Lexer::Hint::TYPE );
    	if ( check ( cli::Lexer::TokenType::STRING ) )
    		return std::make_unique < ImmediateArg > ( matchString ( ) );
    	else {
    		return std::make_unique < ImmediateArg > ( matchType ( ) );
    	}
    }
    
    
    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 ( ) {
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    	if ( check ( cli::Lexer::TokenType::HASH_SIGN, cli::Lexer::TokenType::IDENTIFIER ) ) {
    		return arg ( );
    
    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::unique_ptr < Arg > Parser::optional_variable ( ) {
    	if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) {
    		match ( cli::Lexer::TokenType::DOLAR_SIGN );
    		std::string value = getTokenValue ( );
    		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
    		return std::make_unique < ImmediateArg > ( value );
    	} else {
    		return nullptr;
    	}
    }
    
    std::unique_ptr < Arg > Parser::optional_binding ( ) {
    	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 < ImmediateArg > ( value );
    	} else {
    		return nullptr;
    	}
    }
    
    
    std::shared_ptr < Statement > Parser::in_redirect_file ( ) {
    
    	std::unique_ptr < Arg > fileType;
    
    	if ( check ( cli::Lexer::TokenType::LEFT_BRACKET ) ) {
    		match ( cli::Lexer::TokenType::LEFT_BRACKET );
    		fileType = arg ( );
    		match ( cli::Lexer::TokenType::RIGHT_BRACKET );
    	}
    
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    	std::unique_ptr < TypeOption > type = optional_type_option ( );
    
    	ext::vector < std::unique_ptr < cli::Arg > > templateArgs;
    	while ( check ( cli::Lexer::TokenType::AT_SIGN ) ) {
    		templateArgs.emplace_back ( template_arg ( ) );
    
    	return std::make_shared < FileStatement > ( file ( ), std::move ( fileType ), std::move ( type ), std::move ( templateArgs ) );
    
    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 {
    		return in_redirect_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 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;
    
    		throw exception::CommonException ( "Mismatched set while expanding common rule. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );
    
    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, cli::Lexer::TokenType::LEFT_BRACE ) ) {
    
    		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 > result_type = type ( );
    
    		match ( cli::Lexer::TokenType::RIGHT_PAREN );
    
    		bool move = move_arg ( );
    
    		std::shared_ptr < Statement > castedParam = param ( );
    
    		return std::make_shared < CastStatement > ( std::move ( result_type ), castedParam, move );
    
    	} else {
    
    		throw exception::CommonException ( "Mismatched set while expanding param rule. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );
    
    	}
    }
    
    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, cli::Lexer::TokenType::LEFT_BRACE ) ) {
    
    		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 ( ) );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    		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, cli::Lexer::TokenType::PIPE_SIGN, cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::RIGHT_PAREN, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) {
    
    			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 > result_type = type ( );
    
    		match ( cli::Lexer::TokenType::RIGHT_PAREN );
    		bool move = move_arg ( );
    		std::shared_ptr < Statement > castedStatement = statement ( );
    
    		return std::make_shared < CastStatement > ( std::move ( result_type ), castedStatement, move );
    
    	// TODO builtin statement type to get string type
    
    		throw exception::CommonException ( "Mismatched set while expanding param statement. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    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 ) ) {
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    		match ( cli::Lexer::TokenType::PIPE_SIGN );
    
    		list.emplace_back ( statement ( ) );
    
    	return std::make_shared < StatementList > ( std::move ( list ) );
    
    void Parser::out_redirect_file ( std::shared_ptr < StatementList > & list ) {
    
    	std::unique_ptr < Arg > fileType;
    
    
    	if ( check ( cli::Lexer::TokenType::LEFT_BRACKET ) ) {
    		match ( cli::Lexer::TokenType::LEFT_BRACKET );
    
    		fileType = arg ( );
    
    		match ( cli::Lexer::TokenType::RIGHT_BRACKET );
    	}
    
    	list->append ( std::make_unique < ResultFileStatement > ( file ( ), std::move ( fileType ) ) );
    
    }
    
    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::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) {
    
    		out_redirect_file ( list );
    
    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::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) {
    
    		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;
    
    			throw exception::CommonException ( "Mismatched set while expanding param introspect_cast_from_to. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );
    
    		}
    	}
    	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 ( );
    
    		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 ( ) );
    
    		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 ( );
    
    		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 ( );
    
    		return std::make_unique < CastsIntrospectionCommand > ( std::move ( param ), from_to.first, from_to.second );
    
    	} else if ( check_nonreserved_kw ( "variables" ) ) {
    		match_nonreserved_kw ( "variables" );
    		std::unique_ptr < cli::Arg > param = optional_variable ( );
    		return std::make_unique < VariablesIntrospectionCommand > ( std::move ( param ) );
    	} else if ( check_nonreserved_kw ( "bindings" ) ) {
    		match_nonreserved_kw ( "bindings" );
    		std::unique_ptr < cli::Arg > param = optional_arg ( );
    		return std::make_unique < BindingsIntrospectionCommand > ( std::move ( param ) );
    
    		throw exception::CommonException ( "Mismatched set while expanding param introspect_command. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );
    
    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, cli::Lexer::TokenType::EOT );
    
    	return std::make_unique < CommandList > ( std::move ( list ) );
    }
    
    std::unique_ptr < Command > Parser::command ( ) {
    
    	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 );
    
    		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, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) )
    
    			res = statement_list ( );
    
    		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, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) )
    
    			res = statement_list ( );
    
    		return std::make_unique < QuitCommand > ( res );
    
    	} else if ( check_nonreserved_kw ( "help" ) ) {
    		match_nonreserved_kw ( "help" );
    
    		std::unique_ptr < cli::Arg > command = optional_arg ( );
    
    		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" );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    		std::unique_ptr < Command > command = introspect_command ( );
    		return 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 );
    
    		return std::make_unique < SetCommand > ( std::move ( param ), std::move ( value ) );
    
    	} else if ( check_nonreserved_kw ( "load" ) ) {
    		match_nonreserved_kw ( "load" );
    
    
    		setHint ( Lexer::Hint::FILE );
    
    		std::string libraryName = getTokenValue ( );
    
    		match ( cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING );
    
    
    		return std::make_unique < LoadCommand > ( std::move ( libraryName ) );
    
    	} else if ( check_nonreserved_kw ( "unload" ) ) {
    		match_nonreserved_kw ( "unload" );
    
    
    		setHint ( Lexer::Hint::FILE );
    
    		std::string libraryName = getTokenValue ( );
    
    		match ( cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING );
    
    
    		return std::make_unique < UnloadCommand > ( std::move ( libraryName ) );
    
    	} else if ( check ( cli::Lexer::TokenType::EOT ) ) {
    
    		return std::make_unique < EOTCommand > ( );
    
    		throw exception::CommonException ( "Mismatched set while expanding parse rule. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." );