From 5e08469635c73e29942ad3896e11afb49ebc09ac Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 20 Mar 2021 14:07:48 +0100 Subject: [PATCH] Use custom parser values instead of simple parser values for parsing Zone definitions --- .../Simple/Matcher/SimpleMatcherFactory.cpp | 1 - .../Matcher/ZoneDefinitionCommonMatchers.cpp | 61 ---------- .../Matcher/ZoneDefinitionCommonMatchers.h | 19 --- .../ZoneDefinitionMatcherCharacter.cpp | 14 +++ .../Matcher/ZoneDefinitionMatcherCharacter.h | 15 +++ .../Matcher/ZoneDefinitionMatcherFactory.cpp | 35 ++++++ .../Matcher/ZoneDefinitionMatcherFactory.h | 18 +++ .../Matcher/ZoneDefinitionMatcherKeyword.cpp | 16 +++ .../Matcher/ZoneDefinitionMatcherKeyword.h | 18 +++ .../ZoneDefinitionMatcherValueType.cpp | 13 ++ .../Matcher/ZoneDefinitionMatcherValueType.h | 15 +++ ...equenceZoneDefinitionConsumeEmptyLines.cpp | 14 --- .../SequenceZoneDefinitionConsumeEmptyLines.h | 12 -- .../Sequence/SequenceZoneDefinitionEntry.cpp | 28 ++--- .../Sequence/SequenceZoneDefinitionEntry.h | 2 +- .../Sequence/SequenceZoneDefinitionIgnore.cpp | 14 +-- .../Sequence/SequenceZoneDefinitionIgnore.h | 2 +- .../SequenceZoneDefinitionInclude.cpp | 14 +-- .../Sequence/SequenceZoneDefinitionInclude.h | 2 +- .../SequenceZoneDefinitionMetaData.cpp | 16 +-- .../Sequence/SequenceZoneDefinitionMetaData.h | 2 +- .../ZoneDefinition/ZoneDefinitionLexer.cpp | 72 ++++++++++- .../ZoneDefinition/ZoneDefinitionLexer.h | 12 +- .../ZoneDefinition/ZoneDefinitionParser.cpp | 9 +- .../ZoneDefinition/ZoneDefinitionParser.h | 8 +- .../ZoneDefinitionParserValue.cpp | 115 ++++++++++++++++++ .../ZoneDefinitionParserValue.h | 58 +++++++++ 27 files changed, 431 insertions(+), 174 deletions(-) delete mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.cpp delete mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.h create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.cpp create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.h create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.cpp create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.cpp create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.h create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.cpp create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.h delete mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.cpp delete mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.h create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.cpp create mode 100644 src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.h diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.cpp b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.cpp index 58417e40..d07edd02 100644 --- a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.cpp +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.cpp @@ -1,6 +1,5 @@ #include "SimpleMatcherFactory.h" - #include "SimpleMatcherAnyCharacterBesides.h" #include "SimpleMatcherCharacter.h" #include "SimpleMatcherKeyword.h" diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.cpp deleted file mode 100644 index c4b2c414..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "ZoneDefinitionCommonMatchers.h" - -#include - -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" - -std::unique_ptr ZoneDefinitionCommonMatchers::AssetName(const supplier_t* labelSupplier) -{ - const SimpleMatcherFactory create(labelSupplier); - - return create.And({ - create.Loop(create.Or({ - create.Identifier(), - create.AnyCharBesides({',', '<', '>', '"', '\\', '*', '?', '|', ':'}) - })), - create.Or({ - create.Type(SimpleParserValueType::NEW_LINE), - create.Type(SimpleParserValueType::END_OF_FILE) - }).NoConsume() - }).Transform([](SimpleMatcherFactory::token_list_t& tokens) - { - std::ostringstream str; - auto previousType = SimpleParserValueType::INVALID; - auto previousCharacterWasSlash = false; - - for (const auto& token : tokens) - { - switch (token.get().m_type) - { - case SimpleParserValueType::IDENTIFIER: - if (previousType == SimpleParserValueType::IDENTIFIER) - str << " "; - str << token.get().IdentifierValue(); - break; - - case SimpleParserValueType::CHARACTER: - if (token.get().CharacterValue() == '/') - { - if (previousType != SimpleParserValueType::CHARACTER || !previousCharacterWasSlash) - { - str << "/"; - previousCharacterWasSlash = true; - } - } - else - { - str << token.get().CharacterValue(); - previousCharacterWasSlash = false; - } - break; - - default: - break; - } - - previousType = token.get().m_type; - } - - return SimpleParserValue::Identifier(tokens.front().get().GetPos(), new std::string(str.str())); - }); -} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.h b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.h deleted file mode 100644 index cc75e639..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include - -#include "Parsing/Simple/SimpleParserValue.h" -#include "Parsing/Matcher/AbstractMatcher.h" -#include "Parsing/Matcher/MatcherLabel.h" - -class ZoneDefinitionCommonMatchers -{ -public: - typedef AbstractMatcher matcher_t; - typedef IMatcherForLabelSupplier supplier_t; - - static constexpr int LABEL_ASSET_NAME = std::numeric_limits::max() - 1; - - static std::unique_ptr AssetName(const supplier_t* labelSupplier); -}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.cpp new file mode 100644 index 00000000..f3734ab6 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.cpp @@ -0,0 +1,14 @@ +#include "ZoneDefinitionMatcherCharacter.h" + +ZoneDefinitionMatcherCharacter::ZoneDefinitionMatcherCharacter(const char c) + : m_char(c) +{ +} + +MatcherResult ZoneDefinitionMatcherCharacter::CanMatch(ILexer* lexer, const unsigned tokenOffset) +{ + const auto& token = lexer->GetToken(tokenOffset); + return token.m_type == ZoneDefinitionParserValueType::CHARACTER && token.CharacterValue() == m_char + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.h b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.h new file mode 100644 index 00000000..9cb0fc68 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/Matcher/AbstractMatcher.h" +#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" + +class ZoneDefinitionMatcherCharacter final : public AbstractMatcher +{ + char m_char; + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override; + +public: + explicit ZoneDefinitionMatcherCharacter(char c); +}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.cpp new file mode 100644 index 00000000..4b6acb0d --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.cpp @@ -0,0 +1,35 @@ +#include "ZoneDefinitionMatcherFactory.h" + +#include "ZoneDefinitionMatcherCharacter.h" +#include "ZoneDefinitionMatcherKeyword.h" +#include "ZoneDefinitionMatcherValueType.h" + +ZoneDefinitionMatcherFactory::ZoneDefinitionMatcherFactory(const IMatcherForLabelSupplier* labelSupplier) + : AbstractMatcherFactory(labelSupplier) +{ +} + +MatcherFactoryWrapper ZoneDefinitionMatcherFactory::Type(ZoneDefinitionParserValueType type) const +{ + return MatcherFactoryWrapper(std::make_unique(type)); +} + +MatcherFactoryWrapper ZoneDefinitionMatcherFactory::Keyword(std::string keyword) const +{ + return MatcherFactoryWrapper(std::make_unique(std::move(keyword))); +} + +MatcherFactoryWrapper ZoneDefinitionMatcherFactory::Field() const +{ + return MatcherFactoryWrapper(std::make_unique(ZoneDefinitionParserValueType::FIELD)); +} + +MatcherFactoryWrapper ZoneDefinitionMatcherFactory::String() const +{ + return MatcherFactoryWrapper(std::make_unique(ZoneDefinitionParserValueType::STRING)); +} + +MatcherFactoryWrapper ZoneDefinitionMatcherFactory::Char(char c) const +{ + return MatcherFactoryWrapper(std::make_unique(c)); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h new file mode 100644 index 00000000..9059cb49 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" +#include "Parsing/Matcher/AbstractMatcherFactory.h" + +class ZoneDefinitionMatcherFactory final : public AbstractMatcherFactory +{ +public: + explicit ZoneDefinitionMatcherFactory(const IMatcherForLabelSupplier* labelSupplier); + + _NODISCARD MatcherFactoryWrapper Type(ZoneDefinitionParserValueType type) const; + _NODISCARD MatcherFactoryWrapper Keyword(std::string keyword) const; + _NODISCARD MatcherFactoryWrapper Field() const; + _NODISCARD MatcherFactoryWrapper String() const; + _NODISCARD MatcherFactoryWrapper Char(char c) const; +}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.cpp new file mode 100644 index 00000000..ae787fca --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.cpp @@ -0,0 +1,16 @@ +#include "ZoneDefinitionMatcherKeyword.h" + +ZoneDefinitionMatcherKeyword::ZoneDefinitionMatcherKeyword(std::string value) + : m_value(std::move(value)) +{ + const std::hash hash; + m_hash = hash(m_value); +} + +MatcherResult ZoneDefinitionMatcherKeyword::CanMatch(ILexer* lexer, const unsigned tokenOffset) +{ + const auto& token = lexer->GetToken(tokenOffset); + return token.m_type == ZoneDefinitionParserValueType::FIELD && token.FieldHash() == m_hash && token.FieldValue() == m_value + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.h b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.h new file mode 100644 index 00000000..a643af45 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" +#include "Parsing/Matcher/AbstractMatcher.h" + +class ZoneDefinitionMatcherKeyword final : public AbstractMatcher +{ + size_t m_hash; + std::string m_value; + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override; + +public: + explicit ZoneDefinitionMatcherKeyword(std::string value); +}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.cpp new file mode 100644 index 00000000..d2fd51ab --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.cpp @@ -0,0 +1,13 @@ +#include "ZoneDefinitionMatcherValueType.h" + +ZoneDefinitionMatcherValueType::ZoneDefinitionMatcherValueType(const ZoneDefinitionParserValueType type) + : m_type(type) +{ +} + +MatcherResult ZoneDefinitionMatcherValueType::CanMatch(ILexer* lexer, const unsigned tokenOffset) +{ + return lexer->GetToken(tokenOffset).m_type == m_type + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.h b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.h new file mode 100644 index 00000000..1749a389 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" +#include "Parsing/Matcher/AbstractMatcher.h" + +class ZoneDefinitionMatcherValueType final : public AbstractMatcher +{ + ZoneDefinitionParserValueType m_type; + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override; + +public: + explicit ZoneDefinitionMatcherValueType(ZoneDefinitionParserValueType type); +}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.cpp deleted file mode 100644 index bbba85e9..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "SequenceZoneDefinitionConsumeEmptyLines.h" - -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" - -SequenceZoneDefinitionConsumeEmptyLines::SequenceZoneDefinitionConsumeEmptyLines() -{ - const SimpleMatcherFactory create(this); - - AddMatchers(create.Loop(create.Type(SimpleParserValueType::NEW_LINE))); -} - -void SequenceZoneDefinitionConsumeEmptyLines::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const -{ -} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.h deleted file mode 100644 index d2b6f7d7..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionConsumeEmptyLines.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" - -class SequenceZoneDefinitionConsumeEmptyLines final : public ZoneDefinitionParser::sequence_t -{ -protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; - -public: - SequenceZoneDefinitionConsumeEmptyLines(); -}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp index a4ec4df8..1e1c402e 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp @@ -1,44 +1,38 @@ #include "SequenceZoneDefinitionEntry.h" -#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionCommonMatchers.h" -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" +#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" SequenceZoneDefinitionEntry::SequenceZoneDefinitionEntry() { - const SimpleMatcherFactory create(this); - - AddLabeledMatchers(ZoneDefinitionCommonMatchers::AssetName(this), ZoneDefinitionCommonMatchers::LABEL_ASSET_NAME); + const ZoneDefinitionMatcherFactory create(this); + AddMatchers({ - create.Identifier().Capture(CAPTURE_TYPE_NAME), + create.Field().Capture(CAPTURE_TYPE_NAME), create.Char(','), create.Optional(create.Char(',').Tag(TAG_REFERENCE)), create.Or({ - create.Type(SimpleParserValueType::STRING), - create.Label(ZoneDefinitionCommonMatchers::LABEL_ASSET_NAME) - }).Capture(CAPTURE_ASSET_NAME), - create.Or({ - create.Type(SimpleParserValueType::NEW_LINE), - create.Type(SimpleParserValueType::END_OF_FILE) - }) + create.String(), + create.Field() + }).Capture(CAPTURE_ASSET_NAME) }); } -void SequenceZoneDefinitionEntry::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionEntry::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const { const auto& assetNameCapture = result.NextCapture(CAPTURE_ASSET_NAME); std::string assetName; - if (assetNameCapture.m_type == SimpleParserValueType::STRING) + if (assetNameCapture.m_type == ZoneDefinitionParserValueType::STRING) { assetName = assetNameCapture.StringValue(); } else { - assetName = assetNameCapture.IdentifierValue(); + assetName = assetNameCapture.FieldValue(); } state->m_assets.emplace_back( - result.NextCapture(CAPTURE_TYPE_NAME).IdentifierValue(), + result.NextCapture(CAPTURE_TYPE_NAME).FieldValue(), assetName, result.NextTag() == TAG_REFERENCE); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h index 34df7a7f..e9a6c44f 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h @@ -10,7 +10,7 @@ class SequenceZoneDefinitionEntry final : public ZoneDefinitionParser::sequence_ static constexpr auto CAPTURE_ASSET_NAME = 2; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; public: SequenceZoneDefinitionEntry(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp index 2d15441e..c0814457 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp @@ -1,23 +1,19 @@ #include "SequenceZoneDefinitionIgnore.h" -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" +#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" SequenceZoneDefinitionIgnore::SequenceZoneDefinitionIgnore() { - const SimpleMatcherFactory create(this); + const ZoneDefinitionMatcherFactory create(this); AddMatchers({ create.Keyword("ignore"), create.Char(','), - create.Identifier().Capture(CAPTURE_IGNORE_NAME), - create.Or({ - create.Type(SimpleParserValueType::NEW_LINE), - create.Type(SimpleParserValueType::END_OF_FILE) - }) + create.Field().Capture(CAPTURE_IGNORE_NAME) }); } -void SequenceZoneDefinitionIgnore::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionIgnore::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const { - state->m_ignores.emplace_back(result.NextCapture(CAPTURE_IGNORE_NAME).IdentifierValue()); + state->m_ignores.emplace_back(result.NextCapture(CAPTURE_IGNORE_NAME).FieldValue()); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h index 2654a36f..9b258787 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h @@ -7,7 +7,7 @@ class SequenceZoneDefinitionIgnore final : public ZoneDefinitionParser::sequence static constexpr auto CAPTURE_IGNORE_NAME = 1; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; public: SequenceZoneDefinitionIgnore(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp index e1fc5868..c7613419 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp @@ -1,23 +1,19 @@ #include "SequenceZoneDefinitionInclude.h" -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" +#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" SequenceZoneDefinitionInclude::SequenceZoneDefinitionInclude() { - const SimpleMatcherFactory create(this); + const ZoneDefinitionMatcherFactory create(this); AddMatchers({ create.Keyword("include"), create.Char(','), - create.Identifier().Capture(CAPTURE_INCLUDE_NAME), - create.Or({ - create.Type(SimpleParserValueType::NEW_LINE), - create.Type(SimpleParserValueType::END_OF_FILE) - }) + create.Field().Capture(CAPTURE_INCLUDE_NAME) }); } -void SequenceZoneDefinitionInclude::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionInclude::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const { - state->m_includes.emplace_back(result.NextCapture(CAPTURE_INCLUDE_NAME).IdentifierValue()); + state->m_includes.emplace_back(result.NextCapture(CAPTURE_INCLUDE_NAME).FieldValue()); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h index 6e57ef66..a981bcba 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h @@ -7,7 +7,7 @@ class SequenceZoneDefinitionInclude final : public ZoneDefinitionParser::sequenc static constexpr auto CAPTURE_INCLUDE_NAME = 1; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; public: SequenceZoneDefinitionInclude(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp index 03856caf..b4af39ce 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp @@ -1,24 +1,20 @@ #include "SequenceZoneDefinitionMetaData.h" -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" +#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" SequenceZoneDefinitionMetaData::SequenceZoneDefinitionMetaData() { - const SimpleMatcherFactory create(this); + const ZoneDefinitionMatcherFactory create(this); AddMatchers({ create.Char('>'), - create.Identifier().Capture(CAPTURE_KEY), + create.Field().Capture(CAPTURE_KEY), create.Char(','), - create.Identifier().Capture(CAPTURE_VALUE), - create.Or({ - create.Type(SimpleParserValueType::NEW_LINE), - create.Type(SimpleParserValueType::END_OF_FILE) - }) + create.Field().Capture(CAPTURE_VALUE) }); } -void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const { - state->m_metadata.insert(std::make_pair(result.NextCapture(CAPTURE_KEY).IdentifierValue(), result.NextCapture(CAPTURE_VALUE).IdentifierValue())); + state->m_metadata.insert(std::make_pair(result.NextCapture(CAPTURE_KEY).FieldValue(), result.NextCapture(CAPTURE_VALUE).FieldValue())); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h index 00c19257..efca91c2 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h @@ -8,7 +8,7 @@ class SequenceZoneDefinitionMetaData final : public ZoneDefinitionParser::sequen static constexpr auto CAPTURE_VALUE = 2; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; public: SequenceZoneDefinitionMetaData(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.cpp index 8b4fc28d..4f489d32 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.cpp @@ -1,9 +1,71 @@ #include "ZoneDefinitionLexer.h" +#include + ZoneDefinitionLexer::ZoneDefinitionLexer(IParserLineStream* stream) - : SimpleLexer(stream) + : AbstractLexer(stream) { - SetShouldEmitNewLineTokens(true); - SetShouldReadStrings(true); - SetShouldReadNumbers(false); -} \ No newline at end of file +} + +std::string ZoneDefinitionLexer::ReadField() +{ + const auto& currentLine = CurrentLine(); + assert(m_current_line_offset >= 1); + + const auto startPos = m_current_line_offset - 1; + const auto lineSize = currentLine.m_line.size(); + while (m_current_line_offset < lineSize) + { + const auto c = currentLine.m_line[m_current_line_offset]; + + bool isNonFieldCharacter; + switch (c) + { + case '\"': + case '>': + case '<': + case ',': + isNonFieldCharacter = true; + break; + default: + isNonFieldCharacter = false; + break; + } + + if (isNonFieldCharacter) + break; + + m_current_line_offset++; + } + + return std::string(currentLine.m_line, startPos, m_current_line_offset - startPos); +} + +ZoneDefinitionParserValue ZoneDefinitionLexer::GetNextToken() +{ + auto c = NextChar(); + + while (c != EOF) + { + switch (c) + { + case '\"': + return ZoneDefinitionParserValue::String(GetPreviousCharacterPos(), new std::string(ReadString())); + + case '>': + case '<': + case ',': + return ZoneDefinitionParserValue::Character(GetPreviousCharacterPos(), static_cast(c)); + + default: + if (isspace(c)) + break; + + return ZoneDefinitionParserValue::Field(GetPreviousCharacterPos(), new std::string(ReadField())); + } + + c = NextChar(); + } + + return ZoneDefinitionParserValue::EndOfFile(TokenPos()); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.h b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.h index e14ec839..10f0ddd0 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.h @@ -1,9 +1,15 @@ #pragma once -#include "Parsing/Simple/SimpleLexer.h" +#include "ZoneDefinitionParserValue.h" +#include "Parsing/Impl/AbstractLexer.h" -class ZoneDefinitionLexer final : public SimpleLexer +class ZoneDefinitionLexer final : public AbstractLexer { + std::string ReadField(); + +protected: + ZoneDefinitionParserValue GetNextToken() override; + public: explicit ZoneDefinitionLexer(IParserLineStream* stream); -}; \ No newline at end of file +}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp index 33916eab..ed52f58f 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp @@ -1,25 +1,22 @@ #include "ZoneDefinitionParser.h" - -#include "Sequence/SequenceZoneDefinitionConsumeEmptyLines.h" #include "Sequence/SequenceZoneDefinitionEntry.h" #include "Sequence/SequenceZoneDefinitionIgnore.h" #include "Sequence/SequenceZoneDefinitionInclude.h" #include "Sequence/SequenceZoneDefinitionMetaData.h" -ZoneDefinitionParser::ZoneDefinitionParser(SimpleLexer* lexer) +ZoneDefinitionParser::ZoneDefinitionParser(ZoneDefinitionLexer* lexer) : AbstractParser(lexer, std::make_unique()) { } -const std::vector::sequence_t*>& ZoneDefinitionParser::GetTestsForState() +const std::vector::sequence_t*>& ZoneDefinitionParser::GetTestsForState() { static std::vector tests({ new SequenceZoneDefinitionMetaData(), new SequenceZoneDefinitionInclude(), new SequenceZoneDefinitionIgnore(), - new SequenceZoneDefinitionEntry(), - new SequenceZoneDefinitionConsumeEmptyLines() + new SequenceZoneDefinitionEntry() }); return tests; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h index 911fc066..29a86197 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h @@ -1,16 +1,16 @@ #pragma once -#include "Parsing/Simple/SimpleLexer.h" -#include "Parsing/Simple/SimpleParserValue.h" +#include "ZoneDefinitionLexer.h" +#include "ZoneDefinitionParserValue.h" #include "Parsing/Impl/AbstractParser.h" #include "Zone/Definition/ZoneDefinition.h" -class ZoneDefinitionParser final : public AbstractParser +class ZoneDefinitionParser final : public AbstractParser { protected: const std::vector& GetTestsForState() override; public: - explicit ZoneDefinitionParser(SimpleLexer* lexer); + explicit ZoneDefinitionParser(ZoneDefinitionLexer* lexer); std::unique_ptr GetParsedValue(); }; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.cpp new file mode 100644 index 00000000..ac120cc7 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.cpp @@ -0,0 +1,115 @@ +#include "ZoneDefinitionParserValue.h" + +#include + +ZoneDefinitionParserValue ZoneDefinitionParserValue::Invalid(const TokenPos pos) +{ + ZoneDefinitionParserValue pv(pos, ZoneDefinitionParserValueType::INVALID); + return pv; +} + +ZoneDefinitionParserValue ZoneDefinitionParserValue::EndOfFile(const TokenPos pos) +{ + ZoneDefinitionParserValue pv(pos, ZoneDefinitionParserValueType::END_OF_FILE); + return pv; +} + +ZoneDefinitionParserValue ZoneDefinitionParserValue::Character(const TokenPos pos, const char c) +{ + ZoneDefinitionParserValue pv(pos, ZoneDefinitionParserValueType::CHARACTER); + pv.m_value.char_value = c; + return pv; +} + +ZoneDefinitionParserValue ZoneDefinitionParserValue::String(const TokenPos pos, std::string* str) +{ + ZoneDefinitionParserValue pv(pos, ZoneDefinitionParserValueType::STRING); + pv.m_value.string_value = str; + return pv; +} + +ZoneDefinitionParserValue ZoneDefinitionParserValue::Field(const TokenPos pos, std::string* field) +{ + ZoneDefinitionParserValue pv(pos, ZoneDefinitionParserValueType::FIELD); + pv.m_value.string_value = field; + pv.m_hash = std::hash()(*field); + return pv; +} + +ZoneDefinitionParserValue::ZoneDefinitionParserValue(const TokenPos pos, const ZoneDefinitionParserValueType type) + : m_pos(pos), + m_type(type), + m_hash(0), + m_value{} +{ +} + +ZoneDefinitionParserValue::~ZoneDefinitionParserValue() +{ + switch (m_type) + { + case ZoneDefinitionParserValueType::STRING: + case ZoneDefinitionParserValueType::FIELD: + delete m_value.string_value; + break; + + default: + break; + } + + m_value = ValueType(); +} + +ZoneDefinitionParserValue::ZoneDefinitionParserValue(ZoneDefinitionParserValue&& other) noexcept + : m_pos(other.m_pos), + m_type(other.m_type), + m_hash(other.m_hash), + m_value(other.m_value) +{ + other.m_value = ValueType(); +} + +ZoneDefinitionParserValue& ZoneDefinitionParserValue::operator=(ZoneDefinitionParserValue&& other) noexcept +{ + m_pos = other.m_pos; + m_type = other.m_type; + m_value = other.m_value; + m_hash = other.m_hash; + other.m_value = ValueType(); + + return *this; +} + +bool ZoneDefinitionParserValue::IsEof() const +{ + return m_type == ZoneDefinitionParserValueType::END_OF_FILE; +} + +const TokenPos& ZoneDefinitionParserValue::GetPos() const +{ + return m_pos; +} + +char ZoneDefinitionParserValue::CharacterValue() const +{ + assert(m_type == ZoneDefinitionParserValueType::CHARACTER); + return m_value.char_value; +} + +std::string& ZoneDefinitionParserValue::StringValue() const +{ + assert(m_type == ZoneDefinitionParserValueType::STRING); + return *m_value.string_value; +} + +std::string& ZoneDefinitionParserValue::FieldValue() const +{ + assert(m_type == ZoneDefinitionParserValueType::FIELD); + return *m_value.string_value; +} + +size_t ZoneDefinitionParserValue::FieldHash() const +{ + assert(m_type == ZoneDefinitionParserValueType::FIELD); + return m_hash; +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.h b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.h new file mode 100644 index 00000000..1b57b229 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.h @@ -0,0 +1,58 @@ +#pragma once + +#include + +#include "Parsing/IParserValue.h" +#include "Utils/ClassUtils.h" +#include "Parsing/TokenPos.h" + +enum class ZoneDefinitionParserValueType +{ + // Meta tokens + INVALID, + END_OF_FILE, + + CHARACTER, + STRING, + FIELD, + + // End + MAX +}; + +class ZoneDefinitionParserValue final : public IParserValue +{ +public: + TokenPos m_pos; + ZoneDefinitionParserValueType m_type; + size_t m_hash; + union ValueType + { + char char_value; + std::string* string_value; + } m_value; + + static ZoneDefinitionParserValue Invalid(TokenPos pos); + static ZoneDefinitionParserValue EndOfFile(TokenPos pos); + static ZoneDefinitionParserValue Character(TokenPos pos, char c); + static ZoneDefinitionParserValue String(TokenPos pos, std::string* str); + static ZoneDefinitionParserValue Field(TokenPos pos, std::string* field); + +private: + ZoneDefinitionParserValue(TokenPos pos, ZoneDefinitionParserValueType type); + +public: + ~ZoneDefinitionParserValue() override; + ZoneDefinitionParserValue(const ZoneDefinitionParserValue& other) = delete; + ZoneDefinitionParserValue(ZoneDefinitionParserValue&& other) noexcept; + ZoneDefinitionParserValue& operator=(const ZoneDefinitionParserValue& other) = delete; + ZoneDefinitionParserValue& operator=(ZoneDefinitionParserValue&& other) noexcept; + + _NODISCARD bool IsEof() const override; + _NODISCARD const TokenPos& GetPos() const override; + + _NODISCARD char CharacterValue() const; + _NODISCARD std::string& StringValue() const; + _NODISCARD std::string& FieldValue() const; + _NODISCARD size_t FieldHash() const; +};