implement count sequence parsing

This commit is contained in:
Jan 2021-02-19 19:37:38 +01:00
parent 4a0395c5df
commit 3ffcac04dd
3 changed files with 114 additions and 8 deletions

View File

@ -103,9 +103,9 @@ static constexpr int TAG_EVALUATION = std::numeric_limits<int>::max() - 9;
static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits<int>::max() - 10;
static constexpr int CAPTURE_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 1;
static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits<int>::max() - 1;
static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits<int>::max() - 2;
static constexpr int CAPTURE_OPERATION_TYPE = std::numeric_limits<int>::max() - 3;
static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits<int>::max() - 2;
static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits<int>::max() - 3;
static constexpr int CAPTURE_OPERATION_TYPE = std::numeric_limits<int>::max() - 4;
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::ParseOperandArray(const supplier_t* labelSupplier)
{

View File

@ -1,5 +1,7 @@
#include "SequenceCount.h"
#include "Domain/Definition/ArrayDeclarationModifier.h"
#include "Domain/Definition/PointerDeclarationModifier.h"
#include "Parsing/Commands/Matcher/CommandsMatcherFactory.h"
#include "Parsing/Commands/Matcher/CommandsCommonMatchers.h"
@ -11,16 +13,116 @@ SequenceCount::SequenceCount()
AddLabeledMatchers(CommandsCommonMatchers::Evaluation(this), CommandsCommonMatchers::LABEL_EVALUATION);
AddLabeledMatchers(CommandsCommonMatchers::ArrayDef(this), CommandsCommonMatchers::LABEL_ARRAY_DEF);
AddMatchers({
create.Keyword("set"),
create.Keyword("set").Capture(CAPTURE_START),
create.Keyword("count"),
create.OptionalLoop(create.Char('*').Tag(TAG_POINTER_RESOLVE)),
create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE),
create.OptionalLoop(create.Label(CommandsCommonMatchers::LABEL_ARRAY_DEF).Capture(CAPTURE_ARRAY_INDEX)),
create.Label(CommandsCommonMatchers::LABEL_EVALUATION).Capture(CAPTURE_EVALUATION),
create.Label(CommandsCommonMatchers::LABEL_EVALUATION),
create.Char(';')
});
}
void SequenceCount::SetCountByArrayIndex(CommandsParserState* state, SequenceResult<CommandsParserValue>& result, MemberInformation* member, PointerDeclarationModifier* pointer,
std::unique_ptr<IEvaluation> evaluation)
{
std::vector<int> arraySizes;
std::vector<int> depthSize;
for (const auto& modifier : member->m_member->m_type_declaration->m_declaration_modifiers)
{
if (modifier->GetType() == DeclarationModifierType::ARRAY)
arraySizes.push_back(dynamic_cast<ArrayDeclarationModifier*>(modifier.get())->m_size);
}
depthSize.resize(arraySizes.size());
auto currentDepthSize = 1u;
for (auto i = arraySizes.size(); i > 0; i--)
{
if(i < arraySizes.size())
currentDepthSize *= arraySizes[i];
depthSize[i - 1] = currentDepthSize;
}
if (pointer->m_count_evaluation_by_array_index.empty())
{
auto neededCapacity = 0u;
for (auto arraySize : arraySizes)
{
if (neededCapacity == 0)
neededCapacity = arraySize;
else
neededCapacity *= arraySize;
}
pointer->m_count_evaluation_by_array_index.resize(neededCapacity);
}
auto currentIndex = 0u;
auto currentIndexOffset = 0u;
while (result.HasNextCapture(CAPTURE_ARRAY_INDEX) && currentIndexOffset < depthSize.size())
{
const auto& arrayIndexToken = result.NextCapture(CAPTURE_ARRAY_INDEX);
if (arrayIndexToken.m_type == CommandsParserValueType::INTEGER)
{
currentIndex += depthSize[currentIndexOffset++] * arrayIndexToken.IntegerValue();
}
else
{
auto* enumEntry = state->GetRepository()->GetEnumMemberByName(arrayIndexToken.IdentifierValue());
if (enumEntry == nullptr)
throw ParsingException(arrayIndexToken.GetPos(), "Unknown enum entry");
currentIndex += depthSize[currentIndexOffset++] * enumEntry->m_value;
}
}
pointer->m_count_evaluation_by_array_index[currentIndex] = std::move(evaluation);
}
void SequenceCount::ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const
{
const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE);
StructureInformation* type;
std::vector<MemberInformation*> memberChain;
if (!state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), type, memberChain))
throw ParsingException(typeNameToken.GetPos(), "Unknown type");
if (memberChain.empty())
throw ParsingException(typeNameToken.GetPos(), "Conditions can only be set on members and not for types");
auto resolve = 0u;
while (result.PeekAndRemoveIfTag(TAG_POINTER_RESOLVE) == TAG_POINTER_RESOLVE)
resolve++;
auto* lastMember = memberChain.back();
PointerDeclarationModifier* pointer = nullptr;
for (const auto& modifier : lastMember->m_member->m_type_declaration->m_declaration_modifiers)
{
if (modifier->GetType() == DeclarationModifierType::POINTER)
{
if (resolve > 0)
{
resolve--;
}
else
{
pointer = dynamic_cast<PointerDeclarationModifier*>(modifier.get());
break;
}
}
}
if (pointer == nullptr)
throw ParsingException(result.NextCapture(CAPTURE_START).GetPos(), "No matching pointer modifier found");
auto countEvaluation = CommandsCommonMatchers::ProcessEvaluation(state, result, type);
if (!result.HasNextCapture(CAPTURE_ARRAY_INDEX))
{
pointer->m_count_evaluation = std::move(countEvaluation);
}
else
{
SetCountByArrayIndex(state, result, lastMember, pointer, std::move(countEvaluation));
}
}

View File

@ -1,14 +1,18 @@
#pragma once
#include "Domain/Definition/PointerDeclarationModifier.h"
#include "Parsing/Commands/Impl/CommandsParser.h"
class SequenceCount final : public CommandsParser::sequence_t
{
static constexpr auto TAG_POINTER_RESOLVE = 1;
static constexpr auto CAPTURE_TYPE = 1;
static constexpr auto CAPTURE_ARRAY_INDEX = 2;
static constexpr auto CAPTURE_EVALUATION = 3;
static constexpr auto CAPTURE_START = 1;
static constexpr auto CAPTURE_TYPE = 2;
static constexpr auto CAPTURE_ARRAY_INDEX = 3;
static void SetCountByArrayIndex(CommandsParserState* state, SequenceResult<CommandsParserValue>& result, MemberInformation* member, PointerDeclarationModifier* pointer,
std::unique_ptr<IEvaluation> evaluation);
protected:
void ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const override;