Skip to content
Snippets Groups Projects
Commit 677ff496 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Use same strategy for increment and decrement operators

parent 34ae1c01
No related branches found
No related tags found
1 merge request!37Feature/language
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <ASTNodeAffectationExpressionBuilder.hpp> #include <ASTNodeAffectationExpressionBuilder.hpp>
#include <ASTNodeBinaryOperatorExpressionBuilder.hpp> #include <ASTNodeBinaryOperatorExpressionBuilder.hpp>
#include <ASTNodeIncDecExpressionBuilder.hpp>
#include <PEGGrammar.hpp> #include <PEGGrammar.hpp>
#include <SymbolTable.hpp> #include <SymbolTable.hpp>
...@@ -85,92 +86,6 @@ class UnaryExpressionProcessor final : public INodeProcessor ...@@ -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 class IfStatement final : public INodeProcessor
{ {
Node& m_node; Node& m_node;
...@@ -453,65 +368,6 @@ build_node_type(Node& n) ...@@ -453,65 +368,6 @@ build_node_type(Node& n)
set_unary_operator_processor_for_value(n.m_data_type); 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>()) { if (n.is_root() or n.is<language::bloc>()) {
n.m_node_processor = std::make_unique<NodeList>(n); n.m_node_processor = std::make_unique<NodeList>(n);
} else if (n.is<language::declaration>()) { } else if (n.is<language::declaration>()) {
...@@ -535,14 +391,9 @@ build_node_type(Node& n) ...@@ -535,14 +391,9 @@ build_node_type(Node& n)
} else if (n.is<language::unary_not>()) { } else if (n.is<language::unary_not>()) {
set_unary_operator_processor(n, language::unary_not{}); set_unary_operator_processor(n, language::unary_not{});
} else if (n.is<language::unary_minusminus>()) { } else if (n.is<language::unary_minusminus>() or n.is<language::unary_plusplus>() or
set_inc_dec_operator_processor(n, language::unary_minusminus{}); n.is<language::post_minusminus>() or n.is<language::post_plusplus>()) {
} else if (n.is<language::unary_plusplus>()) { ASTNodeIncDecExpressionBuilder{n};
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::multiply_op>() or n.is<language::divide_op>() or n.is<language::plus_op>() or } 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 n.is<language::minus_op>() or n.is<language::or_op>() or n.is<language::and_op>() or
......
#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
#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
...@@ -10,6 +10,7 @@ add_library( ...@@ -10,6 +10,7 @@ add_library(
ASTNodeAffectationExpressionBuilder.cpp ASTNodeAffectationExpressionBuilder.cpp
ASTNodeBinaryOperatorExpressionBuilder.cpp ASTNodeBinaryOperatorExpressionBuilder.cpp
ASTNodeExpressionBuilder.cpp ASTNodeExpressionBuilder.cpp
ASTNodeIncDecExpressionBuilder.cpp
PugsParser.cpp) PugsParser.cpp)
#include_directories(${PUGS_SOURCE_DIR}/utils) #include_directories(${PUGS_SOURCE_DIR}/utils)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment