mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-25 22:27:53 -05:00
Add raw templater
This commit is contained in:
38
src/RawTemplater/Templating/DirectiveEscapeStreamProxy.cpp
Normal file
38
src/RawTemplater/Templating/DirectiveEscapeStreamProxy.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "DirectiveEscapeStreamProxy.h"
|
||||
|
||||
using namespace templating;
|
||||
|
||||
DirectiveEscapeStreamProxy::DirectiveEscapeStreamProxy(IParserLineStream* stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
ParserLine DirectiveEscapeStreamProxy::NextLine()
|
||||
{
|
||||
auto line = m_stream->NextLine();
|
||||
|
||||
if (line.m_line.size() >= 2 && line.m_line[0] == '#' && line.m_line[1] == '#')
|
||||
line.m_line = line.m_line.substr(1);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
bool DirectiveEscapeStreamProxy::IncludeFile(const std::string& filename)
|
||||
{
|
||||
return m_stream->IncludeFile(filename);
|
||||
}
|
||||
|
||||
void DirectiveEscapeStreamProxy::PopCurrentFile()
|
||||
{
|
||||
m_stream->PopCurrentFile();
|
||||
}
|
||||
|
||||
bool DirectiveEscapeStreamProxy::IsOpen() const
|
||||
{
|
||||
return m_stream->IsOpen();
|
||||
}
|
||||
|
||||
bool DirectiveEscapeStreamProxy::Eof() const
|
||||
{
|
||||
return m_stream->Eof();
|
||||
}
|
20
src/RawTemplater/Templating/DirectiveEscapeStreamProxy.h
Normal file
20
src/RawTemplater/Templating/DirectiveEscapeStreamProxy.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "Parsing/Impl/AbstractDirectiveStreamProxy.h"
|
||||
|
||||
namespace templating
|
||||
{
|
||||
class DirectiveEscapeStreamProxy final : public AbstractDirectiveStreamProxy
|
||||
{
|
||||
public:
|
||||
explicit DirectiveEscapeStreamProxy(IParserLineStream* stream);
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
void PopCurrentFile() override;
|
||||
_NODISCARD bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
|
||||
private:
|
||||
IParserLineStream* const m_stream;
|
||||
};
|
||||
}
|
354
src/RawTemplater/Templating/Templater.cpp
Normal file
354
src/RawTemplater/Templating/Templater.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
#include "Templater.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "DirectiveEscapeStreamProxy.h"
|
||||
#include "TemplatingStreamProxy.h"
|
||||
#include "Parsing/ParsingException.h"
|
||||
#include "Parsing/Impl/DefinesStreamProxy.h"
|
||||
#include "Parsing/Impl/ParserSingleInputStream.h"
|
||||
|
||||
using namespace templating;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace templating
|
||||
{
|
||||
class TemplatingPass
|
||||
{
|
||||
public:
|
||||
TemplatingPass()
|
||||
: m_stream(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
TemplatingPass(std::istream& stream, const std::string& fileName, ITemplaterControl* templaterControl)
|
||||
{
|
||||
m_base_stream = std::make_unique<ParserSingleInputStream>(stream, fileName);
|
||||
|
||||
m_templating_proxy = std::make_unique<TemplatingStreamProxy>(m_base_stream.get(), templaterControl);
|
||||
m_defines_proxy = std::make_unique<DefinesStreamProxy>(m_templating_proxy.get());
|
||||
m_directive_escape_proxy = std::make_unique<DirectiveEscapeStreamProxy>(m_defines_proxy.get());
|
||||
|
||||
m_templating_proxy->SetDefinesProxy(m_defines_proxy.get());
|
||||
m_stream = m_directive_escape_proxy.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<IParserLineStream> m_base_stream;
|
||||
std::unique_ptr<TemplatingStreamProxy> m_templating_proxy;
|
||||
std::unique_ptr<DefinesStreamProxy> m_defines_proxy;
|
||||
std::unique_ptr<DirectiveEscapeStreamProxy> m_directive_escape_proxy;
|
||||
IParserLineStream* m_stream;
|
||||
};
|
||||
|
||||
enum class TemplatingVariationType
|
||||
{
|
||||
OPTIONS,
|
||||
SWITCH
|
||||
};
|
||||
|
||||
class ITemplatingVariation
|
||||
{
|
||||
protected:
|
||||
ITemplatingVariation() = default;
|
||||
|
||||
public:
|
||||
virtual ~ITemplatingVariation() = default;
|
||||
ITemplatingVariation(const ITemplatingVariation& other) = default;
|
||||
ITemplatingVariation(ITemplatingVariation&& other) noexcept = default;
|
||||
ITemplatingVariation& operator=(const ITemplatingVariation& other) = default;
|
||||
ITemplatingVariation& operator=(ITemplatingVariation&& other) noexcept = default;
|
||||
|
||||
virtual const std::string& GetName() = 0;
|
||||
virtual void Advance() = 0;
|
||||
virtual void Apply(DefinesStreamProxy* definesProxy) = 0;
|
||||
_NODISCARD virtual bool IsFinished() const = 0;
|
||||
_NODISCARD virtual TemplatingVariationType GetVariationType() const = 0;
|
||||
};
|
||||
|
||||
class SwitchVariation final : public ITemplatingVariation
|
||||
{
|
||||
public:
|
||||
explicit SwitchVariation(std::string name)
|
||||
: m_name(std::move(name)),
|
||||
m_should_define(true),
|
||||
m_finished(false)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& GetName() override
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Advance() override
|
||||
{
|
||||
if (!m_should_define)
|
||||
m_finished = true;
|
||||
else
|
||||
m_should_define = false;
|
||||
}
|
||||
|
||||
void Apply(DefinesStreamProxy* definesProxy) override
|
||||
{
|
||||
if (m_should_define)
|
||||
definesProxy->AddDefine(DefinesStreamProxy::Define(m_name, "1"));
|
||||
}
|
||||
|
||||
_NODISCARD bool IsFinished() const override
|
||||
{
|
||||
return m_finished;
|
||||
}
|
||||
|
||||
_NODISCARD TemplatingVariationType GetVariationType() const override
|
||||
{
|
||||
return TemplatingVariationType::SWITCH;
|
||||
}
|
||||
|
||||
std::string m_name;
|
||||
bool m_should_define;
|
||||
bool m_finished;
|
||||
};
|
||||
|
||||
class OptionsVariation final : public ITemplatingVariation
|
||||
{
|
||||
public:
|
||||
OptionsVariation(std::string name, std::vector<std::string> values)
|
||||
: m_name(std::move(name)),
|
||||
m_values(std::move(values)),
|
||||
m_value_offset(0u)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& GetName() override
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Advance() override
|
||||
{
|
||||
m_value_offset++;
|
||||
}
|
||||
|
||||
void Apply(DefinesStreamProxy* definesProxy) override
|
||||
{
|
||||
if (m_value_offset < m_values.size())
|
||||
definesProxy->AddDefine(DefinesStreamProxy::Define(m_name, m_values[m_value_offset]));
|
||||
}
|
||||
|
||||
_NODISCARD bool IsFinished() const override
|
||||
{
|
||||
return m_value_offset >= m_values.size();
|
||||
}
|
||||
|
||||
_NODISCARD TemplatingVariationType GetVariationType() const override
|
||||
{
|
||||
return TemplatingVariationType::OPTIONS;
|
||||
}
|
||||
|
||||
std::string m_name;
|
||||
std::vector<std::string> m_values;
|
||||
size_t m_value_offset;
|
||||
};
|
||||
|
||||
class TemplaterControlImpl final : ITemplaterControl
|
||||
{
|
||||
public:
|
||||
TemplaterControlImpl(std::istream& stream, std::string filename, const std::string& outputDirectory)
|
||||
: m_stream(stream),
|
||||
m_filename(std::move(filename)),
|
||||
m_output_directory(outputDirectory),
|
||||
m_first_line(true),
|
||||
m_write_output_to_file(false)
|
||||
{
|
||||
fs::path filenamePath(m_filename);
|
||||
m_default_output_file = (m_output_directory / filenamePath.replace_extension()).string();
|
||||
}
|
||||
|
||||
bool RunNextPass()
|
||||
{
|
||||
m_stream.clear();
|
||||
m_stream.seekg(0, std::ios::beg);
|
||||
|
||||
m_output_file = m_default_output_file;
|
||||
m_current_pass = TemplatingPass(m_stream, m_filename, this);
|
||||
|
||||
for (const auto& activeVariation : m_active_variations)
|
||||
activeVariation->Apply(m_current_pass.m_defines_proxy.get());
|
||||
|
||||
while (!m_current_pass.m_stream->Eof())
|
||||
{
|
||||
auto nextLine = m_current_pass.m_stream->NextLine();
|
||||
|
||||
if (m_write_output_to_file)
|
||||
{
|
||||
if (m_first_line)
|
||||
m_first_line = false;
|
||||
else
|
||||
m_output_stream << '\n';
|
||||
|
||||
m_output_stream << nextLine.m_line;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_first_line)
|
||||
m_first_line = false;
|
||||
else
|
||||
m_output_cache << '\n';
|
||||
|
||||
m_output_cache << nextLine.m_line;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_write_output_to_file)
|
||||
{
|
||||
m_output_stream = std::ofstream(m_output_file);
|
||||
if (!m_output_stream.is_open())
|
||||
{
|
||||
std::cerr << "Failed to open output file \"" << m_output_file << "\"\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto cachedData = m_output_cache.str();
|
||||
if (!cachedData.empty())
|
||||
m_output_stream << cachedData;
|
||||
}
|
||||
|
||||
m_first_line = true;
|
||||
m_write_output_to_file = false;
|
||||
m_output_cache.clear();
|
||||
m_output_cache.str(std::string());
|
||||
m_output_stream.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AdvanceActiveVariations()
|
||||
{
|
||||
while (!m_active_variations.empty())
|
||||
{
|
||||
const auto& lastVariation = m_active_variations[m_active_variations.size() - 1];
|
||||
lastVariation->Advance();
|
||||
|
||||
if (lastVariation->IsFinished())
|
||||
{
|
||||
m_active_variations_by_name.erase(lastVariation->GetName());
|
||||
m_active_variations.pop_back();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_NODISCARD bool HasActiveVariations() const
|
||||
{
|
||||
return !m_active_variations.empty();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool AddSwitch(std::string switchName) override
|
||||
{
|
||||
const auto existingVariation = m_active_variations_by_name.find(switchName);
|
||||
if (existingVariation != m_active_variations_by_name.end())
|
||||
return existingVariation->second->GetVariationType() == TemplatingVariationType::SWITCH;
|
||||
|
||||
auto switchVariation = std::make_unique<SwitchVariation>(std::move(switchName));
|
||||
if (m_current_pass.m_defines_proxy)
|
||||
switchVariation->Apply(m_current_pass.m_defines_proxy.get());
|
||||
m_active_variations_by_name.emplace(switchVariation->m_name, switchVariation.get());
|
||||
m_active_variations.emplace_back(std::move(switchVariation));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddOptions(std::string optionsName, std::vector<std::string> optionValues) override
|
||||
{
|
||||
const auto existingVariation = m_active_variations_by_name.find(optionsName);
|
||||
if (existingVariation != m_active_variations_by_name.end())
|
||||
return existingVariation->second->GetVariationType() == TemplatingVariationType::SWITCH;
|
||||
|
||||
auto optionsVariation = std::make_unique<OptionsVariation>(std::move(optionsName), std::move(optionValues));
|
||||
if (m_current_pass.m_defines_proxy)
|
||||
optionsVariation->Apply(m_current_pass.m_defines_proxy.get());
|
||||
m_active_variations_by_name.emplace(optionsVariation->m_name, optionsVariation.get());
|
||||
m_active_variations.emplace_back(std::move(optionsVariation));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetFileName(const std::string& fileName) override
|
||||
{
|
||||
if (m_write_output_to_file)
|
||||
return false;
|
||||
|
||||
m_output_file = fileName;
|
||||
m_output_stream = std::ofstream(m_output_file);
|
||||
if (!m_output_stream.is_open())
|
||||
{
|
||||
std::cerr << "Failed to open output file \"" << m_output_file << "\"\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_write_output_to_file = true;
|
||||
const auto cachedData = m_output_cache.str();
|
||||
if (!cachedData.empty())
|
||||
m_output_stream << cachedData;
|
||||
m_output_cache.clear();
|
||||
m_output_cache.str(std::string());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<ITemplatingVariation>> m_active_variations;
|
||||
std::unordered_map<std::string, ITemplatingVariation*> m_active_variations_by_name;
|
||||
TemplatingPass m_current_pass;
|
||||
|
||||
std::istream& m_stream;
|
||||
std::string m_filename;
|
||||
std::string m_output_file;
|
||||
std::string m_default_output_file;
|
||||
const fs::path m_output_directory;
|
||||
|
||||
bool m_first_line;
|
||||
bool m_write_output_to_file;
|
||||
std::ofstream m_output_stream;
|
||||
std::ostringstream m_output_cache;
|
||||
};
|
||||
}
|
||||
|
||||
Templater::Templater(std::istream& stream, std::string fileName)
|
||||
: m_stream(stream),
|
||||
m_file_name(std::move(fileName))
|
||||
{
|
||||
}
|
||||
|
||||
bool Templater::TemplateToDirectory(const std::string& outputDirectory)
|
||||
{
|
||||
TemplaterControlImpl control(m_stream, m_file_name, outputDirectory);
|
||||
|
||||
try
|
||||
{
|
||||
if (!control.RunNextPass())
|
||||
return false;
|
||||
|
||||
control.AdvanceActiveVariations();
|
||||
while (control.HasActiveVariations())
|
||||
{
|
||||
if (!control.RunNextPass())
|
||||
return false;
|
||||
|
||||
control.AdvanceActiveVariations();
|
||||
}
|
||||
}
|
||||
catch (ParsingException& e)
|
||||
{
|
||||
std::cerr << "Error: " << e.FullMessage() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
19
src/RawTemplater/Templating/Templater.h
Normal file
19
src/RawTemplater/Templating/Templater.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "Parsing/IParserLineStream.h"
|
||||
|
||||
namespace templating
|
||||
{
|
||||
class Templater
|
||||
{
|
||||
public:
|
||||
Templater(std::istream& stream, std::string fileName);
|
||||
|
||||
bool TemplateToDirectory(const std::string& outputDirectory);
|
||||
|
||||
private:
|
||||
std::istream& m_stream;
|
||||
std::string m_file_name;
|
||||
};
|
||||
}
|
196
src/RawTemplater/Templating/TemplatingStreamProxy.cpp
Normal file
196
src/RawTemplater/Templating/TemplatingStreamProxy.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "TemplatingStreamProxy.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Parsing/ParsingException.h"
|
||||
|
||||
using namespace templating;
|
||||
|
||||
TemplatingStreamProxy::TemplatingStreamProxy(IParserLineStream* stream, ITemplaterControl* templaterControl)
|
||||
: m_stream(stream),
|
||||
m_templater_control(templaterControl),
|
||||
m_defines_proxy(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void TemplatingStreamProxy::SetDefinesProxy(DefinesStreamProxy* definesProxy)
|
||||
{
|
||||
m_defines_proxy = definesProxy;
|
||||
}
|
||||
|
||||
bool TemplatingStreamProxy::MatchSwitchDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) const
|
||||
{
|
||||
auto currentPosition = directiveStartPosition;
|
||||
|
||||
if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(PRAGMA_DIRECTIVE)
|
||||
|| !MatchString(line, currentPosition, PRAGMA_DIRECTIVE, std::char_traits<char>::length(PRAGMA_DIRECTIVE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
return false;
|
||||
|
||||
if (!MatchString(line, currentPosition, SWITCH_PRAGMA_COMMAND, std::char_traits<char>::length(SWITCH_PRAGMA_COMMAND)))
|
||||
return false;
|
||||
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid switch directive.");
|
||||
|
||||
const auto nameStartPosition = currentPosition;
|
||||
if (!ExtractIdentifier(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid switch directive.");
|
||||
|
||||
auto name = line.m_line.substr(nameStartPosition, currentPosition - nameStartPosition);
|
||||
|
||||
std::cout << "Switch: \"" << name << "\"\n";
|
||||
m_templater_control->AddSwitch(std::move(name));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TemplatingStreamProxy::MatchOptionsDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) const
|
||||
{
|
||||
auto currentPosition = directiveStartPosition;
|
||||
|
||||
if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(PRAGMA_DIRECTIVE)
|
||||
|| !MatchString(line, currentPosition, PRAGMA_DIRECTIVE, std::char_traits<char>::length(PRAGMA_DIRECTIVE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
return false;
|
||||
|
||||
if (!MatchString(line, currentPosition, OPTIONS_PRAGMA_COMMAND, std::char_traits<char>::length(OPTIONS_PRAGMA_COMMAND)))
|
||||
return false;
|
||||
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
const auto nameStartPosition = currentPosition;
|
||||
if (!ExtractIdentifier(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
auto name = line.m_line.substr(nameStartPosition, currentPosition - nameStartPosition);
|
||||
|
||||
if (!MatchNextCharacter(line, currentPosition, '('))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
std::vector<std::string> options;
|
||||
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
bool firstArg = true;
|
||||
while (!MatchNextCharacter(line, currentPosition, ')'))
|
||||
{
|
||||
if (!firstArg && !MatchNextCharacter(line, currentPosition, ','))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
const auto optionStartPosition = currentPosition;
|
||||
if (!ExtractIdentifier(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
std::ostringstream optionValueBuilder;
|
||||
optionValueBuilder << '"' << line.m_line.substr(optionStartPosition, currentPosition - optionStartPosition) << '"';
|
||||
options.emplace_back(optionValueBuilder.str());
|
||||
|
||||
firstArg = false;
|
||||
}
|
||||
|
||||
std::cout << "Options: \"" << name << "\" with values:\n";
|
||||
for (const auto& option : options)
|
||||
std::cout << " Value: " << option << "\n";
|
||||
|
||||
m_templater_control->AddOptions(std::move(name), std::move(options));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TemplatingStreamProxy::MatchFilenameDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) const
|
||||
{
|
||||
auto currentPosition = directiveStartPosition;
|
||||
|
||||
if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(PRAGMA_DIRECTIVE)
|
||||
|| !MatchString(line, currentPosition, PRAGMA_DIRECTIVE, std::char_traits<char>::length(PRAGMA_DIRECTIVE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
return false;
|
||||
|
||||
if (!MatchString(line, currentPosition, FILENAME_PRAGMA_COMMAND, std::char_traits<char>::length(FILENAME_PRAGMA_COMMAND)))
|
||||
return false;
|
||||
|
||||
if (!SkipWhitespace(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
const auto expressionString = line.m_line.substr(currentPosition, line.m_line.size() - currentPosition);
|
||||
if (expressionString.empty())
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Cannot pragma filename without an expression.");
|
||||
|
||||
ParserLine expressionStringAsLine(line.m_filename, line.m_line_number, expressionString);
|
||||
m_defines_proxy->ExpandDefines(expressionStringAsLine);
|
||||
|
||||
const auto expression = m_defines_proxy->ParseExpression(expressionStringAsLine.m_line);
|
||||
if (!expression)
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Failed to parse pragma filename expression");
|
||||
|
||||
if (!expression->IsStatic())
|
||||
throw ParsingException(CreatePos(line, currentPosition), "pragma filename expression must be static");
|
||||
|
||||
const auto value = expression->EvaluateStatic();
|
||||
|
||||
if (value.m_type != SimpleExpressionValue::Type::STRING)
|
||||
throw ParsingException(CreatePos(line, currentPosition), "pragma filename expression must evaluate to string");
|
||||
|
||||
std::cout << "Filename: \"" << *value.m_string_value << "\"\n";
|
||||
m_templater_control->SetFileName(*value.m_string_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TemplatingStreamProxy::MatchDirectives(const ParserLine& line)
|
||||
{
|
||||
unsigned directiveStartPos, directiveEndPos;
|
||||
|
||||
if (!FindDirective(line, directiveStartPos, directiveEndPos))
|
||||
return false;
|
||||
|
||||
directiveStartPos++;
|
||||
|
||||
return MatchSwitchDirective(line, directiveStartPos, directiveEndPos)
|
||||
|| MatchOptionsDirective(line, directiveStartPos, directiveEndPos)
|
||||
|| MatchFilenameDirective(line, directiveStartPos, directiveEndPos);
|
||||
}
|
||||
|
||||
ParserLine TemplatingStreamProxy::NextLine()
|
||||
{
|
||||
auto line = m_stream->NextLine();
|
||||
|
||||
while (MatchDirectives(line))
|
||||
line = m_stream->NextLine();
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
bool TemplatingStreamProxy::IncludeFile(const std::string& filename)
|
||||
{
|
||||
return m_stream->IncludeFile(filename);
|
||||
}
|
||||
|
||||
void TemplatingStreamProxy::PopCurrentFile()
|
||||
{
|
||||
m_stream->PopCurrentFile();
|
||||
}
|
||||
|
||||
bool TemplatingStreamProxy::IsOpen() const
|
||||
{
|
||||
return m_stream->IsOpen();
|
||||
}
|
||||
|
||||
bool TemplatingStreamProxy::Eof() const
|
||||
{
|
||||
return m_stream->Eof();
|
||||
}
|
54
src/RawTemplater/Templating/TemplatingStreamProxy.h
Normal file
54
src/RawTemplater/Templating/TemplatingStreamProxy.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Parsing/Impl/AbstractDirectiveStreamProxy.h"
|
||||
#include "Parsing/Impl/DefinesStreamProxy.h"
|
||||
|
||||
namespace templating
|
||||
{
|
||||
class ITemplaterControl
|
||||
{
|
||||
protected:
|
||||
ITemplaterControl() = default;
|
||||
|
||||
public:
|
||||
virtual ~ITemplaterControl() = default;
|
||||
ITemplaterControl(const ITemplaterControl& other) = default;
|
||||
ITemplaterControl(ITemplaterControl&& other) noexcept = default;
|
||||
ITemplaterControl& operator=(const ITemplaterControl& other) = default;
|
||||
ITemplaterControl& operator=(ITemplaterControl&& other) noexcept = default;
|
||||
|
||||
virtual bool AddSwitch(std::string switchName) = 0;
|
||||
virtual bool AddOptions(std::string optionsName, std::vector<std::string> optionValues) = 0;
|
||||
virtual bool SetFileName(const std::string& fileName) = 0;
|
||||
};
|
||||
|
||||
class TemplatingStreamProxy final : public AbstractDirectiveStreamProxy
|
||||
{
|
||||
public:
|
||||
TemplatingStreamProxy(IParserLineStream* stream, ITemplaterControl* templaterControl);
|
||||
|
||||
void SetDefinesProxy(DefinesStreamProxy* definesProxy);
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
void PopCurrentFile() override;
|
||||
_NODISCARD bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
|
||||
private:
|
||||
static constexpr const char* PRAGMA_DIRECTIVE = "pragma";
|
||||
static constexpr const char* SWITCH_PRAGMA_COMMAND = "switch";
|
||||
static constexpr const char* OPTIONS_PRAGMA_COMMAND = "options";
|
||||
static constexpr const char* FILENAME_PRAGMA_COMMAND = "filename";
|
||||
|
||||
_NODISCARD bool MatchSwitchDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition) const;
|
||||
_NODISCARD bool MatchOptionsDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition) const;
|
||||
_NODISCARD bool MatchFilenameDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition) const;
|
||||
bool MatchDirectives(const ParserLine& line);
|
||||
|
||||
IParserLineStream* const m_stream;
|
||||
ITemplaterControl* const m_templater_control;
|
||||
DefinesStreamProxy* m_defines_proxy;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user