mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-09-09 23:47:07 +00:00
Make use of custom functions when converting menus
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
#include "MenuExpressionMatchers.h"
|
||||
|
||||
#include "MenuMatcherFactory.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h"
|
||||
#include "Game/IW4/IW4.h"
|
||||
#include "Game/IW5/IW5.h"
|
||||
#include "Game/IW4/MenuConstantsIW4.h"
|
||||
#include "Game/IW5/MenuConstantsIW5.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.h"
|
||||
|
||||
using namespace menu;
|
||||
|
||||
@@ -10,9 +15,14 @@ static constexpr int TAG_EXPRESSION_FUNCTION_CALL_END = SimpleExpressionMatchers
|
||||
|
||||
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()
|
||||
: SimpleExpressionMatchers(true, true, true, true, true)
|
||||
: MenuExpressionMatchers(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,17 +46,73 @@ std::unique_ptr<SimpleExpressionMatchers::matcher_t> MenuExpressionMatchers::Par
|
||||
});
|
||||
}
|
||||
|
||||
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++)
|
||||
iw4FunctionMap.emplace(std::make_pair(IW4::g_expFunctionNames[i], 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++)
|
||||
iw5FunctionMap.emplace(std::make_pair(IW5::g_expFunctionNames[i], 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");
|
||||
|
||||
auto functionCall = std::make_unique<CommonExpressionFunctionCall>(result.NextCapture(CAPTURE_FUNCTION_NAME).IdentifierValue());
|
||||
const auto& functionCallToken = result.NextCapture(CAPTURE_FUNCTION_NAME);
|
||||
auto functionCallName = functionCallToken.IdentifierValue();
|
||||
|
||||
while (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END)
|
||||
const auto& baseFunctionMap = GetBaseFunctionMapForFeatureLevel(m_state->m_feature_level);
|
||||
const auto foundBaseFunction = baseFunctionMap.find(functionCallName);
|
||||
if(foundBaseFunction != baseFunctionMap.end())
|
||||
{
|
||||
functionCall->m_args.emplace_back(ProcessExpression(result));
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -2,14 +2,20 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Parsing/Menu/MenuFileParserState.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
||||
|
||||
namespace menu
|
||||
{
|
||||
class MenuExpressionMatchers final : public SimpleExpressionMatchers
|
||||
{
|
||||
const MenuFileParserState* m_state;
|
||||
|
||||
static const std::map<std::string, size_t>& GetBaseFunctionMapForFeatureLevel(FeatureLevel featureLevel);
|
||||
|
||||
public:
|
||||
MenuExpressionMatchers();
|
||||
explicit MenuExpressionMatchers(const MenuFileParserState* state);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const override;
|
||||
|
||||
@@ -101,7 +101,7 @@ std::string& MenuMatcherFactory::TokenTextValue(const SimpleParserValue& value)
|
||||
return value.StringValue();
|
||||
}
|
||||
|
||||
int MenuMatcherFactory::TokenIntExpressionValue(SequenceResult<SimpleParserValue>& result)
|
||||
int MenuMatcherFactory::TokenIntExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||
{
|
||||
const auto nextTag = result.PeekTag();
|
||||
|
||||
@@ -115,7 +115,7 @@ int MenuMatcherFactory::TokenIntExpressionValue(SequenceResult<SimpleParserValue
|
||||
if (nextTag == TAG_EXPRESSION)
|
||||
{
|
||||
result.NextTag();
|
||||
const auto expression = MenuExpressionMatchers().ProcessExpression(result);
|
||||
const auto expression = MenuExpressionMatchers(state).ProcessExpression(result);
|
||||
|
||||
if (!expression || !expression->IsStatic())
|
||||
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Not a valid static expression");
|
||||
@@ -131,7 +131,7 @@ int MenuMatcherFactory::TokenIntExpressionValue(SequenceResult<SimpleParserValue
|
||||
throw ParsingException(TokenPos(), "TokenIntExpressionValue must be expression or int");
|
||||
}
|
||||
|
||||
double MenuMatcherFactory::TokenNumericExpressionValue(SequenceResult<SimpleParserValue>& result)
|
||||
double MenuMatcherFactory::TokenNumericExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||
{
|
||||
const auto nextTag = result.PeekTag();
|
||||
|
||||
@@ -145,7 +145,7 @@ double MenuMatcherFactory::TokenNumericExpressionValue(SequenceResult<SimplePars
|
||||
if (nextTag == TAG_EXPRESSION)
|
||||
{
|
||||
result.NextTag();
|
||||
const auto expression = MenuExpressionMatchers().ProcessExpression(result);
|
||||
const auto expression = MenuExpressionMatchers(state).ProcessExpression(result);
|
||||
|
||||
if (!expression || !expression->IsStatic())
|
||||
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Not a valid static expression");
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Parsing/Sequence/SequenceResult.h"
|
||||
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||
#include "Parsing/Menu/MenuFileParserState.h"
|
||||
|
||||
namespace menu
|
||||
{
|
||||
@@ -30,7 +31,7 @@ namespace menu
|
||||
_NODISCARD static double TokenNumericFloatingPointValue(const SimpleParserValue& value);
|
||||
_NODISCARD static std::string& TokenTextValue(const SimpleParserValue& value);
|
||||
|
||||
_NODISCARD static int TokenIntExpressionValue(SequenceResult<SimpleParserValue>& result);
|
||||
_NODISCARD static double TokenNumericExpressionValue(SequenceResult<SimpleParserValue>& result);
|
||||
_NODISCARD static int TokenIntExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||
_NODISCARD static double TokenNumericExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user