mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
Move Menu Expression to Simple Namespace to have generic configurable expressions
This commit is contained in:
parent
4f2a8454a6
commit
38f3d7d10e
@ -1,306 +0,0 @@
|
||||
#include "MenuCommonMatchers.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "MenuMatcherFactory.h"
|
||||
#include "Parsing/Menu/MenuFileLexing.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.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<ISimpleExpression> 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<ISimpleExpression> 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<SimpleExpressionValue>(operandToken.IntegerValue());
|
||||
case SimpleParserValueType::FLOATING_POINT:
|
||||
return std::make_unique<SimpleExpressionValue>(operandToken.FloatingPointValue());
|
||||
case SimpleParserValueType::STRING:
|
||||
return std::make_unique<SimpleExpressionValue>(operandToken.StringValue());
|
||||
case SimpleParserValueType::IDENTIFIER:
|
||||
return std::make_unique<SimpleExpressionValue>(operandToken.IdentifierValue());
|
||||
default:
|
||||
throw ParsingException(TokenPos(), "Unknown operand type @ Operand");
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ISimpleExpression> 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<ISimpleExpression> MenuCommonMatchers::ProcessExpression(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||
{
|
||||
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION)
|
||||
return nullptr;
|
||||
|
||||
std::vector<std::unique_ptr<ISimpleExpression>> operands;
|
||||
std::list<std::pair<unsigned, const SimpleExpressionBinaryOperationType*>> operators;
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::unique_ptr<ISimpleExpression> 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>(SimpleUnaryOperationId::COUNT))
|
||||
throw ParsingException(TokenPos(), "Invalid unary operation id @ Expression");
|
||||
firstStatementPart = std::make_unique<SimpleExpressionUnaryOperation>(SimpleExpressionUnaryOperationType::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>(SimpleBinaryOperationId::COUNT))
|
||||
throw ParsingException(TokenPos(), "Invalid binary operation id @ Expression");
|
||||
|
||||
operators.emplace_back(operators.size(), SimpleExpressionBinaryOperationType::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 SimpleExpressionBinaryOperationType*>& p1, const std::pair<unsigned, const SimpleExpressionBinaryOperationType*>& 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<SimpleExpressionBinaryOperation>(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>(SimpleBinaryOperationId::ADD));
|
||||
}),
|
||||
create.Char('-').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::SUBTRACT));
|
||||
}),
|
||||
create.Char('*').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::MULTIPLY));
|
||||
}),
|
||||
create.Char('/').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::DIVIDE));
|
||||
}),
|
||||
create.Char('%').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::REMAINDER));
|
||||
}),
|
||||
create.Char('&').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::BITWISE_AND));
|
||||
}),
|
||||
create.Char('|').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::SHIFT_RIGHT));
|
||||
}),
|
||||
create.Char('>').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::GREATER_EQUAL_THAN));
|
||||
}),
|
||||
create.Char('<').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::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>(SimpleBinaryOperationId::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>(SimpleUnaryOperationId::NOT));
|
||||
}),
|
||||
create.Char('~').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleUnaryOperationId::BITWISE_NOT));
|
||||
}),
|
||||
create.Char('-').Transform([](const MenuMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(SimpleUnaryOperationId::NEGATIVE));
|
||||
}),
|
||||
}).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);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#include "Parsing/Matcher/AbstractMatcher.h"
|
||||
#include "Parsing/Matcher/MatcherLabel.h"
|
||||
#include "Parsing/Menu/MenuFileParser.h"
|
||||
#include "Parsing/Simple/Expression/ISimpleExpression.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<ISimpleExpression> ProcessExpressionInParenthesis(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||
static std::unique_ptr<ISimpleExpression> ProcessOperand(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||
static std::unique_ptr<ISimpleExpression> ProcessFunctionCall(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<matcher_t> Expression(const supplier_t* labelSupplier);
|
||||
static std::unique_ptr<ISimpleExpression> ProcessExpression(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||
};
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
#include "MenuExpressionMatchers.h"
|
||||
|
||||
#include "MenuMatcherFactory.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h"
|
||||
|
||||
using namespace menu;
|
||||
|
||||
static constexpr int TAG_EXPRESSION_FUNCTION_CALL = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION_EXT + 1;
|
||||
static constexpr int TAG_EXPRESSION_FUNCTION_CALL_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION_EXT + 2;
|
||||
|
||||
static constexpr int CAPTURE_FUNCTION_NAME = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1;
|
||||
|
||||
|
||||
MenuExpressionMatchers::MenuExpressionMatchers()
|
||||
: SimpleExpressionMatchers(true, true, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<SimpleExpressionMatchers::matcher_t> MenuExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const
|
||||
{
|
||||
const MenuMatcherFactory create(labelSupplier);
|
||||
|
||||
return create.Or({
|
||||
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<ISimpleExpression> MenuExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const
|
||||
{
|
||||
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(result));
|
||||
}
|
||||
|
||||
return std::move(functionCall);
|
||||
}
|
18
src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.h
Normal file
18
src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
||||
|
||||
namespace menu
|
||||
{
|
||||
class MenuExpressionMatchers final : public SimpleExpressionMatchers
|
||||
{
|
||||
public:
|
||||
MenuExpressionMatchers();
|
||||
|
||||
protected:
|
||||
std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const override;
|
||||
std::unique_ptr<ISimpleExpression> ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const override;
|
||||
};
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#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,7 +1,7 @@
|
||||
#include "MenuFileReader.h"
|
||||
|
||||
#include "MenuFileLexing.h"
|
||||
#include "MenuFileParser.h"
|
||||
#include "Matcher/MenuExpressionMatchers.h"
|
||||
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
|
||||
#include "Parsing/Impl/DefinesStreamProxy.h"
|
||||
#include "Parsing/Impl/IncludingStreamProxy.h"
|
||||
@ -123,18 +123,9 @@ std::unique_ptr<ParsingResult> MenuFileReader::ReadMenuFile()
|
||||
lexerConfig.m_emit_new_line_tokens = false;
|
||||
lexerConfig.m_read_strings = 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));
|
||||
MenuExpressionMatchers().ApplyTokensToLexerConfig(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);
|
||||
|
||||
if (!parser->Parse())
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "Generic/GenericStringPropertySequence.h"
|
||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h"
|
||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h"
|
||||
#include "Parsing/Menu/Matcher/MenuCommonMatchers.h"
|
||||
#include "Parsing/Menu/Matcher/MenuExpressionMatchers.h"
|
||||
#include "Parsing/Menu/Matcher/MenuMatcherFactory.h"
|
||||
#include "Parsing/Menu/Matcher/MenuMatcherScriptInt.h"
|
||||
#include "Parsing/Menu/Matcher/MenuMatcherScriptNumeric.h"
|
||||
@ -326,8 +326,9 @@ namespace menu::event_handler_set_scope_sequences
|
||||
SequenceSetLocalVar()
|
||||
{
|
||||
const ScriptMatcherFactory create(this);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
|
||||
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
|
||||
AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION);
|
||||
|
||||
AddMatchers({
|
||||
create.Or({
|
||||
@ -337,7 +338,7 @@ namespace menu::event_handler_set_scope_sequences
|
||||
create.ScriptKeyword("setLocalVarString").Tag(TAG_STRING)
|
||||
}),
|
||||
create.ScriptText().Capture(CAPTURE_VAR_NAME),
|
||||
create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
|
||||
create.Label(MenuExpressionMatchers::LABEL_EXPRESSION),
|
||||
create.Optional(create.Char(';'))
|
||||
});
|
||||
}
|
||||
@ -420,10 +421,12 @@ namespace menu::event_handler_set_scope_sequences
|
||||
protected:
|
||||
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||
{
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
|
||||
const auto typeTag = static_cast<SetLocalVarType>(result.NextTag());
|
||||
const auto& varNameToken = result.NextCapture(CAPTURE_VAR_NAME);
|
||||
const auto& varName = MenuMatcherFactory::TokenTextValue(varNameToken);
|
||||
auto expression = MenuCommonMatchers::ProcessExpression(state, result);
|
||||
auto expression = expressionMatchers.ProcessExpression(result);
|
||||
|
||||
if (!expression)
|
||||
throw ParsingException(varNameToken.GetPos(), "No expression");
|
||||
@ -443,13 +446,14 @@ namespace menu::event_handler_set_scope_sequences
|
||||
SequenceIf()
|
||||
{
|
||||
const ScriptMatcherFactory create(this);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
|
||||
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
|
||||
AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION);
|
||||
|
||||
AddMatchers({
|
||||
create.Keyword("if").Capture(CAPTURE_KEYWORD),
|
||||
create.Char('('),
|
||||
create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
|
||||
create.Label(MenuExpressionMatchers::LABEL_EXPRESSION),
|
||||
create.Char(')'),
|
||||
create.Char('{')
|
||||
});
|
||||
@ -458,7 +462,8 @@ namespace menu::event_handler_set_scope_sequences
|
||||
protected:
|
||||
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||
{
|
||||
auto expression = MenuCommonMatchers::ProcessExpression(state, result);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
auto expression = expressionMatchers.ProcessExpression(result);
|
||||
|
||||
if (!expression)
|
||||
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression");
|
||||
@ -485,14 +490,15 @@ namespace menu::event_handler_set_scope_sequences
|
||||
SequenceElseIf()
|
||||
{
|
||||
const ScriptMatcherFactory create(this);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
|
||||
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
|
||||
AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION);
|
||||
|
||||
AddMatchers({
|
||||
create.Char('}'),
|
||||
create.Keyword("elseif").Capture(CAPTURE_KEYWORD),
|
||||
create.Char('('),
|
||||
create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
|
||||
create.Label(MenuExpressionMatchers::LABEL_EXPRESSION),
|
||||
create.Char(')'),
|
||||
create.Char('{')
|
||||
});
|
||||
@ -501,7 +507,8 @@ namespace menu::event_handler_set_scope_sequences
|
||||
protected:
|
||||
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||
{
|
||||
auto expression = MenuCommonMatchers::ProcessExpression(state, result);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
auto expression = expressionMatchers.ProcessExpression(result);
|
||||
|
||||
if (!expression)
|
||||
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression");
|
||||
@ -539,8 +546,9 @@ namespace menu::event_handler_set_scope_sequences
|
||||
SequenceElse()
|
||||
{
|
||||
const ScriptMatcherFactory create(this);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
|
||||
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
|
||||
AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION);
|
||||
|
||||
AddMatchers({
|
||||
create.Char('}'),
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Parsing/Menu/Matcher/MenuCommonMatchers.h"
|
||||
#include "Parsing/Menu/Matcher/MenuExpressionMatchers.h"
|
||||
#include "Parsing/Menu/Matcher/MenuMatcherFactory.h"
|
||||
|
||||
using namespace menu;
|
||||
@ -10,7 +10,8 @@ using namespace menu;
|
||||
GenericExpressionPropertySequence::GenericExpressionPropertySequence(callback_t setCallback)
|
||||
: m_set_callback(std::move(setCallback))
|
||||
{
|
||||
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION);
|
||||
}
|
||||
|
||||
std::unique_ptr<GenericExpressionPropertySequence> GenericExpressionPropertySequence::WithKeyword(std::string keyword, callback_t setCallback)
|
||||
@ -20,7 +21,7 @@ std::unique_ptr<GenericExpressionPropertySequence> GenericExpressionPropertySequ
|
||||
const MenuMatcherFactory create(result.get());
|
||||
result->AddMatchers({
|
||||
create.KeywordIgnoreCase(std::move(keyword)).Capture(CAPTURE_FIRST_TOKEN),
|
||||
create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
|
||||
create.Label(MenuExpressionMatchers::LABEL_EXPRESSION),
|
||||
create.Optional(create.Char(';'))
|
||||
});
|
||||
|
||||
@ -38,7 +39,7 @@ std::unique_ptr<GenericExpressionPropertySequence> GenericExpressionPropertySequ
|
||||
|
||||
result->AddMatchers({
|
||||
create.And(std::move(keywordMatchers)).Capture(CAPTURE_FIRST_TOKEN),
|
||||
create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
|
||||
create.Label(MenuExpressionMatchers::LABEL_EXPRESSION),
|
||||
create.Optional(create.Char(';'))
|
||||
});
|
||||
|
||||
@ -56,10 +57,10 @@ std::unique_ptr<GenericExpressionPropertySequence> GenericExpressionPropertySequ
|
||||
create.And({
|
||||
create.KeywordIgnoreCase("when"),
|
||||
create.Char('('),
|
||||
create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
|
||||
create.Label(MenuExpressionMatchers::LABEL_EXPRESSION),
|
||||
create.Char(')')
|
||||
}),
|
||||
create.Label(MenuCommonMatchers::LABEL_EXPRESSION)
|
||||
create.Label(MenuExpressionMatchers::LABEL_EXPRESSION)
|
||||
}),
|
||||
create.Optional(create.Char(';'))
|
||||
});
|
||||
@ -71,7 +72,8 @@ void GenericExpressionPropertySequence::ProcessMatch(MenuFileParserState* state,
|
||||
{
|
||||
if (m_set_callback)
|
||||
{
|
||||
auto expression = MenuCommonMatchers::ProcessExpression(state, result);
|
||||
const MenuExpressionMatchers expressionMatchers;
|
||||
auto expression = expressionMatchers.ProcessExpression(result);
|
||||
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(expression));
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "Generic/GenericStringPropertySequence.h"
|
||||
#include "Parsing/Menu/Matcher/MenuMatcherFactory.h"
|
||||
#include "Parsing/Menu/Domain/CommonMenuTypes.h"
|
||||
#include "Parsing/Menu/Matcher/MenuCommonMatchers.h"
|
||||
#include "Parsing/Menu/Matcher/MenuExpressionMatchers.h"
|
||||
|
||||
using namespace menu;
|
||||
|
||||
|
@ -3,7 +3,52 @@
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include "AbstractParser.h"
|
||||
#include "ParserSingleInputStream.h"
|
||||
#include "Parsing/ParsingException.h"
|
||||
#include "Parsing/Simple/SimpleLexer.h"
|
||||
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||
|
||||
class DefinesIfDirectiveParsingState
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<ISimpleExpression> m_expression;
|
||||
};
|
||||
|
||||
class DefinesIfDirectiveParser final : public AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>
|
||||
{
|
||||
protected:
|
||||
explicit DefinesIfDirectiveParser(ILexer<SimpleParserValue>* lexer)
|
||||
: AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>(lexer, std::make_unique<DefinesIfDirectiveParsingState>())
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<sequence_t*>& GetTestsForState() override
|
||||
{
|
||||
static std::vector<sequence_t*> sequences
|
||||
{
|
||||
};
|
||||
return sequences;
|
||||
}
|
||||
|
||||
public:
|
||||
static bool EvaluateIfDirective(std::map<std::string, DefinesStreamProxy::Define>& defines, const std::string& value)
|
||||
{
|
||||
std::istringstream ss(value);
|
||||
ParserSingleInputStream inputStream(ss, "");
|
||||
SimpleLexer::Config config{};
|
||||
config.m_emit_new_line_tokens = false;
|
||||
config.m_read_numbers = true;
|
||||
config.m_read_strings = false;
|
||||
SimpleLexer lexer(&inputStream, std::move(config));
|
||||
DefinesIfDirectiveParser parser(&lexer);
|
||||
if (!parser.Parse())
|
||||
return false;
|
||||
|
||||
const auto& expression = parser.m_state->m_expression;
|
||||
return expression->IsStatic() && expression->Evaluate().IsTruthy();
|
||||
}
|
||||
};
|
||||
|
||||
DefinesStreamProxy::DefineParameterPosition::DefineParameterPosition()
|
||||
: m_parameter_index(0u),
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <sstream>
|
||||
|
||||
@ -44,7 +44,7 @@ public:
|
||||
|
||||
private:
|
||||
IParserLineStream* const m_stream;
|
||||
std::unordered_map<std::string, Define> m_defines;
|
||||
std::map<std::string, Define> m_defines;
|
||||
std::stack<bool> m_modes;
|
||||
unsigned m_ignore_depth;
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "MatcherAnd.h"
|
||||
#include "MatcherLabel.h"
|
||||
#include "MatcherLoop.h"
|
||||
#include "MatcherFalse.h"
|
||||
#include "MatcherTrue.h"
|
||||
#include "MatcherOptional.h"
|
||||
#include "MatcherOr.h"
|
||||
#include "Parsing/IParserValue.h"
|
||||
@ -85,6 +87,16 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
_NODISCARD MatcherFactoryWrapper<TokenType> False() const
|
||||
{
|
||||
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherFalse<TokenType>>());
|
||||
}
|
||||
|
||||
_NODISCARD MatcherFactoryWrapper<TokenType> True() const
|
||||
{
|
||||
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherTrue<TokenType>>());
|
||||
}
|
||||
|
||||
_NODISCARD MatcherFactoryWrapper<TokenType> And(std::initializer_list<Movable<std::unique_ptr<AbstractMatcher<TokenType>>>> matchers) const
|
||||
{
|
||||
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherAnd<TokenType>>(matchers));
|
||||
|
23
src/Parser/Parsing/Matcher/MatcherFalse.h
Normal file
23
src/Parser/Parsing/Matcher/MatcherFalse.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Parsing/IParserValue.h"
|
||||
#include "AbstractMatcher.h"
|
||||
|
||||
template <typename TokenType>
|
||||
class MatcherFalse final : public AbstractMatcher<TokenType>
|
||||
{
|
||||
// TokenType must inherit IParserValue
|
||||
static_assert(std::is_base_of<IParserValue, TokenType>::value);
|
||||
|
||||
protected:
|
||||
MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, unsigned tokenOffset) override
|
||||
{
|
||||
return MatcherResult<TokenType>::NoMatch();
|
||||
}
|
||||
|
||||
public:
|
||||
MatcherFalse()
|
||||
= default;
|
||||
};
|
23
src/Parser/Parsing/Matcher/MatcherTrue.h
Normal file
23
src/Parser/Parsing/Matcher/MatcherTrue.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Parsing/IParserValue.h"
|
||||
#include "AbstractMatcher.h"
|
||||
|
||||
template <typename TokenType>
|
||||
class MatcherTrue final : public AbstractMatcher<TokenType>
|
||||
{
|
||||
// TokenType must inherit IParserValue
|
||||
static_assert(std::is_base_of<IParserValue, TokenType>::value);
|
||||
|
||||
protected:
|
||||
MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, unsigned tokenOffset) override
|
||||
{
|
||||
return MatcherResult<TokenType>::Match(0);
|
||||
}
|
||||
|
||||
public:
|
||||
MatcherTrue()
|
||||
= default;
|
||||
};
|
@ -3,14 +3,17 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
SimpleExpressionBinaryOperationType::SimpleExpressionBinaryOperationType(std::string syntax, const SimpleOperationPrecedence precedence, evaluation_function_t evaluationFunction)
|
||||
: m_syntax(std::move(syntax)),
|
||||
SimpleExpressionBinaryOperationType::SimpleExpressionBinaryOperationType(const SimpleBinaryOperationId id, std::string syntax, const SimpleOperationPrecedence precedence,
|
||||
evaluation_function_t evaluationFunction)
|
||||
: m_id(id),
|
||||
m_syntax(std::move(syntax)),
|
||||
m_precedence(precedence),
|
||||
m_evaluation_function(std::move(evaluationFunction))
|
||||
{
|
||||
}
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_ADD(
|
||||
SimpleBinaryOperationId::ADD,
|
||||
"+",
|
||||
SimpleOperationPrecedence::ADDITION_SUBTRACTION,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -48,6 +51,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SUBTRACT(
|
||||
SimpleBinaryOperationId::SUBTRACT,
|
||||
"-",
|
||||
SimpleOperationPrecedence::ADDITION_SUBTRACTION,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -72,6 +76,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_MULTIPLY(
|
||||
SimpleBinaryOperationId::MULTIPLY,
|
||||
"*",
|
||||
SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -96,6 +101,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_DIVIDE(
|
||||
SimpleBinaryOperationId::DIVIDE,
|
||||
"/",
|
||||
SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -120,6 +126,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_REMAINDER(
|
||||
SimpleBinaryOperationId::REMAINDER,
|
||||
"%",
|
||||
SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -132,6 +139,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_BITWISE_AND(
|
||||
SimpleBinaryOperationId::BITWISE_AND,
|
||||
"&",
|
||||
SimpleOperationPrecedence::BITWISE_AND,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -144,6 +152,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_BITWISE_OR(
|
||||
SimpleBinaryOperationId::BITWISE_OR,
|
||||
"|",
|
||||
SimpleOperationPrecedence::BITWISE_OR,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -156,6 +165,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SHIFT_LEFT(
|
||||
SimpleBinaryOperationId::SHIFT_LEFT,
|
||||
"<<",
|
||||
SimpleOperationPrecedence::BITWISE_SHIFT,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -168,6 +178,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SHIFT_RIGHT(
|
||||
SimpleBinaryOperationId::SHIFT_RIGHT,
|
||||
">>",
|
||||
SimpleOperationPrecedence::BITWISE_SHIFT,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -180,6 +191,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_GREATER_THAN(
|
||||
SimpleBinaryOperationId::GREATER_THAN,
|
||||
">",
|
||||
SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -207,6 +219,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_GREATER_EQUAL_THAN(
|
||||
SimpleBinaryOperationId::GREATER_EQUAL_THAN,
|
||||
">=",
|
||||
SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -234,6 +247,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_LESS_THAN(
|
||||
SimpleBinaryOperationId::LESS_THAN,
|
||||
"<",
|
||||
SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -261,6 +275,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_LESS_EQUAL_THAN(
|
||||
SimpleBinaryOperationId::LESS_EQUAL_THAN,
|
||||
"<=",
|
||||
SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -288,6 +303,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_EQUALS(
|
||||
SimpleBinaryOperationId::EQUALS,
|
||||
"==",
|
||||
SimpleOperationPrecedence::RELATIONAL_EQUALS,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -325,6 +341,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_NOT_EQUAL(
|
||||
SimpleBinaryOperationId::NOT_EQUAL,
|
||||
"!=",
|
||||
SimpleOperationPrecedence::RELATIONAL_EQUALS,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -362,6 +379,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_AND(
|
||||
SimpleBinaryOperationId::AND,
|
||||
"&&",
|
||||
SimpleOperationPrecedence::LOGICAL_AND,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
@ -373,6 +391,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O
|
||||
);
|
||||
|
||||
const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_OR(
|
||||
SimpleBinaryOperationId::OR,
|
||||
"||",
|
||||
SimpleOperationPrecedence::LOGICAL_OR,
|
||||
[](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue
|
||||
|
@ -49,12 +49,13 @@ class SimpleExpressionBinaryOperationType
|
||||
public:
|
||||
using evaluation_function_t = std::function<SimpleExpressionValue(const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2)>;
|
||||
|
||||
SimpleBinaryOperationId m_id;
|
||||
std::string m_syntax;
|
||||
SimpleOperationPrecedence m_precedence;
|
||||
evaluation_function_t m_evaluation_function;
|
||||
|
||||
private:
|
||||
SimpleExpressionBinaryOperationType(std::string syntax, SimpleOperationPrecedence precedence, evaluation_function_t evaluationFunction);
|
||||
SimpleExpressionBinaryOperationType(SimpleBinaryOperationId id, std::string syntax, SimpleOperationPrecedence precedence, evaluation_function_t evaluationFunction);
|
||||
|
||||
public:
|
||||
static const SimpleExpressionBinaryOperationType OPERATION_ADD;
|
||||
|
@ -0,0 +1,316 @@
|
||||
#include "SimpleExpressionMatchers.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h"
|
||||
|
||||
static constexpr int TAG_EXPRESSION = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 1;
|
||||
static constexpr int TAG_OPERAND = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 2;
|
||||
static constexpr int TAG_UNARY_OPERATION = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 3;
|
||||
static constexpr int TAG_PARENTHESIS = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 4;
|
||||
static constexpr int TAG_PARENTHESIS_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 5;
|
||||
static constexpr int TAG_BINARY_OPERATION = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 6;
|
||||
static constexpr int TAG_OPERAND_EXT = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 7;
|
||||
static constexpr int TAG_OPERAND_EXT_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 8;
|
||||
|
||||
static constexpr int CAPTURE_OPERAND = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 1;
|
||||
static constexpr int CAPTURE_UNARY_OPERATION_TYPE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 2;
|
||||
static constexpr int CAPTURE_BINARY_OPERATION_TYPE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 3;
|
||||
|
||||
SimpleExpressionMatchers::SimpleExpressionMatchers()
|
||||
: SimpleExpressionMatchers(true, true, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
SimpleExpressionMatchers::SimpleExpressionMatchers(const bool enableStringOperands, const bool enableIdentifierOperands, const bool enableFloatingPointOperands, const bool enableIntOperands)
|
||||
: m_enable_string_operands(enableStringOperands),
|
||||
m_enable_identifier_operands(enableIdentifierOperands),
|
||||
m_enable_floating_point_operands(enableFloatingPointOperands),
|
||||
m_enable_int_operands(enableIntOperands)
|
||||
{
|
||||
}
|
||||
|
||||
SimpleExpressionMatchers::~SimpleExpressionMatchers()
|
||||
= default;
|
||||
|
||||
void SimpleExpressionMatchers::ApplyTokensToLexerConfig(SimpleLexer::Config& lexerConfig)
|
||||
{
|
||||
for (const auto* unaryOperation : SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES)
|
||||
{
|
||||
if (unaryOperation->m_syntax.size() <= 1)
|
||||
continue;
|
||||
|
||||
lexerConfig.m_multi_character_tokens.emplace_back(MULTI_TOKEN_OFFSET_UNARY + static_cast<int>(unaryOperation->m_id), unaryOperation->m_syntax);
|
||||
}
|
||||
|
||||
for (const auto* binaryOperation : SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES)
|
||||
{
|
||||
if (binaryOperation->m_syntax.size() <= 1)
|
||||
continue;
|
||||
|
||||
lexerConfig.m_multi_character_tokens.emplace_back(MULTI_TOKEN_OFFSET_BINARY + static_cast<int>(binaryOperation->m_id), binaryOperation->m_syntax);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const SimpleExpressionUnaryOperationType*> SimpleExpressionMatchers::EnabledUnaryOperations() const
|
||||
{
|
||||
return std::vector(&SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES[0],
|
||||
&SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES[std::extent_v<decltype(SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES)>]);
|
||||
}
|
||||
|
||||
std::vector<const SimpleExpressionBinaryOperationType*> SimpleExpressionMatchers::EnabledBinaryOperations() const
|
||||
{
|
||||
return std::vector(&SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES[0],
|
||||
&SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES[std::extent_v<decltype(SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES)>]);
|
||||
}
|
||||
|
||||
std::unique_ptr<ISimpleExpression> SimpleExpressionMatchers::ProcessExpressionInParenthesis(SequenceResult<SimpleParserValue>& result) const
|
||||
{
|
||||
auto processedEvaluation = ProcessExpression(result);
|
||||
|
||||
if (result.PeekAndRemoveIfTag(TAG_PARENTHESIS_END) != TAG_PARENTHESIS_END)
|
||||
throw ParsingException(TokenPos(), "Expected parenthesis end tag @ ExpressionInParenthesis");
|
||||
|
||||
return processedEvaluation;
|
||||
}
|
||||
|
||||
std::unique_ptr<ISimpleExpression> SimpleExpressionMatchers::ProcessOperand(SequenceResult<SimpleParserValue>& result) const
|
||||
{
|
||||
const auto& operandToken = result.NextCapture(CAPTURE_OPERAND);
|
||||
|
||||
switch (operandToken.m_type)
|
||||
{
|
||||
case SimpleParserValueType::INTEGER:
|
||||
return std::make_unique<SimpleExpressionValue>(operandToken.IntegerValue());
|
||||
case SimpleParserValueType::FLOATING_POINT:
|
||||
return std::make_unique<SimpleExpressionValue>(operandToken.FloatingPointValue());
|
||||
case SimpleParserValueType::STRING:
|
||||
return std::make_unique<SimpleExpressionValue>(operandToken.StringValue());
|
||||
case SimpleParserValueType::IDENTIFIER:
|
||||
return std::make_unique<SimpleExpressionValue>(operandToken.IdentifierValue());
|
||||
default:
|
||||
throw ParsingException(TokenPos(), "Unknown operand type @ Operand");
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ISimpleExpression> SimpleExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<ISimpleExpression> SimpleExpressionMatchers::ProcessExpression(SequenceResult<SimpleParserValue>& result) const
|
||||
{
|
||||
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION)
|
||||
return nullptr;
|
||||
|
||||
std::vector<std::unique_ptr<ISimpleExpression>> operands;
|
||||
std::list<std::pair<unsigned, const SimpleExpressionBinaryOperationType*>> operators;
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::unique_ptr<ISimpleExpression> firstStatementPart;
|
||||
std::vector<int> unaryOperations;
|
||||
auto nextTag = result.NextTag();
|
||||
|
||||
while (nextTag == TAG_UNARY_OPERATION)
|
||||
{
|
||||
unaryOperations.push_back(result.NextCapture(CAPTURE_UNARY_OPERATION_TYPE).IntegerValue());
|
||||
nextTag = result.NextTag();
|
||||
}
|
||||
|
||||
switch (nextTag)
|
||||
{
|
||||
case TAG_PARENTHESIS:
|
||||
firstStatementPart = ProcessExpressionInParenthesis(result);
|
||||
break;
|
||||
|
||||
case TAG_OPERAND:
|
||||
firstStatementPart = ProcessOperand(result);
|
||||
break;
|
||||
|
||||
case TAG_OPERAND_EXT:
|
||||
firstStatementPart = ProcessOperandExtension(result);
|
||||
if (result.PeekAndRemoveIfTag(TAG_OPERAND_EXT_END) != TAG_OPERAND_EXT_END)
|
||||
throw ParsingException(TokenPos(), "Unclosed operand extension @ Expression");
|
||||
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>(SimpleUnaryOperationId::COUNT))
|
||||
throw ParsingException(TokenPos(), "Invalid unary operation id @ Expression");
|
||||
firstStatementPart = std::make_unique<SimpleExpressionUnaryOperation>(SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES[operationIndex],
|
||||
std::move(firstStatementPart));
|
||||
}
|
||||
|
||||
operands.emplace_back(std::move(firstStatementPart));
|
||||
|
||||
if (result.PeekAndRemoveIfTag(TAG_BINARY_OPERATION) == TAG_BINARY_OPERATION)
|
||||
{
|
||||
const auto operationIndex = result.NextCapture(CAPTURE_BINARY_OPERATION_TYPE).IntegerValue();
|
||||
if (operationIndex < 0 || operationIndex >= static_cast<int>(SimpleBinaryOperationId::COUNT))
|
||||
throw ParsingException(TokenPos(), "Invalid binary operation id @ Expression");
|
||||
|
||||
operators.emplace_back(operators.size(), SimpleExpressionBinaryOperationType::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 SimpleExpressionBinaryOperationType*>& p1, const std::pair<unsigned, const SimpleExpressionBinaryOperationType*>& 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<SimpleExpressionBinaryOperation>(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<SimpleExpressionMatchers::matcher_t> SimpleExpressionMatchers::ParseOperand(const supplier_t* labelSupplier) const
|
||||
{
|
||||
const SimpleMatcherFactory create(labelSupplier);
|
||||
|
||||
std::vector<std::unique_ptr<matcher_t>> operandMatchers;
|
||||
operandMatchers.reserve(4);
|
||||
|
||||
if (m_enable_string_operands)
|
||||
operandMatchers.emplace_back(create.String());
|
||||
|
||||
if (m_enable_identifier_operands)
|
||||
operandMatchers.emplace_back(create.Identifier());
|
||||
|
||||
if (m_enable_floating_point_operands)
|
||||
operandMatchers.emplace_back(create.FloatingPoint());
|
||||
|
||||
if (m_enable_int_operands)
|
||||
operandMatchers.emplace_back(create.Integer());
|
||||
|
||||
return create.Or(std::move(operandMatchers)).Tag(TAG_OPERAND).Capture(CAPTURE_OPERAND);
|
||||
}
|
||||
|
||||
std::unique_ptr<SimpleExpressionMatchers::matcher_t> SimpleExpressionMatchers::ParseBinaryOperationType(const supplier_t* labelSupplier) const
|
||||
{
|
||||
const SimpleMatcherFactory create(labelSupplier);
|
||||
|
||||
const auto enabledBinaryOperations = EnabledBinaryOperations();
|
||||
std::vector<std::unique_ptr<matcher_t>> binaryOperationsMatchers;
|
||||
binaryOperationsMatchers.reserve(enabledBinaryOperations.size());
|
||||
|
||||
for (const auto* enabledBinaryOperation : enabledBinaryOperations)
|
||||
{
|
||||
if (enabledBinaryOperation->m_syntax.size() > 1)
|
||||
{
|
||||
binaryOperationsMatchers.emplace_back(
|
||||
create.MultiChar(MULTI_TOKEN_OFFSET_BINARY + static_cast<int>(enabledBinaryOperation->m_id))
|
||||
.Transform([enabledBinaryOperation](const SimpleMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(enabledBinaryOperation->m_id));
|
||||
}));
|
||||
}
|
||||
else if (!enabledBinaryOperation->m_syntax.empty())
|
||||
{
|
||||
binaryOperationsMatchers.emplace_back(
|
||||
create.Char(enabledBinaryOperation->m_syntax[0])
|
||||
.Transform([enabledBinaryOperation](const SimpleMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(enabledBinaryOperation->m_id));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
return create.Or(std::move(binaryOperationsMatchers)).Capture(CAPTURE_BINARY_OPERATION_TYPE);
|
||||
}
|
||||
|
||||
std::unique_ptr<SimpleExpressionMatchers::matcher_t> SimpleExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const
|
||||
{
|
||||
const SimpleMatcherFactory create(labelSupplier);
|
||||
|
||||
return create.False();
|
||||
}
|
||||
|
||||
std::unique_ptr<SimpleExpressionMatchers::matcher_t> SimpleExpressionMatchers::ParseUnaryOperationType(const supplier_t* labelSupplier) const
|
||||
{
|
||||
const SimpleMatcherFactory create(labelSupplier);
|
||||
|
||||
const auto enabledUnaryOperations = EnabledUnaryOperations();
|
||||
std::vector<std::unique_ptr<matcher_t>> unaryOperationsMatchers;
|
||||
unaryOperationsMatchers.reserve(enabledUnaryOperations.size());
|
||||
|
||||
for (const auto* enabledUnaryOperation : enabledUnaryOperations)
|
||||
{
|
||||
if (enabledUnaryOperation->m_syntax.size() > 1)
|
||||
{
|
||||
unaryOperationsMatchers.emplace_back(
|
||||
create.MultiChar(MULTI_TOKEN_OFFSET_UNARY + static_cast<int>(enabledUnaryOperation->m_id))
|
||||
.Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(enabledUnaryOperation->m_id));
|
||||
}));
|
||||
}
|
||||
else if (!enabledUnaryOperation->m_syntax.empty())
|
||||
{
|
||||
unaryOperationsMatchers.emplace_back(
|
||||
create.Char(enabledUnaryOperation->m_syntax[0])
|
||||
.Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values)
|
||||
{
|
||||
return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast<int>(enabledUnaryOperation->m_id));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
return create.Or(std::move(unaryOperationsMatchers)).Tag(TAG_UNARY_OPERATION).Capture(CAPTURE_UNARY_OPERATION_TYPE);
|
||||
}
|
||||
|
||||
std::unique_ptr<SimpleExpressionMatchers::matcher_t> SimpleExpressionMatchers::Expression(const supplier_t* labelSupplier) const
|
||||
{
|
||||
const SimpleMatcherFactory create(labelSupplier);
|
||||
|
||||
return create.And({
|
||||
create.OptionalLoop(ParseUnaryOperationType(labelSupplier)),
|
||||
create.Or({
|
||||
create.And({
|
||||
create.Char('('),
|
||||
create.Label(LABEL_EXPRESSION),
|
||||
create.Char(')').Tag(TAG_PARENTHESIS_END)
|
||||
}).Tag(TAG_PARENTHESIS),
|
||||
create.And({
|
||||
create.True().Tag(TAG_OPERAND_EXT),
|
||||
ParseOperandExtension(labelSupplier),
|
||||
create.True().Tag(TAG_OPERAND_EXT_END)
|
||||
}),
|
||||
ParseOperand(labelSupplier)
|
||||
}),
|
||||
create.Optional(create.And({
|
||||
ParseBinaryOperationType(labelSupplier),
|
||||
create.Label(LABEL_EXPRESSION)
|
||||
}).Tag(TAG_BINARY_OPERATION))
|
||||
}).Tag(TAG_EXPRESSION);
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "SimpleExpressionBinaryOperation.h"
|
||||
#include "SimpleExpressionUnaryOperation.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Parsing/Matcher/AbstractMatcher.h"
|
||||
#include "Parsing/Matcher/MatcherLabel.h"
|
||||
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||
#include "Parsing/Sequence/SequenceResult.h"
|
||||
#include "Parsing/Simple/SimpleParserValue.h"
|
||||
#include <Parsing/Simple/SimpleLexer.h>
|
||||
|
||||
class SimpleExpressionMatchers
|
||||
{
|
||||
public:
|
||||
using matcher_t = AbstractMatcher<SimpleParserValue>;
|
||||
typedef IMatcherForLabelSupplier<SimpleParserValue> supplier_t;
|
||||
|
||||
static constexpr auto CAPTURE_OFFSET_EXPRESSION = 7000;
|
||||
static constexpr auto TAG_OFFSET_EXPRESSION = 7000;
|
||||
static constexpr auto CAPTURE_OFFSET_EXPRESSION_EXT = 8000;
|
||||
static constexpr auto TAG_OFFSET_EXPRESSION_EXT = 8000;
|
||||
static constexpr auto LABEL_EXPRESSION = 7000;
|
||||
static constexpr auto MULTI_TOKEN_OFFSET_UNARY = 700;
|
||||
static constexpr auto MULTI_TOKEN_OFFSET_BINARY = 720;
|
||||
|
||||
private:
|
||||
bool m_enable_string_operands;
|
||||
bool m_enable_identifier_operands;
|
||||
bool m_enable_floating_point_operands;
|
||||
bool m_enable_int_operands;
|
||||
|
||||
public:
|
||||
SimpleExpressionMatchers();
|
||||
virtual ~SimpleExpressionMatchers();
|
||||
SimpleExpressionMatchers(const SimpleExpressionMatchers& other) = default;
|
||||
SimpleExpressionMatchers(SimpleExpressionMatchers&& other) noexcept = default;
|
||||
SimpleExpressionMatchers& operator=(const SimpleExpressionMatchers& other) = default;
|
||||
SimpleExpressionMatchers& operator=(SimpleExpressionMatchers&& other) noexcept = default;
|
||||
|
||||
protected:
|
||||
SimpleExpressionMatchers(bool enableStringOperands, bool enableIdentifierOperands, bool enableFloatingPointOperands, bool enableIntOperands);
|
||||
|
||||
virtual std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const;
|
||||
virtual std::unique_ptr<ISimpleExpression> ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const;
|
||||
|
||||
_NODISCARD virtual std::vector<const SimpleExpressionUnaryOperationType*> EnabledUnaryOperations() const;
|
||||
_NODISCARD virtual std::vector<const SimpleExpressionBinaryOperationType*> EnabledBinaryOperations() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<matcher_t> ParseBinaryOperationType(const supplier_t* labelSupplier) const;
|
||||
std::unique_ptr<matcher_t> ParseOperand(const supplier_t* labelSupplier) const;
|
||||
std::unique_ptr<matcher_t> ParseUnaryOperationType(const supplier_t* labelSupplier) const;
|
||||
|
||||
std::unique_ptr<ISimpleExpression> ProcessExpressionInParenthesis(SequenceResult<SimpleParserValue>& result) const;
|
||||
std::unique_ptr<ISimpleExpression> ProcessOperand(SequenceResult<SimpleParserValue>& result) const;
|
||||
|
||||
public:
|
||||
std::unique_ptr<matcher_t> Expression(const supplier_t* labelSupplier) const;
|
||||
std::unique_ptr<ISimpleExpression> ProcessExpression(SequenceResult<SimpleParserValue>& result) const;
|
||||
|
||||
virtual void ApplyTokensToLexerConfig(SimpleLexer::Config& lexerConfig);
|
||||
};
|
@ -4,13 +4,15 @@
|
||||
|
||||
#include "SimpleExpressionBinaryOperation.h"
|
||||
|
||||
SimpleExpressionUnaryOperationType::SimpleExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction)
|
||||
: m_syntax(std::move(syntax)),
|
||||
SimpleExpressionUnaryOperationType::SimpleExpressionUnaryOperationType(const SimpleUnaryOperationId id, std::string syntax, evaluation_function_t evaluationFunction)
|
||||
: m_id(id),
|
||||
m_syntax(std::move(syntax)),
|
||||
m_evaluation_function(std::move(evaluationFunction))
|
||||
{
|
||||
}
|
||||
|
||||
const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPERATION_NOT(
|
||||
SimpleUnaryOperationId::NOT,
|
||||
"!",
|
||||
[](const SimpleExpressionValue& operand) -> SimpleExpressionValue
|
||||
{
|
||||
@ -19,10 +21,11 @@ const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPE
|
||||
);
|
||||
|
||||
const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPERATION_BITWISE_NOT(
|
||||
SimpleUnaryOperationId::BITWISE_NOT,
|
||||
"~",
|
||||
[](const SimpleExpressionValue& operand) -> SimpleExpressionValue
|
||||
{
|
||||
if(operand.m_type == SimpleExpressionValue::Type::INT)
|
||||
if (operand.m_type == SimpleExpressionValue::Type::INT)
|
||||
return SimpleExpressionValue(~operand.m_int_value);
|
||||
|
||||
return SimpleExpressionValue(0);
|
||||
@ -30,10 +33,11 @@ const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPE
|
||||
);
|
||||
|
||||
const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPERATION_NEGATIVE(
|
||||
SimpleUnaryOperationId::NEGATIVE,
|
||||
"-",
|
||||
[](const SimpleExpressionValue& operand) -> SimpleExpressionValue
|
||||
{
|
||||
if(operand.m_type == SimpleExpressionValue::Type::INT)
|
||||
if (operand.m_type == SimpleExpressionValue::Type::INT)
|
||||
return SimpleExpressionValue(-operand.m_int_value);
|
||||
if (operand.m_type == SimpleExpressionValue::Type::DOUBLE)
|
||||
return SimpleExpressionValue(-operand.m_double_value);
|
||||
|
@ -21,11 +21,12 @@ class SimpleExpressionUnaryOperationType
|
||||
public:
|
||||
using evaluation_function_t = std::function<SimpleExpressionValue(const SimpleExpressionValue& operand)>;
|
||||
|
||||
SimpleUnaryOperationId m_id;
|
||||
std::string m_syntax;
|
||||
evaluation_function_t m_evaluation_function;
|
||||
|
||||
private:
|
||||
SimpleExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction);
|
||||
SimpleExpressionUnaryOperationType(SimpleUnaryOperationId id, std::string syntax, evaluation_function_t evaluationFunction);
|
||||
|
||||
public:
|
||||
static const SimpleExpressionUnaryOperationType OPERATION_NOT;
|
||||
|
@ -9,7 +9,7 @@ class SimpleMatcherFactory : public AbstractMatcherFactory<SimpleParserValue>
|
||||
{
|
||||
public:
|
||||
explicit SimpleMatcherFactory(const IMatcherForLabelSupplier<SimpleParserValue>* labelSupplier);
|
||||
|
||||
|
||||
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> Type(SimpleParserValueType type) const;
|
||||
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> Keyword(std::string value) const;
|
||||
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> KeywordIgnoreCase(std::string value) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user