mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Add domain classes for menu expressions
This commit is contained in:
parent
84a9c5e701
commit
0f017749c8
@ -0,0 +1,418 @@
|
|||||||
|
#include "CommonExpressionBinaryOperation.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
CommonExpressionBinaryOperationType::CommonExpressionBinaryOperationType(std::string syntax, const OperationPrecedence precedence, evaluation_function_t evaluationFunction)
|
||||||
|
: m_syntax(std::move(syntax)),
|
||||||
|
m_precedence(precedence),
|
||||||
|
m_evaluation_function(std::move(evaluationFunction))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_ADD(
|
||||||
|
"+",
|
||||||
|
OperationPrecedence::ADDITION_SUBTRACTION,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value + operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value + static_cast<double>(operand2.m_int_value));
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(std::to_string(operand1.m_double_value) + *operand2.m_string_value);
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(static_cast<double>(operand1.m_int_value) + operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value + operand2.m_int_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(std::to_string(operand1.m_int_value) + *operand2.m_string_value);
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(*operand1.m_string_value + std::to_string(operand2.m_double_value));
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(*operand1.m_string_value + std::to_string(operand2.m_int_value));
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(*operand1.m_string_value + *operand2.m_string_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_SUBTRACT(
|
||||||
|
"-",
|
||||||
|
OperationPrecedence::ADDITION_SUBTRACTION,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value - operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value - static_cast<double>(operand2.m_int_value));
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(static_cast<double>(operand1.m_int_value) - operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value - operand2.m_int_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_MULTIPLY(
|
||||||
|
"*",
|
||||||
|
OperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value * operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value * static_cast<double>(operand2.m_int_value));
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(static_cast<double>(operand1.m_int_value) * operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value * operand2.m_int_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_DIVIDE(
|
||||||
|
"/",
|
||||||
|
OperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value / operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value / static_cast<double>(operand2.m_int_value));
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(static_cast<double>(operand1.m_int_value) / operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value / operand2.m_int_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_REMAINDER(
|
||||||
|
"%",
|
||||||
|
OperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::INT && operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value % operand2.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_BITWISE_AND(
|
||||||
|
"&",
|
||||||
|
OperationPrecedence::BITWISE_AND,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::INT && operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value & operand2.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_BITWISE_OR(
|
||||||
|
"|",
|
||||||
|
OperationPrecedence::BITWISE_OR,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::INT && operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value | operand2.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_SHIFT_LEFT(
|
||||||
|
"<<",
|
||||||
|
OperationPrecedence::BITWISE_SHIFT,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::INT && operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value << operand2.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_SHIFT_RIGHT(
|
||||||
|
">>",
|
||||||
|
OperationPrecedence::BITWISE_SHIFT,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::INT && operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value >> operand2.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_GREATER_THAN(
|
||||||
|
">",
|
||||||
|
OperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::STRING || operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(operand1.IsTruthy() > operand2.IsTruthy());
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value > operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value > operand2.m_int_value);
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value > operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value > operand2.m_int_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_GREATER_EQUAL_THAN(
|
||||||
|
">=",
|
||||||
|
OperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::STRING || operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(operand1.IsTruthy() >= operand2.IsTruthy());
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value >= operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value >= operand2.m_int_value);
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value >= operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value >= operand2.m_int_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_LESS_THAN(
|
||||||
|
"<",
|
||||||
|
OperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::STRING || operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(operand1.IsTruthy() < operand2.IsTruthy());
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value < operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value < operand2.m_int_value);
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value < operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value < operand2.m_int_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_LESS_EQUAL_THAN(
|
||||||
|
"<=",
|
||||||
|
OperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::STRING || operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(operand1.IsTruthy() <= operand2.IsTruthy());
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value <= operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_double_value <= operand2.m_int_value);
|
||||||
|
}
|
||||||
|
else if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value <= operand2.m_double_value);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value <= operand2.m_int_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_EQUALS(
|
||||||
|
"==",
|
||||||
|
OperationPrecedence::RELATIONAL_EQUALS,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) == FP_ZERO);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(std::fpclassify(operand1.m_double_value - static_cast<double>(operand2.m_int_value)) == FP_ZERO);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) == FP_ZERO);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value == operand2.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(*operand1.m_string_value == *operand2.m_string_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_NOT_EQUAL(
|
||||||
|
"!=",
|
||||||
|
OperationPrecedence::RELATIONAL_EQUALS,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) != FP_ZERO);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(std::fpclassify(operand1.m_double_value - static_cast<double>(operand2.m_int_value)) != FP_ZERO);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
return CommonExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) != FP_ZERO);
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(operand1.m_int_value != operand2.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operand1.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
{
|
||||||
|
if (operand2.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
return CommonExpressionValue(*operand1.m_string_value != *operand2.m_string_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_AND(
|
||||||
|
"&&",
|
||||||
|
OperationPrecedence::LOGICAL_AND,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.IsTruthy())
|
||||||
|
return operand2;
|
||||||
|
return operand1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::OPERATION_OR(
|
||||||
|
"||",
|
||||||
|
OperationPrecedence::LOGICAL_OR,
|
||||||
|
[](const CommonExpressionValue& operand1, const CommonExpressionValue& operand2) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if (operand1.IsTruthy())
|
||||||
|
return operand1;
|
||||||
|
return operand2;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonExpressionBinaryOperation::CommonExpressionBinaryOperation(std::unique_ptr<ICommonExpression> operand1, std::unique_ptr<ICommonExpression> operand2,
|
||||||
|
const CommonExpressionBinaryOperationType* operationType)
|
||||||
|
: m_operand1(std::move(operand1)),
|
||||||
|
m_operand2(std::move(operand2)),
|
||||||
|
m_operation_type(operationType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionBinaryOperation::Operand1NeedsParenthesis() const
|
||||||
|
{
|
||||||
|
const auto* operation = dynamic_cast<const CommonExpressionBinaryOperation*>(m_operand1.get());
|
||||||
|
return operation && operation->m_operation_type->m_precedence > m_operation_type->m_precedence;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionBinaryOperation::Operand2NeedsParenthesis() const
|
||||||
|
{
|
||||||
|
const auto* operation = dynamic_cast<const CommonExpressionBinaryOperation*>(m_operand2.get());
|
||||||
|
return operation && operation->m_operation_type->m_precedence > m_operation_type->m_precedence;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionBinaryOperation::IsStatic()
|
||||||
|
{
|
||||||
|
assert(m_operand1 && m_operand2);
|
||||||
|
|
||||||
|
return m_operand1->IsStatic() && m_operand2->IsStatic();
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonExpressionValue CommonExpressionBinaryOperation::Evaluate()
|
||||||
|
{
|
||||||
|
return m_operation_type->m_evaluation_function(m_operand1->Evaluate(), m_operand2->Evaluate());
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "ICommonExpression.h"
|
||||||
|
#include "CommonExpressionValue.h"
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
// https://en.cppreference.com/w/cpp/language/operator_precedence
|
||||||
|
enum class OperationPrecedence
|
||||||
|
{
|
||||||
|
MULTIPLICATION_DIVISION_REMAINDER = 1,
|
||||||
|
ADDITION_SUBTRACTION = 2,
|
||||||
|
BITWISE_SHIFT = 3,
|
||||||
|
RELATIONAL_GREATER_LESS_THAN = 4,
|
||||||
|
RELATIONAL_EQUALS = 5,
|
||||||
|
BITWISE_AND = 6,
|
||||||
|
BITWISE_OR = 8,
|
||||||
|
LOGICAL_AND = 9,
|
||||||
|
LOGICAL_OR = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
class CommonExpressionBinaryOperationType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using evaluation_function_t = std::function<CommonExpressionValue(const CommonExpressionValue& operand1, const CommonExpressionValue& operand2)>;
|
||||||
|
|
||||||
|
std::string m_syntax;
|
||||||
|
OperationPrecedence m_precedence;
|
||||||
|
evaluation_function_t m_evaluation_function;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CommonExpressionBinaryOperationType(std::string syntax, OperationPrecedence precedence, evaluation_function_t evaluationFunction);
|
||||||
|
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_ADD;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_SUBTRACT;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_MULTIPLY;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_DIVIDE;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_REMAINDER;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_BITWISE_AND;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_BITWISE_OR;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_SHIFT_LEFT;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_SHIFT_RIGHT;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_GREATER_THAN;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_GREATER_EQUAL_THAN;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_LESS_THAN;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_LESS_EQUAL_THAN;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_EQUALS;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_NOT_EQUAL;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_AND;
|
||||||
|
static const CommonExpressionBinaryOperationType OPERATION_OR;
|
||||||
|
|
||||||
|
static const CommonExpressionBinaryOperationType* const ALL_OPERATION_TYPES[];
|
||||||
|
};
|
||||||
|
|
||||||
|
class CommonExpressionBinaryOperation final : public ICommonExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::unique_ptr<ICommonExpression> m_operand1;
|
||||||
|
std::unique_ptr<ICommonExpression> m_operand2;
|
||||||
|
const CommonExpressionBinaryOperationType* m_operation_type;
|
||||||
|
|
||||||
|
CommonExpressionBinaryOperation(std::unique_ptr<ICommonExpression> operand1,
|
||||||
|
std::unique_ptr<ICommonExpression> operand2,
|
||||||
|
const CommonExpressionBinaryOperationType* operationType);
|
||||||
|
|
||||||
|
_NODISCARD bool Operand1NeedsParenthesis() const;
|
||||||
|
_NODISCARD bool Operand2NeedsParenthesis() const;
|
||||||
|
|
||||||
|
bool IsStatic() override;
|
||||||
|
CommonExpressionValue Evaluate() override;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
#include "CommonExpressionFunctionCall.h"
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
CommonExpressionFunctionCall::CommonExpressionFunctionCall(std::string functionName)
|
||||||
|
: m_function_name(std::move(functionName))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionFunctionCall::IsStatic()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonExpressionValue CommonExpressionFunctionCall::Evaluate()
|
||||||
|
{
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ICommonExpression.h"
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class CommonExpressionFunctionCall final : public ICommonExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string m_function_name;
|
||||||
|
std::vector<std::unique_ptr<ICommonExpression>> m_args;
|
||||||
|
|
||||||
|
explicit CommonExpressionFunctionCall(std::string functionName);
|
||||||
|
|
||||||
|
bool IsStatic() override;
|
||||||
|
CommonExpressionValue Evaluate() override;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
#include "CommonExpressionUnaryOperation.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "CommonExpressionBinaryOperation.h"
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
CommonExpressionUnaryOperationType::CommonExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction)
|
||||||
|
: m_syntax(std::move(syntax)),
|
||||||
|
m_evaluation_function(std::move(evaluationFunction))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommonExpressionUnaryOperationType CommonExpressionUnaryOperationType::OPERATION_NOT(
|
||||||
|
"!",
|
||||||
|
[](const CommonExpressionValue& operand) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
return CommonExpressionValue(!operand.IsTruthy());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const CommonExpressionUnaryOperationType CommonExpressionUnaryOperationType::OPERATION_BITWISE_NOT(
|
||||||
|
"~",
|
||||||
|
[](const CommonExpressionValue& operand) -> CommonExpressionValue
|
||||||
|
{
|
||||||
|
if(operand.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
return CommonExpressionValue(~operand.m_int_value);
|
||||||
|
|
||||||
|
return CommonExpressionValue(0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonExpressionUnaryOperation::CommonExpressionUnaryOperation(std::unique_ptr<ICommonExpression> operand, const CommonExpressionUnaryOperationType* operationType)
|
||||||
|
: m_operand(std::move(operand)),
|
||||||
|
m_operation_type(operationType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionUnaryOperation::OperandNeedsParenthesis() const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const CommonExpressionBinaryOperation*>(m_operand.get()) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionUnaryOperation::IsStatic()
|
||||||
|
{
|
||||||
|
assert(m_operand);
|
||||||
|
|
||||||
|
return m_operand->IsStatic();
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonExpressionValue CommonExpressionUnaryOperation::Evaluate()
|
||||||
|
{
|
||||||
|
return m_operation_type->m_evaluation_function(m_operand->Evaluate());
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "ICommonExpression.h"
|
||||||
|
#include "CommonExpressionValue.h"
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class CommonExpressionUnaryOperationType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using evaluation_function_t = std::function<CommonExpressionValue(const CommonExpressionValue& operand)>;
|
||||||
|
|
||||||
|
std::string m_syntax;
|
||||||
|
evaluation_function_t m_evaluation_function;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CommonExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction);
|
||||||
|
|
||||||
|
static const CommonExpressionUnaryOperationType OPERATION_NOT;
|
||||||
|
static const CommonExpressionUnaryOperationType OPERATION_BITWISE_NOT;
|
||||||
|
|
||||||
|
static const CommonExpressionUnaryOperationType* const ALL_OPERATION_TYPES[];
|
||||||
|
};
|
||||||
|
|
||||||
|
class CommonExpressionUnaryOperation final : public ICommonExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::unique_ptr<ICommonExpression> m_operand;
|
||||||
|
const CommonExpressionUnaryOperationType* m_operation_type;
|
||||||
|
|
||||||
|
CommonExpressionUnaryOperation(std::unique_ptr<ICommonExpression> operand,
|
||||||
|
const CommonExpressionUnaryOperationType* operationType);
|
||||||
|
|
||||||
|
_NODISCARD bool OperandNeedsParenthesis() const;
|
||||||
|
|
||||||
|
bool IsStatic() override;
|
||||||
|
CommonExpressionValue Evaluate() override;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
#include "CommonExpressionValue.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
CommonExpressionValue::CommonExpressionValue(std::string stringValue)
|
||||||
|
: m_type(Type::STRING),
|
||||||
|
m_string_value(std::make_shared<std::string>(std::move(stringValue)))
|
||||||
|
{
|
||||||
|
m_double_value = 0;
|
||||||
|
m_int_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonExpressionValue::CommonExpressionValue(const double doubleValue)
|
||||||
|
: m_type(Type::DOUBLE)
|
||||||
|
{
|
||||||
|
m_int_value = 0;
|
||||||
|
m_double_value = doubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonExpressionValue::CommonExpressionValue(const int intValue)
|
||||||
|
: m_type(Type::INT)
|
||||||
|
{
|
||||||
|
m_double_value = 0;
|
||||||
|
m_int_value = intValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionValue::IsStatic()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonExpressionValue CommonExpressionValue::Evaluate()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionValue::IsTruthy() const
|
||||||
|
{
|
||||||
|
if (m_type == Type::DOUBLE)
|
||||||
|
return std::fpclassify(m_double_value) != FP_ZERO;
|
||||||
|
if (m_type == Type::INT)
|
||||||
|
return m_int_value != 0;
|
||||||
|
if (m_type == Type::STRING)
|
||||||
|
return m_string_value && !m_string_value->empty();
|
||||||
|
return false;
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "ICommonExpression.h"
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class ICommonExpression;
|
||||||
|
class CommonExpressionValue final : public ICommonExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
STRING,
|
||||||
|
DOUBLE,
|
||||||
|
INT
|
||||||
|
};
|
||||||
|
|
||||||
|
Type m_type;
|
||||||
|
std::shared_ptr<std::string> m_string_value;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
double m_double_value;
|
||||||
|
int m_int_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit CommonExpressionValue(std::string stringValue);
|
||||||
|
explicit CommonExpressionValue(double doubleValue);
|
||||||
|
explicit CommonExpressionValue(int intValue);
|
||||||
|
|
||||||
|
bool IsStatic() override;
|
||||||
|
CommonExpressionValue Evaluate() override;
|
||||||
|
_NODISCARD bool IsTruthy() const;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class CommonExpressionValue;
|
||||||
|
class ICommonExpression
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
ICommonExpression() = default;
|
||||||
|
public:
|
||||||
|
virtual ~ICommonExpression() = default;
|
||||||
|
ICommonExpression(const ICommonExpression& other) = default;
|
||||||
|
ICommonExpression(ICommonExpression&& other) noexcept = default;
|
||||||
|
ICommonExpression& operator=(const ICommonExpression& other) = default;
|
||||||
|
ICommonExpression& operator=(ICommonExpression&& other) noexcept = default;
|
||||||
|
|
||||||
|
virtual bool IsStatic() = 0;
|
||||||
|
virtual CommonExpressionValue Evaluate() = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include CommonExpressionValue after definition to avoid "base class not defined"
|
||||||
|
#include "CommonExpressionValue.h"
|
Loading…
x
Reference in New Issue
Block a user