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,93 @@
#pragma once
#include <unordered_map>
#include <cassert>
#include "SequenceResult.h"
#include "Utils/ClassUtils.h"
#include "Parsing/Matcher/AbstractMatcher.h"
#include "Parsing/Matcher/MatcherAnd.h"
#include "Parsing/Matcher/MatcherLabel.h"
template<typename TokenType, typename ParserState>
class AbstractSequence : protected IMatcherForLabelSupplier<TokenType>
{
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
public:
typedef AbstractMatcher<TokenType> matcher_t;
private:
std::unique_ptr<matcher_t> m_entry;
std::unordered_map<int, std::unique_ptr<matcher_t>> m_matchers;
protected:
static constexpr int ENTRY_LABEL = 0;
AbstractSequence() = default;
virtual void ProcessMatch(ParserState* state, SequenceResult<TokenType>& result) const = 0;
void AddMatchers(std::unique_ptr<matcher_t> matcher)
{
assert(!m_entry);
m_entry = std::move(matcher);
}
void AddMatchers(std::initializer_list<Movable<std::unique_ptr<matcher_t>>> matchers)
{
assert(!m_entry);
m_entry = std::make_unique<MatcherAnd<TokenType>>(matchers);
}
void AddLabeledMatchers(std::unique_ptr<matcher_t> matcher, const int label)
{
assert(m_matchers.find(label) == m_matchers.end());
m_matchers.emplace(label, std::move(matcher));
}
void AddLabeledMatchers(std::initializer_list<Movable<std::unique_ptr<matcher_t>>> matchers, const int label)
{
assert(m_matchers.find(label) == m_matchers.end());
m_matchers.emplace(label, std::make_unique<MatcherAnd<TokenType>>(matchers));
}
public:
~AbstractSequence() override = default;
AbstractSequence(const AbstractSequence& other) = default;
AbstractSequence(AbstractSequence&& other) noexcept = default;
AbstractSequence& operator=(const AbstractSequence& other) = default;
AbstractSequence& operator=(AbstractSequence&& other) noexcept = default;
_NODISCARD matcher_t* GetMatcherForLabel(const int label) const override
{
if (label == 0)
return m_entry.get();
const auto foundEntry = m_matchers.find(label);
if (foundEntry != m_matchers.end())
return foundEntry->second.get();
return nullptr;
}
_NODISCARD bool MatchSequence(ILexer<TokenType>* lexer, ParserState* state, unsigned& consumedTokenCount) const
{
if (!m_entry)
return false;
auto result = m_entry->Match(lexer, 0);
if (result.m_matches)
{
SequenceResult<TokenType> sequenceResult(lexer, result);
ProcessMatch(state, sequenceResult);
consumedTokenCount = result.m_consumed_token_count;
}
return result.m_matches;
}
};

View File

@ -0,0 +1,100 @@
#pragma once
#include <unordered_map>
#include "Utils/ClassUtils.h"
#include "Parsing/Matcher/AbstractMatcher.h"
#include "Parsing/Matcher/MatcherResult.h"
#include "Parsing/ParsingException.h"
template <typename TokenType>
class SequenceResult
{
class Capture
{
public:
unsigned m_offset;
std::vector<std::reference_wrapper<const TokenType>> m_tokens;
Capture()
: m_offset(0)
{
}
};
// TokenType must inherit IParserValue
static_assert(std::is_base_of<IParserValue, TokenType>::value);
std::vector<int> m_tags;
std::unordered_map<int, Capture> m_captures;
unsigned m_tag_offset;
public:
SequenceResult(ILexer<TokenType>* lexer, const MatcherResult<TokenType>& result)
: m_tags(result.m_tags),
m_tag_offset(0)
{
for (const typename MatcherResult<TokenType>::Capture& capture : result.m_captures)
{
if (capture.m_token_index.IsFabricated())
m_captures[capture.GetCaptureId()].m_tokens.push_back(result.m_fabricated_tokens[capture.m_token_index.GetTokenIndex()]);
else
m_captures[capture.GetCaptureId()].m_tokens.push_back(lexer->GetToken(capture.m_token_index.GetTokenIndex()));
}
}
_NODISCARD int PeekTag() const
{
if (m_tag_offset < m_tags.size())
return m_tags[m_tag_offset];
return AbstractMatcher<TokenType>::NO_ID;
}
int PeekAndRemoveIfTag(const int tag)
{
if (m_tag_offset < m_tags.size())
{
const auto result = m_tags[m_tag_offset];
if (result == tag)
m_tag_offset++;
return result;
}
return AbstractMatcher<TokenType>::NO_ID;
}
int NextTag()
{
if (m_tag_offset < m_tags.size())
return m_tags[m_tag_offset++];
return AbstractMatcher<TokenType>::NO_ID;
}
_NODISCARD bool HasNextCapture(int captureId)
{
auto foundEntry = m_captures.find(captureId);
if (foundEntry == m_captures.end())
return false;
return foundEntry->second.m_offset < foundEntry->second.m_tokens.size();
}
const TokenType& NextCapture(int captureId)
{
auto foundEntry = m_captures.find(captureId);
if (foundEntry == m_captures.end())
throw ParsingException(TokenPos(), "Tried to access next capture even though no captures exists!");
if(foundEntry->second.m_offset >= foundEntry->second.m_tokens.size())
throw ParsingException(TokenPos(), "Tried to access next capture even though none exists!");
return foundEntry->second.m_tokens[foundEntry->second.m_offset++];
}
};