/*** 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; }; #if 0 using ConsumeStream_cb = AuFunction; static ConsumeStream_cb StringToConsumable(const AuString &str, AuMach &index) { auto getc = [&](AuUInt8 &byt) mutable { if (index == str.length()) { return false; } byt = str[index]; index++; return true; }; return getc; } #endif struct ParseState { ParseState(const AuSPtr &stream) : stream(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); static bool ConsumeToken(ParsableTag type, const AuString &str, AuMach &index, ParseValueEx &out) { auto strStream = IO::Character::ProviderFromStringUnique(str, index); if (!strStream) return false; if (!ConsumeToken(type, AuUnsafeRaiiToShared(strStream), out)) return false; index = strStream->GetPosition(); return true; } static bool ConsumeToken(ParsableTag type, const AuString &str, ParseValueEx &out) { auto strStream = IO::Character::ProviderFromStringUnique(str); if (!strStream) return false; return ConsumeToken(type, AuUnsafeRaiiToShared(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 strStream = IO::Character::ProviderFromStringUnique(str, index); if (!strStream) return false; ParseState state(AuUnsafeRaiiToShared(strStream)); if (!Parse(state, structure, result)) return false; index = strStream->GetPosition(); return true; } static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str) { auto strStream = IO::Character::ProviderFromStringUnique(str, 0); if (!strStream) return false; ParseState state(AuUnsafeRaiiToShared(strStream)); return Parse(state, structure, result); } AUKN_SYM void SerializeToken(ParsableTag type, const ParseValue &value, AuString &str); AUKN_SYM void Serialize(const ParsedObject &structure, AuString &ret); AUKN_SYM AuResult ParseSInt(const char *begin, const char *&end); AUKN_SYM AuResult ParseUInt(const char *begin, const char *&end); }