/*** 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 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(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 { ParsedBit() {} 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; }; using ConsumeStream_cb = std::function; 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; } struct ParseState { ParseState(ConsumeStream_cb &str) : stringstream(str) {} ParseState(ConsumeStream_cb &&str) : stringstream(std::move(str)) {} ConsumeStream_cb stringstream; AuUInt8 *additionalTokens {}; AuUInt16 countOfTokens {}; bool hasLastToken {}; AuUInt8 lastTokenCharacter {}; AuMach lastTokenAdditional {}; }; AUKN_SYM void VaildateStructure(const ParseObject &object); AUKN_SYM bool ConsumeToken(ParsableTag type, ConsumeStream_cb getc, ParseValue &out); static bool ConsumeToken(ParsableTag type, const AuString &str, AuMach &index, ParseValueEx &out) { return ConsumeToken(type, StringToConsumable(str, index), out); } static bool ConsumeToken(ParsableTag type, const AuString &str, ParseValueEx &out) { AuMach index{}; return ConsumeToken(type, StringToConsumable(str, index), 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) { ParseState state(StringToConsumable(str, index)); return Parse(state, structure, result); } static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str) { AuMach index{}; ParseState state(StringToConsumable(str, index)); 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); }