#pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace hex::pl { class Parser { public: using TokenIter = std::vector::const_iterator; Parser() = default; ~Parser() = default; std::optional>> parse(const std::vector &tokens); const std::optional &getError() { return this->m_error; } private: std::optional m_error; TokenIter m_curr; TokenIter m_originalPosition, m_partOriginalPosition; std::unordered_map> m_types; std::vector m_matchedOptionals; std::vector> m_currNamespace; u32 getLineNumber(i32 index) const { return this->m_curr[index].lineNumber; } template std::unique_ptr create(T *node) { node->setLineNumber(this->getLineNumber(-1)); return std::unique_ptr(node); } template const T &getValue(i32 index) const { auto value = std::get_if(&this->m_curr[index].value); if (value == nullptr) throwParserError("failed to decode token. Invalid type.", getLineNumber(index)); return *value; } Token::Type getType(i32 index) const { return this->m_curr[index].type; } std::string getNamespacePrefixedName(const std::string &name) { std::string result; for (const auto &part : this->m_currNamespace.back()) { result += part + "::"; } result += name; return result; } std::unique_ptr parseFunctionCall(); std::unique_ptr parseStringLiteral(); std::string parseNamespaceResolution(); std::unique_ptr parseScopeResolution(); std::unique_ptr parseRValue(); std::unique_ptr parseRValue(ASTNodeRValue::Path &path); std::unique_ptr parseFactor(); std::unique_ptr parseCastExpression(); std::unique_ptr parseUnaryExpression(); std::unique_ptr parseMultiplicativeExpression(); std::unique_ptr parseAdditiveExpression(); std::unique_ptr parseShiftExpression(); std::unique_ptr parseBinaryAndExpression(); std::unique_ptr parseBinaryXorExpression(); std::unique_ptr parseBinaryOrExpression(); std::unique_ptr parseBooleanAnd(); std::unique_ptr parseBooleanXor(); std::unique_ptr parseBooleanOr(); std::unique_ptr parseRelationExpression(); std::unique_ptr parseEqualityExpression(); std::unique_ptr parseTernaryConditional(); std::unique_ptr parseMathematicalExpression(); std::unique_ptr parseFunctionDefinition(); std::unique_ptr parseFunctionVariableDecl(); std::unique_ptr parseFunctionStatement(); std::unique_ptr parseFunctionVariableAssignment(const std::string &lvalue); std::unique_ptr parseFunctionVariableCompoundAssignment(const std::string &lvalue); std::unique_ptr parseFunctionControlFlowStatement(); std::vector> parseStatementBody(); std::unique_ptr parseFunctionConditional(); std::unique_ptr parseFunctionWhileLoop(); std::unique_ptr parseFunctionForLoop(); void parseAttribute(Attributable *currNode); std::unique_ptr parseConditional(); std::unique_ptr parseWhileStatement(); std::unique_ptr parseType(bool allowFunctionTypes = false); std::shared_ptr parseUsingDeclaration(); std::unique_ptr parsePadding(); std::unique_ptr parseMemberVariable(const std::shared_ptr &type); std::unique_ptr parseMemberArrayVariable(const std::shared_ptr &type); std::unique_ptr parseMemberPointerVariable(const std::shared_ptr &type); std::unique_ptr parseMember(); std::shared_ptr parseStruct(); std::shared_ptr parseUnion(); std::shared_ptr parseEnum(); std::shared_ptr parseBitfield(); std::unique_ptr parseVariablePlacement(const std::shared_ptr &type); std::unique_ptr parseArrayVariablePlacement(const std::shared_ptr &type); std::unique_ptr parsePointerVariablePlacement(const std::shared_ptr &type); std::unique_ptr parsePlacement(); std::vector> parseNamespace(); std::vector> parseStatements(); std::shared_ptr addType(const std::string &name, std::unique_ptr &&node, std::optional endian = std::nullopt); std::vector> parseTillToken(Token::Type endTokenType, const auto value) { std::vector> program; while (this->m_curr->type != endTokenType || (*this->m_curr) != value) { for (auto &statement : parseStatements()) program.push_back(std::move(statement)); } this->m_curr++; return program; } [[noreturn]] void throwParserError(const std::string &error, i32 token = -1) const { throw PatternLanguageError(this->m_curr[token].lineNumber, "Parser: " + error); } /* Token consuming */ enum class Setting { }; constexpr static auto Normal = static_cast(0); constexpr static auto Not = static_cast(1); bool begin() { this->m_originalPosition = this->m_curr; this->m_matchedOptionals.clear(); return true; } bool partBegin() { this->m_partOriginalPosition = this->m_curr; this->m_matchedOptionals.clear(); return true; } void reset() { this->m_curr = this->m_originalPosition; } void partReset() { this->m_curr = this->m_partOriginalPosition; } bool resetIfFailed(bool value) { if (!value) reset(); return value; } template bool sequenceImpl() { if constexpr (S == Normal) return true; else if constexpr (S == Not) return false; else __builtin_unreachable(); } template bool sequenceImpl(Token::Type type, auto value, auto... args) { if constexpr (S == Normal) { if (!peek(type, value)) { partReset(); return false; } this->m_curr++; if (!sequenceImpl(args...)) { partReset(); return false; } return true; } else if constexpr (S == Not) { if (!peek(type, value)) return true; this->m_curr++; if (!sequenceImpl(args...)) return true; partReset(); return false; } else __builtin_unreachable(); } template bool sequence(Token::Type type, auto value, auto... args) { return partBegin() && sequenceImpl(type, value, args...); } template bool oneOfImpl() { if constexpr (S == Normal) return false; else if constexpr (S == Not) return true; else __builtin_unreachable(); } template bool oneOfImpl(Token::Type type, auto value, auto... args) { if constexpr (S == Normal) return sequenceImpl(type, value) || oneOfImpl(args...); else if constexpr (S == Not) return sequenceImpl(type, value) && oneOfImpl(args...); else __builtin_unreachable(); } template bool oneOf(Token::Type type, auto value, auto... args) { return partBegin() && oneOfImpl(type, value, args...); } bool variantImpl(Token::Type type1, auto value1, Token::Type type2, auto value2) { if (!peek(type1, value1)) { if (!peek(type2, value2)) { partReset(); return false; } } this->m_curr++; return true; } bool variant(Token::Type type1, auto value1, Token::Type type2, auto value2) { return partBegin() && variantImpl(type1, value1, type2, value2); } bool optionalImpl(Token::Type type, auto value) { if (peek(type, value)) { this->m_matchedOptionals.push_back(this->m_curr); this->m_curr++; } return true; } bool optional(Token::Type type, auto value) { return partBegin() && optionalImpl(type, value); } bool peek(Token::Type type, auto value, i32 index = 0) { return this->m_curr[index].type == type && this->m_curr[index] == value; } }; }