#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/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 <ast/command/PrintCommand.h> #include <ast/command/ExecuteCommand.h> #include <ast/command/QuitCommand.h> #include <ast/command/EOTCommand.h> #include <ast/command/HelpCommand.h> #include <ast/command/AlgorithmsIntrospectionCommand.h> #include <ast/command/OperatorsIntrospectionCommand.h> #include <ast/command/OverloadsIntrospectionCommand.h> #include <ast/command/DataTypesIntrospectionCommand.h> #include <ast/command/CastsIntrospectionCommand.h> #include <ast/command/BindingsIntrospectionCommand.h> #include <ast/command/VariablesIntrospectionCommand.h> #include <ast/command/SetCommand.h> #include <ast/command/LoadCommand.h> #include <ast/command/UnloadCommand.h> #include <ast/command/CalcCommand.h> #include <ast/command/BlockCommand.h> #include <ast/command/EvalCommand.h> #include <ast/command/InterpretCommand.h> #include <ast/command/IfCommand.h> #include <ast/command/WhileCommand.h> #include <ast/command/BreakCommand.h> #include <ast/command/ContinueCommand.h> #include <ast/command/ReturnCommand.h> #include <ast/expression/BatchExpression.h> #include <ast/expression/BinaryExpression.h> #include <ast/expression/PrefixExpression.h> #include <ast/expression/PostfixExpression.h> #include <ast/expression/CastExpression.h> #include <ast/expression/FunctionCallExpression.h> #include <ast/expression/MethodCallExpression.h> #include <ast/expression/VariableExpression.h> #include <ast/expression/ImmediateExpression.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::UNSIGNED, 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::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < TypeOption > ( std::move ( value ) ); } else { throw exception::CommonException ( "Mismatched colon sign while expanding type_option rule. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." ); } } 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::UNSIGNED, 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::UNSIGNED, 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, cli::Lexer::TokenType::IDENTIFIER ) ) { return arg ( ); } else { return nullptr; } } 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::UNSIGNED, 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::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER ); return std::make_unique < ImmediateArg > ( value ); } else { return nullptr; } } 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 { 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 ); } 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::unique_ptr < Statement > Parser::out_redirect ( ) { if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) { match ( cli::Lexer::TokenType::DOLAR_SIGN ); std::unique_ptr < Arg > name = arg ( ); return std::make_unique < ResultVariableStatement > ( std::move ( name ) ); } else { 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 ); } return std::make_unique < ResultFileStatement > ( file ( ), std::move ( fileType ) ); } } std::shared_ptr < Statement > Parser::common ( ) { clearCheckOptions ( ); 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::LESS_SIGN ) ) { match ( cli::Lexer::TokenType::LESS_SIGN ); 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::UNSIGNED ) ) { 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::UNSIGNED, 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; while ( ! check ( cli::Lexer::TokenType::RIGHT_BRACE ) ) { params.emplace_back ( param ( ) ); } 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 { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding common rule. Token is " + ( ( std::string ) m_current ) + "." ); } } std::shared_ptr < Statement > Parser::param ( ) { clearCheckOptions ( ); if ( check ( cli::Lexer::TokenType::DOLAR_SIGN, cli::Lexer::TokenType::LESS_SIGN, cli::Lexer::TokenType::STRING, cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::HASH_SIGN, cli::Lexer::TokenType::LEFT_BRACE ) ) { return common ( ); } else if ( check ( cli::Lexer::TokenType::MINUS_SIGN ) ) { match ( cli::Lexer::TokenType::MINUS_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 ); std::shared_ptr < Statement > castedParam = param ( ); return std::make_shared < CastStatement > ( std::move ( result_type ), castedParam ); } else { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding param rule. Token is " + ( ( std::string ) m_current ) + "." ); } } std::shared_ptr < Statement > Parser::statement ( ) { clearCheckOptions ( ); if ( check ( cli::Lexer::TokenType::DOLAR_SIGN, cli::Lexer::TokenType::LESS_SIGN, cli::Lexer::TokenType::STRING, cli::Lexer::TokenType::UNSIGNED, 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 ( ) ); } std::unique_ptr < CategoryOption > category = category_option ( ); ext::vector < std::shared_ptr < Statement > > params; while ( ! check ( cli::Lexer::TokenType::MORE_SIGN, cli::Lexer::TokenType::PIPE_SIGN, cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::RIGHT_PAREN, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) { params.emplace_back ( param ( ) ); } return std::make_shared < SingleStatement > ( std::move ( name ), std::move ( templateArgs ), std::move ( params ), std::move ( category ) ); } 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 ); std::shared_ptr < Statement > castedStatement = statement ( ); return std::make_shared < CastStatement > ( std::move ( result_type ), castedStatement ); } else { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding statement rule. Token is " + ( ( std::string ) m_current ) + "." ); } } 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, cli::Lexer::TokenType::MORE_SIGN ) ) { if ( check ( cli::Lexer::TokenType::PIPE_SIGN ) ) { match ( cli::Lexer::TokenType::PIPE_SIGN ); list.emplace_back ( statement ( ) ); } else { match ( cli::Lexer::TokenType::MORE_SIGN ); list.emplace_back ( out_redirect ( ) ); } } return std::make_shared < StatementList > ( std::move ( list ) ); } 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 ); clearCheckOptions ( ); 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 " + ext::to_string ( getCheckOptions ( ) ) + " while expanding introspect_cast_type. Token is " + ( ( std::string ) m_current ) + "." ); } } return std::make_pair ( from, to ); } std::unique_ptr < Command > Parser::introspect_command ( ) { clearCheckOptions ( ); 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 ( "operators" ) ) { match_nonreserved_kw ( "operators" ); return std::make_unique < OperatorsIntrospectionCommand > ( ); } 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 ) ); } else { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding introspection_command rule. Token is " + ( ( std::string ) m_current ) + "." ); } } std::unique_ptr < CommandList > Parser::block ( ) { incNestedLevel ( ); match_nonreserved_kw ( "begin" ); ext::vector < std::unique_ptr < Command > > list; while ( ! check_nonreserved_kw ( "end" ) ) { list.emplace_back ( semicolon_command ( ) ); } decNestedLevel ( ); match_nonreserved_kw ( "end" ); return std::make_unique < CommandList > ( std::move ( list ) ); } std::unique_ptr < Command > Parser::semicolon_command ( ) { bool semicolonFreeCommand = check_nonreserved_kw ( "begin", "if", "while" ); std::unique_ptr < Command > res = command ( ); if ( ! semicolonFreeCommand ) match ( cli::Lexer::TokenType::SEMICOLON_SIGN ); return res; } std::unique_ptr < Expression > Parser::expression ( ) { return assign_expression ( ); } std::unique_ptr < Expression > Parser::batch ( ) { std::shared_ptr < StatementList > res = statement_list ( ); return std::make_unique < BatchExpression > ( std::move ( res ) ); } std::unique_ptr < Expression > Parser::expression_or_batch ( ) { if ( check_nonreserved_kw ( "batch" ) ) { match_nonreserved_kw ( "batch" ); return batch ( ); } else { if ( check_nonreserved_kw ( "expression" ) ) match_nonreserved_kw ( "expression" ); return expression ( ); } } std::unique_ptr < Expression > Parser::batch_or_expression ( ) { if ( check_nonreserved_kw ( "expression" ) ) { match_nonreserved_kw ( "expression" ); return expression ( ); } else { if ( check_nonreserved_kw ( "batch" ) ) match_nonreserved_kw ( "batch" ); return batch ( ); } } std::unique_ptr < Command > Parser::command ( ) { clearCheckOptions ( ); if ( check_nonreserved_kw ( "execute" ) ) { match_nonreserved_kw ( "execute" ); std::unique_ptr < Expression > expr = batch_or_expression ( ); return std::make_unique < ExecuteCommand > ( std::move ( expr ) ); } else if ( check_nonreserved_kw ( "print" ) ) { match_nonreserved_kw ( "print" ); std::unique_ptr < Expression > expr = batch_or_expression ( ); return std::make_unique < PrintCommand > ( std::move ( expr ) ); } else if ( check_nonreserved_kw ( "quit" ) ) { match_nonreserved_kw ( "quit" ); std::unique_ptr < Expression > expr; if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) expr = batch_or_expression ( ); return std::make_unique < QuitCommand > ( std::move ( expr ) ); } else if ( check_nonreserved_kw ( "exit" ) ) { match_nonreserved_kw ( "exit" ); std::unique_ptr < Expression > expr; if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) expr = batch_or_expression ( ); return std::make_unique < QuitCommand > ( std::move ( expr ) ); } else if ( check_nonreserved_kw ( "return" ) ) { match_nonreserved_kw ( "return" ); std::unique_ptr < Expression > expr; if ( ! check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN ) ) expr = expression ( ); return std::make_unique < ReturnCommand > ( std::move ( expr ) ); } 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 ) ); } else if ( check_nonreserved_kw ( "introspect" ) ) { match_nonreserved_kw ( "introspect" ); 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::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER ); std::string value = getTokenValue ( ); match ( cli::Lexer::TokenType::UNSIGNED, 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_nonreserved_kw ( "calc" ) ) { match_nonreserved_kw ( "calc" ); std::unique_ptr < Expression > expr = expression ( ); return std::make_unique < CalcCommand > ( std::move ( expr ) ); } else if ( check_nonreserved_kw ( "begin" ) ) { return std::make_unique < BlockCommand > ( block ( ) ); } else if ( check_nonreserved_kw ( "eval" ) ) { match_nonreserved_kw ( "eval" ); std::string evalString = getTokenValue ( ); match ( cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING ); return std::make_unique < EvalCommand > ( std::move ( evalString ) ); } else if ( check_nonreserved_kw ( "interpret" ) ) { match_nonreserved_kw ( "interpret" ); setHint ( Lexer::Hint::FILE ); std::string fileName = getTokenValue ( ); match ( cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING ); return std::make_unique < InterpretCommand > ( std::move ( fileName ) ); } else if ( check_nonreserved_kw ( "if" ) ) { if ( globalScope ( ) ) throw exception::CommonException ( "Statement not available in global scope." ); match_nonreserved_kw ( "if" ); match ( cli::Lexer::TokenType::LEFT_PAREN ); std::unique_ptr < Expression > condition = expression_or_batch ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); match_nonreserved_kw ( "then" ); std::unique_ptr < Command > thenBranch = semicolon_command ( ); std::unique_ptr < Command > elseBranch; if ( check_nonreserved_kw ( "else" ) ) { match_nonreserved_kw ( "else" ); elseBranch = semicolon_command ( ); } return std::make_unique < IfCommand > ( std::move ( condition ), std::move ( thenBranch ), std::move ( elseBranch ) ); } else if ( check_nonreserved_kw ( "while" ) ) { if ( globalScope ( ) ) throw exception::CommonException ( "Statement not available in global scope." ); match_nonreserved_kw ( "while" ); match ( cli::Lexer::TokenType::LEFT_PAREN ); std::unique_ptr < Expression > condition = expression_or_batch ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); match_nonreserved_kw ( "do" ); std::unique_ptr < Command > body = semicolon_command ( ); return std::make_unique < WhileCommand > ( std::move ( condition ), std::move ( body ) ); } else if ( check_nonreserved_kw ( "break" ) ) { if ( globalScope ( ) ) throw exception::CommonException ( "Statement not available in global scope." ); match_nonreserved_kw ( "break" ); return std::make_unique < BreakCommand > ( ); } else if ( check_nonreserved_kw ( "continue" ) ) { if ( globalScope ( ) ) throw exception::CommonException ( "Statement not available in global scope." ); match_nonreserved_kw ( "continue" ); return std::make_unique < ContinueCommand > ( ); } else { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding parse rule. Token is " + ( ( std::string ) m_current ) + "." ); } } std::unique_ptr < CommandList > Parser::parse ( ) { ext::vector < std::unique_ptr < Command > > list; if ( check ( cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT ) ) { list.emplace_back ( std::make_unique < EOTCommand > ( ) ); return std::make_unique < CommandList > ( std::move ( 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 < Expression > Parser::assign_expression ( ) { std::unique_ptr < Expression > res = or_expression ( ); if ( check ( cli::Lexer::TokenType::ASSIGN_OPERATOR ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); match ( cli::Lexer::TokenType::ASSIGN_OPERATOR ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::ASSIGN, std::move ( res ), assign_expression ( ) ); restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::or_expression ( ) { std::unique_ptr < Expression > res = and_expression ( ); while ( check ( cli::Lexer::TokenType::OR_OPERATOR ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); match ( cli::Lexer::TokenType::OR_OPERATOR ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LOGICAL_OR, std::move ( res ), and_expression ( ) ); restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::and_expression ( ) { std::unique_ptr < Expression > res = bitwise_or_expression ( ); while ( check ( cli::Lexer::TokenType::AND_OPERATOR ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); match ( cli::Lexer::TokenType::AND_OPERATOR ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LOGICAL_AND, std::move ( res ), bitwise_or_expression ( ) ); restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::bitwise_or_expression ( ) { std::unique_ptr < Expression > res = bitwise_and_expression ( ); while ( check ( cli::Lexer::TokenType::PIPE_SIGN ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); match ( cli::Lexer::TokenType::PIPE_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_OR, std::move ( res ), bitwise_and_expression ( ) ); restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::bitwise_and_expression ( ) { std::unique_ptr < Expression > res = bitwise_xor_expression ( ); while ( check ( cli::Lexer::TokenType::AMPERSAND_SIGN ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); match ( cli::Lexer::TokenType::AMPERSAND_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_AND, std::move ( res ), bitwise_xor_expression ( ) ); restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::bitwise_xor_expression ( ) { std::unique_ptr < Expression > res = equality_expression ( ); while ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); match ( cli::Lexer::TokenType::CARET_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_XOR, std::move ( res ), equality_expression ( ) ); restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::equality_expression ( ) { std::unique_ptr < Expression > res = relational_expression ( ); auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); if ( check ( cli::Lexer::TokenType::EQUAL_OPERATOR ) ) { match ( cli::Lexer::TokenType::EQUAL_OPERATOR ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::EQUALS, std::move ( res ), relational_expression ( ) ); } else if ( check ( cli::Lexer::TokenType::NOT_EQUAL_OPERATOR ) ) { match ( cli::Lexer::TokenType::NOT_EQUAL_OPERATOR ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::NOT_EQUALS, std::move ( res ), relational_expression ( ) ); } restoreCheckOptions ( checkOptions ); return res; } std::unique_ptr < Expression > Parser::relational_expression ( ) { std::unique_ptr < Expression > res = add_expression ( ); auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); if ( check ( cli::Lexer::TokenType::LESS_SIGN ) ) { match ( cli::Lexer::TokenType::LESS_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LESS, std::move ( res ), add_expression ( ) ); } else if ( check ( cli::Lexer::TokenType::LESS_OR_EQUAL_OPERATOR ) ) { match ( cli::Lexer::TokenType::LESS_OR_EQUAL_OPERATOR ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LESS_OR_EQUAL, std::move ( res ), add_expression ( ) ); } else if ( check ( cli::Lexer::TokenType::MORE_SIGN ) ) { match ( cli::Lexer::TokenType::MORE_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MORE, std::move ( res ), add_expression ( ) ); } else if ( check ( cli::Lexer::TokenType::MORE_OR_EQUAL_OPERATOR ) ) { match ( cli::Lexer::TokenType::MORE_OR_EQUAL_OPERATOR ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MORE_OR_EQUAL, std::move ( res ), add_expression ( ) ); } restoreCheckOptions ( checkOptions ); return res; } std::unique_ptr < Expression > Parser::add_expression ( ) { std::unique_ptr < Expression > res = mul_expression ( ); while ( check ( cli::Lexer::TokenType::PLUS_SIGN, cli::Lexer::TokenType::MINUS_SIGN ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); if ( check ( cli::Lexer::TokenType::PLUS_SIGN ) ) { match ( cli::Lexer::TokenType::PLUS_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::ADD, std::move ( res ), mul_expression ( ) ); } else { match ( cli::Lexer::TokenType::MINUS_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::SUB, std::move ( res ), mul_expression ( ) ); } restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::mul_expression ( ) { std::unique_ptr < Expression > res = prefix_expression ( ); while ( check ( cli::Lexer::TokenType::STAR_SIGN, cli::Lexer::TokenType::PERCENTAGE_SIGN, cli::Lexer::TokenType::SLASH_SIGN ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); if ( check ( cli::Lexer::TokenType::STAR_SIGN ) ) { match ( cli::Lexer::TokenType::STAR_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MUL, std::move ( res ), prefix_expression ( ) ); } else if ( check ( cli::Lexer::TokenType::PERCENTAGE_SIGN ) ) { match ( cli::Lexer::TokenType::PERCENTAGE_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::MOD, std::move ( res ), prefix_expression ( ) ); } else { match ( cli::Lexer::TokenType::SLASH_SIGN ); res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::DIV, std::move ( res ), prefix_expression ( ) ); } restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::prefix_expression ( ) { clearCheckOptions ( ); if ( check_nonreserved_kw ( "cast" ) ) { match_nonreserved_kw ( "cast" ); match ( cli::Lexer::TokenType::LEFT_PAREN ); std::unique_ptr < Arg > result_type = type ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); std::unique_ptr < Expression > expression = prefix_expression ( ); return std::make_unique < CastExpression > ( std::move ( result_type ), std::move ( expression ) ); } else if ( check ( cli::Lexer::TokenType::PLUS_SIGN ) ) { match ( cli::Lexer::TokenType::PLUS_SIGN ); std::unique_ptr < Expression > expression = prefix_expression ( ); return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::PLUS, std::move ( expression ) ); } else if ( check ( cli::Lexer::TokenType::MINUS_SIGN ) ) { match ( cli::Lexer::TokenType::MINUS_SIGN ); std::unique_ptr < Expression > expression = prefix_expression ( ); return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::MINUS, std::move ( expression ) ); } else if ( check ( cli::Lexer::TokenType::EXCLAMATION_SIGN ) ) { match ( cli::Lexer::TokenType::EXCLAMATION_SIGN ); std::unique_ptr < Expression > expression = prefix_expression ( ); return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::LOGICAL_NOT, std::move ( expression ) ); } else if ( check ( cli::Lexer::TokenType::TYLDE_SIGN ) ) { match ( cli::Lexer::TokenType::TYLDE_SIGN ); std::unique_ptr < Expression > expression = prefix_expression ( ); return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::BINARY_NEG, std::move ( expression ) ); } else if ( check ( cli::Lexer::TokenType::INC_OPERATOR ) ) { match ( cli::Lexer::TokenType::INC_OPERATOR ); std::unique_ptr < Expression > expression = prefix_expression ( ); return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::INCREMENT, std::move ( expression ) ); } else if ( check ( cli::Lexer::TokenType::DEC_OPERATOR ) ) { match ( cli::Lexer::TokenType::DEC_OPERATOR ); std::unique_ptr < Expression > expression = prefix_expression ( ); return std::make_unique < PrefixExpression > ( abstraction::Operators::PrefixOperators::DECREMENT, std::move ( expression ) ); } else { return suffix_expression ( ); } } std::unique_ptr < Expression > Parser::suffix_expression ( ) { std::unique_ptr < Expression > res = atom ( ); clearCheckOptions ( ); while ( check ( cli::Lexer::TokenType::DOT, cli::Lexer::TokenType::INC_OPERATOR, cli::Lexer::TokenType::DEC_OPERATOR ) ) { auto checkOptions = getCheckOptions ( ); clearCheckOptions ( ); if ( check ( cli::Lexer::TokenType::DOT ) ) { match ( cli::Lexer::TokenType::DOT ); std::string memberName = getTokenValue ( ); match ( cli::Lexer::TokenType::IDENTIFIER ); std::vector < std::unique_ptr < Expression > > params = bracketed_expression_list ( ); res = std::make_unique < MethodCallExpression > ( std::move ( res ), std::move ( memberName ), std::move ( params ) ); } else if ( check ( cli::Lexer::TokenType::INC_OPERATOR ) ){ match ( cli::Lexer::TokenType::INC_OPERATOR ); res = std::make_unique < PostfixExpression > ( abstraction::Operators::PostfixOperators::INCREMENT, std::move ( res ) ); } else if ( check ( cli::Lexer::TokenType::DEC_OPERATOR ) ){ match ( cli::Lexer::TokenType::DEC_OPERATOR ); res = std::make_unique < PostfixExpression > ( abstraction::Operators::PostfixOperators::DECREMENT, std::move ( res ) ); } else { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding suffix_expression rule. Token is " + ( ( std::string ) m_current ) + "." ); } restoreCheckOptions ( checkOptions ); } return res; } std::unique_ptr < Expression > Parser::atom ( ) { if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) { std::string routineName = getTokenValue ( ); match ( cli::Lexer::TokenType::IDENTIFIER ); std::vector < std::unique_ptr < Expression > > params = bracketed_expression_list ( ); return std::make_unique < FunctionCallExpression > ( routineName, std::move ( params ) ); } else if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) { match ( cli::Lexer::TokenType::DOLAR_SIGN ); std::unique_ptr < Arg > name = arg ( ); return std::make_unique < VariableExpression > ( std::move ( name ) ); } else if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) { match ( cli::Lexer::TokenType::LEFT_PAREN ); std::unique_ptr < Expression > expr = expression ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); return expr; } else if ( check ( cli::Lexer::TokenType::STRING ) ) { std::string value = matchString ( ); return std::make_unique < ImmediateExpression < std::string > > ( value ); } else if ( check ( cli::Lexer::TokenType::UNSIGNED ) ) { int value = matchInteger ( ); return std::make_unique < ImmediateExpression < int > > ( value ); } else { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding prefix_expression and atom rules. Token is " + ( ( std::string ) m_current ) + "." ); } } std::vector < std::unique_ptr < Expression > > Parser::bracketed_expression_list ( ) { std::vector < std::unique_ptr < Expression > > res; match ( cli::Lexer::TokenType::LEFT_PAREN ); if ( ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) { res.push_back ( expression ( ) ); while ( check ( cli::Lexer::TokenType::COMMA ) ) { match ( cli::Lexer::TokenType::COMMA ); res.push_back ( expression ( ) ); } } match ( cli::Lexer::TokenType::RIGHT_PAREN ); return res; } } /* namespace cli */