mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-09-05 00:07:25 +00:00
Add file inclusion for ZCG cpp
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Parsing/IParserLineStream.h"
|
||||
|
||||
class CommentRemovingStreamProxy final : IParserLineStream
|
||||
{
|
||||
public:
|
||||
std::string NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
};
|
116
src/ZoneCodeGeneratorNew/Parsing/Impl/IncludingStreamProxy.cpp
Normal file
116
src/ZoneCodeGeneratorNew/Parsing/Impl/IncludingStreamProxy.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "IncludingStreamProxy.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "Parsing/ParsingException.h"
|
||||
|
||||
IncludingStreamProxy::IncludingStreamProxy(IParserLineStream* stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line) const
|
||||
{
|
||||
unsigned includeDirectivePos = 0;
|
||||
auto hasIncludeDirective = false;
|
||||
|
||||
for (; includeDirectivePos < line.m_line.size() - INCLUDE_DIRECTIVE_MINIMUM_TOTAL_LENGTH; includeDirectivePos++)
|
||||
{
|
||||
const auto c = line.m_line[includeDirectivePos];
|
||||
|
||||
if (isspace(c))
|
||||
continue;
|
||||
|
||||
if (c != '#')
|
||||
return false;
|
||||
|
||||
if (line.m_line.compare(includeDirectivePos + 1, INCLUDE_DIRECTIVE_LENGTH, INCLUDE_DIRECTIVE) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
hasIncludeDirective = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hasIncludeDirective)
|
||||
return false;
|
||||
|
||||
auto currentPos = includeDirectivePos + INCLUDE_DIRECTIVE_LENGTH + 1;
|
||||
bool isDoubleQuotes;
|
||||
if (line.m_line[currentPos] == '"')
|
||||
isDoubleQuotes = true;
|
||||
else if (line.m_line[currentPos] == '<')
|
||||
isDoubleQuotes = false;
|
||||
else
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR);
|
||||
|
||||
const auto filenameStart = ++currentPos;
|
||||
unsigned filenameEnd = 0;
|
||||
auto filenameHasEnd = false;
|
||||
|
||||
for (; currentPos < line.m_line.size(); currentPos++)
|
||||
{
|
||||
const auto c = line.m_line[currentPos];
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
if(!isDoubleQuotes)
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), "");
|
||||
filenameEnd = currentPos;
|
||||
filenameHasEnd = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '>')
|
||||
{
|
||||
if (isDoubleQuotes)
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR);
|
||||
filenameEnd = currentPos;
|
||||
filenameHasEnd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!filenameHasEnd)
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR);
|
||||
|
||||
if(filenameEnd <= filenameStart)
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), "No filename specified");
|
||||
|
||||
const auto filename = line.m_line.substr(filenameStart, filenameEnd - filenameStart);
|
||||
|
||||
if(!m_stream->IncludeFile(filename))
|
||||
{
|
||||
std::ostringstream errorStr;
|
||||
errorStr << "Could not include file \"" << filename << "\"";
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), errorStr.str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ParserLine IncludingStreamProxy::NextLine()
|
||||
{
|
||||
auto line = m_stream->NextLine();
|
||||
|
||||
if (MatchIncludeDirective(line))
|
||||
return m_stream->NextLine();
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::IncludeFile(const std::string& filename)
|
||||
{
|
||||
return m_stream->IncludeFile(filename);
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::IsOpen() const
|
||||
{
|
||||
return m_stream->IsOpen();
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::Eof() const
|
||||
{
|
||||
return m_stream->Eof();
|
||||
}
|
23
src/ZoneCodeGeneratorNew/Parsing/Impl/IncludingStreamProxy.h
Normal file
23
src/ZoneCodeGeneratorNew/Parsing/Impl/IncludingStreamProxy.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "Parsing/IParserLineStream.h"
|
||||
|
||||
class IncludingStreamProxy final : public IParserLineStream
|
||||
{
|
||||
static constexpr const char* INCLUDE_QUOTES_ERROR = "Invalid include directive. Expected \"\" or <>";
|
||||
static constexpr const char* INCLUDE_DIRECTIVE = "include ";
|
||||
static constexpr int INCLUDE_DIRECTIVE_LENGTH = std::char_traits<char>::length(INCLUDE_DIRECTIVE);
|
||||
static constexpr int INCLUDE_DIRECTIVE_MINIMUM_TOTAL_LENGTH = INCLUDE_DIRECTIVE_LENGTH + 1 + 2; // #=+1 ""=+2
|
||||
|
||||
IParserLineStream* m_stream;
|
||||
|
||||
bool MatchIncludeDirective(const ParserLine& line) const;
|
||||
|
||||
public:
|
||||
explicit IncludingStreamProxy(IParserLineStream* stream);
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
_NODISCARD bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
};
|
@@ -0,0 +1,93 @@
|
||||
#include "ParserFilesystemStream.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const std::string ParserFilesystemStream::EMPTY_FILE_NAME;
|
||||
|
||||
ParserFilesystemStream::FileInfo::FileInfo(std::string filePath)
|
||||
: m_file_path(std::move(filePath)),
|
||||
m_stream(m_file_path),
|
||||
m_line_number(1)
|
||||
{
|
||||
}
|
||||
|
||||
ParserFilesystemStream::ParserFilesystemStream(std::string path)
|
||||
{
|
||||
m_files.emplace(FileInfo(std::move(path)));
|
||||
}
|
||||
|
||||
bool ParserFilesystemStream::IsOpen() const
|
||||
{
|
||||
return !m_files.empty()
|
||||
&& m_files.top().m_stream.is_open();
|
||||
}
|
||||
|
||||
ParserLine ParserFilesystemStream::NextLine()
|
||||
{
|
||||
std::ostringstream str;
|
||||
auto hasLength = false;
|
||||
|
||||
if (m_files.empty())
|
||||
return ParserLine(EMPTY_FILE_NAME, 0, std::string());
|
||||
|
||||
while(!m_files.empty())
|
||||
{
|
||||
auto& fileInfo = m_files.top();
|
||||
|
||||
auto c = fileInfo.m_stream.get();
|
||||
while (c != EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
c = fileInfo.m_stream.get();
|
||||
if (c == '\n')
|
||||
return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number++, str.str());
|
||||
str << '\r';
|
||||
hasLength = true;
|
||||
continue;
|
||||
|
||||
case '\n':
|
||||
return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number++, str.str());
|
||||
|
||||
default:
|
||||
str << static_cast<char>(c);
|
||||
hasLength = true;
|
||||
break;
|
||||
}
|
||||
|
||||
c = fileInfo.m_stream.get();
|
||||
}
|
||||
|
||||
if(hasLength)
|
||||
return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number, str.str());
|
||||
m_files.pop();
|
||||
}
|
||||
|
||||
return ParserLine(EMPTY_FILE_NAME, 0, std::string());
|
||||
}
|
||||
|
||||
bool ParserFilesystemStream::IncludeFile(const std::string& filename)
|
||||
{
|
||||
if (m_files.empty())
|
||||
return false;
|
||||
|
||||
const auto newFilePath = fs::path(m_files.top().m_file_path).remove_filename().concat(filename);
|
||||
|
||||
FileInfo fileInfo(newFilePath.string());
|
||||
|
||||
if (!fileInfo.m_stream.is_open())
|
||||
return false;
|
||||
|
||||
m_files.emplace(std::move(fileInfo));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserFilesystemStream::Eof() const
|
||||
{
|
||||
return m_files.empty()
|
||||
|| m_files.top().m_stream.eof();
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <stack>
|
||||
#include <fstream>
|
||||
|
||||
#include "Parsing/IParserLineStream.h"
|
||||
|
||||
class ParserFilesystemStream final : public IParserLineStream
|
||||
{
|
||||
static const std::string EMPTY_FILE_NAME;
|
||||
|
||||
class FileInfo
|
||||
{
|
||||
public:
|
||||
std::string m_file_path;
|
||||
std::ifstream m_stream;
|
||||
int m_line_number;
|
||||
|
||||
explicit FileInfo(std::string filePath);
|
||||
};
|
||||
std::stack<FileInfo> m_files;
|
||||
|
||||
public:
|
||||
explicit ParserFilesystemStream(std::string path);
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
_NODISCARD bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
};
|
Reference in New Issue
Block a user