Add stream proxy for declaring pack values

This commit is contained in:
Jan 2021-02-14 10:27:18 +01:00
parent efa39a8ac3
commit 3f08be0564
6 changed files with 188 additions and 1 deletions

View File

@ -8,11 +8,13 @@
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
#include "Parsing/Impl/DefinesStreamProxy.h"
#include "Parsing/Impl/IncludingStreamProxy.h"
#include "Parsing/Impl/PackDefinitionStreamProxy.h"
#include "Parsing/Impl/ParserFilesystemStream.h"
HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
: m_args(args),
m_filename(std::move(filename)),
m_pack_value_supplier(nullptr),
m_stream(nullptr)
{
}
@ -35,13 +37,16 @@ void HeaderFileReader::SetupStreamProxies()
{
auto commentProxy = std::make_unique<CommentRemovingStreamProxy>(m_stream);
auto includeProxy = std::make_unique<IncludingStreamProxy>(commentProxy.get());
auto definesProxy = std::make_unique<DefinesStreamProxy>(includeProxy.get());
auto packProxy = std::make_unique<PackDefinitionStreamProxy>(includeProxy.get());
auto definesProxy = std::make_unique<DefinesStreamProxy>(packProxy.get());
definesProxy->AddDefine(ZONE_CODE_GENERATOR_DEFINE_NAME, ZONE_CODE_GENERATOR_DEFINE_VALUE);
m_pack_value_supplier = packProxy.get();
m_stream = definesProxy.get();
m_open_streams.emplace_back(std::move(commentProxy));
m_open_streams.emplace_back(std::move(includeProxy));
m_open_streams.emplace_back(std::move(packProxy));
m_open_streams.emplace_back(std::move(definesProxy));
}

View File

@ -3,6 +3,7 @@
#include <string>
#include "ZoneCodeGeneratorArguments.h"
#include "Parsing/IPackValueSupplier.h"
#include "Parsing/IParserLineStream.h"
#include "Persistence/IDataRepository.h"
@ -15,6 +16,7 @@ class HeaderFileReader
std::string m_filename;
std::vector<std::unique_ptr<IParserLineStream>> m_open_streams;
IPackValueSupplier* m_pack_value_supplier;
IParserLineStream* m_stream;
bool OpenBaseStream();

View File

@ -0,0 +1,14 @@
#pragma once
class IPackValueSupplier
{
public:
IPackValueSupplier() = default;
virtual ~IPackValueSupplier() = default;
IPackValueSupplier(const IPackValueSupplier& other) = default;
IPackValueSupplier(IPackValueSupplier&& other) noexcept = default;
IPackValueSupplier& operator=(const IPackValueSupplier& other) = default;
IPackValueSupplier& operator=(IPackValueSupplier&& other) noexcept = default;
virtual int GetCurrentPack() = 0;
};

View File

@ -0,0 +1,92 @@
#include "PackDefinitionStreamProxy.h"
#include "Parsing/ParsingException.h"
PackDefinitionStreamProxy::PackDefinitionStreamProxy(IParserLineStream* stream)
: m_stream(stream)
{
}
bool PackDefinitionStreamProxy::MatchPackDirective(const ParserLine& line, unsigned directivePosition)
{
auto packValue = 0;
if (!MatchString(line, directivePosition, PRAGMA_PACK_DIRECTIVE, std::char_traits<char>::length(PRAGMA_PACK_DIRECTIVE)))
return false;
if (!MatchNextCharacter(line, directivePosition, '('))
throw ParsingException(CreatePos(line, directivePosition), "Invalid pack directive.");
bool isPush;
if (MatchNextString(line, directivePosition, PUSH_KEYWORD, std::char_traits<char>::length(PUSH_KEYWORD)))
isPush = true;
else if (MatchNextString(line, directivePosition, POP_KEYWORD, std::char_traits<char>::length(POP_KEYWORD)))
isPush = false;
else
throw ParsingException(CreatePos(line, directivePosition), "Unknown pack directive command.");
if(isPush)
{
if (!MatchNextCharacter(line, directivePosition, ','))
throw ParsingException(CreatePos(line, directivePosition), "Invalid pack directive.");
if (!ExtractInteger(line, directivePosition, packValue))
throw ParsingException(CreatePos(line, directivePosition), "Invalid pack value.");
}
if (!MatchNextCharacter(line, directivePosition, ')'))
throw ParsingException(CreatePos(line, directivePosition), "Invalid pack directive.");
if(isPush)
m_current_pack.push(packValue);
else if (!m_current_pack.empty())
m_current_pack.pop();
return true;
}
bool PackDefinitionStreamProxy::MatchDirectives(const ParserLine& line)
{
unsigned directivePos;
if (!FindDirective(line, directivePos))
return false;
directivePos++;
return MatchPackDirective(line, directivePos);
}
ParserLine PackDefinitionStreamProxy::NextLine()
{
auto line = m_stream->NextLine();
while (MatchDirectives(line))
line = m_stream->NextLine();
return line;
}
bool PackDefinitionStreamProxy::IncludeFile(const std::string& filename)
{
return m_stream->IncludeFile(filename);
}
void PackDefinitionStreamProxy::PopCurrentFile()
{
m_stream->PopCurrentFile();
}
bool PackDefinitionStreamProxy::IsOpen() const
{
return m_stream->IsOpen();
}
bool PackDefinitionStreamProxy::Eof() const
{
return m_stream->Eof();
}
int PackDefinitionStreamProxy::GetCurrentPack()
{
return m_current_pack.empty() ? DEFAULT_PACK : m_current_pack.top();
}

View File

@ -0,0 +1,35 @@
#pragma once
#include <stack>
#include "AbstractDirectiveStreamProxy.h"
#include "Parsing/IPackValueSupplier.h"
#include "Parsing/IParserLineStream.h"
class PackDefinitionStreamProxy final : public AbstractDirectiveStreamProxy, public IPackValueSupplier
{
public:
static constexpr int DEFAULT_PACK = 8;
private:
static constexpr const char* PRAGMA_PACK_DIRECTIVE = "pragma pack";
static constexpr const char* PUSH_KEYWORD = "push";
static constexpr const char* POP_KEYWORD = "pop";
IParserLineStream* const m_stream;
std::stack<int> m_current_pack;
_NODISCARD bool MatchPackDirective(const ParserLine& line, unsigned directivePosition);
_NODISCARD bool MatchDirectives(const ParserLine& line);
public:
explicit PackDefinitionStreamProxy(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;
int GetCurrentPack() override;
};

View File

@ -0,0 +1,39 @@
#include <catch2/catch.hpp>
#include "Parsing/Impl/PackDefinitionStreamProxy.h"
#include "Parsing/Mock/MockParserLineStream.h"
namespace test::parsing::impl::pack_definition_stream_proxy
{
void ExpectLine(IParserLineStream* stream, const int lineNumber, const std::string& value)
{
auto line = stream->NextLine();
REQUIRE(line.m_line_number == lineNumber);
REQUIRE(line.m_line == value);
}
TEST_CASE("PackDefinitionStreamProxy: Ensure simple pack directives are working", "[parsing][parsingstream]")
{
const std::vector<std::string> lines
{
"hello world",
"#pragma pack(push, 32)",
"hello galaxy",
"#pragma pack(pop)",
"hello universe"
};
MockParserLineStream mockStream(lines);
PackDefinitionStreamProxy proxy(&mockStream);
REQUIRE(proxy.GetCurrentPack() == PackDefinitionStreamProxy::DEFAULT_PACK);
ExpectLine(&proxy, 1, "hello world");
REQUIRE(proxy.GetCurrentPack() == PackDefinitionStreamProxy::DEFAULT_PACK);
ExpectLine(&proxy, 3, "hello galaxy");
REQUIRE(proxy.GetCurrentPack() == 32);
ExpectLine(&proxy, 5, "hello universe");
REQUIRE(proxy.GetCurrentPack() == PackDefinitionStreamProxy::DEFAULT_PACK);
REQUIRE(proxy.Eof());
}
}