diff --git a/src/Utils/Utils/ClassUtils.h b/src/Utils/Utils/ClassUtils.h index d71a0082..899eb12b 100644 --- a/src/Utils/Utils/ClassUtils.h +++ b/src/Utils/Utils/ClassUtils.h @@ -16,4 +16,22 @@ #else #define _NODISCARD #endif -#endif \ No newline at end of file +#endif + +template +struct Movable +{ + mutable T m_val; + + // ReSharper disable once CppNonExplicitConversionOperator + operator T() const && + { + return std::move(m_val); + } + + // ReSharper disable once CppNonExplicitConvertingConstructor + Movable(T&& in) + : m_val(std::move(in)) + { + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.h b/src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.h index a1d5413a..23e37c1c 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.h +++ b/src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.h @@ -5,12 +5,16 @@ #include "Utils/ClassUtils.h" #include "ILexer.h" +#include "IParserValue.h" #include "IParserLineStream.h" #include "ParsingException.h" template class AbstractLexer : public ILexer { + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + protected: std::deque m_token_cache; IParserLineStream* const m_stream; @@ -164,7 +168,7 @@ protected: const auto* start = &m_current_line.m_line.c_str()[m_current_line_offset - 1]; char* end; - integerValue = std::strtoul(start, &end, 16); + integerValue = static_cast(std::strtoul(start, &end, 16)); const auto numberLength = static_cast(end - start); if (numberLength == 0 || isalnum(*end) || *end == '_') throw ParsingException(GetPreviousCharacterPos(), "Invalid hex number"); @@ -179,9 +183,7 @@ protected: auto dot = false; auto exponent = false; - if (*currentCharacter == '-') - currentCharacter++; - else if (*currentCharacter == '+') + if (*currentCharacter == '-' || *currentCharacter == '+') currentCharacter++; while (*currentCharacter) @@ -289,4 +291,14 @@ public: { m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount); } + + _NODISCARD bool IsEof() + { + return GetToken(0).IsEof(); + } + + _NODISCARD const TokenPos& GetPos() + { + return GetToken(0).GetPos(); + } }; diff --git a/src/ZoneCodeGeneratorLib/Parsing/AbstractParser.h b/src/ZoneCodeGeneratorLib/Parsing/AbstractParser.h new file mode 100644 index 00000000..5907ef22 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/AbstractParser.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include + +#include "AbstractLexer.h" +#include "Sequence/AbstractSequence.h" + +template +class AbstractParser +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + +public: + typedef AbstractSequence sequence_t; + +protected: + AbstractLexer* m_lexer; + std::unique_ptr m_state; + + explicit AbstractParser(AbstractLexer* lexer, std::unique_ptr state) + : m_lexer(lexer), + m_state(std::move(state)) + { + } + + virtual const std::vector& GetTestsForState() = 0; + +public: + virtual ~AbstractParser() = default; + AbstractParser(const AbstractParser& other) = default; + AbstractParser(AbstractParser&& other) noexcept = default; + AbstractParser& operator=(const AbstractParser& other) = default; + AbstractParser& operator=(AbstractParser&& other) noexcept = default; + + bool Parse() + { + try + { + while (!m_lexer->IsEof()) + { + auto testSuccessful = false; + const auto& availableTests = GetTestsForState(); + + for (const sequence_t* test : availableTests) + { + unsigned consumedTokenCount; + + if (test->MatchSequence(m_lexer, m_state.get(), consumedTokenCount)) + { + m_lexer->PopTokens(consumedTokenCount); + testSuccessful = true; + break; + } + } + + if (!testSuccessful) + { + const TokenPos& pos = m_lexer->GetPos(); + std::cout << "Error: " << pos.m_filename << " L" << pos.m_line << ':' << pos.m_column << " Could not parse expression." << std::endl; + return false; + } + } + } + catch (const ParsingException& e) + { + std::cout << "Error: " << e.FullMessage() << std::endl; + return false; + } + + return true; + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp index 71aaf75d..18d48e38 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp @@ -16,7 +16,8 @@ CommandsParserValue CommandsParserValue::EndOfFile(const TokenPos pos) CommandsParserValue CommandsParserValue::Character(const TokenPos pos, const char c) { - CommandsParserValue pv(pos, c); + CommandsParserValue pv(pos, CommandsParserValueType::CHARACTER); + pv.m_value.char_value = c; return pv; } @@ -93,6 +94,7 @@ CommandsParserValue CommandsParserValue::Identifier(const TokenPos pos, std::str { CommandsParserValue pv(pos, CommandsParserValueType::IDENTIFIER); pv.m_value.string_value = identifier; + pv.m_hash = std::hash()(*identifier); return pv; } @@ -103,10 +105,11 @@ CommandsParserValue CommandsParserValue::TypeName(const TokenPos pos, std::strin return pv; } -CommandsParserValue::CommandsParserValue(const TokenPos pos, const int type) +CommandsParserValue::CommandsParserValue(const TokenPos pos, const CommandsParserValueType type) : m_pos(pos), m_type(type), - m_value() + m_hash(0), + m_value{} { } @@ -129,6 +132,7 @@ CommandsParserValue::~CommandsParserValue() CommandsParserValue::CommandsParserValue(CommandsParserValue&& other) noexcept : m_type(other.m_type), + m_hash(other.m_hash), m_value(other.m_value) { other.m_value = ValueType(); @@ -138,11 +142,28 @@ CommandsParserValue& CommandsParserValue::operator=(CommandsParserValue&& other) { m_type = other.m_type; m_value = other.m_value; + m_hash = other.m_hash; other.m_value = ValueType(); return *this; } +bool CommandsParserValue::IsEof() const +{ + return m_type == CommandsParserValueType::END_OF_FILE; +} + +const TokenPos& CommandsParserValue::GetPos() const +{ + return m_pos; +} + +char CommandsParserValue::CharacterValue() const +{ + assert(m_type == CommandsParserValueType::CHARACTER); + return m_value.char_value; +} + int CommandsParserValue::IntegerValue() const { assert(m_type == CommandsParserValueType::INTEGER); @@ -167,6 +188,12 @@ std::string& CommandsParserValue::IdentifierValue() const return *m_value.string_value; } +size_t CommandsParserValue::IdentifierHash() const +{ + assert(m_type == CommandsParserValueType::IDENTIFIER); + return m_hash; +} + std::string& CommandsParserValue::TypeNameValue() const { assert(m_type == CommandsParserValueType::TYPE_NAME); diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h index 5529b96f..d2c452bf 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h @@ -2,53 +2,52 @@ #include + +#include "Parsing/IParserValue.h" #include "Utils/ClassUtils.h" #include "Parsing/TokenPos.h" -class CommandsParserValueType +enum class CommandsParserValueType { - CommandsParserValueType() = default; + // Meta tokens + INVALID, + END_OF_FILE, -public: - enum - { - FIRST = 0x100, + // Single character + CHARACTER, - // Meta tokens - INVALID = FIRST, - END_OF_FILE, + // Symbol tokens + SHIFT_LEFT, + SHIFT_RIGHT, + EQUALS, + NOT_EQUAL, + GREATER_EQUAL, + LESS_EQUAL, + LOGICAL_AND, + LOGICAL_OR, - // 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, - // Generic token types - INTEGER, - FLOATING_POINT, - STRING, - IDENTIFIER, + // Parser created + TYPE_NAME, - // Parser created - TYPE_NAME, - - // End - MAX - }; + // End + MAX }; -class CommandsParserValue +class CommandsParserValue final : public IParserValue { public: TokenPos m_pos; - int m_type; + CommandsParserValueType m_type; + size_t m_hash; union ValueType { + char char_value; int int_value; double double_value; std::string* string_value; @@ -72,18 +71,23 @@ public: static CommandsParserValue TypeName(TokenPos pos, std::string* typeName); private: - CommandsParserValue(TokenPos pos, int type); + CommandsParserValue(TokenPos pos, CommandsParserValueType type); public: - ~CommandsParserValue(); + ~CommandsParserValue() override; CommandsParserValue(const CommandsParserValue& other) = delete; CommandsParserValue(CommandsParserValue&& other) noexcept; CommandsParserValue& operator=(const CommandsParserValue& other) = delete; CommandsParserValue& operator=(CommandsParserValue&& other) noexcept; + _NODISCARD bool IsEof() const override; + _NODISCARD const TokenPos& GetPos() const override; + + _NODISCARD char CharacterValue() const; _NODISCARD int IntegerValue() const; _NODISCARD double FloatingPointValue() const; _NODISCARD std::string& StringValue() const; _NODISCARD std::string& IdentifierValue() const; + _NODISCARD size_t IdentifierHash() const; _NODISCARD std::string& TypeNameValue() const; }; \ No newline at end of file diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp index 7a15a98b..457acf4c 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp @@ -3,6 +3,7 @@ #include #include "Impl/HeaderLexer.h" +#include "Impl/HeaderParser.h" #include "Parsing/ParsingException.h" #include "Parsing/Impl/CommentRemovingStreamProxy.h" #include "Parsing/Impl/DefinesStreamProxy.h" @@ -53,100 +54,8 @@ bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository) SetupStreamProxies(); - auto lexer = std::make_unique(m_stream); + const auto lexer = std::make_unique(m_stream); + const auto parser = std::make_unique(lexer.get(), repository); - try - { - /*while (true) - { - auto line = m_stream->NextLine(); - - if (line.IsEof()) - break; - - std::cout << "Line " << line.m_filename.get() << ":" << line.m_line_number << ": " << line.m_line << "\n"; - }*/ - - auto eof = false; - while (!eof) - { - const auto& token = lexer->GetToken(0); - - switch (token.m_type) - { - case HeaderParserValueType::END_OF_FILE: - case HeaderParserValueType::INVALID: - eof = true; - break; - - case HeaderParserValueType::CHARACTER: - std::cout << "Token " << token.CharacterValue() << "\n"; - break; - - case HeaderParserValueType::IDENTIFIER: - std::cout << "Token IDENTIFIER \"" << token.IdentifierValue() << "\"\n"; - break; - - case HeaderParserValueType::STRING: - std::cout << "Token STRING \"" << token.StringValue() << "\"\n"; - break; - - case HeaderParserValueType::INTEGER: - std::cout << "Token INTEGER " << token.IntegerValue() << "\n"; - break; - - case HeaderParserValueType::FLOATING_POINT: - std::cout << "Token FLOATINGPOINT " << token.FloatingPointValue() << "\n"; - break; - - case HeaderParserValueType::DECLSPEC: - std::cout << "Token DECLSPEC\n"; - break; - - case HeaderParserValueType::ALIGN: - std::cout << "Token ALIGN\n"; - break; - - case HeaderParserValueType::ALIGNAS: - std::cout << "Token ALIGNAS\n"; - break; - - case HeaderParserValueType::CONST: - std::cout << "Token CONST\n"; - break; - - case HeaderParserValueType::ENUM: - std::cout << "Token ENUM\n"; - break; - - case HeaderParserValueType::NAMESPACE: - std::cout << "Token NAMESPACE\n"; - break; - - case HeaderParserValueType::STRUCT: - std::cout << "Token STRUCT\n"; - break; - - case HeaderParserValueType::TYPEDEF: - std::cout << "Token TYPEDEF\n"; - break; - - case HeaderParserValueType::UNION: - std::cout << "Token UNION\n"; - break; - - default: - std::cout << "Token UNKNOWN\n"; - break; - } - - lexer->PopTokens(1); - } - } - catch (const ParsingException& e) - { - std::cout << "Error: " << e.FullMessage() << std::endl; - } - - return true; + return parser->Parse(); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.cpp index e69de29b..8e3644e5 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.cpp @@ -0,0 +1,17 @@ +#include "HeaderParser.h" + +#include "Parsing/Header/Sequence/SequenceNamespace.h" + +HeaderParser::HeaderParser(HeaderLexer* lexer, IDataRepository* targetRepository) + : AbstractParser(lexer, std::make_unique()), + m_repository(targetRepository) +{ + auto sequenceNamespace = std::make_unique(); + m_normal_tests.push_back(sequenceNamespace.get()); + m_tests.emplace_back(std::move(sequenceNamespace)); +} + +const std::vector& HeaderParser::GetTestsForState() +{ + return m_normal_tests; +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.h index c7a02df4..17cb189a 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParser.h @@ -1,6 +1,20 @@ #pragma once -class HeaderParser -{ +#include "HeaderLexer.h" +#include "HeaderParserState.h" +#include "Parsing/AbstractParser.h" +#include "Persistence/IDataRepository.h" -}; \ No newline at end of file +class HeaderParser final : public AbstractParser +{ + IDataRepository* m_repository; + + std::vector> m_tests; + std::vector m_normal_tests; + +protected: + const std::vector& GetTestsForState() override; + +public: + HeaderParser(HeaderLexer* lexer, IDataRepository* targetRepository); +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserState.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserState.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserState.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserState.h new file mode 100644 index 00000000..12aafd80 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserState.h @@ -0,0 +1,7 @@ +#pragma once + +class HeaderParserState +{ +public: + +}; \ No newline at end of file diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.cpp index 740f6a1e..5eb1db58 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.cpp @@ -149,6 +149,16 @@ HeaderParserValue& HeaderParserValue::operator=(HeaderParserValue&& other) noexc return *this; } +bool HeaderParserValue::IsEof() const +{ + return m_type == HeaderParserValueType::END_OF_FILE; +} + +const TokenPos& HeaderParserValue::GetPos() const +{ + return m_pos; +} + char HeaderParserValue::CharacterValue() const { assert(m_type == HeaderParserValueType::CHARACTER); diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.h index d51588d1..427ef5fa 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Impl/HeaderParserValue.h @@ -2,6 +2,8 @@ #include + +#include "Parsing/IParserValue.h" #include "Utils/ClassUtils.h" #include "Parsing/TokenPos.h" @@ -48,7 +50,7 @@ enum class HeaderParserValueType MAX }; -class HeaderParserValue +class HeaderParserValue final : public IParserValue { public: TokenPos m_pos; @@ -83,12 +85,15 @@ private: HeaderParserValue(TokenPos pos, HeaderParserValueType type); public: - ~HeaderParserValue(); + ~HeaderParserValue() override; HeaderParserValue(const HeaderParserValue& other) = delete; HeaderParserValue(HeaderParserValue&& other) noexcept; HeaderParserValue& operator=(const HeaderParserValue& other) = delete; HeaderParserValue& operator=(HeaderParserValue&& other) noexcept; + _NODISCARD bool IsEof() const override; + _NODISCARD const TokenPos& GetPos() const override; + _NODISCARD char CharacterValue() const; _NODISCARD int IntegerValue() const; _NODISCARD double FloatingPointValue() const; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherCharacter.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherCharacter.cpp new file mode 100644 index 00000000..62cbb30a --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherCharacter.cpp @@ -0,0 +1,14 @@ +#include "HeaderMatcherCharacter.h" + +HeaderMatcherCharacter::HeaderMatcherCharacter(const char c) + : m_char(c) +{ +} + +MatcherResult HeaderMatcherCharacter::CanMatch(AbstractLexer* lexer, const unsigned tokenOffset) +{ + const auto& token = lexer->GetToken(tokenOffset); + return token.m_type == HeaderParserValueType::CHARACTER && token.CharacterValue() == m_char + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherCharacter.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherCharacter.h new file mode 100644 index 00000000..756533c1 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherCharacter.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/Header/Impl/HeaderParserValue.h" +#include "Parsing/Matcher/AbstractMatcher.h" + +class HeaderMatcherCharacter final : public AbstractMatcher +{ + char m_char; + +protected: + MatcherResult CanMatch(AbstractLexer* lexer, unsigned tokenOffset) override; + +public: + explicit HeaderMatcherCharacter(char c); +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherFactory.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherFactory.cpp new file mode 100644 index 00000000..928de2f8 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherFactory.cpp @@ -0,0 +1,19 @@ +#include "HeaderMatcherFactory.h" + +#include "HeaderMatcherCharacter.h" +#include "HeaderMatcherValueType.h" + +HeaderMatcherFactory::HeaderMatcherFactory(const IMatcherForLabelSupplier* labelSupplier) + : AbstractMatcherFactory(labelSupplier) +{ +} + +MatcherFactoryWrapper HeaderMatcherFactory::Type(HeaderParserValueType type) const +{ + return MatcherFactoryWrapper(std::make_unique(type)); +} + +MatcherFactoryWrapper HeaderMatcherFactory::Char(char c) const +{ + return MatcherFactoryWrapper(std::make_unique(c)); +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherFactory.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherFactory.h new file mode 100644 index 00000000..606c31ed --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherFactory.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Parsing/Header/Impl/HeaderParserValue.h" +#include "Parsing/Matcher/AbstractMatcherFactory.h" + +class HeaderMatcherFactory final : public AbstractMatcherFactory +{ +public: + explicit HeaderMatcherFactory(const IMatcherForLabelSupplier* labelSupplier); + + _NODISCARD MatcherFactoryWrapper Type(HeaderParserValueType type) const; + _NODISCARD MatcherFactoryWrapper Char(char c) const; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherValueType.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherValueType.cpp new file mode 100644 index 00000000..305912ed --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherValueType.cpp @@ -0,0 +1,13 @@ +#include "HeaderMatcherValueType.h" + +HeaderMatcherValueType::HeaderMatcherValueType(HeaderParserValueType type) + : m_type(type) +{ +} + +MatcherResult HeaderMatcherValueType::CanMatch(AbstractLexer* lexer, const unsigned tokenOffset) +{ + return lexer->GetToken(tokenOffset).m_type == m_type + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherValueType.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherValueType.h new file mode 100644 index 00000000..c8e7c6f4 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Matcher/HeaderMatcherValueType.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/Header/Impl/HeaderParserValue.h" +#include "Parsing/Matcher/AbstractMatcher.h" + +class HeaderMatcherValueType final : public AbstractMatcher +{ + HeaderParserValueType m_type; + +protected: + MatcherResult CanMatch(AbstractLexer* lexer, unsigned tokenOffset) override; + +public: + explicit HeaderMatcherValueType(HeaderParserValueType type); +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceCloseBlock.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceCloseBlock.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceCloseBlock.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceCloseBlock.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnum.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnum.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnum.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnum.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnumMember.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnumMember.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnumMember.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceEnumMember.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceForwardDecl.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceForwardDecl.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceForwardDecl.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceForwardDecl.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceNamespace.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceNamespace.cpp new file mode 100644 index 00000000..25679f55 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceNamespace.cpp @@ -0,0 +1,18 @@ +#include "SequenceNamespace.h" + +#include "Parsing/Header/Matcher/HeaderMatcherFactory.h" + +SequenceNamespace::SequenceNamespace() +{ + const HeaderMatcherFactory create(this); + + AddMatchers({ + create.Type(HeaderParserValueType::NAMESPACE), + create.Type(HeaderParserValueType::IDENTIFIER).Capture(CAPTURE_NAME), + create.Char('{') + }); +} + +void SequenceNamespace::ProcessMatch(HeaderParserState* state, const SequenceResult& result) const +{ +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceNamespace.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceNamespace.h new file mode 100644 index 00000000..54e5d04c --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceNamespace.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Parsing/Sequence/AbstractSequence.h" +#include "Parsing/Header/Impl/HeaderParserState.h" +#include "Parsing/Header/Impl/HeaderParserValue.h" + +class SequenceNamespace final : public AbstractSequence +{ + static constexpr int CAPTURE_NAME = 0; + +protected: + void ProcessMatch(HeaderParserState* state, const SequenceResult& result) const override; + +public: + SequenceNamespace(); +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceStruct.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceStruct.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceStruct.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceStruct.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceUnion.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceUnion.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceUnion.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceUnion.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCodeGeneratorLib/Parsing/IParserValue.h b/src/ZoneCodeGeneratorLib/Parsing/IParserValue.h new file mode 100644 index 00000000..3dfd4c4c --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/IParserValue.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Utils/ClassUtils.h" +#include "TokenPos.h" + +class IParserValue +{ +protected: + IParserValue() = default; + +public: + virtual ~IParserValue() = default; + IParserValue(const IParserValue& other) = default; + IParserValue(IParserValue&& other) noexcept = default; + IParserValue& operator=(const IParserValue& other) = default; + IParserValue& operator=(IParserValue&& other) noexcept = default; + + _NODISCARD virtual bool IsEof() const = 0; + _NODISCARD virtual const TokenPos& GetPos() const = 0; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcher.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcher.h new file mode 100644 index 00000000..2b7d1be2 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcher.h @@ -0,0 +1,95 @@ +#pragma once + +#include + +#include "Parsing/IParserValue.h" +#include "Parsing/AbstractLexer.h" +#include "Parsing/Matcher/MatcherResult.h" + +template +class AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + +public: + static constexpr int NO_ID = -1; + +private: + int m_tag_id; + int m_capture_id; + bool m_no_consume; + std::function>)> m_transform_func; + +protected: + AbstractMatcher() + : m_tag_id(NO_ID), + m_capture_id(NO_ID), + m_no_consume(false) + { + } + + virtual MatcherResult CanMatch(AbstractLexer* 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>)> transform) + { + m_transform_func = std::move(transform); + } + + MatcherResult Match(AbstractLexer* lexer, const unsigned tokenOffset) + { + MatcherResult result = CanMatch(lexer, tokenOffset); + + if (!result.m_matches) + return result; + + if (m_tag_id != NO_ID) + result.m_tags.push_back(m_tag_id); + + if (m_capture_id != NO_ID) + { + if (m_transform_func) + { + std::vector> 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_captures.emplace_back(m_capture_id, result.m_fabricated_tokens.size() - 1, true); + } + else + { + for (auto i = 0u; i < result.m_consumed_token_count; i++) + { + result.m_captures.emplace_back(m_capture_id, tokenOffset + i); + } + } + } + + return result; + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcherFactory.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcherFactory.h new file mode 100644 index 00000000..8312dcf6 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcherFactory.h @@ -0,0 +1,113 @@ +#pragma once + +#include + +#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 +class MatcherFactoryWrapper +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + std::unique_ptr> m_matcher; + +public: + explicit MatcherFactoryWrapper(std::unique_ptr> matcher) + : m_matcher(std::move(matcher)) + { + } + + MatcherFactoryWrapper& Tag(const int tagId) + { + m_matcher->SetTag(tagId); + return *this; + } + + MatcherFactoryWrapper& Capture(const int captureId) + { + m_matcher->SetCapture(captureId); + return *this; + } + + MatcherFactoryWrapper& NoConsume() + { + m_matcher->SetConsume(false); + return *this; + } + + MatcherFactoryWrapper& Transform(std::function>)> transform) + { + m_matcher->SetTransform(std::move(transform)); + return *this; + } + + std::unique_ptr> Build() + { + return std::move(m_matcher); + } + + // ReSharper disable once CppNonExplicitConversionOperator + operator std::unique_ptr>() + { + return Build(); + } + + // ReSharper disable once CppNonExplicitConversionOperator + operator Movable>>() + { + return Build(); + } +}; + +template +class AbstractMatcherFactory +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + const IMatcherForLabelSupplier* m_label_supplier; + +public: + explicit AbstractMatcherFactory(const IMatcherForLabelSupplier* labelSupplier) + : m_label_supplier(labelSupplier) + { + } + + _NODISCARD MatcherFactoryWrapper And(std::initializer_list>> matchers) const + { + return MatcherFactoryWrapper(std::make_unique>(std::move(matchers))); + } + + _NODISCARD MatcherFactoryWrapper Or(std::initializer_list>> matchers) const + { + return MatcherFactoryWrapper(std::make_unique>(std::move(matchers))); + } + + _NODISCARD MatcherFactoryWrapper Loop(std::unique_ptr> matcher) const + { + return MatcherFactoryWrapper(std::make_unique>(std::move(matcher))); + } + + _NODISCARD MatcherFactoryWrapper OptionalLoop(std::unique_ptr> matcher) const + { + return MatcherFactoryWrapper(std::make_unique>(std::make_unique>(std::move(matcher)))); + } + + _NODISCARD MatcherFactoryWrapper Optional(std::unique_ptr> matcher) const + { + return MatcherFactoryWrapper(std::make_unique>(std::move(matcher))); + } + + _NODISCARD MatcherFactoryWrapper Label(const int label) const + { + return MatcherFactoryWrapper(std::make_unique>(label)); + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherAnd.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherAnd.h new file mode 100644 index 00000000..c9461b03 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherAnd.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#include "Parsing/IParserValue.h" +#include "AbstractMatcher.h" + +template +class MatcherAnd final : public AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + std::vector>> m_matchers; + +protected: + MatcherResult CanMatch(AbstractLexer* lexer, const unsigned tokenOffset) override + { + auto matchResult = MatcherResult::Match(0); + + for (const std::unique_ptr>& matcher : m_matchers) + { + MatcherResult result = matcher->Match(lexer, tokenOffset + matchResult.m_consumed_token_count); + + if (!result.m_matches) + return MatcherResult::NoMatch(); + + matchResult.Absorb(std::move(result)); + } + + return matchResult; + } + +public: + MatcherAnd(std::initializer_list>>> matchers) + : m_matchers(std::make_move_iterator(matchers.begin()), std::make_move_iterator(matchers.end())) + { + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherLabel.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherLabel.h new file mode 100644 index 00000000..d23efdb8 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherLabel.h @@ -0,0 +1,50 @@ +#pragma once + +#include "Utils/ClassUtils.h" +#include "Parsing/IParserValue.h" +#include "AbstractMatcher.h" + +template +class IMatcherForLabelSupplier +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::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* GetMatcherForLabel(int label) const = 0; +}; + +template +class MatcherLabel final : public AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + const IMatcherForLabelSupplier* m_supplier; + int m_label; + +protected: + MatcherResult CanMatch(AbstractLexer* lexer, unsigned tokenOffset) override + { + AbstractMatcher* matcher = m_supplier->GetMatcherForLabel(m_label); + + if (matcher) + return matcher->Match(lexer, tokenOffset); + + return MatcherResult::NoMatch(); + } + +public: + MatcherLabel(const IMatcherForLabelSupplier* supplier, const int label) + : m_supplier(supplier), + m_label(label) + { + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherLoop.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherLoop.h new file mode 100644 index 00000000..aea6f046 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherLoop.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include "Parsing/IParserValue.h" +#include "AbstractMatcher.h" + +template +class MatcherLoop final : public AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + std::unique_ptr> m_matcher; + +protected: + MatcherResult CanMatch(AbstractLexer* lexer, const unsigned tokenOffset) override + { + auto matchResult = MatcherResult::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::NoMatch(); + } + + loopedAtLeastOnce = true; + matchResult.Absorb(std::move(result)); + } + } + +public: + explicit MatcherLoop(std::unique_ptr> matcher) + : m_matcher(std::move(matcher)) + { + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherOptional.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherOptional.h new file mode 100644 index 00000000..5b456f49 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherOptional.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include "Parsing/IParserValue.h" +#include "AbstractMatcher.h" + +template +class MatcherOptional final : public AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + std::unique_ptr> m_matcher; + +protected: + MatcherResult CanMatch(AbstractLexer* lexer, unsigned tokenOffset) override + { + auto result = m_matcher->Match(lexer, tokenOffset); + + if (result.m_matches) + return result; + + return MatcherResult::Match(0); + } + +public: + explicit MatcherOptional(std::unique_ptr> matcher) + : m_matcher(std::move(matcher)) + { + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherOr.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherOr.h new file mode 100644 index 00000000..159b8b77 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherOr.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include "Parsing/IParserValue.h" +#include "AbstractMatcher.h" + +template +class MatcherOr final : public AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + std::vector>> m_matchers; + +protected: + MatcherResult CanMatch(AbstractLexer* lexer, unsigned tokenOffset) override + { + for (const auto& matcher : m_matchers) + { + const auto result = matcher->Match(lexer, tokenOffset); + + if (!result.m_matches) + continue; + + return result; + } + + return MatcherResult::NoMatch(); + } + +public: + MatcherOr(std::initializer_list>>> matchers) + : m_matchers(std::make_move_iterator(matchers.begin()), std::make_move_iterator(matchers.end())) + { + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherResult.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherResult.h new file mode 100644 index 00000000..8e0aab13 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/MatcherResult.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include + +#include "Utils/ClassUtils.h" +#include "Parsing/IParserValue.h" + +template +class MatcherResult +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + +public: + class Capture + { + static constexpr unsigned FABRICATED_FLAG_MASK = std::numeric_limits::max() ^ std::numeric_limits::max(); + static constexpr unsigned TOKEN_INDEX_MASK = ~FABRICATED_FLAG_MASK; + + int m_capture_id; + unsigned m_token_index; + + public: + 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(!isFabricated ? tokenIndex : tokenIndex | FABRICATED_FLAG_MASK) + { + } + + _NODISCARD int GetCaptureId() const + { + return m_capture_id; + } + + _NODISCARD bool IsFabricated() const + { + return m_token_index & FABRICATED_FLAG_MASK; + } + + _NODISCARD unsigned GetTokenIndex() const + { + return m_token_index & TOKEN_INDEX_MASK; + } + }; + + bool m_matches; + unsigned m_consumed_token_count; + std::vector m_tags; + std::vector m_captures; + std::vector 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&& 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.IsFabricated()) + m_captures.emplace_back(capture.GetCaptureId(), m_fabricated_tokens.size() + capture.GetTokenIndex(), true); + else + m_captures.emplace_back(capture.GetCaptureId(), capture.GetTokenIndex()); + } + + for(auto& fabricated : other.m_fabricated_tokens) + { + m_fabricated_tokens.emplace_back(std::move(fabricated)); + } + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Sequence/AbstractSequence.h b/src/ZoneCodeGeneratorLib/Parsing/Sequence/AbstractSequence.h new file mode 100644 index 00000000..df58c251 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Sequence/AbstractSequence.h @@ -0,0 +1,80 @@ +#pragma once + +#include + +#include "SequenceResult.h" +#include "Utils/ClassUtils.h" +#include "Parsing/Matcher/AbstractMatcher.h" +#include "Parsing/Matcher/MatcherAnd.h" +#include "Parsing/Matcher/MatcherLabel.h" + +template +class AbstractSequence : protected IMatcherForLabelSupplier +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + +public: + typedef AbstractMatcher matcher_t; + +private: + + std::unique_ptr m_entry; + std::unordered_map> m_matchers; + +protected: + static constexpr int ENTRY_LABEL = 0; + + AbstractSequence() = default; + + virtual void ProcessMatch(ParserState* state, const SequenceResult& result) const = 0; + + void AddMatchers(std::initializer_list>> matchers) + { + assert(!m_entry); + m_entry = std::make_unique>(matchers); + } + + void AddLabeledMatchers(int label, std::initializer_list>> matchers) + { + assert(m_matchers.find(label) == m_matchers.end()); + m_matchers.emplace(label, std::make_unique>(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(AbstractLexer* lexer, ParserState* state, unsigned& consumedTokenCount) const + { + if (!m_entry) + return false; + + auto result = m_entry->Match(lexer, 0); + + if (result.m_matches) + { + SequenceResult sequenceResult(lexer, result); + ProcessMatch(state, sequenceResult); + consumedTokenCount = result.m_consumed_token_count; + } + + return result.m_matches; + } +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Sequence/SequenceResult.h b/src/ZoneCodeGeneratorLib/Parsing/Sequence/SequenceResult.h new file mode 100644 index 00000000..e396d564 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Sequence/SequenceResult.h @@ -0,0 +1,84 @@ +#pragma once + +#include + +#include "Utils/ClassUtils.h" +#include "Parsing/Matcher/AbstractMatcher.h" +#include "Parsing/Matcher/MatcherResult.h" + +template +class SequenceResult +{ + class Capture + { + public: + unsigned m_offset; + std::vector> m_tokens; + + Capture() + : m_offset(0) + { + } + }; + + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + + std::vector m_tags; + std::unordered_map m_captures; + + unsigned m_tag_offset; + +public: + SequenceResult(AbstractLexer* lexer, const MatcherResult& result) + : m_tags(result.m_tags), + m_tag_offset(0) + { + for (const typename MatcherResult::Capture& capture : result.m_captures) + { + if (capture.IsFabricated()) + m_captures[capture.GetCaptureId()].m_tokens.push_back(result.m_fabricated_tokens[capture.GetTokenIndex()]); + else + m_captures[capture.GetCaptureId()].m_tokens.push_back(lexer->GetToken(capture.GetTokenIndex())); + } + } + + _NODISCARD int PeekTag() const + { + if (m_tag_offset < m_tags.size()) + return m_tags[m_tag_offset]; + + return AbstractMatcher::NO_ID; + } + + int NextTag() + { + if (m_tag_offset < m_tags.size()) + return m_tags[m_tag_offset++]; + + return AbstractMatcher::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++]; + } +}; diff --git a/src/ZoneCodeGeneratorNew/main.cpp b/src/ZoneCodeGeneratorNew/main.cpp index 9025da72..f21346df 100644 --- a/src/ZoneCodeGeneratorNew/main.cpp +++ b/src/ZoneCodeGeneratorNew/main.cpp @@ -1,7 +1,14 @@ +#include +#include + #include "ZoneCodeGenerator.h" int main(const int argc, const char** argv) { + int i = 5; + std::vector> asdf; + asdf.emplace_back(1, i); + const ZoneCodeGenerator zoneCodeGenerator; return zoneCodeGenerator.Run(argc, argv); }