mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Add expression parsing for menu parser
This commit is contained in:
parent
c5d7d71a51
commit
69c08def7f
@ -385,11 +385,32 @@ const CommonExpressionBinaryOperationType CommonExpressionBinaryOperationType::O
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
CommonExpressionBinaryOperation::CommonExpressionBinaryOperation(std::unique_ptr<ICommonExpression> operand1, std::unique_ptr<ICommonExpression> operand2,
|
const CommonExpressionBinaryOperationType* const CommonExpressionBinaryOperationType::ALL_OPERATION_TYPES[static_cast<int>(BinaryOperationId::COUNT)]
|
||||||
const CommonExpressionBinaryOperationType* operationType)
|
{
|
||||||
: m_operand1(std::move(operand1)),
|
&OPERATION_ADD,
|
||||||
m_operand2(std::move(operand2)),
|
&OPERATION_SUBTRACT,
|
||||||
m_operation_type(operationType)
|
&OPERATION_MULTIPLY,
|
||||||
|
&OPERATION_DIVIDE,
|
||||||
|
&OPERATION_REMAINDER,
|
||||||
|
&OPERATION_BITWISE_AND,
|
||||||
|
&OPERATION_BITWISE_OR,
|
||||||
|
&OPERATION_SHIFT_LEFT,
|
||||||
|
&OPERATION_SHIFT_RIGHT,
|
||||||
|
&OPERATION_GREATER_THAN,
|
||||||
|
&OPERATION_GREATER_EQUAL_THAN,
|
||||||
|
&OPERATION_LESS_THAN,
|
||||||
|
&OPERATION_LESS_EQUAL_THAN,
|
||||||
|
&OPERATION_EQUALS,
|
||||||
|
&OPERATION_NOT_EQUAL,
|
||||||
|
&OPERATION_AND,
|
||||||
|
&OPERATION_OR
|
||||||
|
};
|
||||||
|
|
||||||
|
CommonExpressionBinaryOperation::CommonExpressionBinaryOperation(const CommonExpressionBinaryOperationType* operationType, std::unique_ptr<ICommonExpression> operand1,
|
||||||
|
std::unique_ptr<ICommonExpression> operand2)
|
||||||
|
: m_operation_type(operationType),
|
||||||
|
m_operand1(std::move(operand1)),
|
||||||
|
m_operand2(std::move(operand2))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,29 @@ namespace menu
|
|||||||
LOGICAL_OR = 10
|
LOGICAL_OR = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class BinaryOperationId
|
||||||
|
{
|
||||||
|
ADD,
|
||||||
|
SUBTRACT,
|
||||||
|
MULTIPLY,
|
||||||
|
DIVIDE,
|
||||||
|
REMAINDER,
|
||||||
|
BITWISE_AND,
|
||||||
|
BITWISE_OR,
|
||||||
|
SHIFT_LEFT,
|
||||||
|
SHIFT_RIGHT,
|
||||||
|
GREATER_THAN,
|
||||||
|
GREATER_EQUAL_THAN,
|
||||||
|
LESS_THAN,
|
||||||
|
LESS_EQUAL_THAN,
|
||||||
|
EQUALS,
|
||||||
|
NOT_EQUAL,
|
||||||
|
AND,
|
||||||
|
OR,
|
||||||
|
|
||||||
|
COUNT
|
||||||
|
};
|
||||||
|
|
||||||
class CommonExpressionBinaryOperationType
|
class CommonExpressionBinaryOperationType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -35,6 +58,7 @@ namespace menu
|
|||||||
private:
|
private:
|
||||||
CommonExpressionBinaryOperationType(std::string syntax, OperationPrecedence precedence, evaluation_function_t evaluationFunction);
|
CommonExpressionBinaryOperationType(std::string syntax, OperationPrecedence precedence, evaluation_function_t evaluationFunction);
|
||||||
|
|
||||||
|
public:
|
||||||
static const CommonExpressionBinaryOperationType OPERATION_ADD;
|
static const CommonExpressionBinaryOperationType OPERATION_ADD;
|
||||||
static const CommonExpressionBinaryOperationType OPERATION_SUBTRACT;
|
static const CommonExpressionBinaryOperationType OPERATION_SUBTRACT;
|
||||||
static const CommonExpressionBinaryOperationType OPERATION_MULTIPLY;
|
static const CommonExpressionBinaryOperationType OPERATION_MULTIPLY;
|
||||||
@ -53,19 +77,19 @@ namespace menu
|
|||||||
static const CommonExpressionBinaryOperationType OPERATION_AND;
|
static const CommonExpressionBinaryOperationType OPERATION_AND;
|
||||||
static const CommonExpressionBinaryOperationType OPERATION_OR;
|
static const CommonExpressionBinaryOperationType OPERATION_OR;
|
||||||
|
|
||||||
static const CommonExpressionBinaryOperationType* const ALL_OPERATION_TYPES[];
|
static const CommonExpressionBinaryOperationType* const ALL_OPERATION_TYPES[static_cast<int>(BinaryOperationId::COUNT)];
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommonExpressionBinaryOperation final : public ICommonExpression
|
class CommonExpressionBinaryOperation final : public ICommonExpression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
const CommonExpressionBinaryOperationType* m_operation_type;
|
||||||
std::unique_ptr<ICommonExpression> m_operand1;
|
std::unique_ptr<ICommonExpression> m_operand1;
|
||||||
std::unique_ptr<ICommonExpression> m_operand2;
|
std::unique_ptr<ICommonExpression> m_operand2;
|
||||||
const CommonExpressionBinaryOperationType* m_operation_type;
|
|
||||||
|
|
||||||
CommonExpressionBinaryOperation(std::unique_ptr<ICommonExpression> operand1,
|
CommonExpressionBinaryOperation(const CommonExpressionBinaryOperationType* operationType,
|
||||||
std::unique_ptr<ICommonExpression> operand2,
|
std::unique_ptr<ICommonExpression> operand1,
|
||||||
const CommonExpressionBinaryOperationType* operationType);
|
std::unique_ptr<ICommonExpression> operand2);
|
||||||
|
|
||||||
_NODISCARD bool Operand1NeedsParenthesis() const;
|
_NODISCARD bool Operand1NeedsParenthesis() const;
|
||||||
_NODISCARD bool Operand2NeedsParenthesis() const;
|
_NODISCARD bool Operand2NeedsParenthesis() const;
|
||||||
|
@ -31,9 +31,15 @@ const CommonExpressionUnaryOperationType CommonExpressionUnaryOperationType::OPE
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
CommonExpressionUnaryOperation::CommonExpressionUnaryOperation(std::unique_ptr<ICommonExpression> operand, const CommonExpressionUnaryOperationType* operationType)
|
const CommonExpressionUnaryOperationType* const CommonExpressionUnaryOperationType::ALL_OPERATION_TYPES[static_cast<int>(UnaryOperationId::COUNT)]
|
||||||
: m_operand(std::move(operand)),
|
{
|
||||||
m_operation_type(operationType)
|
&OPERATION_NOT,
|
||||||
|
&OPERATION_BITWISE_NOT,
|
||||||
|
};
|
||||||
|
|
||||||
|
CommonExpressionUnaryOperation::CommonExpressionUnaryOperation(const CommonExpressionUnaryOperationType* operationType, std::unique_ptr<ICommonExpression> operand)
|
||||||
|
: m_operation_type(operationType),
|
||||||
|
m_operand(std::move(operand))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,14 @@
|
|||||||
|
|
||||||
namespace menu
|
namespace menu
|
||||||
{
|
{
|
||||||
|
enum class UnaryOperationId
|
||||||
|
{
|
||||||
|
NOT,
|
||||||
|
BITWISE_NOT,
|
||||||
|
|
||||||
|
COUNT
|
||||||
|
};
|
||||||
|
|
||||||
class CommonExpressionUnaryOperationType
|
class CommonExpressionUnaryOperationType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -20,20 +28,20 @@ namespace menu
|
|||||||
private:
|
private:
|
||||||
CommonExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction);
|
CommonExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction);
|
||||||
|
|
||||||
|
public:
|
||||||
static const CommonExpressionUnaryOperationType OPERATION_NOT;
|
static const CommonExpressionUnaryOperationType OPERATION_NOT;
|
||||||
static const CommonExpressionUnaryOperationType OPERATION_BITWISE_NOT;
|
static const CommonExpressionUnaryOperationType OPERATION_BITWISE_NOT;
|
||||||
|
|
||||||
static const CommonExpressionUnaryOperationType* const ALL_OPERATION_TYPES[];
|
static const CommonExpressionUnaryOperationType* const ALL_OPERATION_TYPES[static_cast<int>(UnaryOperationId::COUNT)];
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommonExpressionUnaryOperation final : public ICommonExpression
|
class CommonExpressionUnaryOperation final : public ICommonExpression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<ICommonExpression> m_operand;
|
|
||||||
const CommonExpressionUnaryOperationType* m_operation_type;
|
const CommonExpressionUnaryOperationType* m_operation_type;
|
||||||
|
std::unique_ptr<ICommonExpression> m_operand;
|
||||||
|
|
||||||
CommonExpressionUnaryOperation(std::unique_ptr<ICommonExpression> operand,
|
CommonExpressionUnaryOperation(const CommonExpressionUnaryOperationType* operationType, std::unique_ptr<ICommonExpression> operand);
|
||||||
const CommonExpressionUnaryOperationType* operationType);
|
|
||||||
|
|
||||||
_NODISCARD bool OperandNeedsParenthesis() const;
|
_NODISCARD bool OperandNeedsParenthesis() const;
|
||||||
|
|
||||||
|
302
src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.cpp
Normal file
302
src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.cpp
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
#include "MenuCommonMatchers.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "MenuMatcherFactory.h"
|
||||||
|
#include "Parsing/Menu/MenuFileLexing.h"
|
||||||
|
#include "Parsing/Menu/Domain/Expression/CommonExpressionBinaryOperation.h"
|
||||||
|
#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h"
|
||||||
|
#include "Parsing/Menu/Domain/Expression/CommonExpressionUnaryOperation.h"
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
static constexpr int TAG_OPERAND = std::numeric_limits<int>::max() - 1;
|
||||||
|
static constexpr int TAG_EXPRESSION_UNARY_OPERATION = std::numeric_limits<int>::max() - 2;
|
||||||
|
static constexpr int TAG_EXPRESSION_FUNCTION_CALL = std::numeric_limits<int>::max() - 3;
|
||||||
|
static constexpr int TAG_EXPRESSION_FUNCTION_CALL_END = std::numeric_limits<int>::max() - 4;
|
||||||
|
static constexpr int TAG_EXPRESSION_PARENTHESIS = std::numeric_limits<int>::max() - 5;
|
||||||
|
static constexpr int TAG_EXPRESSION_PARENTHESIS_END = std::numeric_limits<int>::max() - 6;
|
||||||
|
static constexpr int TAG_EXPRESSION = std::numeric_limits<int>::max() - 7;
|
||||||
|
static constexpr int TAG_EXPRESSION_BINARY_OPERATION = std::numeric_limits<int>::max() - 8;
|
||||||
|
|
||||||
|
static constexpr int CAPTURE_OPERAND = std::numeric_limits<int>::max() - 1;
|
||||||
|
static constexpr int CAPTURE_UNARY_OPERATION_TYPE = std::numeric_limits<int>::max() - 2;
|
||||||
|
static constexpr int CAPTURE_BINARY_OPERATION_TYPE = std::numeric_limits<int>::max() - 3;
|
||||||
|
static constexpr int CAPTURE_FUNCTION_NAME = std::numeric_limits<int>::max() - 4;
|
||||||
|
|
||||||
|
std::unique_ptr<ICommonExpression> MenuCommonMatchers::ProcessExpressionInParenthesis(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||||
|
{
|
||||||
|
auto processedEvaluation = ProcessExpression(state, result);
|
||||||
|
|
||||||
|
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_PARENTHESIS_END) != TAG_EXPRESSION_PARENTHESIS_END)
|
||||||
|
throw ParsingException(TokenPos(), "Expected parenthesis end tag @ ExpressionInParenthesis");
|
||||||
|
|
||||||
|
return processedEvaluation;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ICommonExpression> MenuCommonMatchers::ProcessOperand(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||||
|
{
|
||||||
|
const auto& operandToken = result.NextCapture(CAPTURE_OPERAND);
|
||||||
|
|
||||||
|
switch (operandToken.m_type)
|
||||||
|
{
|
||||||
|
case SimpleParserValueType::INTEGER:
|
||||||
|
return std::make_unique<CommonExpressionValue>(operandToken.IntegerValue());
|
||||||
|
case SimpleParserValueType::FLOATING_POINT:
|
||||||
|
return std::make_unique<CommonExpressionValue>(operandToken.FloatingPointValue());
|
||||||
|
case SimpleParserValueType::STRING:
|
||||||
|
return std::make_unique<CommonExpressionValue>(operandToken.StringValue());
|
||||||
|
case SimpleParserValueType::IDENTIFIER:
|
||||||
|
return std::make_unique<CommonExpressionValue>(operandToken.IdentifierValue());
|
||||||
|
default:
|
||||||
|
throw ParsingException(TokenPos(), "Unknown operand type @ Operand");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ICommonExpression> MenuCommonMatchers::ProcessFunctionCall(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||||
|
{
|
||||||
|
auto functionCall = std::make_unique<CommonExpressionFunctionCall>(result.NextCapture(CAPTURE_FUNCTION_NAME).IdentifierValue());
|
||||||
|
|
||||||
|
while (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END)
|
||||||
|
{
|
||||||
|
functionCall->m_args.emplace_back(ProcessExpression(state, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(functionCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ICommonExpression> MenuCommonMatchers::ProcessExpression(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||||
|
{
|
||||||
|
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<ICommonExpression>> operands;
|
||||||
|
std::list<std::pair<unsigned, const CommonExpressionBinaryOperationType*>> operators;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::unique_ptr<ICommonExpression> firstStatementPart;
|
||||||
|
std::vector<int> unaryOperations;
|
||||||
|
auto nextTag = result.NextTag();
|
||||||
|
|
||||||
|
while (nextTag == TAG_EXPRESSION_UNARY_OPERATION)
|
||||||
|
{
|
||||||
|
unaryOperations.push_back(result.NextCapture(CAPTURE_UNARY_OPERATION_TYPE).IntegerValue());
|
||||||
|
nextTag = result.NextTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (nextTag)
|
||||||
|
{
|
||||||
|
case TAG_EXPRESSION_PARENTHESIS:
|
||||||
|
firstStatementPart = ProcessExpressionInParenthesis(state, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TAG_EXPRESSION_FUNCTION_CALL:
|
||||||
|
firstStatementPart = ProcessFunctionCall(state, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TAG_OPERAND:
|
||||||
|
firstStatementPart = ProcessOperand(state, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw ParsingException(TokenPos(), "Invalid followup tag @ Expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = unaryOperations.size(); i > 0; i--)
|
||||||
|
{
|
||||||
|
const auto operationIndex = unaryOperations[i - 1];
|
||||||
|
if (operationIndex < 0 || operationIndex >= static_cast<int>(UnaryOperationId::COUNT))
|
||||||
|
throw ParsingException(TokenPos(), "Invalid unary operation id @ Expression");
|
||||||
|
firstStatementPart = std::make_unique<CommonExpressionUnaryOperation>(CommonExpressionUnaryOperationType::ALL_OPERATION_TYPES[operationIndex],
|
||||||
|
std::move(firstStatementPart));
|
||||||
|
}
|
||||||
|
|
||||||
|
operands.emplace_back(std::move(firstStatementPart));
|
||||||
|
|
||||||
|
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_BINARY_OPERATION) == TAG_EXPRESSION_BINARY_OPERATION)
|
||||||
|
{
|
||||||
|
const auto operationIndex = result.NextCapture(CAPTURE_BINARY_OPERATION_TYPE).IntegerValue();
|
||||||
|
if (operationIndex < 0 || operationIndex >= static_cast<int>(BinaryOperationId::COUNT))
|
||||||
|
throw ParsingException(TokenPos(), "Invalid binary operation id @ Expression");
|
||||||
|
|
||||||
|
operators.emplace_back(operators.size(), CommonExpressionBinaryOperationType::ALL_OPERATION_TYPES[operationIndex]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION)
|
||||||
|
throw ParsingException(TokenPos(), "Expected EvaluationTag @ Evaluation");
|
||||||
|
}
|
||||||
|
|
||||||
|
operators.sort([](const std::pair<unsigned, const CommonExpressionBinaryOperationType*>& p1, const std::pair<unsigned, const CommonExpressionBinaryOperationType*>& p2)
|
||||||
|
{
|
||||||
|
if (p1.second->m_precedence != p2.second->m_precedence)
|
||||||
|
return p1.second->m_precedence > p2.second->m_precedence;
|
||||||
|
|
||||||
|
return p1.first > p2.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
while (!operators.empty())
|
||||||
|
{
|
||||||
|
const auto [operatorIndex, operatorType] = operators.back();
|
||||||
|
|
||||||
|
auto operation = std::make_unique<CommonExpressionBinaryOperation>(operatorType, std::move(operands[operatorIndex]), std::move(operands[operatorIndex + 1]));
|
||||||
|
operands.erase(operands.begin() + static_cast<int>(operatorIndex));
|
||||||
|
operands[operatorIndex] = std::move(operation);
|
||||||
|
|
||||||
|
operators.pop_back();
|
||||||
|
|
||||||
|
for (auto& [opIndex, _] : operators)
|
||||||
|
{
|
||||||
|
if (opIndex > operatorIndex)
|
||||||
|
opIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(operands.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MenuCommonMatchers::matcher_t> MenuCommonMatchers::ParseOperand(const supplier_t* labelSupplier)
|
||||||
|
{
|
||||||
|
const MenuMatcherFactory create(labelSupplier);
|
||||||
|
|
||||||
|
return create.Or({
|
||||||
|
create.Integer(),
|
||||||
|
create.FloatingPoint(),
|
||||||
|
create.String(),
|
||||||
|
create.Identifier(),
|
||||||
|
}).Tag(TAG_OPERAND).Capture(CAPTURE_OPERAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MenuCommonMatchers::matcher_t> MenuCommonMatchers::ParseBinaryOperationType(const supplier_t* labelSupplier)
|
||||||
|
{
|
||||||
|
const MenuMatcherFactory create(labelSupplier);
|
||||||
|
|
||||||
|
return create.Or({
|
||||||
|
create.Char('+').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::ADD));
|
||||||
|
}),
|
||||||
|
create.Char('-').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::SUBTRACT));
|
||||||
|
}),
|
||||||
|
create.Char('*').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::MULTIPLY));
|
||||||
|
}),
|
||||||
|
create.Char('/').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::DIVIDE));
|
||||||
|
}),
|
||||||
|
create.Char('%').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::REMAINDER));
|
||||||
|
}),
|
||||||
|
create.Char('&').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::BITWISE_AND));
|
||||||
|
}),
|
||||||
|
create.Char('|').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::BITWISE_OR));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::SHIFT_LEFT)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::SHIFT_LEFT));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::SHIFT_RIGHT)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::SHIFT_RIGHT));
|
||||||
|
}),
|
||||||
|
create.Char('>').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::GREATER_THAN));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::GREATER_EQUAL)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::GREATER_EQUAL_THAN));
|
||||||
|
}),
|
||||||
|
create.Char('<').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::LESS_THAN));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::LESS_EQUAL)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::LESS_EQUAL_THAN));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::EQUALS)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::EQUALS));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::NOT_EQUAL)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::NOT_EQUAL));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::LOGICAL_AND)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::AND));
|
||||||
|
}),
|
||||||
|
create.MultiChar(static_cast<int>(MenuFileLexing::MultiChar::LOGICAL_OR)).Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(BinaryOperationId::OR));
|
||||||
|
}),
|
||||||
|
}).Capture(CAPTURE_BINARY_OPERATION_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MenuCommonMatchers::matcher_t> MenuCommonMatchers::ParseFunctionCall(const supplier_t* labelSupplier)
|
||||||
|
{
|
||||||
|
const MenuMatcherFactory create(labelSupplier);
|
||||||
|
|
||||||
|
return create.And({
|
||||||
|
create.Identifier().Capture(CAPTURE_FUNCTION_NAME),
|
||||||
|
create.Char('('),
|
||||||
|
create.Optional(create.And({
|
||||||
|
create.Label(LABEL_EXPRESSION),
|
||||||
|
create.OptionalLoop(create.And({
|
||||||
|
create.Char(','),
|
||||||
|
create.Label(LABEL_EXPRESSION)
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
create.Char(')').Tag(TAG_EXPRESSION_FUNCTION_CALL_END)
|
||||||
|
}).Tag(TAG_EXPRESSION_FUNCTION_CALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MenuCommonMatchers::matcher_t> MenuCommonMatchers::ParseUnaryOperationType(const supplier_t* labelSupplier)
|
||||||
|
{
|
||||||
|
const MenuMatcherFactory create(labelSupplier);
|
||||||
|
|
||||||
|
return create.Or({
|
||||||
|
create.Char('!').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(UnaryOperationId::NOT));
|
||||||
|
}),
|
||||||
|
create.Char('~').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||||
|
{
|
||||||
|
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(UnaryOperationId::BITWISE_NOT));
|
||||||
|
}),
|
||||||
|
}).Tag(TAG_EXPRESSION_UNARY_OPERATION).Capture(CAPTURE_UNARY_OPERATION_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MenuCommonMatchers::matcher_t> MenuCommonMatchers::Expression(const supplier_t* labelSupplier)
|
||||||
|
{
|
||||||
|
const MenuMatcherFactory create(labelSupplier);
|
||||||
|
|
||||||
|
return create.And({
|
||||||
|
create.OptionalLoop(ParseUnaryOperationType(labelSupplier)),
|
||||||
|
create.Or({
|
||||||
|
create.And({
|
||||||
|
create.Char('('),
|
||||||
|
create.Label(LABEL_EXPRESSION),
|
||||||
|
create.Char(')').Tag(TAG_EXPRESSION_PARENTHESIS_END)
|
||||||
|
}).Tag(TAG_EXPRESSION_PARENTHESIS),
|
||||||
|
ParseFunctionCall(labelSupplier),
|
||||||
|
ParseOperand(labelSupplier)
|
||||||
|
}),
|
||||||
|
create.Optional(create.And({
|
||||||
|
ParseBinaryOperationType(labelSupplier),
|
||||||
|
create.Label(LABEL_EXPRESSION)
|
||||||
|
}).Tag(TAG_EXPRESSION_BINARY_OPERATION))
|
||||||
|
}).Tag(TAG_EXPRESSION);
|
||||||
|
}
|
37
src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.h
Normal file
37
src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Parsing/Matcher/AbstractMatcher.h"
|
||||||
|
#include "Parsing/Matcher/MatcherLabel.h"
|
||||||
|
#include "Parsing/Menu/MenuFileParser.h"
|
||||||
|
#include "Parsing/Menu/Domain/Expression/ICommonExpression.h"
|
||||||
|
#include "Parsing/Sequence/SequenceResult.h"
|
||||||
|
#include "Parsing/Simple/SimpleParserValue.h"
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class MenuCommonMatchers
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using matcher_t = MenuFileParser::sequence_t::matcher_t;
|
||||||
|
typedef IMatcherForLabelSupplier<SimpleParserValue> supplier_t;
|
||||||
|
|
||||||
|
static constexpr int LABEL_EXPRESSION = std::numeric_limits<int>::max() - 1;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::unique_ptr<matcher_t> ParseBinaryOperationType(const supplier_t* labelSupplier);
|
||||||
|
static std::unique_ptr<matcher_t> ParseOperand(const supplier_t* labelSupplier);
|
||||||
|
static std::unique_ptr<matcher_t> ParseFunctionCall(const supplier_t* labelSupplier);
|
||||||
|
static std::unique_ptr<matcher_t> ParseUnaryOperationType(const supplier_t* labelSupplier);
|
||||||
|
|
||||||
|
static std::unique_ptr<ICommonExpression> ProcessExpressionInParenthesis(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||||
|
static std::unique_ptr<ICommonExpression> ProcessOperand(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||||
|
static std::unique_ptr<ICommonExpression> ProcessFunctionCall(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<matcher_t> Expression(const supplier_t* labelSupplier);
|
||||||
|
static std::unique_ptr<ICommonExpression> ProcessExpression(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||||
|
};
|
||||||
|
}
|
22
src/ObjLoading/Parsing/Menu/MenuFileLexing.h
Normal file
22
src/ObjLoading/Parsing/Menu/MenuFileLexing.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class MenuFileLexing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class MultiChar
|
||||||
|
{
|
||||||
|
SHIFT_LEFT,
|
||||||
|
SHIFT_RIGHT,
|
||||||
|
GREATER_EQUAL,
|
||||||
|
LESS_EQUAL,
|
||||||
|
EQUALS,
|
||||||
|
NOT_EQUAL,
|
||||||
|
LOGICAL_AND,
|
||||||
|
LOGICAL_OR
|
||||||
|
};
|
||||||
|
|
||||||
|
MenuFileLexing() = delete;
|
||||||
|
};
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include "MenuFileReader.h"
|
#include "MenuFileReader.h"
|
||||||
|
|
||||||
|
#include "MenuFileLexing.h"
|
||||||
#include "MenuFileParser.h"
|
#include "MenuFileParser.h"
|
||||||
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
|
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
|
||||||
#include "Parsing/Impl/DefinesStreamProxy.h"
|
#include "Parsing/Impl/DefinesStreamProxy.h"
|
||||||
@ -115,6 +116,16 @@ std::unique_ptr<ParsingResult> MenuFileReader::ReadMenuFile()
|
|||||||
lexerConfig.m_emit_new_line_tokens = false;
|
lexerConfig.m_emit_new_line_tokens = false;
|
||||||
lexerConfig.m_read_strings = true;
|
lexerConfig.m_read_strings = true;
|
||||||
lexerConfig.m_read_numbers = true;
|
lexerConfig.m_read_numbers = true;
|
||||||
|
lexerConfig.m_multi_character_tokens = std::vector<SimpleLexer::Config::MultiCharacterToken>({
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::SHIFT_LEFT), "<<"},
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::SHIFT_RIGHT), ">>"},
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::GREATER_EQUAL), ">="},
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::LESS_EQUAL), "<="},
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::EQUALS), "=="},
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::NOT_EQUAL), "!="},
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::LOGICAL_AND), "&&"},
|
||||||
|
{static_cast<int>(MenuFileLexing::MultiChar::LOGICAL_OR), "||"},
|
||||||
|
});
|
||||||
const auto lexer = std::make_unique<SimpleLexer>(m_stream, std::move(lexerConfig));
|
const auto lexer = std::make_unique<SimpleLexer>(m_stream, std::move(lexerConfig));
|
||||||
|
|
||||||
const auto parser = std::make_unique<MenuFileParser>(lexer.get(), m_feature_level);
|
const auto parser = std::make_unique<MenuFileParser>(lexer.get(), m_feature_level);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "GenericStringPropertySequence.h"
|
#include "GenericStringPropertySequence.h"
|
||||||
#include "Parsing/Menu/Matcher/MenuMatcherFactory.h"
|
#include "Parsing/Menu/Matcher/MenuMatcherFactory.h"
|
||||||
#include "Parsing/Menu/Domain/CommonMenuTypes.h"
|
#include "Parsing/Menu/Domain/CommonMenuTypes.h"
|
||||||
|
#include "Parsing/Menu/Matcher/MenuCommonMatchers.h"
|
||||||
|
|
||||||
using namespace menu;
|
using namespace menu;
|
||||||
|
|
||||||
@ -63,6 +64,52 @@ namespace menu::menu_properties
|
|||||||
state->m_current_menu->m_rect = rect;
|
state->m_current_menu->m_rect = rect;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SequenceBooleanExpression final : public MenuFileParser::sequence_t
|
||||||
|
{
|
||||||
|
static constexpr auto CAPTURE_EXPRESSION = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SequenceBooleanExpression(std::string keyword)
|
||||||
|
{
|
||||||
|
const MenuMatcherFactory create(this);
|
||||||
|
|
||||||
|
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
|
||||||
|
|
||||||
|
AddMatchers({
|
||||||
|
create.KeywordIgnoreCase(std::move(keyword)),
|
||||||
|
create.Or({
|
||||||
|
create.And({
|
||||||
|
create.KeywordIgnoreCase("when"),
|
||||||
|
create.Char('('),
|
||||||
|
create.Label(MenuCommonMatchers::LABEL_EXPRESSION).Capture(CAPTURE_EXPRESSION),
|
||||||
|
create.Char(')')
|
||||||
|
}),
|
||||||
|
create.Label(MenuCommonMatchers::LABEL_EXPRESSION)
|
||||||
|
}),
|
||||||
|
create.Char(';')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||||
|
{
|
||||||
|
assert(state->m_current_menu);
|
||||||
|
|
||||||
|
const auto expression = MenuCommonMatchers::ProcessExpression(state, result);
|
||||||
|
|
||||||
|
std::cout << "Evaluated expression!\n";
|
||||||
|
std::cout << " IsStatic: " << expression->IsStatic() << "\n";
|
||||||
|
|
||||||
|
const auto value = expression->Evaluate();
|
||||||
|
if(value.m_type == CommonExpressionValue::Type::DOUBLE)
|
||||||
|
std::cout << " Value: " << value.m_double_value << "\n";
|
||||||
|
else if(value.m_type == CommonExpressionValue::Type::INT)
|
||||||
|
std::cout << " Value: " << value.m_int_value << "\n";
|
||||||
|
else if (value.m_type == CommonExpressionValue::Type::STRING)
|
||||||
|
std::cout << " Value: \"" << *value.m_string_value << "\"\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace menu_properties;
|
using namespace menu_properties;
|
||||||
@ -187,4 +234,6 @@ void MenuPropertySequences::AddSequences(FeatureLevel featureLevel)
|
|||||||
{
|
{
|
||||||
state->m_current_menu->m_text_only_focus = true;
|
state->m_current_menu->m_text_only_focus = true;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
AddSequence(std::make_unique<SequenceBooleanExpression>("visible"));
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits<int>::max()
|
|||||||
static constexpr int CAPTURE_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 1;
|
static constexpr int CAPTURE_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 1;
|
||||||
static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits<int>::max() - 2;
|
static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits<int>::max() - 2;
|
||||||
static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits<int>::max() - 3;
|
static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits<int>::max() - 3;
|
||||||
static constexpr int CAPTURE_OPERATION_TYPE = std::numeric_limits<int>::max() - 4;
|
static constexpr int CAPTURE_BINARY_OPERATION_TYPE = std::numeric_limits<int>::max() - 4;
|
||||||
|
|
||||||
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::ParseOperandArray(const supplier_t* labelSupplier)
|
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::ParseOperandArray(const supplier_t* labelSupplier)
|
||||||
{
|
{
|
||||||
@ -209,7 +209,7 @@ std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Parse
|
|||||||
{
|
{
|
||||||
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_OR);
|
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_OR);
|
||||||
})
|
})
|
||||||
}).Capture(CAPTURE_OPERATION_TYPE);
|
}).Capture(CAPTURE_BINARY_OPERATION_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Evaluation(const supplier_t* labelSupplier)
|
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Evaluation(const supplier_t* labelSupplier)
|
||||||
@ -324,7 +324,7 @@ std::unique_ptr<IEvaluation> CommandsCommonMatchers::ProcessEvaluation(CommandsP
|
|||||||
operands.emplace_back(std::move(firstStatementPart));
|
operands.emplace_back(std::move(firstStatementPart));
|
||||||
|
|
||||||
if (result.PeekAndRemoveIfTag(TAG_EVALUATION_OPERATION) == TAG_EVALUATION_OPERATION)
|
if (result.PeekAndRemoveIfTag(TAG_EVALUATION_OPERATION) == TAG_EVALUATION_OPERATION)
|
||||||
operators.emplace_back(operators.size(), result.NextCapture(CAPTURE_OPERATION_TYPE).OpTypeValue());
|
operators.emplace_back(operators.size(), result.NextCapture(CAPTURE_BINARY_OPERATION_TYPE).OpTypeValue());
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user