From a172d7718572b0618ce6a61fd6cf572a3b492671 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Wed, 27 Nov 2019 14:01:18 +0100 Subject: [PATCH] expression parsing in cli --- alib2cli/src/ast/Expression.h | 36 +++ alib2cli/src/ast/command/CalcCommand.h | 26 ++ .../src/ast/expression/BinaryExpression.h | 34 +++ alib2cli/src/ast/expression/CastExpression.h | 29 +++ .../ast/expression/FunctionCallExpression.h | 41 +++ .../src/ast/expression/ImmediateExpression.h | 27 ++ .../src/ast/expression/MethodCallExpression.h | 43 ++++ .../src/ast/expression/PostfixExpression.h | 29 +++ .../src/ast/expression/PrefixExpression.h | 29 +++ .../src/ast/expression/VariableExpression.h | 24 ++ alib2cli/src/parser/Parser.cpp | 235 ++++++++++++++++++ alib2cli/src/parser/Parser.h | 31 +++ 12 files changed, 584 insertions(+) create mode 100644 alib2cli/src/ast/Expression.h create mode 100644 alib2cli/src/ast/command/CalcCommand.h create mode 100644 alib2cli/src/ast/expression/BinaryExpression.h create mode 100644 alib2cli/src/ast/expression/CastExpression.h create mode 100644 alib2cli/src/ast/expression/FunctionCallExpression.h create mode 100644 alib2cli/src/ast/expression/ImmediateExpression.h create mode 100644 alib2cli/src/ast/expression/MethodCallExpression.h create mode 100644 alib2cli/src/ast/expression/PostfixExpression.h create mode 100644 alib2cli/src/ast/expression/PrefixExpression.h create mode 100644 alib2cli/src/ast/expression/VariableExpression.h diff --git a/alib2cli/src/ast/Expression.h b/alib2cli/src/ast/Expression.h new file mode 100644 index 0000000000..47599d420e --- /dev/null +++ b/alib2cli/src/ast/Expression.h @@ -0,0 +1,36 @@ +#ifndef _CLI_EXPRESSION_H_ +#define _CLI_EXPRESSION_H_ + +#include <ast/Ast.h> +#include <abstraction/OperationAbstraction.hpp> +#include <environment/Environment.h> + +namespace cli { + +class Expression { +public: + enum class Operation { + LOGICAL_OR, + LOGICAL_AND, + COMPARE_EQUALITY, + COMPARE_INEQUALITY, + COMPARE_LESS_OR_EQUAL, + COMPARE_LESS, + COMPARE_MORE_OR_EQUAL, + COMPARE_MORE, + ADD, + SUB, + MUL, + MOD, + DIV, + NOT + }; + + virtual ~Expression ( ) noexcept = default; + + virtual std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const = 0; +}; + +} /* namespace cli */ + +#endif /* _CLI_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/command/CalcCommand.h b/alib2cli/src/ast/command/CalcCommand.h new file mode 100644 index 0000000000..050a84bde4 --- /dev/null +++ b/alib2cli/src/ast/command/CalcCommand.h @@ -0,0 +1,26 @@ +#ifndef _CLI_CALC_COMMAND_H_ +#define _CLI_CALC_COMMAND_H_ + +#include <ast/Command.h> +#include <environment/Environment.h> +#include <ast/Expression.h> + +namespace cli { + +class CalcCommand : public Command { + std::unique_ptr < cli::Expression > m_expr; + +public: + CalcCommand ( std::unique_ptr < cli::Expression > expr ) : m_expr ( std::move ( expr ) ) { + } + + CommandResult run ( Environment & environment ) const override { + m_expr->translateAndEval ( environment ); + + return cli::CommandResult::OK; + } +}; + +} /* namespace cli */ + +#endif /* _CLI_CALC_COMMAND_H_ */ diff --git a/alib2cli/src/ast/expression/BinaryExpression.h b/alib2cli/src/ast/expression/BinaryExpression.h new file mode 100644 index 0000000000..3cc02c96c9 --- /dev/null +++ b/alib2cli/src/ast/expression/BinaryExpression.h @@ -0,0 +1,34 @@ +#ifndef _CLI_BINARY_EXPRESSION_H_ +#define _CLI_BINARY_EXPRESSION_H_ + +#include <ast/Expression.h> + +#include <common/Operators.hpp> +#include <common/EvalHelper.h> + +namespace cli { + +class BinaryExpression final : public Expression { + abstraction::Operators::BinaryOperators m_operation; + std::unique_ptr < Expression > m_left; + std::unique_ptr < Expression > m_right; + +public: + BinaryExpression ( abstraction::Operators::BinaryOperators operation, std::unique_ptr < Expression > left, std::unique_ptr < Expression > right ) : m_operation ( operation ), m_left ( std::move ( left ) ), m_right ( std::move ( right ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + ext::vector < std::shared_ptr < abstraction::Value > > params; + params.push_back ( m_left->translateAndEval ( environment ) ); + params.push_back ( m_right->translateAndEval ( environment ) ); + + abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE; + + return abstraction::EvalHelper::evalOperator ( environment, m_operation, params, category ); + } + +}; + +} /* namespace cli */ + +#endif /* _CLI_BINARY_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/expression/CastExpression.h b/alib2cli/src/ast/expression/CastExpression.h new file mode 100644 index 0000000000..62bec1dc30 --- /dev/null +++ b/alib2cli/src/ast/expression/CastExpression.h @@ -0,0 +1,29 @@ +#ifndef _CLI_CAST_EXPRESSION_H_ +#define _CLI_CAST_EXPRESSION_H_ + +#include <ast/Expression.h> +#include <common/CastHelper.h> + +namespace cli { + +class CastExpression final : public Expression { + std::unique_ptr < cli::Arg > m_type; + std::unique_ptr < Expression > m_expression; + +public: + CastExpression ( std::unique_ptr < cli::Arg > type, std::unique_ptr < Expression > expression ) : m_type ( std::move ( type ) ), m_expression ( std::move ( expression ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + std::string type = m_type->eval ( environment ); + + std::shared_ptr < abstraction::Value > translatedExpression = m_expression->translateAndEval ( environment ); + + return abstraction::CastHelper::eval ( environment, translatedExpression, type ); + } + +}; + +} /* namespace cli */ + +#endif /* _CLI_CAST_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/expression/FunctionCallExpression.h b/alib2cli/src/ast/expression/FunctionCallExpression.h new file mode 100644 index 0000000000..ed52a3f1af --- /dev/null +++ b/alib2cli/src/ast/expression/FunctionCallExpression.h @@ -0,0 +1,41 @@ +#ifndef _CLI_FUNCTION_CALL_EXPRESSION_H_ +#define _CLI_FUNCTION_CALL_EXPRESSION_H_ + +#include <alib/foreach> + +#include <ast/Expression.h> +#include <environment/Environment.h> + +namespace cli { + +class FunctionCallExpression : public Expression { + std::string m_name; + std::vector < std::unique_ptr < Expression > > m_params; + +public: + FunctionCallExpression ( std::string name, std::vector < std::unique_ptr < Expression > > params ) : m_name ( std::move ( name ) ), m_params ( std::move ( params ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + ext::vector < std::shared_ptr < abstraction::Value > > params; + for ( const std::unique_ptr < Expression > & param : m_params ) { + params.push_back ( param->translateAndEval ( environment ) ); + } + + std::string name = m_name; + + ext::vector < std::string > templateParams; +/* for ( const std::unique_ptr < cli::Arg > & templateParam : m_templateParams ) + templateParams.push_back ( templateParam->eval ( environment ) );*/ + + abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE; +/* if ( m_category ) + category = m_category->getCategory ( );*/ + + return abstraction::EvalHelper::evalAlgorithm ( environment, name, templateParams, params, category ); + } +}; + +} /* namespace cli */ + +#endif /* _CLI_FUNCTION_CALL_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/expression/ImmediateExpression.h b/alib2cli/src/ast/expression/ImmediateExpression.h new file mode 100644 index 0000000000..49a4305c36 --- /dev/null +++ b/alib2cli/src/ast/expression/ImmediateExpression.h @@ -0,0 +1,27 @@ +#ifndef _IMMEDIATE_EXPRESSION_H_ +#define _IMMEDIATE_EXPRESSION_H_ + +#include <ast/Expression.h> + +namespace cli { + +template < class Type > +class ImmediateExpression final : public Expression { + Type m_value; + +public: + ImmediateExpression ( Type value ) : m_value ( std::move ( value ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + Type copy = m_value; + std::shared_ptr < abstraction::ValueHolder < Type > > value = std::make_shared < abstraction::ValueHolder < Type > > ( std::move ( copy ), true ); + environment.holdTemporary ( value ); + return value; + } + +}; + +} /* namespace cli */ + +#endif /* _IMMEDIATE_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/expression/MethodCallExpression.h b/alib2cli/src/ast/expression/MethodCallExpression.h new file mode 100644 index 0000000000..2e48abff0f --- /dev/null +++ b/alib2cli/src/ast/expression/MethodCallExpression.h @@ -0,0 +1,43 @@ +#ifndef _CLI_METHOD_CALL_EXPRESSION_H_ +#define _CLI_METHOD_CALL_EXPRESSION_H_ + +#include <alib/foreach> + +#include <ast/Expression.h> +#include <environment/Environment.h> + +namespace cli { + +class MethodCallExpression : public Expression { + std::unique_ptr < Expression > m_object; + std::string m_name; + std::vector < std::unique_ptr < Expression > > m_params; + +public: + MethodCallExpression ( std::unique_ptr < Expression > object, std::string name, std::vector < std::unique_ptr < Expression > > params ) : m_object ( std::move ( object ) ), m_name ( std::move ( name ) ), m_params ( std::move ( params ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + ext::vector < std::shared_ptr < abstraction::Value > > params; + params.push_back ( m_object->translateAndEval ( environment ) ); + for ( const std::unique_ptr < Expression > & param : m_params ) { + params.push_back ( param->translateAndEval ( environment ) ); + } + + std::string name = m_name; + + ext::vector < std::string > templateParams; +/* for ( const std::unique_ptr < cli::Arg > & templateParam : m_templateParams ) + templateParams.push_back ( templateParam->eval ( environment ) );*/ + + abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE; +/* if ( m_category ) + category = m_category->getCategory ( );*/ + + return abstraction::EvalHelper::evalAlgorithm ( environment, name, templateParams, params, category ); + } +}; + +} /* namespace cli */ + +#endif /* _CLI_METHOD_CALL_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/expression/PostfixExpression.h b/alib2cli/src/ast/expression/PostfixExpression.h new file mode 100644 index 0000000000..d915e1425d --- /dev/null +++ b/alib2cli/src/ast/expression/PostfixExpression.h @@ -0,0 +1,29 @@ +#ifndef _CLI_POSTFIX_EXPRESSION_H_ +#define _CLI_POSTFIX_EXPRESSION_H_ + +#include <ast/Expression.h> + +namespace cli { + +class PostfixExpression final : public Expression { + abstraction::Operators::PostfixOperators m_operation; + std::unique_ptr < Expression > m_expr; + +public: + PostfixExpression ( abstraction::Operators::PostfixOperators operation, std::unique_ptr < Expression > expr ) : m_operation ( operation ), m_expr ( std::move ( expr ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + ext::vector < std::shared_ptr < abstraction::Value > > params; + params.push_back ( m_expr->translateAndEval ( environment ) ); + + abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE; + + return abstraction::EvalHelper::evalOperator ( environment, m_operation, params, category ); + } + +}; + +} /* namespace cli */ + +#endif /* _CLI_POSTFIX_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/expression/PrefixExpression.h b/alib2cli/src/ast/expression/PrefixExpression.h new file mode 100644 index 0000000000..97f55ef70a --- /dev/null +++ b/alib2cli/src/ast/expression/PrefixExpression.h @@ -0,0 +1,29 @@ +#ifndef _CLI_PREFIX_EXPRESSION_H_ +#define _CLI_PREFIX_EXPRESSION_H_ + +#include <ast/Expression.h> + +namespace cli { + +class PrefixExpression final : public Expression { + abstraction::Operators::PrefixOperators m_operation; + std::unique_ptr < Expression > m_expr; + +public: + PrefixExpression ( abstraction::Operators::PrefixOperators operation, std::unique_ptr < Expression > expr ) : m_operation ( operation ), m_expr ( std::move ( expr ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + ext::vector < std::shared_ptr < abstraction::Value > > params; + params.push_back ( m_expr->translateAndEval ( environment ) ); + + abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE; + + return abstraction::EvalHelper::evalOperator ( environment, m_operation, params, category ); + } + +}; + +} /* namespace cli */ + +#endif /* _CLI_PREFIX_EXPRESSION_H_ */ diff --git a/alib2cli/src/ast/expression/VariableExpression.h b/alib2cli/src/ast/expression/VariableExpression.h new file mode 100644 index 0000000000..c8b27e51ab --- /dev/null +++ b/alib2cli/src/ast/expression/VariableExpression.h @@ -0,0 +1,24 @@ +#ifndef _CLI_VARIABLE_EXPRESSION_H_ +#define _CLI_VARIABLE_EXPRESSION_H_ + +#include <alib/string> +#include <ast/Expression.h> + +namespace cli { + +class VariableExpression final : public Expression { + std::unique_ptr < cli::Arg > m_name; + +public: + VariableExpression ( std::unique_ptr < cli::Arg > name ) : m_name ( std::move ( name ) ) { + } + + std::shared_ptr < abstraction::Value > translateAndEval ( Environment & environment ) const override { + return environment.getVariable ( m_name->eval ( environment ) ); + } + +}; + +} /* namespace cli */ + +#endif /* _CLI_VARIABLE_EXPRESSION_H_ */ diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp index a18e1aabf1..203f70d820 100644 --- a/alib2cli/src/parser/Parser.cpp +++ b/alib2cli/src/parser/Parser.cpp @@ -29,6 +29,16 @@ #include <ast/command/SetCommand.h> #include <ast/command/LoadCommand.h> #include <ast/command/UnloadCommand.h> +#include <ast/command/CalcCommand.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 { @@ -412,9 +422,234 @@ std::unique_ptr < Command > Parser::command ( ) { 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 = assign_expression ( ); + return std::make_unique < CalcCommand > ( std::move ( expr ) ); } else { throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding parse rule. Token is " + ( ( std::string ) m_current ) + "." ); } } +std::unique_ptr < Expression > Parser::assign_expression ( ) { + std::unique_ptr < Expression > res = or_expression ( ); + if ( check ( cli::Lexer::TokenType::ASSIGN_OPERATOR ) ) { + match ( cli::Lexer::TokenType::ASSIGN_OPERATOR ); + + res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::ASSIGN, std::move ( res ), assign_expression ( ) ); + } + return res; +} + +std::unique_ptr < Expression > Parser::or_expression ( ) { + std::unique_ptr < Expression > res = and_expression ( ); + while ( check ( cli::Lexer::TokenType::OR_OPERATOR ) ) { + match ( cli::Lexer::TokenType::OR_OPERATOR ); + + res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LOGICAL_OR, std::move ( res ), and_expression ( ) ); + } + return res; +} + +std::unique_ptr < Expression > Parser::and_expression ( ) { + std::unique_ptr < Expression > res = bitwise_or_expression ( ); + while ( check ( cli::Lexer::TokenType::AND_OPERATOR ) ) { + match ( cli::Lexer::TokenType::AND_OPERATOR ); + + res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::LOGICAL_AND, std::move ( res ), bitwise_or_expression ( ) ); + } + 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 ) ) { + match ( cli::Lexer::TokenType::PIPE_SIGN ); + + res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_OR, std::move ( res ), bitwise_and_expression ( ) ); + } + 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 ) ) { + match ( cli::Lexer::TokenType::AMPERSAND_SIGN ); + + res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_AND, std::move ( res ), bitwise_xor_expression ( ) ); + } + return res; +} + +std::unique_ptr < Expression > Parser::bitwise_xor_expression ( ) { + std::unique_ptr < Expression > res = equality_expression ( ); + while ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) { + match ( cli::Lexer::TokenType::CARET_SIGN ); + + res = std::make_unique < BinaryExpression > ( abstraction::Operators::BinaryOperators::BINARY_XOR, std::move ( res ), equality_expression ( ) ); + } + return res; +} + +std::unique_ptr < Expression > Parser::equality_expression ( ) { + std::unique_ptr < Expression > res = relational_expression ( ); + 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 ( ) ); + } + return res; +} + +std::unique_ptr < Expression > Parser::relational_expression ( ) { + std::unique_ptr < Expression > res = add_expression ( ); + 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 ( ) ); + } + 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 ) ) { + 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 ( ) ); + } + } + 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 ) ) { + 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 ( ) ); + } + } + return res; +} + +std::unique_ptr < Expression > Parser::prefix_expression ( ) { + 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 ( ); + while ( check ( cli::Lexer::TokenType::DOT, cli::Lexer::TokenType::INC_OPERATOR, cli::Lexer::TokenType::DEC_OPERATOR ) ) { + 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 while expanding suffix expression rule. Token is " + Lexer::tokenTypeToString ( m_current.m_type ) + "." ); + } + } + 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 = assign_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 while expanding parse rule. 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 ( assign_expression ( ) ); + while ( check ( cli::Lexer::TokenType::COMMA ) ) { + match ( cli::Lexer::TokenType::COMMA ); + res.push_back ( assign_expression ( ) ); + } + } + match ( cli::Lexer::TokenType::RIGHT_PAREN ); + return res; +} + } /* namespace cli */ diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h index bacd165f24..2461141cd1 100644 --- a/alib2cli/src/parser/Parser.h +++ b/alib2cli/src/parser/Parser.h @@ -4,6 +4,7 @@ #include <ast/Statement.h> #include <ast/Option.h> #include <ast/Arg.h> +#include <ast/Expression.h> #include <ast/options/TypeOption.h> #include <ast/options/CategoryOption.h> @@ -139,6 +140,36 @@ public: return m_current.m_value; } + std::unique_ptr < Expression > assign_expression ( ); + + std::unique_ptr < Expression > or_expression ( ); + + std::unique_ptr < Expression > and_expression ( ); + + std::unique_ptr < Expression > bitwise_or_expression ( ); + + std::unique_ptr < Expression > bitwise_and_expression ( ); + + std::unique_ptr < Expression > bitwise_xor_expression ( ); + + std::unique_ptr < Expression > equality_expression ( ); + + std::unique_ptr < Expression > relational_expression ( ); + + std::unique_ptr < Expression > add_expression ( ); + + std::unique_ptr < Expression > mul_expression ( ); + + std::unique_ptr < Expression > cast_expression ( ); + + std::unique_ptr < Expression > prefix_expression ( ); + + std::unique_ptr < Expression > suffix_expression ( ); + + std::unique_ptr < Expression > atom ( ); + + std::vector < std::unique_ptr < Expression > > bracketed_expression_list ( ); + std::unique_ptr < CategoryOption > category_option ( ); std::unique_ptr < TypeOption > type_option ( ); -- GitLab