diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp index 1be256c49086ff53e896bd399b9d67dbfaadc0be..6dc2db33cb9252632ee5827ed423f27519c7bc8b 100644 --- a/src/language/ASTNodeExpressionBuilder.cpp +++ b/src/language/ASTNodeExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <ASTNodeAffectationExpressionBuilder.hpp> #include <ASTNodeBinaryOperatorExpressionBuilder.hpp> +#include <ASTNodeIncDecExpressionBuilder.hpp> #include <PEGGrammar.hpp> #include <SymbolTable.hpp> @@ -85,92 +86,6 @@ class UnaryExpressionProcessor final : public INodeProcessor } }; -template <typename Op> -struct IncDecOp; - -template <> -struct IncDecOp<language::unary_minusminus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return --a; - } -}; - -template <> -struct IncDecOp<language::unary_plusplus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return ++a; - } -}; - -template <> -struct IncDecOp<language::post_minusminus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return a--; - } -}; - -template <> -struct IncDecOp<language::post_plusplus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return a++; - } -}; - -template <typename IncDecOpT, typename ValueT, typename DataT> -class IncDecExpressionProcessor final : public INodeProcessor -{ - Node& m_node; - DataVariant* p_value{nullptr}; - - static inline const bool _is_defined{[] { - if constexpr (std::is_same_v<IncDecOpT, language::unary_minusminus> or - std::is_same_v<IncDecOpT, language::unary_plusplus> or - std::is_same_v<IncDecOpT, language::post_minusminus> or - std::is_same_v<IncDecOpT, language::post_plusplus>) { - return not std::is_same_v<std::decay_t<DataT>, bool>; - } - return true; - }()}; - - public: - IncDecExpressionProcessor(Node& node) : m_node{node} - { - if constexpr (_is_defined) { - Assert(m_node.children[0]->is<language::name>()); - // It is sure at this point that children 0 is a variable name - const std::string& symbol = m_node.children[0]->string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol); - Assert(found); - p_value = &i_symbol->second.value(); - } else { - throw parse_error("invalid operand to unary operator", std::vector{m_node.begin()}); - } - } - void - execute(ExecUntilBreakOrContinue&) - { - if constexpr (_is_defined) { - m_node.m_value = IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); - } - } -}; - class IfStatement final : public INodeProcessor { Node& m_node; @@ -453,65 +368,6 @@ build_node_type(Node& n) set_unary_operator_processor_for_value(n.m_data_type); }; - auto set_inc_dec_operator_processor = [](Node& n, const auto& operator_v) { - auto set_inc_dec_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<IncDecExpressionProcessor<OperatorT, ValueT, bool>>(n); - break; - } - case DataType::unsigned_int_t: { - n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, ValueT, uint64_t>>(n); - break; - } - case DataType::int_t: { - n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, ValueT, int64_t>>(n); - break; - } - case DataType::double_t: { - n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, ValueT, double>>(n); - break; - } - default: { - throw parse_error("undefined operand type for unary operator", std::vector{n.children[0]->begin()}); - } - } - }; - - auto set_inc_dec_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_inc_dec_operator_processor_for_data(bool{}, data_type); - break; - } - case DataType::unsigned_int_t: { - set_inc_dec_operator_processor_for_data(uint64_t{}, data_type); - break; - } - case DataType::int_t: { - set_inc_dec_operator_processor_for_data(int64_t{}, data_type); - break; - } - case DataType::double_t: { - set_inc_dec_operator_processor_for_data(double{}, data_type); - break; - } - default: { - throw parse_error("undefined value type for unary operator", std::vector{n.begin()}); - } - } - }; - - if (not n.children[0]->is<language::name>()) { - throw parse_error("invalid operand type for unary operator", std::vector{n.begin()}); - } - - set_inc_dec_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>()) { @@ -535,14 +391,9 @@ build_node_type(Node& n) } else if (n.is<language::unary_not>()) { set_unary_operator_processor(n, language::unary_not{}); - } else if (n.is<language::unary_minusminus>()) { - set_inc_dec_operator_processor(n, language::unary_minusminus{}); - } else if (n.is<language::unary_plusplus>()) { - set_inc_dec_operator_processor(n, language::unary_plusplus{}); - } else if (n.is<language::post_minusminus>()) { - set_inc_dec_operator_processor(n, language::post_minusminus{}); - } else if (n.is<language::post_plusplus>()) { - set_inc_dec_operator_processor(n, language::post_plusplus{}); + } 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>()) { + ASTNodeIncDecExpressionBuilder{n}; } else if (n.is<language::multiply_op>() or n.is<language::divide_op>() or n.is<language::plus_op>() or n.is<language::minus_op>() or n.is<language::or_op>() or n.is<language::and_op>() or diff --git a/src/language/ASTNodeIncDecExpressionBuilder.cpp b/src/language/ASTNodeIncDecExpressionBuilder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5594ad0faf3c939669e73ab85b41e8a6ba0fd79d --- /dev/null +++ b/src/language/ASTNodeIncDecExpressionBuilder.cpp @@ -0,0 +1,166 @@ +#include <ASTNodeIncDecExpressionBuilder.hpp> +#include <PEGGrammar.hpp> +#include <SymbolTable.hpp> + +namespace language +{ +template <typename Op> +struct IncDecOp; + +template <> +struct IncDecOp<language::unary_minusminus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return --a; + } +}; + +template <> +struct IncDecOp<language::unary_plusplus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return ++a; + } +}; + +template <> +struct IncDecOp<language::post_minusminus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return a--; + } +}; + +template <> +struct IncDecOp<language::post_plusplus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return a++; + } +}; + +template <typename IncDecOpT, typename ValueT, typename DataT> +class IncDecExpressionProcessor final : public INodeProcessor +{ + Node& m_node; + DataVariant* p_value{nullptr}; + + static inline const bool _is_defined{[] { + if constexpr (std::is_same_v<IncDecOpT, language::unary_minusminus> or + std::is_same_v<IncDecOpT, language::unary_plusplus> or + std::is_same_v<IncDecOpT, language::post_minusminus> or + std::is_same_v<IncDecOpT, language::post_plusplus>) { + return not std::is_same_v<std::decay_t<DataT>, bool>; + } + return true; + }()}; + + public: + IncDecExpressionProcessor(Node& node) : m_node{node} + { + if constexpr (_is_defined) { + Assert(m_node.children[0]->is<language::name>()); + // It is sure at this point that children 0 is a variable name + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol); + Assert(found); + p_value = &i_symbol->second.value(); + } else { + throw parse_error("invalid operand to unary operator", std::vector{m_node.begin()}); + } + } + void + execute(ExecUntilBreakOrContinue&) + { + if constexpr (_is_defined) { + m_node.m_value = IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); + } + } +}; + +ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(Node& n) +{ + auto set_inc_dec_operator_processor = [](Node& n, const auto& operator_v) { + auto set_inc_dec_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<IncDecExpressionProcessor<OperatorT, ValueT, bool>>(n); + break; + } + case DataType::unsigned_int_t: { + n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, ValueT, uint64_t>>(n); + break; + } + case DataType::int_t: { + n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, ValueT, int64_t>>(n); + break; + } + case DataType::double_t: { + n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, ValueT, double>>(n); + break; + } + default: { + throw parse_error("undefined operand type for unary operator", std::vector{n.children[0]->begin()}); + } + } + }; + + auto set_inc_dec_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_inc_dec_operator_processor_for_data(bool{}, data_type); + break; + } + case DataType::unsigned_int_t: { + set_inc_dec_operator_processor_for_data(uint64_t{}, data_type); + break; + } + case DataType::int_t: { + set_inc_dec_operator_processor_for_data(int64_t{}, data_type); + break; + } + case DataType::double_t: { + set_inc_dec_operator_processor_for_data(double{}, data_type); + break; + } + default: { + throw parse_error("undefined value type for unary operator", std::vector{n.begin()}); + } + } + }; + + if (not n.children[0]->is<language::name>()) { + throw parse_error("invalid operand type for unary operator", std::vector{n.begin()}); + } + + set_inc_dec_processor_for_value(n.m_data_type); + }; + + if (n.is<language::unary_minusminus>()) { + set_inc_dec_operator_processor(n, language::unary_minusminus{}); + } else if (n.is<language::unary_plusplus>()) { + set_inc_dec_operator_processor(n, language::unary_plusplus{}); + } else if (n.is<language::post_minusminus>()) { + set_inc_dec_operator_processor(n, language::post_minusminus{}); + } else if (n.is<language::post_plusplus>()) { + set_inc_dec_operator_processor(n, language::post_plusplus{}); + } else { + throw parse_error("unexpected error: undefined increment/decrement operator", std::vector{n.begin()}); + } +} +} // namespace language diff --git a/src/language/ASTNodeIncDecExpressionBuilder.hpp b/src/language/ASTNodeIncDecExpressionBuilder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..26d35680cef68a31de3179b4664efa6671c913cf --- /dev/null +++ b/src/language/ASTNodeIncDecExpressionBuilder.hpp @@ -0,0 +1,14 @@ +#ifndef AST_NODE_INC_DEC_EXPRESSION_BUILDER_HPP +#define AST_NODE_INC_DEC_EXPRESSION_BUILDER_HPP + +#include <ASTNode.hpp> + +namespace language +{ +struct ASTNodeIncDecExpressionBuilder +{ + ASTNodeIncDecExpressionBuilder(Node& node); +}; +} // namespace language + +#endif // AST_NODE_INC_DEC_EXPRESSION_BUILDER_HPP diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index 8436a645f2b66cb3567c71ec2385e4664bc25434..c9699c103b0720db96f775431f379ec6bb865b21 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -10,6 +10,7 @@ add_library( ASTNodeAffectationExpressionBuilder.cpp ASTNodeBinaryOperatorExpressionBuilder.cpp ASTNodeExpressionBuilder.cpp + ASTNodeIncDecExpressionBuilder.cpp PugsParser.cpp) #include_directories(${PUGS_SOURCE_DIR}/utils)