2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-10-26 00:05:52 +00:00

Extract commonly used Parser code to new Parser component

This commit is contained in:
Jan
2021-03-08 20:06:34 +01:00
parent d96f813e73
commit 8d9080066f
39 changed files with 54 additions and 3 deletions

View File

@@ -0,0 +1,103 @@
#pragma once
#include <functional>
#include "Parsing/IParserValue.h"
#include "Parsing/ILexer.h"
#include "Parsing/Matcher/MatcherResult.h"
template <typename TokenType>
class AbstractMatcher
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
public:
static constexpr int NO_ID = -1;
typedef std::vector<std::reference_wrapper<const TokenType>> token_list_t;
private:
int m_tag_id;
int m_capture_id;
bool m_no_consume;
std::function<TokenType(token_list_t&)> m_transform_func;
protected:
AbstractMatcher()
: m_tag_id(NO_ID),
m_capture_id(NO_ID),
m_no_consume(false)
{
}
virtual MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, unsigned tokenOffset) = 0;
public:
virtual ~AbstractMatcher() = default;
AbstractMatcher(const AbstractMatcher& other) = default;
AbstractMatcher(AbstractMatcher&& other) noexcept = default;
AbstractMatcher& operator=(const AbstractMatcher& other) = default;
AbstractMatcher& operator=(AbstractMatcher&& other) noexcept = default;
void SetTag(const int tagId)
{
m_tag_id = tagId;
}
void SetCapture(const int captureId)
{
m_capture_id = captureId;
}
void SetConsume(const bool value)
{
m_no_consume = !value;
}
void SetTransform(std::function<TokenType(std::vector<std::reference_wrapper<const TokenType>>&)> transform)
{
m_transform_func = std::move(transform);
}
MatcherResult<TokenType> Match(ILexer<TokenType>* lexer, const unsigned tokenOffset)
{
MatcherResult<TokenType> result = CanMatch(lexer, tokenOffset);
if (!result.m_matches)
return result;
if (m_tag_id != NO_ID)
result.m_tags.insert(result.m_tags.begin(), m_tag_id);
if (m_transform_func)
{
std::vector<std::reference_wrapper<const TokenType>> tokens;
tokens.reserve(result.m_consumed_token_count);
for (auto i = 0u; i < result.m_consumed_token_count; i++)
tokens.emplace_back(lexer->GetToken(tokenOffset + i));
result.m_fabricated_tokens.push_back(m_transform_func(tokens));
result.m_matched_tokens.clear();
result.m_matched_tokens.emplace_back(result.m_fabricated_tokens.size() - 1, true);
}
else if(result.m_matched_tokens.empty())
{
for (auto i = 0u; i < result.m_consumed_token_count; i++)
result.m_matched_tokens.emplace_back(tokenOffset + i, false);
}
if (m_capture_id != NO_ID)
{
for (const auto& match : result.m_matched_tokens)
result.m_captures.emplace_back(m_capture_id, match);
}
if (m_no_consume)
result.m_consumed_token_count = 0;
return result;
}
};

View File

@@ -0,0 +1,117 @@
#pragma once
#include <memory>
#include "Utils/ClassUtils.h"
#include "AbstractMatcher.h"
#include "MatcherAnd.h"
#include "MatcherLabel.h"
#include "MatcherLoop.h"
#include "MatcherOptional.h"
#include "MatcherOr.h"
#include "Parsing/IParserValue.h"
template <typename TokenType>
class MatcherFactoryWrapper
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
std::unique_ptr<AbstractMatcher<TokenType>> m_matcher;
public:
typedef typename AbstractMatcher<TokenType>::token_list_t token_list_t;
explicit MatcherFactoryWrapper(std::unique_ptr<AbstractMatcher<TokenType>> matcher)
: m_matcher(std::move(matcher))
{
}
MatcherFactoryWrapper<TokenType>& Tag(const int tagId)
{
m_matcher->SetTag(tagId);
return *this;
}
MatcherFactoryWrapper<TokenType>& Capture(const int captureId)
{
m_matcher->SetCapture(captureId);
return *this;
}
MatcherFactoryWrapper<TokenType>& NoConsume()
{
m_matcher->SetConsume(false);
return *this;
}
MatcherFactoryWrapper<TokenType>& Transform(std::function<TokenType(token_list_t&)> transform)
{
m_matcher->SetTransform(std::move(transform));
return *this;
}
std::unique_ptr<AbstractMatcher<TokenType>> Build()
{
return std::move(m_matcher);
}
// ReSharper disable once CppNonExplicitConversionOperator
operator std::unique_ptr<AbstractMatcher<TokenType>>()
{
return Build();
}
// ReSharper disable once CppNonExplicitConversionOperator
operator Movable<std::unique_ptr<AbstractMatcher<TokenType>>>()
{
return Build();
}
};
template <typename TokenType>
class AbstractMatcherFactory
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
const IMatcherForLabelSupplier<TokenType>* m_label_supplier;
public:
typedef typename AbstractMatcher<TokenType>::token_list_t token_list_t;
explicit AbstractMatcherFactory(const IMatcherForLabelSupplier<TokenType>* labelSupplier)
: m_label_supplier(labelSupplier)
{
}
_NODISCARD MatcherFactoryWrapper<TokenType> And(std::initializer_list<Movable<std::unique_ptr<AbstractMatcher<TokenType>>>> matchers) const
{
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherAnd<TokenType>>(matchers));
}
_NODISCARD MatcherFactoryWrapper<TokenType> Or(std::initializer_list<Movable<std::unique_ptr<AbstractMatcher<TokenType>>>> matchers) const
{
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherOr<TokenType>>(matchers));
}
_NODISCARD MatcherFactoryWrapper<TokenType> Loop(std::unique_ptr<AbstractMatcher<TokenType>> matcher) const
{
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherLoop<TokenType>>(std::move(matcher)));
}
_NODISCARD MatcherFactoryWrapper<TokenType> OptionalLoop(std::unique_ptr<AbstractMatcher<TokenType>> matcher) const
{
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherOptional<TokenType>>(std::make_unique<MatcherLoop<TokenType>>(std::move(matcher))));
}
_NODISCARD MatcherFactoryWrapper<TokenType> Optional(std::unique_ptr<AbstractMatcher<TokenType>> matcher) const
{
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherOptional<TokenType>>(std::move(matcher)));
}
_NODISCARD MatcherFactoryWrapper<TokenType> Label(const int label) const
{
return MatcherFactoryWrapper<TokenType>(std::make_unique<MatcherLabel<TokenType>>(m_label_supplier, label));
}
};

View File

@@ -0,0 +1,40 @@
#pragma once
#include <iterator>
#include <memory>
#include "Parsing/IParserValue.h"
#include "AbstractMatcher.h"
template <typename TokenType>
class MatcherAnd final : public AbstractMatcher<TokenType>
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
std::vector<std::unique_ptr<AbstractMatcher<TokenType>>> m_matchers;
protected:
MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, const unsigned tokenOffset) override
{
auto matchResult = MatcherResult<TokenType>::Match(0);
for (const std::unique_ptr<AbstractMatcher<TokenType>>& matcher : m_matchers)
{
MatcherResult<TokenType> result = matcher->Match(lexer, tokenOffset + matchResult.m_consumed_token_count);
if (!result.m_matches)
return MatcherResult<TokenType>::NoMatch();
matchResult.Absorb(std::move(result));
}
return matchResult;
}
public:
MatcherAnd(std::initializer_list<Movable<std::unique_ptr<AbstractMatcher<TokenType>>>> matchers)
: m_matchers(std::make_move_iterator(matchers.begin()), std::make_move_iterator(matchers.end()))
{
}
};

View File

@@ -0,0 +1,50 @@
#pragma once
#include "Utils/ClassUtils.h"
#include "Parsing/IParserValue.h"
#include "AbstractMatcher.h"
template <typename TokenType>
class IMatcherForLabelSupplier
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
public:
IMatcherForLabelSupplier() = default;
virtual ~IMatcherForLabelSupplier() = default;
IMatcherForLabelSupplier(const IMatcherForLabelSupplier& other) = default;
IMatcherForLabelSupplier(IMatcherForLabelSupplier&& other) noexcept = default;
IMatcherForLabelSupplier& operator=(const IMatcherForLabelSupplier& other) = default;
IMatcherForLabelSupplier& operator=(IMatcherForLabelSupplier&& other) noexcept = default;
_NODISCARD virtual AbstractMatcher<TokenType>* GetMatcherForLabel(int label) const = 0;
};
template <typename TokenType>
class MatcherLabel final : public AbstractMatcher<TokenType>
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
const IMatcherForLabelSupplier<TokenType>* m_supplier;
int m_label;
protected:
MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, unsigned tokenOffset) override
{
AbstractMatcher<TokenType>* matcher = m_supplier->GetMatcherForLabel(m_label);
if (matcher)
return matcher->Match(lexer, tokenOffset);
return MatcherResult<TokenType>::NoMatch();
}
public:
MatcherLabel(const IMatcherForLabelSupplier<TokenType>* supplier, const int label)
: m_supplier(supplier),
m_label(label)
{
}
};

View File

@@ -0,0 +1,44 @@
#pragma once
#include <memory>
#include "Parsing/IParserValue.h"
#include "AbstractMatcher.h"
template <typename TokenType>
class MatcherLoop final : public AbstractMatcher<TokenType>
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
std::unique_ptr<AbstractMatcher<TokenType>> m_matcher;
protected:
MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, const unsigned tokenOffset) override
{
auto matchResult = MatcherResult<TokenType>::Match(0);
auto loopedAtLeastOnce = false;
while(true)
{
auto result = m_matcher->Match(lexer, tokenOffset + matchResult.m_consumed_token_count);
if(!result.m_matches)
{
if (loopedAtLeastOnce)
return matchResult;
return MatcherResult<TokenType>::NoMatch();
}
loopedAtLeastOnce = true;
matchResult.Absorb(std::move(result));
}
}
public:
explicit MatcherLoop(std::unique_ptr<AbstractMatcher<TokenType>> matcher)
: m_matcher(std::move(matcher))
{
}
};

View File

@@ -0,0 +1,32 @@
#pragma once
#include <memory>
#include "Parsing/IParserValue.h"
#include "AbstractMatcher.h"
template <typename TokenType>
class MatcherOptional final : public AbstractMatcher<TokenType>
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
std::unique_ptr<AbstractMatcher<TokenType>> m_matcher;
protected:
MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, unsigned tokenOffset) override
{
auto result = m_matcher->Match(lexer, tokenOffset);
if (result.m_matches)
return result;
return MatcherResult<TokenType>::Match(0);
}
public:
explicit MatcherOptional(std::unique_ptr<AbstractMatcher<TokenType>> matcher)
: m_matcher(std::move(matcher))
{
}
};

View File

@@ -0,0 +1,38 @@
#pragma once
#include <iterator>
#include <memory>
#include "Parsing/IParserValue.h"
#include "AbstractMatcher.h"
template <typename TokenType>
class MatcherOr final : public AbstractMatcher<TokenType>
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
std::vector<std::unique_ptr<AbstractMatcher<TokenType>>> m_matchers;
protected:
MatcherResult<TokenType> CanMatch(ILexer<TokenType>* lexer, unsigned tokenOffset) override
{
for (const std::unique_ptr<AbstractMatcher<TokenType>>& matcher : m_matchers)
{
MatcherResult<TokenType> result = matcher->Match(lexer, tokenOffset);
if (!result.m_matches)
continue;
return result;
}
return MatcherResult<TokenType>::NoMatch();
}
public:
MatcherOr(std::initializer_list<Movable<std::unique_ptr<AbstractMatcher<TokenType>>>> matchers)
: m_matchers(std::make_move_iterator(matchers.begin()), std::make_move_iterator(matchers.end()))
{
}
};

View File

@@ -0,0 +1,124 @@
#pragma once
#include <iterator>
#include <vector>
#include "Utils/ClassUtils.h"
#include "Parsing/IParserValue.h"
template <typename TokenType>
class MatcherResult
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
public:
class TokenIndex
{
static constexpr unsigned FABRICATED_FLAG_MASK = std::numeric_limits<unsigned>::max() ^ std::numeric_limits<int>::max();
static constexpr unsigned TOKEN_INDEX_MASK = ~FABRICATED_FLAG_MASK;
unsigned m_token_index;
public:
TokenIndex(const unsigned index, const bool isFabricated)
{
m_token_index = index & TOKEN_INDEX_MASK;
if (isFabricated)
m_token_index |= FABRICATED_FLAG_MASK;
}
_NODISCARD bool IsFabricated() const
{
return m_token_index & FABRICATED_FLAG_MASK;
}
_NODISCARD unsigned GetTokenIndex() const
{
return m_token_index & TOKEN_INDEX_MASK;
}
};
class Capture
{
public:
int m_capture_id;
TokenIndex m_token_index;
Capture(const int captureId, const unsigned tokenIndex)
: Capture(captureId, tokenIndex, false)
{
}
Capture(const int captureId, const unsigned tokenIndex, const bool isFabricated)
: m_capture_id(captureId),
m_token_index(tokenIndex, isFabricated)
{
}
Capture(const int captureId, const TokenIndex index)
: m_capture_id(captureId),
m_token_index(index)
{
}
_NODISCARD int GetCaptureId() const
{
return m_capture_id;
}
};
bool m_matches;
unsigned m_consumed_token_count;
std::vector<int> m_tags;
std::vector<Capture> m_captures;
std::vector<TokenIndex> m_matched_tokens;
std::vector<TokenType> m_fabricated_tokens;
private:
MatcherResult(const bool matches, const unsigned consumedTokenCount)
: m_matches(matches),
m_consumed_token_count(consumedTokenCount)
{
}
public:
static MatcherResult Match(unsigned consumedTokenCount)
{
return MatcherResult(true, consumedTokenCount);
}
static MatcherResult NoMatch()
{
return MatcherResult(false, 0);
}
void Absorb(MatcherResult<TokenType>&& other)
{
m_consumed_token_count += other.m_consumed_token_count;
if (!other.m_tags.empty())
std::copy(other.m_tags.begin(), other.m_tags.end(), std::back_inserter(m_tags));
for (const auto& capture : other.m_captures)
{
if (capture.m_token_index.IsFabricated())
m_captures.emplace_back(capture.GetCaptureId(), TokenIndex(m_fabricated_tokens.size() + capture.m_token_index.GetTokenIndex(), true));
else
m_captures.emplace_back(capture.GetCaptureId(), capture.m_token_index);
}
for (const auto& token : other.m_matched_tokens)
{
if (token.IsFabricated())
m_matched_tokens.emplace_back(m_fabricated_tokens.size() + token.GetTokenIndex(), true);
else
m_matched_tokens.emplace_back(token.GetTokenIndex(), false);
}
for (auto& fabricated : other.m_fabricated_tokens)
{
m_fabricated_tokens.emplace_back(std::move(fabricated));
}
}
};