mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 15:52:53 +00:00
130 lines
5.1 KiB
C++
130 lines
5.1 KiB
C++
#include "MenuExpressionMatchers.h"
|
|
|
|
#include "Game/IW4/IW4.h"
|
|
#include "Game/IW4/MenuConstantsIW4.h"
|
|
#include "Game/IW5/IW5.h"
|
|
#include "Game/IW5/MenuConstantsIW5.h"
|
|
#include "MenuMatcherFactory.h"
|
|
#include "Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h"
|
|
#include "Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.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(const MenuFileParserState* state)
|
|
: SimpleExpressionMatchers(true, true, true, true, true),
|
|
m_state(state)
|
|
{
|
|
}
|
|
|
|
MenuExpressionMatchers::MenuExpressionMatchers()
|
|
: MenuExpressionMatchers(nullptr)
|
|
{
|
|
}
|
|
|
|
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),
|
|
});
|
|
}
|
|
|
|
const std::map<std::string, size_t>& MenuExpressionMatchers::GetBaseFunctionMapForFeatureLevel(const FeatureLevel featureLevel)
|
|
{
|
|
if (featureLevel == FeatureLevel::IW4)
|
|
{
|
|
static std::map<std::string, size_t> iw4FunctionMap;
|
|
static bool iw4FunctionMapInitialized = false;
|
|
|
|
if (!iw4FunctionMapInitialized)
|
|
{
|
|
for (size_t i = IW4::expressionFunction_e::EXP_FUNC_DYN_START; i < std::extent_v<decltype(IW4::g_expFunctionNames)>; i++)
|
|
{
|
|
std::string functionName(IW4::g_expFunctionNames[i]);
|
|
utils::MakeStringLowerCase(functionName);
|
|
iw4FunctionMap.emplace(std::make_pair(functionName, i));
|
|
}
|
|
}
|
|
|
|
return iw4FunctionMap;
|
|
}
|
|
if (featureLevel == FeatureLevel::IW5)
|
|
{
|
|
static std::map<std::string, size_t> iw5FunctionMap;
|
|
static bool iw5FunctionMapInitialized = false;
|
|
|
|
if (!iw5FunctionMapInitialized)
|
|
{
|
|
for (size_t i = IW5::expressionFunction_e::EXP_FUNC_DYN_START; i < std::extent_v<decltype(IW5::g_expFunctionNames)>; i++)
|
|
{
|
|
std::string functionName(IW5::g_expFunctionNames[i]);
|
|
utils::MakeStringLowerCase(functionName);
|
|
iw5FunctionMap.emplace(std::make_pair(std::move(functionName), i));
|
|
}
|
|
}
|
|
|
|
return iw5FunctionMap;
|
|
}
|
|
|
|
assert(false);
|
|
throw ParsingException(TokenPos(), "Feature level has no functions registered!!");
|
|
}
|
|
|
|
std::unique_ptr<ISimpleExpression> MenuExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const
|
|
{
|
|
assert(m_state);
|
|
if (m_state == nullptr)
|
|
throw ParsingException(TokenPos(), "No state when processing menu operand extension!!");
|
|
|
|
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL) != TAG_EXPRESSION_FUNCTION_CALL)
|
|
throw ParsingException(TokenPos(), "Menu Operand Extension must be function call");
|
|
|
|
const auto& functionCallToken = result.NextCapture(CAPTURE_FUNCTION_NAME);
|
|
auto functionCallName = functionCallToken.IdentifierValue();
|
|
utils::MakeStringLowerCase(functionCallName);
|
|
|
|
const auto& baseFunctionMap = GetBaseFunctionMapForFeatureLevel(m_state->m_feature_level);
|
|
const auto foundBaseFunction = baseFunctionMap.find(functionCallName);
|
|
if (foundBaseFunction != baseFunctionMap.end())
|
|
{
|
|
auto functionCall = std::make_unique<CommonExpressionBaseFunctionCall>(std::move(functionCallName), foundBaseFunction->second);
|
|
while (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END)
|
|
{
|
|
functionCall->m_args.emplace_back(ProcessExpression(result));
|
|
}
|
|
return std::move(functionCall);
|
|
}
|
|
|
|
const auto foundCustomFunction = m_state->m_functions_by_name.find(functionCallName);
|
|
if (foundCustomFunction != m_state->m_functions_by_name.end())
|
|
{
|
|
auto functionCall = std::make_unique<CommonExpressionCustomFunctionCall>(std::move(functionCallName));
|
|
|
|
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END)
|
|
throw ParsingException(functionCallToken.GetPos(), "Custom functions cannot be called with arguments");
|
|
|
|
return std::move(functionCall);
|
|
}
|
|
|
|
throw ParsingException(functionCallToken.GetPos(), "Unknown function");
|
|
}
|