Add ParserMultiInputStream

This commit is contained in:
Jan 2021-10-31 14:53:05 +01:00
parent d5a8d038a6
commit dcffa3d14d
8 changed files with 160 additions and 16 deletions

View File

@ -2,7 +2,7 @@
#include "LocalizeFileParser.h"
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
#include "Parsing/Impl/ParserInputStream.h"
#include "Parsing/Impl/ParserSingleInputStream.h"
LocalizeFileReader::LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language)
: m_file_name(std::move(fileName)),
@ -16,7 +16,7 @@ LocalizeFileReader::LocalizeFileReader(std::istream& stream, std::string fileNam
bool LocalizeFileReader::OpenBaseStream(std::istream& stream)
{
m_open_streams.emplace_back(std::make_unique<ParserInputStream>(stream, m_file_name));
m_open_streams.emplace_back(std::make_unique<ParserSingleInputStream>(stream, m_file_name));
return true;
}

View File

@ -4,7 +4,7 @@
#include <sstream>
#include <cmath>
#include "Parsing/Impl/ParserInputStream.h"
#include "Parsing/Impl/ParserSingleInputStream.h"
#include "Parsing/Simple/SimpleLexer.h"
AbstractMenuDumper::AbstractMenuDumper(std::ostream& stream)
@ -65,7 +65,7 @@ std::vector<std::string> AbstractMenuDumper::CreateScriptTokenList(const char* s
{
const std::string scriptString(script);
std::istringstream stringStream(scriptString);
ParserInputStream inputStream(stringStream, "MenuScript");
ParserSingleInputStream inputStream(stringStream, "MenuScript");
SimpleLexer lexer(&inputStream, SimpleLexer::Config{false, true, false});
std::vector<std::string> result;

View File

@ -65,7 +65,7 @@ bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, unsigne
unsigned filenameStart, filenameEnd;
if (!ExtractIncludeFilename(line, directivePosition, filenameStart, filenameEnd))
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, directivePosition), INCLUDE_QUOTES_ERROR);
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(directivePosition)), INCLUDE_QUOTES_ERROR);
if (filenameEnd <= filenameStart)
throw ParsingException(CreatePos(line, directivePosition), "No filename specified");

View File

@ -0,0 +1,104 @@
#include "ParserMultiInputStream.h"
#include <sstream>
ParserMultiInputStream::FileInfo::FileInfo(std::unique_ptr<std::istream> stream, std::string filePath)
: m_owned_stream(std::move(stream)),
m_stream(*m_owned_stream),
m_file_path(std::move(filePath)),
m_line_number(1)
{
}
ParserMultiInputStream::FileInfo::FileInfo(std::istream& stream, std::string filePath)
: m_stream(stream),
m_file_path(std::move(filePath)),
m_line_number(1)
{
}
ParserMultiInputStream::ParserMultiInputStream(std::unique_ptr<std::istream> stream, std::string fileName, include_callback_t includeCallback)
: m_include_callback(std::move(includeCallback))
{
m_files.emplace(std::move(stream), std::move(fileName));
}
ParserMultiInputStream::ParserMultiInputStream(std::istream& stream, std::string fileName, include_callback_t includeCallback)
: m_include_callback(std::move(includeCallback))
{
m_files.emplace(stream, std::move(fileName));
}
ParserLine ParserMultiInputStream::NextLine()
{
std::ostringstream str;
auto hasLength = false;
if (m_files.empty())
return ParserLine();
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();
}
bool ParserMultiInputStream::IncludeFile(const std::string& filename)
{
if (!m_include_callback)
return false;
auto newFile = m_include_callback(filename);
if (!newFile)
return false;
m_files.emplace(std::move(newFile), filename);
return true;
}
void ParserMultiInputStream::PopCurrentFile()
{
if (!m_files.empty())
m_files.pop();
}
bool ParserMultiInputStream::IsOpen() const
{
return !m_files.empty();
}
bool ParserMultiInputStream::Eof() const
{
return m_files.empty();
}

View File

@ -0,0 +1,40 @@
#pragma once
#include <istream>
#include <stack>
#include <memory>
#include <functional>
#include "Parsing/IParserLineStream.h"
class ParserMultiInputStream final : public IParserLineStream
{
public:
using include_callback_t = std::function<std::unique_ptr<std::istream>(const std::string& filename)>;
private:
class FileInfo
{
public:
std::unique_ptr<std::istream> m_owned_stream;
std::istream& m_stream;
std::string m_file_path;
int m_line_number;
FileInfo(std::unique_ptr<std::istream> stream, std::string filePath);
FileInfo(std::istream& stream, std::string filePath);
};
const include_callback_t m_include_callback;
std::stack<FileInfo> m_files;
public:
ParserMultiInputStream(std::unique_ptr<std::istream> stream, std::string fileName, include_callback_t includeCallback);
ParserMultiInputStream(std::istream& stream, std::string fileName, include_callback_t includeCallback);
ParserLine NextLine() override;
bool IncludeFile(const std::string& filename) override;
void PopCurrentFile() override;
_NODISCARD bool IsOpen() const override;
_NODISCARD bool Eof() const override;
};

View File

@ -1,15 +1,15 @@
#include "ParserInputStream.h"
#include "ParserSingleInputStream.h"
#include <sstream>
ParserInputStream::ParserInputStream(std::istream& stream, std::string fileName)
ParserSingleInputStream::ParserSingleInputStream(std::istream& stream, std::string fileName)
: m_stream(stream),
m_file_name(std::move(fileName)),
m_line_number(1)
{
}
ParserLine ParserInputStream::NextLine()
ParserLine ParserSingleInputStream::NextLine()
{
std::ostringstream str;
auto hasLength = false;
@ -45,21 +45,21 @@ ParserLine ParserInputStream::NextLine()
return ParserLine();
}
bool ParserInputStream::IncludeFile(const std::string& filename)
bool ParserSingleInputStream::IncludeFile(const std::string& filename)
{
return false;
}
void ParserInputStream::PopCurrentFile()
void ParserSingleInputStream::PopCurrentFile()
{
}
bool ParserInputStream::IsOpen() const
bool ParserSingleInputStream::IsOpen() const
{
return !m_stream.eof();
}
bool ParserInputStream::Eof() const
bool ParserSingleInputStream::Eof() const
{
return !m_stream.eof();
}

View File

@ -4,14 +4,14 @@
#include "Parsing/IParserLineStream.h"
class ParserInputStream final : public IParserLineStream
class ParserSingleInputStream final : public IParserLineStream
{
std::istream& m_stream;
std::string m_file_name;
int m_line_number;
public:
ParserInputStream(std::istream& stream, std::string fileName);
ParserSingleInputStream(std::istream& stream, std::string fileName);
ParserLine NextLine() override;
bool IncludeFile(const std::string& filename) override;

View File

@ -2,7 +2,7 @@
#include <chrono>
#include "Parsing/Impl/ParserInputStream.h"
#include "Parsing/Impl/ParserSingleInputStream.h"
#include <Parsing/Impl/CommentRemovingStreamProxy.h>
#include "Parsing/Impl/DefinesStreamProxy.h"
@ -22,7 +22,7 @@ ZoneDefinitionInputStream::ZoneDefinitionInputStream(std::istream& stream, std::
bool ZoneDefinitionInputStream::OpenBaseStream(std::istream& stream)
{
m_open_streams.emplace_back(std::make_unique<ParserInputStream>(stream, m_file_name));
m_open_streams.emplace_back(std::make_unique<ParserSingleInputStream>(stream, m_file_name));
return true;
}