2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-01-24 08:53:04 +00:00

chore: use CommonTechset instead of TechsetDefinition

This commit is contained in:
Jan Laupetin
2026-01-19 22:13:12 +00:00
parent 2a034d512e
commit d714afbcdd
40 changed files with 306 additions and 301 deletions

View File

@@ -0,0 +1 @@
#include "CommonTechniqueLoader.h"

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Asset/AssetCreationContext.h"
#include "Techset/CommonTechnique.h"
#include <memory>
namespace techset
{
std::unique_ptr<CommonTechnique>
LoadCommonTechnique(const AssetCreationContext& context, const CommonCodeSourceInfos& codeSourceInfos, const CommonStreamRoutingInfos& routingInfos);
} // namespace techset

View File

@@ -0,0 +1,49 @@
#include "CommonTechsetLoader.h"
#include "Parsing/IParserLineStream.h"
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
#include "Parsing/Impl/ParserSingleInputStream.h"
#include "Parsing/Simple/SimpleLexer.h"
#include "Techset/Parsing/TechsetFileParser.h"
#include "Techset/TechsetCommon.h"
#include "Utils/Logging/Log.h"
#include <format>
#include <iostream>
#include <memory>
#include <string>
namespace techset
{
std::unique_ptr<CommonTechset>
LoadCommonTechset(const std::string& assetName, const CommonTechniqueTypeNames& techniqueTypeNames, ISearchPath& searchPath, bool& failure)
{
failure = false;
const auto fileName = GetFileNameForTechniqueName(assetName);
const auto techniqueFile = searchPath.Open(fileName);
if (!techniqueFile.IsOpen())
return nullptr;
SimpleLexer::Config lexerConfig;
lexerConfig.m_emit_new_line_tokens = false;
lexerConfig.m_read_strings = true;
lexerConfig.m_string_escape_sequences = false;
lexerConfig.m_read_integer_numbers = false;
lexerConfig.m_read_floating_point_numbers = false;
ParserSingleInputStream baseStream(*techniqueFile.m_stream, fileName);
CommentRemovingStreamProxy commentProxy(&baseStream);
const auto lexer = std::make_unique<SimpleLexer>(&commentProxy, std::move(lexerConfig));
const auto parser = std::make_unique<TechsetParser>(*lexer, techniqueTypeNames);
const auto success = parser->Parse();
if (success)
return parser->GetParsingResult();
con::error("Parsing techset file \"{}\" failed!", fileName);
failure = true;
return nullptr;
}
} // namespace techset

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Asset/AssetCreationContext.h"
#include "Techset/CommonTechset.h"
#include <memory>
namespace techset
{
std::unique_ptr<CommonTechset>
LoadCommonTechset(const std::string& assetName, const CommonTechniqueTypeNames& techniqueTypeNames, ISearchPath& searchPath, bool& failure);
} // namespace techset

View File

@@ -0,0 +1,41 @@
#include "TechniqueNoScopeSequences.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
#include <cassert>
using namespace techset;
namespace techset
{
class SequencePass final : public TechniqueParser::sequence_t
{
public:
SequencePass()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Char('{'),
});
}
protected:
void ProcessMatch(TechniqueParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
assert(state->m_in_pass == false);
state->m_in_pass = true;
state->m_acceptor->AcceptNextPass();
}
};
} // namespace techset
const std::vector<TechniqueParser::sequence_t*>& TechniqueNoScopeSequences::GetSequences()
{
static std::vector<TechniqueParser::sequence_t*> tests({
new SequencePass(),
});
return tests;
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "Techset/Parsing/TechniqueFileParser.h"
#include <vector>
namespace techset
{
class TechniqueNoScopeSequences
{
TechniqueNoScopeSequences() = default;
public:
static const std::vector<TechniqueParser::sequence_t*>& GetSequences();
};
} // namespace techset

View File

@@ -0,0 +1,215 @@
#include "TechniquePassScopeSequences.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
#include <cassert>
#include <sstream>
using namespace techset;
namespace techset
{
class SequenceEndPass final : public TechniqueParser::sequence_t
{
static constexpr auto CAPTURE_FIRST_TOKEN = 1;
public:
SequenceEndPass()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Char('}').Capture(CAPTURE_FIRST_TOKEN),
});
}
protected:
void ProcessMatch(TechniqueParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
assert(state->m_in_pass == true);
std::string errorMessage;
if (!state->m_acceptor->AcceptEndPass(errorMessage))
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), errorMessage);
state->m_in_pass = false;
}
};
class SequenceStateMap final : public TechniqueParser::sequence_t
{
static constexpr auto CAPTURE_START = 1;
static constexpr auto CAPTURE_STATE_MAP_NAME = 2;
public:
SequenceStateMap()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("stateMap").Capture(CAPTURE_START),
create.String().Capture(CAPTURE_STATE_MAP_NAME),
create.Char(';'),
});
}
protected:
void ProcessMatch(TechniqueParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
const auto& firstToken = result.NextCapture(CAPTURE_START);
std::string errorMessage;
const auto acceptorResult = state->m_acceptor->AcceptStateMap(result.NextCapture(CAPTURE_STATE_MAP_NAME).StringValue(), errorMessage);
if (!acceptorResult)
throw ParsingException(firstToken.GetPos(), std::move(errorMessage));
}
};
class SequenceShader final : public TechniqueParser::sequence_t
{
static constexpr auto TAG_VERTEX_SHADER = 1;
static constexpr auto TAG_PIXEL_SHADER = 2;
static constexpr auto CAPTURE_START = 1;
static constexpr auto CAPTURE_VERSION = 2;
static constexpr auto CAPTURE_VERSION_MAJOR = 3;
static constexpr auto CAPTURE_VERSION_MINOR = 4;
static constexpr auto CAPTURE_SHADER_NAME = 5;
public:
SequenceShader()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create
.Or({
create.Keyword("vertexShader").Tag(TAG_VERTEX_SHADER),
create.Keyword("pixelShader").Tag(TAG_PIXEL_SHADER),
})
.Capture(CAPTURE_START),
create.Or({
create.And({
create.Integer().Capture(CAPTURE_VERSION_MAJOR),
create.Char('.'),
create.Integer().Capture(CAPTURE_VERSION_MINOR),
}),
create.FloatingPoint().Capture(CAPTURE_VERSION), // This is dumb but cod devs made the format so cannot change it
create.String().Capture(CAPTURE_VERSION),
}),
create.String().Capture(CAPTURE_SHADER_NAME),
create.Char('{'),
});
}
protected:
void ProcessMatch(TechniqueParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
const auto& firstToken = result.NextCapture(CAPTURE_START);
// Don't care about shader version since it's stated in the shader bin anyway
const auto& shaderNameToken = result.NextCapture(CAPTURE_SHADER_NAME);
bool acceptorResult;
std::string errorMessage;
const auto shaderTag = result.NextTag();
assert(shaderTag == TAG_VERTEX_SHADER || shaderTag == TAG_PIXEL_SHADER);
if (shaderTag == TAG_VERTEX_SHADER)
{
acceptorResult = state->m_acceptor->AcceptVertexShader(shaderNameToken.StringValue(), errorMessage);
state->m_current_shader = ShaderSelector::VERTEX_SHADER;
}
else
{
acceptorResult = state->m_acceptor->AcceptPixelShader(shaderNameToken.StringValue(), errorMessage);
state->m_current_shader = ShaderSelector::PIXEL_SHADER;
}
state->m_in_shader = true;
if (!acceptorResult)
throw ParsingException(firstToken.GetPos(), std::move(errorMessage));
}
};
class SequenceVertexStreamRouting final : public TechniqueParser::sequence_t
{
static constexpr auto CAPTURE_FIRST_TOKEN = 1;
static constexpr auto CAPTURE_STREAM_DESTINATION_NAME = 2;
static constexpr auto CAPTURE_STREAM_DESTINATION_INDEX = 3;
static constexpr auto CAPTURE_STREAM_SOURCE_NAME = 4;
static constexpr auto CAPTURE_STREAM_SOURCE_INDEX = 5;
public:
SequenceVertexStreamRouting()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("vertex").Capture(CAPTURE_FIRST_TOKEN),
create.Char('.'),
create.Identifier().Capture(CAPTURE_STREAM_DESTINATION_NAME),
create.Optional(create.And({
create.Char('['),
create.Integer().Capture(CAPTURE_STREAM_DESTINATION_INDEX),
create.Char(']'),
})),
create.Char('='),
create.Keyword("code"),
create.Char('.'),
create.Identifier().Capture(CAPTURE_STREAM_SOURCE_NAME),
create.Optional(create.And({
create.Char('['),
create.Integer().Capture(CAPTURE_STREAM_SOURCE_INDEX),
create.Char(']'),
})),
create.Char(';'),
});
}
static std::string CreateRoutingString(SequenceResult<SimpleParserValue>& result, const int nameCapture, const int indexCapture)
{
if (result.HasNextCapture(indexCapture))
{
const auto& indexToken = result.NextCapture(indexCapture);
if (indexToken.IntegerValue() < 0)
throw ParsingException(indexToken.GetPos(), "Index cannot be negative");
std::ostringstream ss;
ss << result.NextCapture(nameCapture).IdentifierValue() << '[' << indexToken.IntegerValue() << ']';
return ss.str();
}
return result.NextCapture(nameCapture).IdentifierValue();
}
protected:
void ProcessMatch(TechniqueParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
const auto& firstToken = result.NextCapture(CAPTURE_FIRST_TOKEN);
const std::string destinationString = CreateRoutingString(result, CAPTURE_STREAM_DESTINATION_NAME, CAPTURE_STREAM_DESTINATION_INDEX);
const std::string sourceString = CreateRoutingString(result, CAPTURE_STREAM_SOURCE_NAME, CAPTURE_STREAM_SOURCE_INDEX);
std::string errorMessage;
if (!state->m_acceptor->AcceptVertexStreamRouting(destinationString, sourceString, errorMessage))
throw ParsingException(firstToken.GetPos(), std::move(errorMessage));
}
};
} // namespace techset
const std::vector<TechniqueParser::sequence_t*>& TechniquePassScopeSequences::GetSequences()
{
static std::vector<TechniqueParser::sequence_t*> tests({
new SequenceEndPass(),
new SequenceStateMap(),
new SequenceShader(),
new SequenceVertexStreamRouting(),
});
return tests;
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "Techset/Parsing/TechniqueFileParser.h"
#include <vector>
namespace techset
{
class TechniquePassScopeSequences
{
TechniquePassScopeSequences() = default;
public:
static const std::vector<TechniqueParser::sequence_t*>& GetSequences();
};
} // namespace techset

View File

@@ -0,0 +1,242 @@
#include "TechniqueShaderScopeSequences.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
#include <cassert>
using namespace techset;
namespace techset
{
class SequenceEndShader final : public TechniqueParser::sequence_t
{
public:
SequenceEndShader()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Char('}'),
});
}
protected:
void ProcessMatch(TechniqueParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
assert(state->m_in_shader == true);
state->m_in_shader = false;
}
};
class SequenceShaderArgument final : public TechniqueParser::sequence_t
{
static constexpr auto TAG_CONSTANT = 1;
static constexpr auto TAG_SAMPLER = 2;
static constexpr auto TAG_LITERAL = 3;
static constexpr auto TAG_MATERIAL = 4;
static constexpr auto CAPTURE_FIRST_TOKEN = 1;
static constexpr auto CAPTURE_SHADER_ARGUMENT = 2;
static constexpr auto CAPTURE_SHADER_INDEX = 3;
static constexpr auto CAPTURE_CODE_ACCESSOR = 4;
static constexpr auto CAPTURE_CODE_INDEX = 5;
static constexpr auto CAPTURE_LITERAL_VALUE = 6;
static constexpr auto CAPTURE_MATERIAL_HASH = 7;
static constexpr auto CAPTURE_MATERIAL_NAME = 8;
static std::unique_ptr<matcher_t> CodeMatchers(const SimpleMatcherFactory& create)
{
return create.And({
create.Or({
create.Keyword("constant").Tag(TAG_CONSTANT),
create.Keyword("sampler").Tag(TAG_SAMPLER),
}),
create.Char('.'),
create.Identifier().Capture(CAPTURE_CODE_ACCESSOR),
create.OptionalLoop(create.And({
create.Char('.'),
create.Identifier().Capture(CAPTURE_CODE_ACCESSOR),
})),
create.Optional(create.And({
create.Char('['),
create.Integer().Capture(CAPTURE_CODE_INDEX),
create.Char(']'),
})),
});
}
static std::unique_ptr<matcher_t> LiteralValueMatchers(const SimpleMatcherFactory& create)
{
return create
.Or({
create.FloatingPoint(),
create.Integer(),
})
.Capture(CAPTURE_LITERAL_VALUE);
}
static std::unique_ptr<matcher_t> LiteralMatchers(const SimpleMatcherFactory& create)
{
return create
.And({
create.Keyword("float4"),
create.Char('('),
LiteralValueMatchers(create),
create.Char(','),
LiteralValueMatchers(create),
create.Char(','),
LiteralValueMatchers(create),
create.Char(','),
LiteralValueMatchers(create),
create.Char(')'),
})
.Tag(TAG_LITERAL);
}
static std::unique_ptr<matcher_t> MaterialMatchers(const SimpleMatcherFactory& create)
{
return create
.And({
create.Keyword("material"),
create.Char('.'),
create.Or({
create.And({
create.Char('#'),
create.Integer().Capture(CAPTURE_MATERIAL_HASH),
}),
create.Identifier().Capture(CAPTURE_MATERIAL_NAME),
}),
})
.Tag(TAG_MATERIAL);
}
public:
SequenceShaderArgument()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Identifier().Capture(CAPTURE_FIRST_TOKEN).NoConsume(),
create.Identifier().Capture(CAPTURE_SHADER_ARGUMENT),
create.Optional(create.And({
create.Char('['),
create.Integer().Capture(CAPTURE_SHADER_INDEX),
create.Char(']'),
})),
create.Char('='),
create.Or({
CodeMatchers(create),
LiteralMatchers(create),
MaterialMatchers(create),
}),
create.Char(';'),
});
}
static void ProcessCodeArgument(const TechniqueParserState* state, SequenceResult<SimpleParserValue>& result, ShaderArgument arg, const bool isSampler)
{
std::vector<std::string> accessors;
while (result.HasNextCapture(CAPTURE_CODE_ACCESSOR))
accessors.emplace_back(result.NextCapture(CAPTURE_CODE_ACCESSOR).IdentifierValue());
ShaderArgumentCodeSource source;
if (result.HasNextCapture(CAPTURE_CODE_INDEX))
{
const auto& codeIndexToken = result.NextCapture(CAPTURE_CODE_INDEX);
if (codeIndexToken.IntegerValue() < 0)
throw ParsingException(codeIndexToken.GetPos(), "Index cannot be negative");
source = ShaderArgumentCodeSource(std::move(accessors), static_cast<size_t>(codeIndexToken.IntegerValue()));
}
else
source = ShaderArgumentCodeSource(std::move(accessors));
std::string errorMessage;
if (!isSampler)
{
if (!state->m_acceptor->AcceptShaderConstantArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage))
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage));
}
else
{
if (!state->m_acceptor->AcceptShaderSamplerArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage))
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage));
}
}
static void ProcessLiteralArgument(const TechniqueParserState* state, SequenceResult<SimpleParserValue>& result, ShaderArgument arg)
{
float value[4];
for (float& i : value)
{
const auto& literalValueToken = result.NextCapture(CAPTURE_LITERAL_VALUE);
if (literalValueToken.m_type == SimpleParserValueType::FLOATING_POINT)
i = static_cast<float>(literalValueToken.FloatingPointValue());
else
i = static_cast<float>(literalValueToken.IntegerValue());
}
const ShaderArgumentLiteralSource source(value);
std::string errorMessage;
if (!state->m_acceptor->AcceptShaderLiteralArgument(state->m_current_shader, std::move(arg), source, errorMessage))
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage));
}
static void ProcessMaterialArgument(const TechniqueParserState* state, SequenceResult<SimpleParserValue>& result, ShaderArgument arg)
{
std::string errorMessage;
if (result.HasNextCapture(CAPTURE_MATERIAL_HASH))
{
ShaderArgumentMaterialSource source(static_cast<size_t>(result.NextCapture(CAPTURE_MATERIAL_HASH).IntegerValue()));
if (!state->m_acceptor->AcceptShaderMaterialArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage))
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage));
}
else
{
ShaderArgumentMaterialSource source(result.NextCapture(CAPTURE_MATERIAL_NAME).IdentifierValue());
if (!state->m_acceptor->AcceptShaderMaterialArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage))
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage));
}
}
protected:
void ProcessMatch(TechniqueParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
assert(state->m_in_shader == true);
const auto& shaderArgumentNameToken = result.NextCapture(CAPTURE_SHADER_ARGUMENT);
ShaderArgument arg;
if (result.HasNextCapture(CAPTURE_SHADER_INDEX))
{
const auto& shaderArgumentIndexToken = result.NextCapture(CAPTURE_SHADER_INDEX);
if (shaderArgumentIndexToken.IntegerValue() < 0)
throw ParsingException(shaderArgumentIndexToken.GetPos(), "Index cannot be negative");
const auto index = static_cast<unsigned>(shaderArgumentIndexToken.IntegerValue());
arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue(), index);
}
else
arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue());
const auto typeTag = result.NextTag();
assert(typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL);
if (typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER)
ProcessCodeArgument(state, result, std::move(arg), typeTag == TAG_SAMPLER);
else if (typeTag == TAG_LITERAL)
ProcessLiteralArgument(state, result, std::move(arg));
else
ProcessMaterialArgument(state, result, std::move(arg));
}
};
} // namespace techset
const std::vector<TechniqueParser::sequence_t*>& TechniqueShaderScopeSequences::GetSequences()
{
static std::vector<TechniqueParser::sequence_t*> tests({
new SequenceEndShader(),
new SequenceShaderArgument(),
});
return tests;
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "Techset/Parsing/TechniqueFileParser.h"
#include <vector>
namespace techset
{
class TechniqueShaderScopeSequences
{
TechniqueShaderScopeSequences() = default;
public:
static const std::vector<TechniqueParser::sequence_t*>& GetSequences();
};
} // namespace techset

View File

@@ -0,0 +1,23 @@
#include "TechniqueFileParser.h"
#include "Sequence/TechniqueNoScopeSequences.h"
#include "Sequence/TechniquePassScopeSequences.h"
#include "Sequence/TechniqueShaderScopeSequences.h"
using namespace techset;
TechniqueParser::TechniqueParser(SimpleLexer* lexer, ITechniqueDefinitionAcceptor* acceptor)
: AbstractParser(lexer, std::make_unique<TechniqueParserState>(acceptor))
{
}
const std::vector<TechniqueParser::sequence_t*>& TechniqueParser::GetTestsForState()
{
if (m_state->m_in_shader)
return TechniqueShaderScopeSequences::GetSequences();
if (m_state->m_in_pass)
return TechniquePassScopeSequences::GetSequences();
return TechniqueNoScopeSequences::GetSequences();
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "Parsing/Impl/AbstractParser.h"
#include "Parsing/Simple/SimpleLexer.h"
#include "Parsing/Simple/SimpleParserValue.h"
#include "TechniqueFileParserState.h"
namespace techset
{
class TechniqueParser final : public AbstractParser<SimpleParserValue, TechniqueParserState>
{
protected:
const std::vector<sequence_t*>& GetTestsForState() override;
public:
TechniqueParser(SimpleLexer* lexer, ITechniqueDefinitionAcceptor* acceptor);
};
} // namespace techset

View File

@@ -0,0 +1,14 @@
#include "TechniqueFileParserState.h"
#include <cassert>
using namespace techset;
TechniqueParserState::TechniqueParserState(ITechniqueDefinitionAcceptor* acceptor)
: m_acceptor(acceptor),
m_in_pass(false),
m_in_shader(false),
m_current_shader(ShaderSelector::VERTEX_SHADER)
{
assert(acceptor);
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "Techset/TechniqueDefinitionAcceptor.h"
namespace techset
{
class TechniqueParserState
{
public:
explicit TechniqueParserState(ITechniqueDefinitionAcceptor* acceptor);
ITechniqueDefinitionAcceptor* const m_acceptor;
bool m_in_pass;
bool m_in_shader;
ShaderSelector m_current_shader;
};
} // namespace techset

View File

@@ -0,0 +1,97 @@
#include "TechsetFileParser.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
using namespace techset;
namespace
{
class SequenceTechniqueTypeName final : public TechsetParser::sequence_t
{
static constexpr auto CAPTURE_TYPE_NAME = 1;
public:
SequenceTechniqueTypeName()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.String().Capture(CAPTURE_TYPE_NAME),
create.Char(':'),
});
}
protected:
void ProcessMatch(TechsetParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE_NAME);
const auto maybeTechniqueTypeIndex = state->m_technique_type_names.GetTechniqueTypeByName(typeNameToken.StringValue());
if (!maybeTechniqueTypeIndex.has_value())
throw ParsingException(typeNameToken.GetPos(), "Unknown technique type name");
state->m_current_technique_types.push_back(maybeTechniqueTypeIndex.value());
}
};
class SequenceTechniqueName final : public TechsetParser::sequence_t
{
static constexpr auto CAPTURE_NAME = 1;
public:
SequenceTechniqueName()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create
.Or({
create.Identifier(),
create.String(),
})
.Capture(CAPTURE_NAME),
create.Char(';'),
});
}
protected:
void ProcessMatch(TechsetParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
assert(!state->m_current_technique_types.empty());
const auto& techniqueNameToken = result.NextCapture(CAPTURE_NAME);
const auto& techniqueName =
techniqueNameToken.m_type == SimpleParserValueType::STRING ? techniqueNameToken.StringValue() : techniqueNameToken.IdentifierValue();
for (const auto techniqueTypeIndex : state->m_current_technique_types)
state->m_definition->m_technique_names[techniqueTypeIndex] = techniqueName;
state->m_current_technique_types.clear();
}
};
} // namespace
namespace techset
{
TechsetParser::TechsetParser(SimpleLexer& lexer, const CommonTechniqueTypeNames& techniqueTypeNames)
: AbstractParser(&lexer, std::make_unique<TechsetParserState>(techniqueTypeNames))
{
}
const std::vector<TechsetParser::sequence_t*>& TechsetParser::GetTestsForState()
{
static std::vector<sequence_t*> allTests({
new SequenceTechniqueTypeName(),
new SequenceTechniqueName(),
});
static std::vector<sequence_t*> techniqueTypeNameOnlyTests({
new SequenceTechniqueTypeName(),
});
return m_state->m_current_technique_types.empty() ? techniqueTypeNameOnlyTests : allTests;
}
std::unique_ptr<CommonTechset> TechsetParser::GetParsingResult() const
{
return std::move(m_state->m_definition);
}
} // namespace techset

View File

@@ -0,0 +1,19 @@
#pragma once
#include "Parsing/Impl/AbstractParser.h"
#include "Parsing/Simple/SimpleLexer.h"
#include "Parsing/Simple/SimpleParserValue.h"
#include "TechsetFileParserState.h"
namespace techset
{
class TechsetParser final : public AbstractParser<SimpleParserValue, TechsetParserState>
{
public:
TechsetParser(SimpleLexer& lexer, const CommonTechniqueTypeNames& techniqueTypeNames);
[[nodiscard]] std::unique_ptr<CommonTechset> GetParsingResult() const;
protected:
const std::vector<sequence_t*>& GetTestsForState() override;
};
} // namespace techset

View File

@@ -0,0 +1,10 @@
#include "TechsetFileParserState.h"
namespace techset
{
TechsetParserState::TechsetParserState(const CommonTechniqueTypeNames& techniqueTypeNames)
: m_technique_type_names(techniqueTypeNames),
m_definition(std::make_unique<CommonTechset>(techniqueTypeNames.GetTechniqueTypeCount()))
{
}
} // namespace techset

View File

@@ -0,0 +1,20 @@
#pragma once
#include "Techset/CommonTechset.h"
#include <cstddef>
#include <memory>
#include <vector>
namespace techset
{
class TechsetParserState
{
public:
explicit TechsetParserState(const CommonTechniqueTypeNames& techniqueTypeNames);
const CommonTechniqueTypeNames& m_technique_type_names;
std::unique_ptr<CommonTechset> m_definition;
std::vector<size_t> m_current_technique_types;
};
} // namespace techset