diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp index 6dc2db33cb9252632ee5827ed423f27519c7bc8b..b89fd96c3b828c9f0441e7327208f34b29910e26 100644 --- a/src/language/ASTNodeExpressionBuilder.cpp +++ b/src/language/ASTNodeExpressionBuilder.cpp @@ -3,6 +3,7 @@ #include <ASTNodeAffectationExpressionBuilder.hpp> #include <ASTNodeBinaryOperatorExpressionBuilder.hpp> #include <ASTNodeIncDecExpressionBuilder.hpp> +#include <ASTNodeUnaryOperatorExpressionBuilder.hpp> #include <PEGGrammar.hpp> #include <SymbolTable.hpp> @@ -38,54 +39,6 @@ class NoProcess final : public INodeProcessor } }; -template <typename Op> -struct UnaryOp; - -template <> -struct UnaryOp<language::unary_minus> -{ - template <typename A> - PUGS_INLINE A - eval(const A& a) - { - return -a; - } -}; - -template <> -struct UnaryOp<language::unary_not> -{ - template <typename A> - PUGS_INLINE bool - eval(const A& a) - { - return not a; - } -}; - -template <typename UnaryOpT, typename ValueT, typename DataT> -class UnaryExpressionProcessor final : public INodeProcessor -{ - Node& m_node; - - public: - PUGS_INLINE ValueT - eval(const DataVariant& a) - { - return UnaryOp<UnaryOpT>().eval(std::get<DataT>(a)); - } - - public: - UnaryExpressionProcessor(Node& node) : m_node{node} {} - - void - execute(ExecUntilBreakOrContinue& exec_policy) - { - m_node.children[0]->execute(exec_policy); - m_node.m_value = eval(m_node.children[0]->m_value); - } -}; - class IfStatement final : public INodeProcessor { Node& m_node; @@ -313,61 +266,6 @@ namespace internal void build_node_type(Node& n) { - auto set_unary_operator_processor = [](Node& n, const auto& operator_v) { - auto set_unary_operator_processor_for_data = [&](const auto& value, const DataType& data_type) { - using OperatorT = std::decay_t<decltype(operator_v)>; - using ValueT = std::decay_t<decltype(value)>; - switch (data_type) { - case DataType::bool_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, bool>>(n); - break; - } - case DataType::unsigned_int_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, uint64_t>>(n); - break; - } - case DataType::int_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, int64_t>>(n); - break; - } - case DataType::double_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, double>>(n); - break; - } - default: { - throw parse_error("undefined operand type for unary operator", std::vector{n.children[0]->begin()}); - } - } - }; - - auto set_unary_operator_processor_for_value = [&](const DataType& value_type) { - const DataType data_type = n.children[0]->m_data_type; - switch (value_type) { - case DataType::bool_t: { - set_unary_operator_processor_for_data(bool{}, data_type); - break; - } - case DataType::unsigned_int_t: { - set_unary_operator_processor_for_data(uint64_t{}, data_type); - break; - } - case DataType::int_t: { - set_unary_operator_processor_for_data(int64_t{}, data_type); - break; - } - case DataType::double_t: { - set_unary_operator_processor_for_data(double{}, data_type); - break; - } - default: { - throw parse_error("undefined value type for unary operator", std::vector{n.begin()}); - } - } - }; - - set_unary_operator_processor_for_value(n.m_data_type); - }; - if (n.is_root() or n.is<language::bloc>()) { n.m_node_processor = std::make_unique<NodeList>(n); } else if (n.is<language::declaration>()) { @@ -386,10 +284,8 @@ build_node_type(Node& n) } else if (n.is<language::name>()) { n.m_node_processor = std::make_unique<NameExpression>(n); - } else if (n.is<language::unary_minus>()) { - set_unary_operator_processor(n, language::unary_minus{}); - } else if (n.is<language::unary_not>()) { - set_unary_operator_processor(n, language::unary_not{}); + } else if (n.is<language::unary_minus>() or n.is<language::unary_not>()) { + ASTNodeUnaryOperatorExpressionBuilder{n}; } else if (n.is<language::unary_minusminus>() or n.is<language::unary_plusplus>() or n.is<language::post_minusminus>() or n.is<language::post_plusplus>()) { diff --git a/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4bdb6f0a9148e63535e45735e9f7a464bb7a543 --- /dev/null +++ b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp @@ -0,0 +1,120 @@ +#include <ASTNodeUnaryOperatorExpressionBuilder.hpp> +#include <PEGGrammar.hpp> +#include <SymbolTable.hpp> + +namespace language +{ +template <typename Op> +struct UnaryOp; + +template <> +struct UnaryOp<language::unary_minus> +{ + template <typename A> + PUGS_INLINE A + eval(const A& a) + { + return -a; + } +}; + +template <> +struct UnaryOp<language::unary_not> +{ + template <typename A> + PUGS_INLINE bool + eval(const A& a) + { + return not a; + } +}; + +template <typename UnaryOpT, typename ValueT, typename DataT> +class UnaryExpressionProcessor final : public INodeProcessor +{ + Node& m_node; + + public: + PUGS_INLINE ValueT + eval(const DataVariant& a) + { + return UnaryOp<UnaryOpT>().eval(std::get<DataT>(a)); + } + + public: + UnaryExpressionProcessor(Node& node) : m_node{node} {} + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + m_node.children[0]->execute(exec_policy); + m_node.m_value = eval(m_node.children[0]->m_value); + } +}; + +ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(Node& n) +{ + auto set_unary_operator_processor = [](Node& n, const auto& operator_v) { + auto set_unary_operator_processor_for_data = [&](const auto& value, const DataType& data_type) { + using OperatorT = std::decay_t<decltype(operator_v)>; + using ValueT = std::decay_t<decltype(value)>; + switch (data_type) { + case DataType::bool_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, bool>>(n); + break; + } + case DataType::unsigned_int_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, uint64_t>>(n); + break; + } + case DataType::int_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, int64_t>>(n); + break; + } + case DataType::double_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, double>>(n); + break; + } + default: { + throw parse_error("undefined operand type for unary operator", std::vector{n.children[0]->begin()}); + } + } + }; + + auto set_unary_operator_processor_for_value = [&](const DataType& value_type) { + const DataType data_type = n.children[0]->m_data_type; + switch (value_type) { + case DataType::bool_t: { + set_unary_operator_processor_for_data(bool{}, data_type); + break; + } + case DataType::unsigned_int_t: { + set_unary_operator_processor_for_data(uint64_t{}, data_type); + break; + } + case DataType::int_t: { + set_unary_operator_processor_for_data(int64_t{}, data_type); + break; + } + case DataType::double_t: { + set_unary_operator_processor_for_data(double{}, data_type); + break; + } + default: { + throw parse_error("undefined value type for unary operator", std::vector{n.begin()}); + } + } + }; + + set_unary_operator_processor_for_value(n.m_data_type); + }; + + if (n.is<language::unary_minus>()) { + set_unary_operator_processor(n, language::unary_minus{}); + } else if (n.is<language::unary_not>()) { + set_unary_operator_processor(n, language::unary_not{}); + } else { + throw parse_error("unexpected error: undefined unary operator", std::vector{n.begin()}); + } +} +} // namespace language diff --git a/src/language/ASTNodeUnaryOperatorExpressionBuilder.hpp b/src/language/ASTNodeUnaryOperatorExpressionBuilder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ea58aa7d82e042ab6ff41741651ca2982eb4b69c --- /dev/null +++ b/src/language/ASTNodeUnaryOperatorExpressionBuilder.hpp @@ -0,0 +1,14 @@ +#ifndef AST_NODE_UNARY_OPERATOR_EXPRESSION_BUILDER_HPP +#define AST_NODE_UNARY_OPERATOR_EXPRESSION_BUILDER_HPP + +#include <ASTNode.hpp> + +namespace language +{ +struct ASTNodeUnaryOperatorExpressionBuilder +{ + ASTNodeUnaryOperatorExpressionBuilder(Node& node); +}; +} // namespace language + +#endif // AST_NODE_UNARY_OPERATOR_EXPRESSION_BUILDER_HPP diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index c9699c103b0720db96f775431f379ec6bb865b21..c84943ca41a9ccc1757e92ad3f7e0ff1e28e5903 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -11,6 +11,7 @@ add_library( ASTNodeBinaryOperatorExpressionBuilder.cpp ASTNodeExpressionBuilder.cpp ASTNodeIncDecExpressionBuilder.cpp + ASTNodeUnaryOperatorExpressionBuilder.cpp PugsParser.cpp) #include_directories(${PUGS_SOURCE_DIR}/utils)