/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Parser.hpp Date: 2021-6-9 Author: Reece ***/ #pragma once #include #include #include #include #include namespace Aurora::Parse { enum class ParsableTag { kParseUInt = (const int)Data::EDataType::kTypeUInt, kParseSInt = (const int)Data::EDataType::kTypeSInt, kParseNumber = (const int)Data::EDataType::kTypeNumber, kParseString = (const int)Data::EDataType::kTypeString, kParseBoolean = (const int)Data::EDataType::kTypeBoolean, kParseUUID = (const int)Data::EDataType::kTypeUUID, kParseVec3 = (const int)Data::EDataType::kTypeVec3, kParseVec4 = (const int)Data::EDataType::kTypeVec4, kParseObject, kParseStringVararg }; struct ParseBit; struct ParsedBit; using ParseObject = AuList; using ParsedObject = AuList; using ParsePrimativeValue = Data::PrimitiveValue; using ParseValue = Data::Value; struct ParseValueEx : ParseValue { ParsedObject object; }; struct ParseBit { ParseBit(const ParseBit &in) = default; ParseBit(ParsableTag tag, const AuString &label) : tag(tag), label(label) {} ParseBit(ParsableTag tag, const AuString &label, bool array, bool optional, bool _vararg) : tag(tag), label(label), array(array), optional(optional), vararg(_vararg) {} ParseBit(ParsableTag tag) : tag(tag) {} ParseBit(ParsableTag tag, bool array, bool optional, bool _vararg) : tag(tag), array(array), optional(optional), vararg(_vararg) {} ParseBit(ParseObject _ObjectParse) : tag(ParsableTag::kParseObject), objectParse(_ObjectParse) {} ParseBit(ParseObject _ObjectParse, const AuString &label) : tag(ParsableTag::kParseObject), objectParse(_ObjectParse), label(label) {} // marks this "parse bit" and all following part bits optional bool optional = false; // if true, the lexer yoinks a length prefix token before iterating over array length bool array = false; // if true, the lexer parses tag or object parse until EOS bool vararg = false; // parse defintion ParsableTag tag; ParseObject objectParse; // optional: AuString label = ""; // parse object // {...} // single parse bit: // // optional: // () // var arg: // ( ...) // arrays // [ ] }; struct ParsedBit { inline ParsedBit() {} inline ParsedBit(ParsableTag tag) : tag(tag) {} AuMach count {}; ParsableTag tag; bool isArray {}; struct { ParseValueEx single; AuList array; } value; }; struct ParseResult { AuString syntaxError; AuString debugTree; ParsedObject result; }; struct ParseState { inline ParseState(const AuSPtr &stream) : stream(stream) {} inline ParseState(const AuSPtr &stream) : stream(Aurora::IO::Character::BufferConsumerFromProviderShared(stream)) {} inline ParseState(const AuSPtr &stream) : stream(Aurora::IO::Character::BufferConsumerFromProviderShared(stream)) {} AuSPtr stream; AuUInt8 *additionalTokens {}; AuUInt16 countOfTokens {}; bool hasLastToken {}; AuUInt8 lastTokenCharacter {}; AuMach lastTokenAdditional {}; }; AUKN_SYM void VaildateStructure(const ParseObject &object); AUKN_SYM bool ConsumeToken(ParsableTag type, const AuSPtr &getc, ParseValue &out); AUKN_SYM bool ConsumeToken(ParsableTag type, const AuSPtr &getc, ParseValue &out); AUKN_SYM bool ConsumeToken(ParseState &state, ParsableTag type, ParseValue &out); static bool ConsumeToken(ParsableTag type, const AuString &str, AuMach &index, ParseValueEx &out) { auto base = IO::Character::ProviderFromStringUnique(str, index); if (!base) return false; auto strStream = IO::Character::BufferConsumerFromProviderShared(AuUnsafeRaiiToShared(base)); if (!strStream) return false; if (!ConsumeToken(type, strStream, out)) return false; index = base->GetPosition() - strStream->HasBufferedNext(); return true; } static bool ConsumeToken(ParsableTag type, const AuString &str, ParseValueEx &out) { auto base = IO::Character::ProviderFromStringUnique(str); if (!base) return false; auto strStream = IO::Character::BufferConsumerFromProviderShared(AuUnsafeRaiiToShared(base)); if (!strStream) return false; return ConsumeToken(type, strStream, out); } AUKN_SYM bool Parse(ParseState &state, const ParseObject &structure, ParseResult &result); static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str, AuMach &index) { auto base = IO::Character::ProviderFromStringUnique(str); if (!base) return false; auto strStream = IO::Character::BufferConsumerFromProviderShared(AuUnsafeRaiiToShared(base)); if (!strStream) return false; ParseState state(strStream); if (!Parse(state, structure, result)) return false; index = base->GetPosition() - state.stream->HasBufferedNext(); return true; } static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str) { auto base = IO::Character::ProviderFromStringUnique(str); if (!base) return false; auto strStream = IO::Character::BufferConsumerFromProviderShared(AuUnsafeRaiiToShared(base)); if (!strStream) return false; ParseState state(strStream); return Parse(state, structure, result); } AUKN_SYM AuList ConsumeTokens(ParsableTag type, const AuSPtr &getc); AUKN_SYM AuList ConsumeTokens(ParsableTag type, const AuSPtr &getc); AUKN_SYM void SerializeToken(ParsableTag type, const ParseValue &value, AuString &str); AUKN_SYM void Serialize(const ParsedObject &structure, AuString &ret); AUKN_SYM AuString StringifyUInt16(AuUInt64 in, bool bZeroX = true); AUKN_SYM AuString StringifySInt16(AuInt64 in, bool bZeroX = true); /** * @brief Parse base10 null string */ AUKN_SYM AuResult ParseSInt(const char *begin, const char *&end); /** * @brief Parse base10 null string */ AUKN_SYM AuResult ParseUInt(const char *begin, const char *&end); /** * @brief Parse base16 string with optional 0x suffix and 'h' ending */ AUKN_SYM AuResult ParseSInt16(const char *begin, const char *&end); /** * @brief Parse base16 string with optional 0x suffix and 'h' ending */ AUKN_SYM AuResult ParseUInt16(const char *begin, const char *&end); /** * @brief Parse base16 null terminated string with optional 0x suffix and 'h' ending */ AUKN_SYM AuResult ParseSInt16(const char *begin); /** * @brief Parse base16 abi terminated string with optional 0x suffix and 'h' ending */ AUKN_SYM AuResult ParseSInt16(const AuString &str); /** * @brief Parse base16 null terminated string with optional 0x suffix and 'h' ending */ AUKN_SYM AuResult ParseUInt16(const char *begin); /** * @brief Parse base16 abi terminated string with optional 0x suffix and 'h' ending */ AUKN_SYM AuResult ParseUInt16(const AuString &str); /** * @brief Parse abi null terminated string */ AUKN_SYM AuResult ParseSInt(const AuString &str); /** * @brief Parse base10 null terminated string */ AUKN_SYM AuResult ParseSInt(const char *begin); /** * @brief Parse base10 abi terminated string */ AUKN_SYM AuResult ParseUInt(const AuString &str); /** * @brief Parse base10 null terminated string */ AUKN_SYM AuResult ParseUInt(const char *begin); }