mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-09-24 09:16:39 +00:00
chore: parse includes and assetlists while parsing zone definition
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
#include "SequenceZoneDefinitionAssetList.h"
|
||||
|
||||
#include "Zone/AssetList/AssetListReader.h"
|
||||
#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h"
|
||||
|
||||
SequenceZoneDefinitionAssetList::SequenceZoneDefinitionAssetList()
|
||||
{
|
||||
const ZoneDefinitionMatcherFactory create(this);
|
||||
|
||||
AddMatchers({
|
||||
create.Keyword("assetlist").Capture(CAPTURE_ASSET_LIST_KEYWORD),
|
||||
create.Char(','),
|
||||
create.Field().Capture(CAPTURE_ASSET_LIST_NAME),
|
||||
});
|
||||
}
|
||||
|
||||
void SequenceZoneDefinitionAssetList::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const
|
||||
{
|
||||
if (state->m_definition->m_game == GameId::COUNT)
|
||||
{
|
||||
const auto& assetListKeywordToken = result.NextCapture(CAPTURE_ASSET_LIST_KEYWORD);
|
||||
throw ParsingException(assetListKeywordToken.GetPos(), "Must define game before using assetlist");
|
||||
}
|
||||
|
||||
const auto& assetListNameToken = result.NextCapture(CAPTURE_ASSET_LIST_NAME);
|
||||
|
||||
AssetListReader assetListReader(state->m_search_path, state->m_definition->m_game);
|
||||
const auto maybeAssetList = assetListReader.ReadAssetList(assetListNameToken.FieldValue());
|
||||
|
||||
if (!maybeAssetList)
|
||||
throw ParsingException(assetListNameToken.GetPos(), "Failed to read asset list");
|
||||
|
||||
for (auto& assetListEntry : maybeAssetList->m_entries)
|
||||
state->m_definition->m_assets.emplace_back(assetListEntry.m_type, std::move(assetListEntry.m_name), assetListEntry.m_is_reference);
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Definition/Parsing/ZoneDefinitionParser.h"
|
||||
|
||||
class SequenceZoneDefinitionAssetList final : public ZoneDefinitionParser::sequence_t
|
||||
{
|
||||
static constexpr auto CAPTURE_ASSET_LIST_KEYWORD = 1;
|
||||
static constexpr auto CAPTURE_ASSET_LIST_NAME = 2;
|
||||
|
||||
protected:
|
||||
void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const override;
|
||||
|
||||
public:
|
||||
SequenceZoneDefinitionAssetList();
|
||||
};
|
@@ -0,0 +1,19 @@
|
||||
#include "SequenceZoneDefinitionBuild.h"
|
||||
|
||||
#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h"
|
||||
|
||||
SequenceZoneDefinitionBuild::SequenceZoneDefinitionBuild()
|
||||
{
|
||||
const ZoneDefinitionMatcherFactory create(this);
|
||||
|
||||
AddMatchers({
|
||||
create.Keyword("build"),
|
||||
create.Char(','),
|
||||
create.Field().Capture(CAPTURE_BUILD_TARGET_NAME),
|
||||
});
|
||||
}
|
||||
|
||||
void SequenceZoneDefinitionBuild::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const
|
||||
{
|
||||
state->m_definition->m_targets_to_build.emplace_back(result.NextCapture(CAPTURE_BUILD_TARGET_NAME).FieldValue());
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Definition/Parsing/ZoneDefinitionParser.h"
|
||||
|
||||
class SequenceZoneDefinitionBuild final : public ZoneDefinitionParser::sequence_t
|
||||
{
|
||||
static constexpr auto CAPTURE_BUILD_TARGET_NAME = 1;
|
||||
|
||||
protected:
|
||||
void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const override;
|
||||
|
||||
public:
|
||||
SequenceZoneDefinitionBuild();
|
||||
};
|
@@ -0,0 +1,41 @@
|
||||
#include "SequenceZoneDefinitionEntry.h"
|
||||
|
||||
#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h"
|
||||
|
||||
SequenceZoneDefinitionEntry::SequenceZoneDefinitionEntry()
|
||||
{
|
||||
const ZoneDefinitionMatcherFactory create(this);
|
||||
|
||||
AddMatchers({
|
||||
create.Field().Capture(CAPTURE_TYPE_NAME),
|
||||
create.Char(','),
|
||||
create.Optional(create.Char(',').Tag(TAG_REFERENCE)),
|
||||
create
|
||||
.Or({
|
||||
create.String(),
|
||||
create.Field(),
|
||||
})
|
||||
.Capture(CAPTURE_ASSET_NAME),
|
||||
});
|
||||
}
|
||||
|
||||
void SequenceZoneDefinitionEntry::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const
|
||||
{
|
||||
const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE_NAME);
|
||||
|
||||
if (!state->m_asset_name_resolver)
|
||||
throw ParsingException(typeNameToken.GetPos(), "Must define game before first asset");
|
||||
|
||||
const auto maybeAssetType = state->m_asset_name_resolver->GetAssetTypeByName(typeNameToken.FieldValue());
|
||||
if (!maybeAssetType)
|
||||
throw ParsingException(typeNameToken.GetPos(), "Unknown asset type");
|
||||
|
||||
const auto& assetNameToken = result.NextCapture(CAPTURE_ASSET_NAME);
|
||||
std::string assetName;
|
||||
if (assetNameToken.m_type == ZoneDefinitionParserValueType::STRING)
|
||||
assetName = assetNameToken.StringValue();
|
||||
else
|
||||
assetName = assetNameToken.FieldValue();
|
||||
|
||||
state->m_definition->m_assets.emplace_back(*maybeAssetType, assetName, result.NextTag() == TAG_REFERENCE);
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Definition/Parsing/ZoneDefinitionParser.h"
|
||||
|
||||
class SequenceZoneDefinitionEntry final : public ZoneDefinitionParser::sequence_t
|
||||
{
|
||||
static constexpr auto TAG_REFERENCE = 1;
|
||||
|
||||
static constexpr auto CAPTURE_TYPE_NAME = 1;
|
||||
static constexpr auto CAPTURE_ASSET_NAME = 2;
|
||||
|
||||
protected:
|
||||
void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const override;
|
||||
|
||||
public:
|
||||
SequenceZoneDefinitionEntry();
|
||||
};
|
@@ -0,0 +1,19 @@
|
||||
#include "SequenceZoneDefinitionIgnore.h"
|
||||
|
||||
#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h"
|
||||
|
||||
SequenceZoneDefinitionIgnore::SequenceZoneDefinitionIgnore()
|
||||
{
|
||||
const ZoneDefinitionMatcherFactory create(this);
|
||||
|
||||
AddMatchers({
|
||||
create.Keyword("ignore"),
|
||||
create.Char(','),
|
||||
create.Field().Capture(CAPTURE_IGNORE_NAME),
|
||||
});
|
||||
}
|
||||
|
||||
void SequenceZoneDefinitionIgnore::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const
|
||||
{
|
||||
state->m_definition->m_ignores.emplace_back(result.NextCapture(CAPTURE_IGNORE_NAME).FieldValue());
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Definition/Parsing/ZoneDefinitionParser.h"
|
||||
|
||||
class SequenceZoneDefinitionIgnore final : public ZoneDefinitionParser::sequence_t
|
||||
{
|
||||
static constexpr auto CAPTURE_IGNORE_NAME = 1;
|
||||
|
||||
protected:
|
||||
void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const override;
|
||||
|
||||
public:
|
||||
SequenceZoneDefinitionIgnore();
|
||||
};
|
@@ -0,0 +1,32 @@
|
||||
#include "SequenceZoneDefinitionInclude.h"
|
||||
|
||||
#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h"
|
||||
|
||||
#include <format>
|
||||
|
||||
SequenceZoneDefinitionInclude::SequenceZoneDefinitionInclude()
|
||||
{
|
||||
const ZoneDefinitionMatcherFactory create(this);
|
||||
|
||||
AddMatchers({
|
||||
create.Keyword("include"),
|
||||
create.Char(','),
|
||||
create.Field().Capture(CAPTURE_INCLUDE_NAME),
|
||||
});
|
||||
}
|
||||
|
||||
void SequenceZoneDefinitionInclude::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const
|
||||
{
|
||||
const auto& inclusionNameToken = result.NextCapture(CAPTURE_INCLUDE_NAME);
|
||||
const auto inclusionName = inclusionNameToken.FieldValue();
|
||||
const auto existingInclusion = state->m_inclusions.find(inclusionName);
|
||||
if (existingInclusion != state->m_inclusions.end())
|
||||
throw ParsingException(inclusionNameToken.GetPos(), "Zone definition has already been included");
|
||||
|
||||
const auto zoneDefinitionFileNameToInclude = std::format("{}.zone", inclusionName);
|
||||
|
||||
if (!state->m_underlying_stream.IncludeFile(zoneDefinitionFileNameToInclude))
|
||||
throw ParsingException(inclusionNameToken.GetPos(), "Could not find zone definition with this filename");
|
||||
|
||||
state->m_inclusions.emplace(inclusionName);
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Definition/Parsing/ZoneDefinitionParser.h"
|
||||
|
||||
class SequenceZoneDefinitionInclude final : public ZoneDefinitionParser::sequence_t
|
||||
{
|
||||
static constexpr auto CAPTURE_INCLUDE_NAME = 1;
|
||||
|
||||
protected:
|
||||
void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const override;
|
||||
|
||||
public:
|
||||
SequenceZoneDefinitionInclude();
|
||||
};
|
@@ -0,0 +1,166 @@
|
||||
#include "SequenceZoneDefinitionMetaData.h"
|
||||
|
||||
#include "Utils/StringUtils.h"
|
||||
#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <optional>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr auto METADATA_GAME = "game";
|
||||
constexpr auto METADATA_GDT = "gdt";
|
||||
constexpr auto METADATA_NAME = "name";
|
||||
constexpr auto METADATA_TYPE = "type";
|
||||
|
||||
constexpr auto METADATA_IPAK = "ipak";
|
||||
constexpr auto METADATA_IWD = "iwd";
|
||||
|
||||
std::optional<GameId> GetGameByName(const std::string& gameName)
|
||||
{
|
||||
auto upperGameName = gameName;
|
||||
utils::MakeStringUpperCase(upperGameName);
|
||||
|
||||
for (auto i = 0u; i < static_cast<unsigned>(GameId::COUNT); i++)
|
||||
{
|
||||
if (upperGameName == GameId_Names[i])
|
||||
return static_cast<GameId>(i);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
enum class ProjectType : std::uint8_t
|
||||
{
|
||||
NONE,
|
||||
FASTFILE,
|
||||
IPAK,
|
||||
|
||||
COUNT
|
||||
};
|
||||
constexpr const char* ProjectType_Names[]{
|
||||
"none",
|
||||
"fastfile",
|
||||
"ipak",
|
||||
};
|
||||
static_assert(std::extent_v<decltype(ProjectType_Names)> == static_cast<unsigned>(ProjectType::COUNT));
|
||||
|
||||
std::optional<ProjectType> GetProjectTypeByName(const std::string& projectTypeName)
|
||||
{
|
||||
auto lowerProjectTypeName = projectTypeName;
|
||||
utils::MakeStringLowerCase(lowerProjectTypeName);
|
||||
|
||||
for (auto i = 0u; i < static_cast<unsigned>(ProjectType::COUNT); i++)
|
||||
{
|
||||
if (lowerProjectTypeName == ProjectType_Names[i])
|
||||
return static_cast<ProjectType>(i);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SequenceZoneDefinitionMetaData::SequenceZoneDefinitionMetaData()
|
||||
{
|
||||
const ZoneDefinitionMatcherFactory create(this);
|
||||
|
||||
AddMatchers({
|
||||
create.Char('>'),
|
||||
create.Field().Capture(CAPTURE_KEY),
|
||||
create.Char(','),
|
||||
create.Field().Capture(CAPTURE_VALUE),
|
||||
});
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void ProcessMetaDataGame(ZoneDefinitionParserState* state, const ZoneDefinitionParserValue& valueToken, const std::string& value)
|
||||
{
|
||||
const auto game = GetGameByName(value);
|
||||
if (!game)
|
||||
throw ParsingException(valueToken.GetPos(), "Unknown game name");
|
||||
|
||||
const auto previousGame = state->m_definition->m_game;
|
||||
if (previousGame != GameId::COUNT && previousGame != *game)
|
||||
throw ParsingException(valueToken.GetPos(), std::format("Game was previously defined as: {}", GameId_Names[static_cast<unsigned>(previousGame)]));
|
||||
|
||||
state->SetGame(*game);
|
||||
}
|
||||
|
||||
void ProcessMetaDataType(ZoneDefinitionParserState* state, const ZoneDefinitionParserValue& keyToken, const ZoneDefinitionParserValue& valueToken)
|
||||
{
|
||||
const auto projectType = GetProjectTypeByName(valueToken.FieldValue());
|
||||
if (!projectType)
|
||||
throw ParsingException(valueToken.GetPos(), "Unknown project type name");
|
||||
|
||||
// TODO: Remove deprecated type
|
||||
|
||||
std::string deprecationSuggestedAction;
|
||||
if (*projectType == ProjectType::IPAK)
|
||||
{
|
||||
deprecationSuggestedAction = "Use \">ipak,name_of_ipak\" instead.";
|
||||
state->StartIPak(state->m_definition->m_name);
|
||||
}
|
||||
else if (*projectType == ProjectType::FASTFILE)
|
||||
{
|
||||
deprecationSuggestedAction = "A fastfile will always be built when appropriate assets have been added.";
|
||||
}
|
||||
else
|
||||
{
|
||||
deprecationSuggestedAction = "It now has no effect.";
|
||||
}
|
||||
|
||||
const auto keyPos = keyToken.GetPos();
|
||||
std::cerr << std::format("Warning: {} L{}: Zone definition \">type,{}\" is deprecated and should be removed. {}\n",
|
||||
keyPos.m_filename.get(),
|
||||
keyPos.m_line,
|
||||
keyToken.FieldValue(),
|
||||
deprecationSuggestedAction);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const
|
||||
{
|
||||
const auto& keyToken = result.NextCapture(CAPTURE_KEY);
|
||||
auto key = keyToken.FieldValue();
|
||||
const auto& valueToken = result.NextCapture(CAPTURE_VALUE);
|
||||
const auto& value = valueToken.FieldValue();
|
||||
|
||||
utils::MakeStringLowerCase(key);
|
||||
|
||||
if (key == METADATA_GAME)
|
||||
{
|
||||
ProcessMetaDataGame(state, valueToken, value);
|
||||
}
|
||||
else if (key == METADATA_GDT)
|
||||
{
|
||||
state->m_definition->m_gdts.emplace_back(value);
|
||||
}
|
||||
else if (key == METADATA_NAME)
|
||||
{
|
||||
state->m_definition->m_name = value;
|
||||
}
|
||||
else if (key == METADATA_TYPE)
|
||||
{
|
||||
ProcessMetaDataType(state, keyToken, valueToken);
|
||||
}
|
||||
else if (key == METADATA_IPAK)
|
||||
{
|
||||
if (!value.empty())
|
||||
state->StartIPak(value);
|
||||
else
|
||||
throw ParsingException(valueToken.GetPos(), "IPak must have a name");
|
||||
}
|
||||
else if (key == METADATA_IWD)
|
||||
{
|
||||
if (!value.empty())
|
||||
state->StartIwd(value);
|
||||
else
|
||||
throw ParsingException(valueToken.GetPos(), "IWD must have a name");
|
||||
}
|
||||
else
|
||||
{
|
||||
state->m_definition->m_properties.AddProperty(key, value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Definition/Parsing/ZoneDefinitionParser.h"
|
||||
|
||||
class SequenceZoneDefinitionMetaData final : public ZoneDefinitionParser::sequence_t
|
||||
{
|
||||
static constexpr auto CAPTURE_KEY = 1;
|
||||
static constexpr auto CAPTURE_VALUE = 2;
|
||||
|
||||
protected:
|
||||
void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const override;
|
||||
|
||||
public:
|
||||
SequenceZoneDefinitionMetaData();
|
||||
};
|
Reference in New Issue
Block a user