mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
Add file inclusion for ZCG cpp
This commit is contained in:
parent
21440daf27
commit
d876bc5e25
0
src/ZoneCodeGeneratorNew/Parsing/AbstractLexer.cpp
Normal file
0
src/ZoneCodeGeneratorNew/Parsing/AbstractLexer.cpp
Normal file
37
src/ZoneCodeGeneratorNew/Parsing/AbstractLexer.h
Normal file
37
src/ZoneCodeGeneratorNew/Parsing/AbstractLexer.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include "ILexer.h"
|
||||||
|
#include "IParserLineStream.h"
|
||||||
|
|
||||||
|
template <typename TokenType>
|
||||||
|
class AbstractLexer : public ILexer
|
||||||
|
{
|
||||||
|
std::deque<TokenType> m_token_cache;
|
||||||
|
IParserLineStream* const m_stream;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit AbstractLexer(IParserLineStream* stream)
|
||||||
|
: m_stream(stream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual TokenType GetNextToken() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const TokenType& GetToken(int index)
|
||||||
|
{
|
||||||
|
assert(index >= 0);
|
||||||
|
while (index <= m_token_cache.size())
|
||||||
|
m_token_cache.emplace_back(std::move(GetNextToken()));
|
||||||
|
|
||||||
|
return m_token_cache[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopTokens(int amount) override
|
||||||
|
{
|
||||||
|
m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount);
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,11 @@
|
|||||||
|
#include "CommandsLexer.h"
|
||||||
|
|
||||||
|
CommandsLexer::CommandsLexer(IParserLineStream* stream)
|
||||||
|
: AbstractLexer(stream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsLexer::GetNextToken()
|
||||||
|
{
|
||||||
|
return CommandsParserValue::Invalid(TokenPos());
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CommandsParserValue.h"
|
||||||
|
#include "Parsing/AbstractLexer.h"
|
||||||
|
|
||||||
|
class CommandsLexer final : public AbstractLexer<CommandsParserValue>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
CommandsParserValue GetNextToken() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CommandsLexer(IParserLineStream* stream);
|
||||||
|
};
|
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CommandsParser
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
@ -0,0 +1,174 @@
|
|||||||
|
#include "CommandsParserValue.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::Invalid(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::INVALID);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::EndOfFile(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::END_OF_FILE);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::Character(const TokenPos pos, const char c)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, c);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::ShiftLeft(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::SHIFT_LEFT);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::ShiftRight(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::SHIFT_RIGHT);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::Equals(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::EQUALS);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::NotEqual(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::NOT_EQUAL);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::GreaterEqual(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::GREATER_EQUAL);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::LessEqual(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::LESS_EQUAL);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::LogicalAnd(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::LOGICAL_AND);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::LogicalOr(const TokenPos pos)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::LOGICAL_OR);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::Integer(const TokenPos pos, const int value)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::INTEGER);
|
||||||
|
pv.m_value.int_value = value;
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::FloatingPoint(const TokenPos pos, const double value)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::FLOATING_POINT);
|
||||||
|
pv.m_value.double_value = value;
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::String(const TokenPos pos, std::string* stringValue)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::STRING);
|
||||||
|
pv.m_value.string_value = stringValue;
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::Identifier(const TokenPos pos, std::string* identifier)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::IDENTIFIER);
|
||||||
|
pv.m_value.string_value = identifier;
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue CommandsParserValue::TypeName(const TokenPos pos, std::string* typeName)
|
||||||
|
{
|
||||||
|
CommandsParserValue pv(pos, CommandsParserValueType::TYPE_NAME);
|
||||||
|
pv.m_value.string_value = typeName;
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue::CommandsParserValue(const TokenPos pos, const int type)
|
||||||
|
: m_pos(pos),
|
||||||
|
m_type(type),
|
||||||
|
m_value()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue::~CommandsParserValue()
|
||||||
|
{
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
case CommandsParserValueType::STRING:
|
||||||
|
case CommandsParserValueType::IDENTIFIER:
|
||||||
|
case CommandsParserValueType::TYPE_NAME:
|
||||||
|
delete m_value.string_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_value = ValueType();
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue::CommandsParserValue(CommandsParserValue&& other) noexcept
|
||||||
|
: m_type(other.m_type),
|
||||||
|
m_value(other.m_value)
|
||||||
|
{
|
||||||
|
other.m_value = ValueType();
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandsParserValue& CommandsParserValue::operator=(CommandsParserValue&& other) noexcept
|
||||||
|
{
|
||||||
|
m_type = other.m_type;
|
||||||
|
m_value = other.m_value;
|
||||||
|
other.m_value = ValueType();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CommandsParserValue::IntegerValue() const
|
||||||
|
{
|
||||||
|
assert(m_type == CommandsParserValueType::INTEGER);
|
||||||
|
return m_value.int_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
double CommandsParserValue::FloatingPointValue() const
|
||||||
|
{
|
||||||
|
assert(m_type == CommandsParserValueType::FLOATING_POINT);
|
||||||
|
return m_value.double_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string& CommandsParserValue::StringValue() const
|
||||||
|
{
|
||||||
|
assert(m_type == CommandsParserValueType::STRING);
|
||||||
|
return *m_value.string_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string& CommandsParserValue::IdentifierValue() const
|
||||||
|
{
|
||||||
|
assert(m_type == CommandsParserValueType::IDENTIFIER);
|
||||||
|
return *m_value.string_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string& CommandsParserValue::TypeNameValue() const
|
||||||
|
{
|
||||||
|
assert(m_type == CommandsParserValueType::TYPE_NAME);
|
||||||
|
return *m_value.string_value;
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Parsing/TokenPos.h"
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
|
|
||||||
|
class CommandsParserValueType
|
||||||
|
{
|
||||||
|
CommandsParserValueType() = default;
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FIRST = 0x100,
|
||||||
|
|
||||||
|
// Meta tokens
|
||||||
|
INVALID = FIRST,
|
||||||
|
END_OF_FILE,
|
||||||
|
|
||||||
|
// Symbol tokens
|
||||||
|
SHIFT_LEFT,
|
||||||
|
SHIFT_RIGHT,
|
||||||
|
EQUALS,
|
||||||
|
NOT_EQUAL,
|
||||||
|
GREATER_EQUAL,
|
||||||
|
LESS_EQUAL,
|
||||||
|
LOGICAL_AND,
|
||||||
|
LOGICAL_OR,
|
||||||
|
|
||||||
|
// Generic token types
|
||||||
|
INTEGER,
|
||||||
|
FLOATING_POINT,
|
||||||
|
STRING,
|
||||||
|
IDENTIFIER,
|
||||||
|
|
||||||
|
// Parser created
|
||||||
|
TYPE_NAME,
|
||||||
|
|
||||||
|
// End
|
||||||
|
MAX
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class CommandsParserValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TokenPos m_pos;
|
||||||
|
int m_type;
|
||||||
|
union ValueType
|
||||||
|
{
|
||||||
|
int int_value;
|
||||||
|
double double_value;
|
||||||
|
std::string* string_value;
|
||||||
|
} m_value;
|
||||||
|
|
||||||
|
static CommandsParserValue Invalid(TokenPos pos);
|
||||||
|
static CommandsParserValue EndOfFile(TokenPos pos);
|
||||||
|
static CommandsParserValue Character(TokenPos pos, char c);
|
||||||
|
static CommandsParserValue ShiftLeft(TokenPos pos);
|
||||||
|
static CommandsParserValue ShiftRight(TokenPos pos);
|
||||||
|
static CommandsParserValue Equals(TokenPos pos);
|
||||||
|
static CommandsParserValue NotEqual(TokenPos pos);
|
||||||
|
static CommandsParserValue GreaterEqual(TokenPos pos);
|
||||||
|
static CommandsParserValue LessEqual(TokenPos pos);
|
||||||
|
static CommandsParserValue LogicalAnd(TokenPos pos);
|
||||||
|
static CommandsParserValue LogicalOr(TokenPos pos);
|
||||||
|
static CommandsParserValue Integer(TokenPos pos, int value);
|
||||||
|
static CommandsParserValue FloatingPoint(TokenPos pos, double value);
|
||||||
|
static CommandsParserValue String(TokenPos pos, std::string* stringValue);
|
||||||
|
static CommandsParserValue Identifier(TokenPos pos, std::string* identifier);
|
||||||
|
static CommandsParserValue TypeName(TokenPos pos, std::string* typeName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CommandsParserValue(TokenPos pos, int type);
|
||||||
|
|
||||||
|
public:
|
||||||
|
~CommandsParserValue();
|
||||||
|
CommandsParserValue(const CommandsParserValue& other) = delete;
|
||||||
|
CommandsParserValue(CommandsParserValue&& other) noexcept;
|
||||||
|
CommandsParserValue& operator=(const CommandsParserValue& other) = delete;
|
||||||
|
CommandsParserValue& operator=(CommandsParserValue&& other) noexcept;
|
||||||
|
|
||||||
|
_NODISCARD int IntegerValue() const;
|
||||||
|
_NODISCARD double FloatingPointValue() const;
|
||||||
|
_NODISCARD std::string& StringValue() const;
|
||||||
|
_NODISCARD std::string& IdentifierValue() const;
|
||||||
|
_NODISCARD std::string& TypeNameValue() const;
|
||||||
|
};
|
@ -2,14 +2,39 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
#include "Parsing/Impl/IncludingStreamProxy.h"
|
||||||
|
#include "Parsing/Impl/ParserFilesystemStream.h"
|
||||||
|
|
||||||
HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
|
HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
|
||||||
: m_args(args),
|
: m_args(args),
|
||||||
m_filename(std::move(filename))
|
m_filename(std::move(filename))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository)
|
bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository) const
|
||||||
{
|
{
|
||||||
std::cout << "Reading header file: " << m_filename << std::endl;
|
std::cout << "Reading header file: " << m_filename << std::endl;
|
||||||
|
|
||||||
|
ParserFilesystemStream stream(m_filename);
|
||||||
|
if(!stream.IsOpen())
|
||||||
|
{
|
||||||
|
std::cout << "Could not open header file" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IncludingStreamProxy includeProxy(&stream);
|
||||||
|
IParserLineStream* lineStream = &includeProxy;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
auto line = lineStream->NextLine();
|
||||||
|
|
||||||
|
if (line.IsEof())
|
||||||
|
break;
|
||||||
|
|
||||||
|
std::cout << "Line " << line.m_filename << ":" << line.m_line_number << ": " << line.m_line << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,5 @@ class HeaderFileReader
|
|||||||
public:
|
public:
|
||||||
HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename);
|
HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename);
|
||||||
|
|
||||||
bool ReadHeaderFile(IDataRepository* repository);
|
bool ReadHeaderFile(IDataRepository* repository) const;
|
||||||
};
|
};
|
||||||
|
15
src/ZoneCodeGeneratorNew/Parsing/ILexer.h
Normal file
15
src/ZoneCodeGeneratorNew/Parsing/ILexer.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class ILexer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ILexer() = default;
|
||||||
|
virtual ~ILexer() = default;
|
||||||
|
ILexer(const ILexer& other) = default;
|
||||||
|
ILexer(ILexer&& other) noexcept = default;
|
||||||
|
ILexer& operator=(const ILexer& other) = default;
|
||||||
|
ILexer& operator=(ILexer&& other) noexcept = default;
|
||||||
|
|
||||||
|
virtual void PopTokens(int amount) = 0;
|
||||||
|
};
|
13
src/ZoneCodeGeneratorNew/Parsing/IParserLineStream.cpp
Normal file
13
src/ZoneCodeGeneratorNew/Parsing/IParserLineStream.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "IParserLineStream.h"
|
||||||
|
|
||||||
|
ParserLine::ParserLine(const std::string& filename, const int lineNumber, std::string line)
|
||||||
|
: m_filename(filename),
|
||||||
|
m_line_number(lineNumber),
|
||||||
|
m_line(std::move(line))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserLine::IsEof() const
|
||||||
|
{
|
||||||
|
return m_line_number <= 0;
|
||||||
|
}
|
34
src/ZoneCodeGeneratorNew/Parsing/IParserLineStream.h
Normal file
34
src/ZoneCodeGeneratorNew/Parsing/IParserLineStream.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
|
|
||||||
|
class ParserLine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const std::string& m_filename;
|
||||||
|
const int m_line_number;
|
||||||
|
std::string m_line;
|
||||||
|
|
||||||
|
ParserLine(const std::string& filename, int lineNumber, std::string line);
|
||||||
|
|
||||||
|
_NODISCARD bool IsEof() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IParserLineStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IParserLineStream() = default;
|
||||||
|
virtual ~IParserLineStream() = default;
|
||||||
|
|
||||||
|
IParserLineStream(const IParserLineStream& other) = default;
|
||||||
|
IParserLineStream(IParserLineStream&& other) noexcept = default;
|
||||||
|
IParserLineStream& operator=(const IParserLineStream& other) = default;
|
||||||
|
IParserLineStream& operator=(IParserLineStream&& other) noexcept = default;
|
||||||
|
|
||||||
|
virtual ParserLine NextLine() = 0;
|
||||||
|
virtual bool IncludeFile(const std::string& filename) = 0;
|
||||||
|
_NODISCARD virtual bool IsOpen() const = 0;
|
||||||
|
_NODISCARD virtual bool Eof() const = 0;
|
||||||
|
};
|
@ -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;
|
||||||
|
};
|
32
src/ZoneCodeGeneratorNew/Parsing/ParsingException.cpp
Normal file
32
src/ZoneCodeGeneratorNew/Parsing/ParsingException.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "ParsingException.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
ParsingException::ParsingException(const TokenPos position, std::string message)
|
||||||
|
: m_pos(position),
|
||||||
|
m_message(std::move(message))
|
||||||
|
{
|
||||||
|
std::ostringstream str;
|
||||||
|
str << m_pos.m_line << ':' << m_pos.m_column << ' ' << m_message;
|
||||||
|
m_full_message = str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenPos ParsingException::Position() const
|
||||||
|
{
|
||||||
|
return m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& ParsingException::Message() const
|
||||||
|
{
|
||||||
|
return m_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ParsingException::FullMessage() const
|
||||||
|
{
|
||||||
|
return m_full_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* ParsingException::what() const
|
||||||
|
{
|
||||||
|
return m_full_message.c_str();
|
||||||
|
}
|
22
src/ZoneCodeGeneratorNew/Parsing/ParsingException.h
Normal file
22
src/ZoneCodeGeneratorNew/Parsing/ParsingException.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "TokenPos.h"
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
|
|
||||||
|
class ParsingException final : std::exception
|
||||||
|
{
|
||||||
|
TokenPos m_pos;
|
||||||
|
std::string m_message;
|
||||||
|
std::string m_full_message;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ParsingException(TokenPos position, std::string message);
|
||||||
|
|
||||||
|
_NODISCARD TokenPos Position() const;
|
||||||
|
_NODISCARD const std::string& Message() const;
|
||||||
|
_NODISCARD std::string FullMessage() const;
|
||||||
|
_NODISCARD char const* what() const override;
|
||||||
|
};
|
17
src/ZoneCodeGeneratorNew/Parsing/TokenPos.cpp
Normal file
17
src/ZoneCodeGeneratorNew/Parsing/TokenPos.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "TokenPos.h"
|
||||||
|
|
||||||
|
const std::string TokenPos::EMPTY_FILENAME;
|
||||||
|
|
||||||
|
TokenPos::TokenPos()
|
||||||
|
: m_filename(EMPTY_FILENAME),
|
||||||
|
m_line(1),
|
||||||
|
m_column(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenPos::TokenPos(const std::string& filename, const int line, const int column)
|
||||||
|
: m_filename(filename),
|
||||||
|
m_line(line),
|
||||||
|
m_column(column)
|
||||||
|
{
|
||||||
|
}
|
16
src/ZoneCodeGeneratorNew/Parsing/TokenPos.h
Normal file
16
src/ZoneCodeGeneratorNew/Parsing/TokenPos.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class TokenPos
|
||||||
|
{
|
||||||
|
static const std::string EMPTY_FILENAME;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const std::string& m_filename;
|
||||||
|
int m_line;
|
||||||
|
int m_column;
|
||||||
|
|
||||||
|
TokenPos();
|
||||||
|
TokenPos(const std::string& filename, int line, int column);
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user