diff --git a/Import/VlppGlrParser.cpp b/Import/VlppGlrParser.cpp new file mode 100644 index 00000000..f0751228 --- /dev/null +++ b/Import/VlppGlrParser.cpp @@ -0,0 +1,6716 @@ +/*********************************************************************** +THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY +DEVELOPER: Zihan Chen(vczh) +***********************************************************************/ +#include "VlppGlrParser.h" + +/*********************************************************************** +.\ASTBASE.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + using namespace collections; + using namespace stream; + +/*********************************************************************** +JsonVisitorBase +***********************************************************************/ + + void JsonVisitorBase::BeginObject() + { + writer.WriteString(L"{"); + indentation++; + indices.Add(0); + } + + void JsonVisitorBase::BeginField(const WString& field) + { + vint last = indices[indices.Count() - 1]; + if (last > 0) + { + writer.WriteString(L","); + } + writer.WriteLine(L""); + WriteIndent(); + writer.WriteChar(L'\"'); + writer.WriteString(field); + writer.WriteChar(L'\"'); + writer.WriteString(L": "); + } + + void JsonVisitorBase::EndField() + { + indices[indices.Count() - 1]++; + } + + void JsonVisitorBase::EndObject() + { + indices.RemoveAt(indices.Count() - 1); + indentation--; + writer.WriteLine(L""); + WriteIndent(); + writer.WriteString(L"}"); + } + + void JsonVisitorBase::BeginArray() + { + writer.WriteString(L"["); + indices.Add(0); + } + + void JsonVisitorBase::BeginArrayItem() + { + vint last = indices[indices.Count() - 1]; + if (last > 0) + { + writer.WriteString(L", "); + } + } + + void JsonVisitorBase::EndArrayItem() + { + indices[indices.Count() - 1]++; + } + + void JsonVisitorBase::EndArray() + { + indices.RemoveAt(indices.Count() - 1); + writer.WriteString(L"]"); + } + + void JsonVisitorBase::WriteIndent() + { + for (vint i = 0; i < indentation; i++) + { + writer.WriteString(L" "); + } + } + + void JsonVisitorBase::WriteRange(const ParsingTextRange& range) + { + writer.WriteString(L"{\"start\": {\"row\": "); + writer.WriteString(itow(range.start.row)); + writer.WriteString(L", \"column\": "); + writer.WriteString(itow(range.start.column)); + writer.WriteString(L", \"index\": "); + writer.WriteString(itow(range.start.index)); + writer.WriteString(L"}, \"end\": {\"row\": "); + writer.WriteString(itow(range.end.row)); + writer.WriteString(L", \"column\": "); + writer.WriteString(itow(range.end.column)); + writer.WriteString(L", \"index\": "); + writer.WriteString(itow(range.end.index)); + writer.WriteString(L"}, \"codeIndex\": "); + writer.WriteString(itow(range.codeIndex)); + writer.WriteString(L"}"); + } + + void JsonVisitorBase::WriteToken(const ParsingToken& token) + { + if (printTokenCodeRange) + { + writer.WriteString(L"{ \"value\": "); + WriteString(token.value); + writer.WriteString(L", \"codeRange\": "); + WriteRange(token.codeRange); + writer.WriteString(L"}"); + } + else + { + WriteString(token.value); + } + } + + void JsonVisitorBase::WriteType(const WString& type, ParsingAstBase* node) + { + if (printAstType && printAstCodeRange) + { + BeginField(L"$ast"); + writer.WriteString(L"{ \"type\": "); + WriteString(type); + writer.WriteString(L", \"codeRange\": "); + WriteRange(node->codeRange); + writer.WriteString(L"}"); + EndField(); + } + else if (printAstType) + { + BeginField(L"$ast"); + WriteString(type); + EndField(); + } + else if (printAstCodeRange) + { + BeginField(L"$ast"); + writer.WriteString(L"{ \"codeRange\": "); + WriteRange(node->codeRange); + writer.WriteString(L"}"); + EndField(); + } + } + + void JsonVisitorBase::WriteString(const WString& text) + { + writer.WriteChar(L'\"'); + JsonEscapeString(text, writer); + writer.WriteChar(L'\"'); + } + + void JsonVisitorBase::WriteNull() + { + writer.WriteString(L"null"); + } + + JsonVisitorBase::JsonVisitorBase(stream::StreamWriter& _writer) + :writer(_writer) + { + } + +/*********************************************************************** +Json Printing +***********************************************************************/ + + void JsonEscapeString(const WString& text, stream::TextWriter& writer) + { + const wchar_t* reading = text.Buffer(); + while (wchar_t c = *reading++) + { + switch (c) + { + case L'\"': writer.WriteString(L"\\\""); break; + case L'\\': writer.WriteString(L"\\\\"); break; + case L'/': writer.WriteString(L"\\/"); break; + case L'\b': writer.WriteString(L"\\b"); break; + case L'\f': writer.WriteString(L"\\f"); break; + case L'\n': writer.WriteString(L"\\n"); break; + case L'\r': writer.WriteString(L"\\r"); break; + case L'\t': writer.WriteString(L"\\t"); break; + default: writer.WriteChar(c); + } + } + } + + vuint16_t GetHex(wchar_t c) + { + if (L'0' <= c && c <= L'9') + { + return c - L'0'; + } + else if (L'A' <= c && c <= L'F') + { + return c - L'A'; + } + else if (L'a' <= c && c <= L'f') + { + return c - L'a'; + } + else + { + return 0; + } + } + + void JsonUnescapeString(const WString& text, stream::TextWriter& writer) + { + const wchar_t* reading = text.Buffer(); + while (wchar_t c = *reading++) + { + if (c == L'\\' && *reading) + { + switch (c = *reading++) + { + case L'b': writer.WriteChar(L'\b'); break; + case L'f': writer.WriteChar(L'\f'); break; + case L'n': writer.WriteChar(L'\n'); break; + case L'r': writer.WriteChar(L'\r'); break; + case L't': writer.WriteChar(L'\t'); break; + case L'u': + { + wchar_t h1, h2, h3, h4; + if ((h1 = reading[0]) && (h2 = reading[1]) && (h3 = reading[2]) && (h4 = reading[3])) + { + reading += 4; + wchar_t h = (wchar_t)(vuint16_t)( + (GetHex(h1) << 12) + + (GetHex(h2) << 8) + + (GetHex(h3) << 4) + + (GetHex(h4) << 0) + ); + writer.WriteChar(h); + } + } + break; + default: writer.WriteChar(c); + } + } + else + { + writer.WriteChar(c); + } + } + } + +/*********************************************************************** +AstInsReceiverBase +***********************************************************************/ + + void AstInsReceiverBase::EnsureContinuable() + { + if (corrupted) + { + throw AstInsException( + L"An exception has been thrown therefore this receiver cannot be used anymore.", + AstInsErrorType::Corrupted + ); + } + if (finished) + { + throw AstInsException( + L"The finished instruction has been executed therefore this receiver cannot be used anymore.", + AstInsErrorType::Finished + ); + } + } + + void AstInsReceiverBase::SetField(ParsingAstBase* object, vint32_t field, const ObjectOrToken& value) + { + if (value.object) + { + SetField(object, field, value.object); + } + else if (value.enumItem != -1) + { + SetField(object, field, value.enumItem); + } + else + { + SetField(object, field, value.token, value.tokenIndex); + } + } + + AstInsReceiverBase::CreatedObject& AstInsReceiverBase::PushCreated(CreatedObject&& createdObject) + { + if (created.Count() == 0) + { + created.Add(std::move(createdObject)); + } + else + { + auto& top = created[created.Count() - 1]; + if ( + !top.object && + top.pushedCount == createdObject.pushedCount && + top.delayedToken.reading == createdObject.delayedToken.reading && + top.delayedFieldAssignments.Count() == 0 + ) + { + top.object = createdObject.object; + top.extraEmptyDfaBelow++; + } + else + { + created.Add(std::move(createdObject)); + } + } + return created[created.Count() - 1]; + } + + const AstInsReceiverBase::CreatedObject& AstInsReceiverBase::TopCreated() + { + return created[created.Count() - 1]; + } + + void AstInsReceiverBase::PopCreated() + { + auto& top = created[created.Count() - 1]; + if (top.extraEmptyDfaBelow == 0) + { + created.RemoveAt(created.Count() - 1); + } + else if (top.object) + { + top.object = nullptr; + top.delayedFieldAssignments.Clear(); + top.extraEmptyDfaBelow--; + } + } + + void AstInsReceiverBase::DelayAssign(FieldAssignment&& fa) + { + created[created.Count() - 1].delayedFieldAssignments.Add(std::move(fa)); + } + + void AstInsReceiverBase::Execute(AstIns instruction, const regex::RegexToken& token, vint32_t tokenIndex) + { + EnsureContinuable(); + try + { + if (created.Count() == 0 && instruction.type != AstInsType::BeginObject) + { + switch (instruction.type) + { + case AstInsType::BeginObject: + case AstInsType::BeginObjectLeftRecursive: + case AstInsType::DelayFieldAssignment: + case AstInsType::ResolveAmbiguity: + case AstInsType::AccumulatedDfa: + break; + default: + throw AstInsException( + L"There is no created objects.", + AstInsErrorType::NoRootObject + ); + } + } + + vint expectedLeavings = 0; + if (created.Count() > 0) + { + expectedLeavings = TopCreated().pushedCount; + } + + switch (instruction.type) + { + case AstInsType::Token: + { + pushed.Add(ObjectOrToken{ token,tokenIndex }); + } + break; + case AstInsType::EnumItem: + { + pushed.Add(ObjectOrToken{ instruction.param }); + } + break; + case AstInsType::BeginObject: + { + auto value = CreateAstNode(instruction.param); + value->codeRange = { &token,&token }; + PushCreated(CreatedObject{ value,pushed.Count() }); + } + break; + case AstInsType::BeginObjectLeftRecursive: + { + if (pushed.Count() < expectedLeavings + 1) + { + throw AstInsException( + L"There is no pushed value to create left recursive object.", + AstInsErrorType::MissingLeftRecursiveValue + ); + } + + auto subValue = pushed[pushed.Count() - 1]; + if (subValue.object) + { + auto value = CreateAstNode(instruction.param); + value->codeRange = subValue.object->codeRange; + PushCreated(CreatedObject{ value,pushed.Count() - 1 }); + } + else + { + throw AstInsException( + L"The pushed value to create left recursive object is not an object.", + AstInsErrorType::LeftRecursiveValueIsNotObject + ); + } + } + break; + case AstInsType::DelayFieldAssignment: + { + PushCreated(CreatedObject{ nullptr,pushed.Count(),token }); + } + break; + case AstInsType::ReopenObject: + { + auto& createdObject = created[created.Count() - 1]; + if (createdObject.object) + { + throw AstInsException( + L"DelayFieldAssignment is not submitted before ReopenObject.", + AstInsErrorType::MissingDfaBeforeReopen + ); + } + if (pushed.Count() < expectedLeavings + 1) + { + throw AstInsException( + L"There is no pushed value to reopen.", + AstInsErrorType::MissingValueToReopen + ); + } + if (pushed.Count() > expectedLeavings + 1) + { + throw AstInsException( + L"The value to reopen is not the only unassigned value.", + AstInsErrorType::TooManyUnassignedValues + ); + } + + auto value = pushed[pushed.Count() - 1]; + if (value.object) + { + pushed.RemoveAt(pushed.Count() - 1); + createdObject.object = value.object; + createdObject.object->codeRange.start = ParsingTextPos::Start(&createdObject.delayedToken); + + for (auto&& dfa : createdObject.delayedFieldAssignments) + { + SetField(createdObject.object.Obj(), dfa.field, dfa.value); + } + createdObject.delayedFieldAssignments.Clear(); + } + else + { + throw AstInsException( + L"The pushed value to reopen is not an object.", + AstInsErrorType::ReopenedValueIsNotObject + ); + } + } + break; + case AstInsType::EndObject: + { + Ptr objectToPush; + { + auto& createdObject = TopCreated(); + if (!createdObject.object) + { + throw AstInsException( + L"There is no created objects after DelayFieldAssignment.", + AstInsErrorType::NoRootObjectAfterDfa + ); + } + if (pushed.Count() > createdObject.pushedCount) + { + throw AstInsException( + L"There are still values to assign to fields before finishing an object.", + AstInsErrorType::LeavingUnassignedValues + ); + } + + objectToPush = createdObject.object; + PopCreated(); + } + + objectToPush->codeRange.end = ParsingTextPos::End(&token); + pushed.Add(ObjectOrToken{ objectToPush }); + } + break; + case AstInsType::DiscardValue: + { + auto& createdObject = TopCreated(); + if (pushed.Count() <= createdObject.pushedCount) + { + throw AstInsException( + L"There is no pushed value to discard.", + AstInsErrorType::MissingValueToDiscard + ); + } + pushed.RemoveAt(pushed.Count() - 1); + } + break; + case AstInsType::Field: + { + auto& createdObject = TopCreated(); + if (pushed.Count() <= createdObject.pushedCount) + { + throw AstInsException( + L"There is no pushed value to be assigned to a field.", + AstInsErrorType::MissingFieldValue + ); + } + + auto value = pushed[pushed.Count() - 1]; + pushed.RemoveAt(pushed.Count() - 1); + + if (createdObject.object) + { + SetField(createdObject.object.Obj(), instruction.param, value); + } + else + { + DelayAssign({ value,instruction.param }); + } + } + break; + case AstInsType::ResolveAmbiguity: + { + if (instruction.count <= 0 || pushed.Count() < expectedLeavings + instruction.count) + { + throw AstInsException( + L"There are not enough candidates to create an ambiguity node.", + AstInsErrorType::MissingAmbiguityCandidate + ); + } + + for (vint i = 0; i < instruction.count; i++) + { + if (!pushed[pushed.Count() - i - 1].object) + { + throw AstInsException( + L"Tokens or enum items cannot be ambiguity candidates.", + AstInsErrorType::AmbiguityCandidateIsNotObject + ); + } + } + + Array> candidates(instruction.count); + for (vint i = 0; i < instruction.count; i++) + { + auto value = pushed[pushed.Count() - 1]; + pushed.RemoveAt(pushed.Count() - 1); + candidates[i] = value.object; + } + + pushed.Add(ObjectOrToken{ ResolveAmbiguity(instruction.param, candidates) }); + } + break; + case AstInsType::AccumulatedDfa: + { + auto&& createdObject = PushCreated(CreatedObject{ nullptr,pushed.Count(),token }); + createdObject.extraEmptyDfaBelow += instruction.count - 1; + } + break; + case AstInsType::AccumulatedEoRo: + { + while (instruction.count > 0) + { + auto& createdObject = created[created.Count() - 1]; + if (!createdObject.object) + { + throw AstInsException( + L"There is no created objects after DelayFieldAssignment.", + AstInsErrorType::NoRootObjectAfterDfa + ); + } + if (pushed.Count() > createdObject.pushedCount) + { + throw AstInsException( + L"There are still values to assign to fields before finishing an object.", + AstInsErrorType::LeavingUnassignedValues + ); + } + + if (createdObject.extraEmptyDfaBelow >= instruction.count) + { + createdObject.object->codeRange.start = ParsingTextPos::Start(&createdObject.delayedToken); + createdObject.object->codeRange.end = ParsingTextPos::End(&token); + createdObject.extraEmptyDfaBelow -= instruction.count; + instruction.count = 0; + } + else + { + instruction.count -= createdObject.extraEmptyDfaBelow + 1; + createdObject.extraEmptyDfaBelow = 0; + Execute({ AstInsType::EndObject }, token, tokenIndex); + Execute({ AstInsType::ReopenObject }, token, tokenIndex); + } + } + } + break; + default: + CHECK_FAIL(L"vl::glr::AstInsReceiverBase::Execute(AstIns, const regex::RegexToken&)#Unknown Instruction."); + } + } + catch (const AstInsException&) + { + corrupted = true; + throw; + } + } + + Ptr AstInsReceiverBase::Finished() + { + EnsureContinuable(); + try + { + if (created.Count() > 0 || pushed.Count() > 1) + { + throw AstInsException( + L"No more instruction but the root object has not been completed yet.", + AstInsErrorType::InstructionNotComplete + ); + } + + auto object = pushed[0].object; + if (!object) + { + throw AstInsException( + L"No more instruction but the root object has not been completed yet.", + AstInsErrorType::InstructionNotComplete + ); + } + pushed.Clear(); + finished = true; + return object; + } + catch (const AstInsException&) + { + corrupted = true; + throw; + } + } + +/*********************************************************************** +IAstInsReceiver (Code Generation Error Templates) +***********************************************************************/ + + Ptr AssemblyThrowCannotCreateAbstractType(vint32_t type, const wchar_t* cppTypeName) + { + if (cppTypeName) + { + throw AstInsException( + WString::Unmanaged(L"Unable to create abstract class \"") + + WString::Unmanaged(cppTypeName) + + WString::Unmanaged(L"\"."), + AstInsErrorType::UnsupportedAbstractType, type); + } + else + { + throw AstInsException(L"The type id does not exist.", vl::glr::AstInsErrorType::UnknownType, type); + } + } + + void AssemblyThrowFieldNotObject(vint32_t field, const wchar_t* cppFieldName) + { + if (cppFieldName) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" is not an object."), + AstInsErrorType::ObjectTypeMismatchedToField, field); + } + else + { + throw AstInsException(L"The field id does not exist.", vl::glr::AstInsErrorType::UnknownField, field); + } + } + + void AssemblyThrowFieldNotToken(vint32_t field, const wchar_t* cppFieldName) + { + if (cppFieldName) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" is not a token."), + AstInsErrorType::ObjectTypeMismatchedToField, field); + } + else + { + throw AstInsException(L"The field id does not exist.", vl::glr::AstInsErrorType::UnknownField, field); + } + } + + void AssemblyThrowFieldNotEnum(vint32_t field, const wchar_t* cppFieldName) + { + if (cppFieldName) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" is not an enum item."), + AstInsErrorType::ObjectTypeMismatchedToField, field); + } + else + { + throw AstInsException(L"The field id does not exist.", vl::glr::AstInsErrorType::UnknownField, field); + } + } + + Ptr AssemblyThrowTypeNotAllowAmbiguity(vint32_t type, const wchar_t* cppTypeName) + { + if (cppTypeName) + { + throw AstInsException( + WString::Unmanaged(L"Type \"") + + WString::Unmanaged(cppTypeName) + + WString::Unmanaged(L"\" is not configured to allow ambiguity."), + AstInsErrorType::UnsupportedAmbiguityType, type); + } + else + { + throw AstInsException(L"The type id does not exist.", vl::glr::AstInsErrorType::UnknownType, type); + } + } + +/*********************************************************************** +Compression +***********************************************************************/ + + void DecompressSerializedData(const char** buffer, bool decompress, vint solidRows, vint rows, vint block, vint remain, stream::IStream& outputStream) + { + if (decompress) + { + MemoryStream compressedStream; + DecompressSerializedData(buffer, false, solidRows, rows, block, remain, compressedStream); + compressedStream.SeekFromBegin(0); + DecompressStream(compressedStream, outputStream); + } + else + { + for (vint i = 0; i < rows; i++) + { + vint size = i == solidRows ? remain : block; + outputStream.Write((void*)buffer[i], size); + } + } + } + } + +/*********************************************************************** +Reflection +***********************************************************************/ + + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + IMPL_TYPE_INFO_RENAME(vl::glr::ParsingTextPos, system::ParsingTextPos) + IMPL_TYPE_INFO_RENAME(vl::glr::ParsingTextRange, system::ParsingTextRange) + IMPL_TYPE_INFO_RENAME(vl::glr::ParsingToken, system::ParsingToken) + IMPL_TYPE_INFO_RENAME(vl::glr::ParsingAstBase, system::ParsingAstBase) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_STRUCT_MEMBER(vl::glr::ParsingTextPos) + STRUCT_MEMBER(index) + STRUCT_MEMBER(row) + STRUCT_MEMBER(column) + END_STRUCT_MEMBER(vl::glr::ParsingTextPos) + + BEGIN_STRUCT_MEMBER(vl::glr::ParsingTextRange) + STRUCT_MEMBER(start) + STRUCT_MEMBER(end) + STRUCT_MEMBER(codeIndex) + END_STRUCT_MEMBER(vl::glr::ParsingTextRange) + + BEGIN_STRUCT_MEMBER(vl::glr::ParsingToken) + STRUCT_MEMBER(codeRange) + STRUCT_MEMBER(index) + STRUCT_MEMBER(token) + STRUCT_MEMBER(value) + END_STRUCT_MEMBER(vl::glr::ParsingToken) + + BEGIN_CLASS_MEMBER(vl::glr::ParsingAstBase) + CLASS_MEMBER_FIELD(codeRange) + END_CLASS_MEMBER(vl::glr::ParsingAstBase) + + class Parsing2TypeLoader : public vl::Object, public ITypeLoader + { + public: + void Load(ITypeManager* manager) + { + ADD_TYPE_INFO(vl::glr::ParsingTextPos) + ADD_TYPE_INFO(vl::glr::ParsingTextRange) + ADD_TYPE_INFO(vl::glr::ParsingToken) + ADD_TYPE_INFO(vl::glr::ParsingAstBase) + } + + void Unload(ITypeManager* manager) + { + } + }; +#endif +#endif + bool LoadParsing2Types() + { +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + if (auto manager = GetGlobalTypeManager()) + { + Ptr loader = new Parsing2TypeLoader; + return manager->AddTypeLoader(loader); + } +#endif + return false; + } + } + } +} + +/*********************************************************************** +.\ASTPRINT.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + +/*********************************************************************** +ParsingEmptyPrintNodeRecorder +***********************************************************************/ + + ParsingEmptyPrintNodeRecorder::ParsingEmptyPrintNodeRecorder() + { + } + + ParsingEmptyPrintNodeRecorder::~ParsingEmptyPrintNodeRecorder() + { + } + + void ParsingEmptyPrintNodeRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range) + { + } + +/*********************************************************************** +ParsingMultiplePrintNodeRecorder +***********************************************************************/ + + ParsingMultiplePrintNodeRecorder::ParsingMultiplePrintNodeRecorder() + { + } + + ParsingMultiplePrintNodeRecorder::~ParsingMultiplePrintNodeRecorder() + { + } + + void ParsingMultiplePrintNodeRecorder::AddRecorder(Ptr recorder) + { + recorders.Add(recorder); + } + + void ParsingMultiplePrintNodeRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range) + { + for (auto recorder : recorders) + { + recorder->Record(node, range); + } + } + +/*********************************************************************** +ParsingOriginalLocationRecorder +***********************************************************************/ + + ParsingOriginalLocationRecorder::ParsingOriginalLocationRecorder(Ptr _recorder) + :recorder(_recorder) + { + } + + ParsingOriginalLocationRecorder::~ParsingOriginalLocationRecorder() + { + } + + void ParsingOriginalLocationRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range) + { + auto codeRange = node->codeRange; + codeRange.codeIndex = range.codeIndex; + recorder->Record(node, codeRange); + } + +/*********************************************************************** +ParsingGeneratedLocationRecorder +***********************************************************************/ + + ParsingGeneratedLocationRecorder::ParsingGeneratedLocationRecorder(RangeMap& _rangeMap) + :rangeMap(_rangeMap) + { + } + + ParsingGeneratedLocationRecorder::~ParsingGeneratedLocationRecorder() + { + } + + void ParsingGeneratedLocationRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range) + { + rangeMap.Add(node, range); + } + +/*********************************************************************** +ParsingUpdateLocationRecorder +***********************************************************************/ + + ParsingUpdateLocationRecorder::ParsingUpdateLocationRecorder() + { + } + + ParsingUpdateLocationRecorder::~ParsingUpdateLocationRecorder() + { + } + + void ParsingUpdateLocationRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range) + { + node->codeRange = range; + } + +/*********************************************************************** +ParsingWriter +***********************************************************************/ + + void ParsingWriter::HandleChar(wchar_t c) + { + lastPos = currentPos; + switch (c) + { + case L'\n': + currentPos.index++; + currentPos.row++; + currentPos.column = 0; + break; + default: + currentPos.index++; + currentPos.column++; + } + } + + ParsingWriter::ParsingWriter(stream::TextWriter& _writer, Ptr _recorder, vint _codeIndex) + :writer(_writer) + , recorder(_recorder) + , codeIndex(_codeIndex) + , lastPos(-1, 0, -1) + , currentPos(0, 0, 0) + { + } + + ParsingWriter::~ParsingWriter() + { + } + + void ParsingWriter::WriteChar(wchar_t c) + { + writer.WriteChar(c); + if (!recorder) return; + HandleChar(c); + } + + void ParsingWriter::WriteString(const wchar_t* string, vint charCount) + { + writer.WriteString(string, charCount); + if (!recorder) return; + for (vint i = 0; i < charCount; i++) + { + HandleChar(string[i]); + } + } + + void ParsingWriter::BeforePrint(ParsingAstBase* node) + { + if (!recorder) return; + nodePositions.Add(NodePosPair(node, currentPos)); + } + + void ParsingWriter::AfterPrint(ParsingAstBase* node) + { + if (!recorder) return; + + auto pair = nodePositions[nodePositions.Count() - 1]; + nodePositions.RemoveAt(nodePositions.Count() - 1); + CHECK_ERROR(pair.key == node, L"vl::parsing::ParsingWriter::AfterPrint(ParsingTreeNode*)#BeforePrint and AfterPrint should be call in pairs."); + + ParsingTextRange range(pair.value, lastPos, codeIndex); + recorder->Record(node, range); + } + } +} + +/*********************************************************************** +.\EXECUTABLE.CPP +***********************************************************************/ + +namespace vl +{ + namespace stream + { + namespace internal + { + using namespace glr; + using namespace glr::automaton; + + SERIALIZE_ENUM(AstInsType) + SERIALIZE_ENUM(EdgePriority) + + BEGIN_SERIALIZATION(AstIns) + SERIALIZE(type) + SERIALIZE(param) + SERIALIZE(count) + END_SERIALIZATION + + BEGIN_SERIALIZATION(InstructionArray) + SERIALIZE(start) + SERIALIZE(count) + END_SERIALIZATION + + BEGIN_SERIALIZATION(ReturnIndexArray) + SERIALIZE(start) + SERIALIZE(count) + END_SERIALIZATION + + BEGIN_SERIALIZATION(EdgeArray) + SERIALIZE(start) + SERIALIZE(count) + END_SERIALIZATION + + BEGIN_SERIALIZATION(ReturnDesc) + SERIALIZE(consumedRule) + SERIALIZE(returnState) + SERIALIZE(priority) + SERIALIZE(insAfterInput) + END_SERIALIZATION + + BEGIN_SERIALIZATION(EdgeDesc) + SERIALIZE(fromState) + SERIALIZE(toState) + SERIALIZE(priority) + SERIALIZE(insBeforeInput) + SERIALIZE(insAfterInput) + SERIALIZE(returnIndices) + END_SERIALIZATION + + BEGIN_SERIALIZATION(StateDesc) + SERIALIZE(rule) + SERIALIZE(clause) + SERIALIZE(endingState) + END_SERIALIZATION + + BEGIN_SERIALIZATION(Executable) + SERIALIZE(tokenCount) + SERIALIZE(ruleCount) + SERIALIZE(ruleStartStates) + SERIALIZE(transitions) + SERIALIZE(instructions) + SERIALIZE(returnIndices) + SERIALIZE(returns) + SERIALIZE(edges) + SERIALIZE(states) + END_SERIALIZATION + } + } + + namespace glr + { + namespace automaton + { + using namespace stream; + +/*********************************************************************** +Executable +***********************************************************************/ + + Executable::Executable(stream::IStream& inputStream) + { + internal::ContextFreeReader reader(inputStream); + reader << *this; + } + + void Executable::Serialize(stream::IStream& outputStream) + { + internal::ContextFreeWriter writer(outputStream); + writer << *this; + } + } + } +} + +/*********************************************************************** +.\SYNTAXBASE.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { +/*********************************************************************** +ErrorArgs +***********************************************************************/ + + ErrorArgs ErrorArgs::UnrecognizedToken(const regex::RegexToken& token) + { + return { + true, + ErrorType::UnrecognizedToken, + token.codeIndex, + const_cast(token), + *static_cast*>(nullptr), + *static_cast(nullptr), + *static_cast(nullptr), + nullptr + }; + } + + ErrorArgs ErrorArgs::InvalidToken(regex::RegexToken& token, collections::List& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager) + { + return { + true, + ErrorType::InvalidToken, + token.codeIndex, + token, + tokens, + executable, + traceManager, + nullptr + }; + } + + ErrorArgs ErrorArgs::InputIncomplete(vint codeIndex, collections::List& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager) + { + return { + true, + ErrorType::InputIncomplete, + codeIndex, + *static_cast(nullptr), + tokens, + executable, + traceManager, + nullptr + }; + } + + ErrorArgs ErrorArgs::UnexpectedAstType(collections::List& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager, Ptr ast) + { + return { + true, + ErrorType::UnexpectedAstType, + ast->codeRange.codeIndex, + *static_cast(nullptr), + tokens, + executable, + traceManager, + ast + }; + } + + ParsingError ErrorArgs::ToParsingError() + { + switch (error) + { + case ErrorType::UnrecognizedToken: + return { + nullptr, + {&token,&token}, + WString::Unmanaged(L"Unrecognized token: \"") + WString::CopyFrom(token.reading,token.length) + WString::Unmanaged(L"\".") + }; + case ErrorType::InvalidToken: + return { + nullptr, + {&token,&token}, + WString::Unmanaged(L"Parser stops at incorrect input: \"") + WString::CopyFrom(token.reading,token.length) + WString::Unmanaged(L"\".") + }; + case ErrorType::InputIncomplete: + if (tokens.Count() == 0) + { + return { + nullptr, + {&tokens[tokens.Count()-1],&tokens[tokens.Count() - 1]}, + L"Input is incomplete." + }; + } + else + { + return { + nullptr, + {{0,0,0},{0,0,0},codeIndex}, + L"Input is incomplete." + }; + } + case ErrorType::UnexpectedAstType: + return { + nullptr, + ast->codeRange, + L"Unexpected type of the created AST." + }; + default: + CHECK_FAIL(L"vl::glr::ErrorArgs::ToParsingError()#Unknown error type."); + } + } + } +} + +/*********************************************************************** +.\JSON\GLRJSON.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace json + { + using namespace stream; + using namespace collections; + +/*********************************************************************** +JsonUnescapeVisitor +***********************************************************************/ + + class JsonUnescapeVisitor : public traverse_visitor::AstVisitor + { + protected: + void Traverse(JsonObjectField* node) override + { + node->name.value = GenerateToStream( + [node](TextWriter& writer) + { + JsonUnescapeString(node->name.value.Sub(1, node->name.value.Length() - 2), writer); + }); + } + + void Traverse(JsonString* node) override + { + node->content.value = GenerateToStream( + [node](TextWriter& writer) + { + JsonUnescapeString(node->content.value.Sub(1, node->content.value.Length() - 2), writer); + }); + } + }; + +/*********************************************************************** +JsonPrintVisitor +***********************************************************************/ + + class JsonPrintVisitor : public Object, public JsonNode::IVisitor + { + public: + TextWriter& writer; + + JsonPrintVisitor(TextWriter& _writer) + :writer(_writer) + { + } + + void Visit(JsonLiteral* node) override + { + switch(node->value) + { + case JsonLiteralValue::True: + writer.WriteString(L"true"); + break; + case JsonLiteralValue::False: + writer.WriteString(L"false"); + break; + case JsonLiteralValue::Null: + writer.WriteString(L"null"); + break; + } + } + + void Visit(JsonString* node) override + { + writer.WriteChar(L'\"'); + JsonEscapeString(node->content.value, writer); + writer.WriteChar(L'\"'); + } + + void Visit(JsonNumber* node) override + { + writer.WriteString(node->content.value); + } + + void Visit(JsonArray* node) override + { + writer.WriteChar(L'['); + for (auto [item, i] : indexed(node->items)) + { + if(i>0) writer.WriteChar(L','); + item->Accept(this); + } + writer.WriteChar(L']'); + } + + void Visit(JsonObject* node) override + { + writer.WriteChar(L'{'); + for (auto [field, i] : indexed(node->fields)) + { + if(i>0) writer.WriteChar(L','); + writer.WriteChar(L'\"'); + JsonEscapeString(field->name.value, writer); + writer.WriteString(L"\":"); + field->value->Accept(this); + } + writer.WriteChar(L'}'); + } + }; + +/*********************************************************************** +API +***********************************************************************/ + + Ptr JsonParse(const WString& input, const Parser& parser) + { + auto ast = parser.ParseJRoot(input); + JsonUnescapeVisitor().InspectInto(ast.Obj()); + return ast; + } + + void JsonPrint(Ptr node, stream::TextWriter& writer) + { + JsonPrintVisitor visitor(writer); + node->Accept(&visitor); + } + + WString JsonToString(Ptr node) + { + return GenerateToStream([&](StreamWriter& writer) + { + JsonPrint(node, writer); + }); + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSONAST.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { +/*********************************************************************** +Visitor Pattern Implementation +***********************************************************************/ + + void JsonLiteral::Accept(JsonNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void JsonString::Accept(JsonNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void JsonNumber::Accept(JsonNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void JsonArray::Accept(JsonNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void JsonObject::Accept(JsonNode::IVisitor* visitor) + { + visitor->Visit(this); + } + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonNode, system::json::JsonNode) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonNode::IVisitor, system::json::JsonNode::IVisitor) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonLiteralValue, system::json::JsonLiteralValue) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonLiteral, system::json::JsonLiteral) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonString, system::json::JsonString) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonNumber, system::json::JsonNumber) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonArray, system::json::JsonArray) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonObjectField, system::json::JsonObjectField) + IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonObject, system::json::JsonObject) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_CLASS_MEMBER(vl::glr::json::JsonNode) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + END_CLASS_MEMBER(vl::glr::json::JsonNode) + + BEGIN_ENUM_ITEM(vl::glr::json::JsonLiteralValue) + ENUM_ITEM_NAMESPACE(vl::glr::json::JsonLiteralValue) + ENUM_NAMESPACE_ITEM(True) + ENUM_NAMESPACE_ITEM(False) + ENUM_NAMESPACE_ITEM(Null) + END_ENUM_ITEM(vl::glr::json::JsonLiteralValue) + + BEGIN_CLASS_MEMBER(vl::glr::json::JsonLiteral) + CLASS_MEMBER_BASE(vl::glr::json::JsonNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(value) + END_CLASS_MEMBER(vl::glr::json::JsonLiteral) + + BEGIN_CLASS_MEMBER(vl::glr::json::JsonString) + CLASS_MEMBER_BASE(vl::glr::json::JsonNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(content) + END_CLASS_MEMBER(vl::glr::json::JsonString) + + BEGIN_CLASS_MEMBER(vl::glr::json::JsonNumber) + CLASS_MEMBER_BASE(vl::glr::json::JsonNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(content) + END_CLASS_MEMBER(vl::glr::json::JsonNumber) + + BEGIN_CLASS_MEMBER(vl::glr::json::JsonArray) + CLASS_MEMBER_BASE(vl::glr::json::JsonNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(items) + END_CLASS_MEMBER(vl::glr::json::JsonArray) + + BEGIN_CLASS_MEMBER(vl::glr::json::JsonObjectField) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + CLASS_MEMBER_FIELD(value) + END_CLASS_MEMBER(vl::glr::json::JsonObjectField) + + BEGIN_CLASS_MEMBER(vl::glr::json::JsonObject) + CLASS_MEMBER_BASE(vl::glr::json::JsonNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(fields) + END_CLASS_MEMBER(vl::glr::json::JsonObject) + + BEGIN_INTERFACE_MEMBER(vl::glr::json::JsonNode::IVisitor) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonLiteral* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonString* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonNumber* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonArray* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonObject* node)) + END_INTERFACE_MEMBER(vl::glr::json::JsonNode) + +#endif + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + class JsonAstTypeLoader : public vl::Object, public ITypeLoader + { + public: + void Load(ITypeManager* manager) + { + ADD_TYPE_INFO(vl::glr::json::JsonNode) + ADD_TYPE_INFO(vl::glr::json::JsonNode::IVisitor) + ADD_TYPE_INFO(vl::glr::json::JsonLiteralValue) + ADD_TYPE_INFO(vl::glr::json::JsonLiteral) + ADD_TYPE_INFO(vl::glr::json::JsonString) + ADD_TYPE_INFO(vl::glr::json::JsonNumber) + ADD_TYPE_INFO(vl::glr::json::JsonArray) + ADD_TYPE_INFO(vl::glr::json::JsonObjectField) + ADD_TYPE_INFO(vl::glr::json::JsonObject) + } + + void Unload(ITypeManager* manager) + { + } + }; +#endif +#endif + + bool JsonAstLoadTypes() + { +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + if (auto manager = GetGlobalTypeManager()) + { + Ptr loader = new JsonAstTypeLoader; + return manager->AddTypeLoader(loader); + } +#endif + return false; + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_BUILDER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace builder + { + +/*********************************************************************** +MakeArray +***********************************************************************/ + + MakeArray& MakeArray::items(const vl::Ptr& value) + { + node->items.Add(value); + return *this; + } + +/*********************************************************************** +MakeLiteral +***********************************************************************/ + + MakeLiteral& MakeLiteral::value(JsonLiteralValue value) + { + node->value = value; + return *this; + } + +/*********************************************************************** +MakeNumber +***********************************************************************/ + + MakeNumber& MakeNumber::content(const vl::WString& value) + { + node->content.value = value; + return *this; + } + +/*********************************************************************** +MakeObject +***********************************************************************/ + + MakeObject& MakeObject::fields(const vl::Ptr& value) + { + node->fields.Add(value); + return *this; + } + +/*********************************************************************** +MakeObjectField +***********************************************************************/ + + MakeObjectField& MakeObjectField::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + + MakeObjectField& MakeObjectField::value(const vl::Ptr& value) + { + node->value = value; + return *this; + } + +/*********************************************************************** +MakeString +***********************************************************************/ + + MakeString& MakeString::content(const vl::WString& value) + { + node->content.value = value; + return *this; + } + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_COPY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace copy_visitor + { + void AstVisitor::CopyFields(JsonArray* from, JsonArray* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->items) + { + to->items.Add(CopyNode(listItem.Obj())); + } + } + + void AstVisitor::CopyFields(JsonLiteral* from, JsonLiteral* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->value = from->value; + } + + void AstVisitor::CopyFields(JsonNode* from, JsonNode* to) + { + } + + void AstVisitor::CopyFields(JsonNumber* from, JsonNumber* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->content = from->content; + } + + void AstVisitor::CopyFields(JsonObject* from, JsonObject* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->fields) + { + to->fields.Add(CopyNode(listItem.Obj())); + } + } + + void AstVisitor::CopyFields(JsonObjectField* from, JsonObjectField* to) + { + to->name = from->name; + to->value = CopyNode(from->value.Obj()); + } + + void AstVisitor::CopyFields(JsonString* from, JsonString* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->content = from->content; + } + + void AstVisitor::Visit(JsonObjectField* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(JsonLiteral* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(JsonString* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(JsonNumber* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(JsonArray* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(JsonObject* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + vl::Ptr AstVisitor::CopyNode(JsonNode* node) + { + if (!node) return nullptr; + node->Accept(static_cast(this)); + return this->result.Cast(); + } + + vl::Ptr AstVisitor::CopyNode(JsonObjectField* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr AstVisitor::CopyNode(JsonArray* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(JsonLiteral* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(JsonNumber* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(JsonObject* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(JsonString* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_EMPTY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace empty_visitor + { + +/*********************************************************************** +NodeVisitor +***********************************************************************/ + + // Visitor Members ----------------------------------- + + void NodeVisitor::Visit(JsonLiteral* node) + { + } + + void NodeVisitor::Visit(JsonString* node) + { + } + + void NodeVisitor::Visit(JsonNumber* node) + { + } + + void NodeVisitor::Visit(JsonArray* node) + { + } + + void NodeVisitor::Visit(JsonObject* node) + { + } + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_JSON.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace json_visitor + { + void AstVisitor::PrintFields(JsonArray* node) + { + BeginField(L"items"); + BeginArray(); + for (auto&& listItem : node->items) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + } + void AstVisitor::PrintFields(JsonLiteral* node) + { + BeginField(L"value"); + switch (node->value) + { + case vl::glr::json::JsonLiteralValue::False: + WriteString(L"False"); + break; + case vl::glr::json::JsonLiteralValue::Null: + WriteString(L"Null"); + break; + case vl::glr::json::JsonLiteralValue::True: + WriteString(L"True"); + break; + default: + WriteNull(); + } + EndField(); + } + void AstVisitor::PrintFields(JsonNode* node) + { + } + void AstVisitor::PrintFields(JsonNumber* node) + { + BeginField(L"content"); + WriteToken(node->content); + EndField(); + } + void AstVisitor::PrintFields(JsonObject* node) + { + BeginField(L"fields"); + BeginArray(); + for (auto&& listItem : node->fields) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + } + void AstVisitor::PrintFields(JsonObjectField* node) + { + BeginField(L"name"); + WriteToken(node->name); + EndField(); + BeginField(L"value"); + Print(node->value.Obj()); + EndField(); + } + void AstVisitor::PrintFields(JsonString* node) + { + BeginField(L"content"); + WriteToken(node->content); + EndField(); + } + + void AstVisitor::Visit(JsonLiteral* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Literal", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(JsonString* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"String", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(JsonNumber* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Number", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(JsonArray* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Array", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(JsonObject* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Object", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + AstVisitor::AstVisitor(vl::stream::StreamWriter& _writer) + : vl::glr::JsonVisitorBase(_writer) + { + } + + void AstVisitor::Print(JsonNode* node) + { + if (!node) + { + WriteNull(); + return; + } + node->Accept(static_cast(this)); + } + + void AstVisitor::Print(JsonObjectField* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"ObjectField", node); + PrintFields(static_cast(node)); + EndObject(); + } + + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_TRAVERSE.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace traverse_visitor + { + void AstVisitor::Traverse(vl::glr::ParsingToken& token) {} + void AstVisitor::Traverse(vl::glr::ParsingAstBase* node) {} + void AstVisitor::Traverse(JsonArray* node) {} + void AstVisitor::Traverse(JsonLiteral* node) {} + void AstVisitor::Traverse(JsonNode* node) {} + void AstVisitor::Traverse(JsonNumber* node) {} + void AstVisitor::Traverse(JsonObject* node) {} + void AstVisitor::Traverse(JsonObjectField* node) {} + void AstVisitor::Traverse(JsonString* node) {} + + void AstVisitor::Finishing(vl::glr::ParsingAstBase* node) {} + void AstVisitor::Finishing(JsonArray* node) {} + void AstVisitor::Finishing(JsonLiteral* node) {} + void AstVisitor::Finishing(JsonNode* node) {} + void AstVisitor::Finishing(JsonNumber* node) {} + void AstVisitor::Finishing(JsonObject* node) {} + void AstVisitor::Finishing(JsonObjectField* node) {} + void AstVisitor::Finishing(JsonString* node) {} + + void AstVisitor::Visit(JsonLiteral* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(JsonString* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->content); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(JsonNumber* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->content); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(JsonArray* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->items) + { + InspectInto(listItem.Obj()); + } + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(JsonObject* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->fields) + { + InspectInto(listItem.Obj()); + } + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::InspectInto(JsonNode* node) + { + if (!node) return; + node->Accept(static_cast(this)); + } + + void AstVisitor::InspectInto(JsonObjectField* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->name); + InspectInto(node->value.Obj()); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSONPARSER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Json +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + void JsonParserData(vl::stream::IStream& outputStream) + { + static const vl::vint dataLength = 1866; // 16217 bytes before compressing + static const vl::vint dataBlock = 256; + static const vl::vint dataRemain = 74; + static const vl::vint dataSolidRows = 7; + static const vl::vint dataRows = 8; + static const char* compressed[] = { + "\x59\x3F\x00\x00\x42\x07\x00\x00\x0C\x00\x01\x82\x80\x06\x03\x82\x81\x82\x06\x89\x82\x87\x0A\x80\x81\x84\x09\x0A\x98\x0A\x9D\x0A\x86\x65\x01\x84\xFF\x19\x9A\x99\x8A\x80\x03\x8D\x8D\x1D\x9D\x97\x89\x83\x96\x81\x93\x81\x02\x0A\xA7\x82\x8F\x8A\x8D\x8F\x96\x1C\x8A\xB0\x9F\x7F\x90\x99\x9B\x96\x37\x9F\x9D\x83\x0A\x92\x84\x03\x9E\x18\xB6\xB2\x82\xA1\xA0\x9F\xA0\xA3\x45\xBA\x87\xAA\xA9\xA0\x93\xA4\xA7\x4D\xAE\x8F\xB2\xA1\xA9\x99\xAA\x9A\x53\xD6\x86\x93\x99\x98\xAA\x83\x02\x40\xDB\x84\xA2\xB8\xA4\xB0\xA6\xB3\x5E\x83\x9C\xB9\xA8\xAF\xA9\xAE\xAA\x68\xF0\xAA\xA3\xB3\xBD\xB1\xBB\xB3\x77\xE9\x87\x81\xB9\xBA\xB8\x96\xBA\x7F\xF6\x81\xD8\xB3\xC2\xBD\x81\xB5\x6E\xEC\xAF\xBA\xAD\xBC\xC5\xC2\xBF\x87\x80\xD1\xC2\xC1\x84\x84\x92\xC5\x98\x89\xDA\xD1\xBE\xC3\xC8\xC2\xCF\x86\x9E\x92\xC2\xD4\xCC\xD3\xCE\xD3\xA1\x88\xDC\xCD\xB6\x80\x04\xBF\xC7\x9D\xA8\xD0\xD2\xD1\xDA\xD5\xC6\xD6\xB7\x8B\xF8\xD0\xDB\xD8\xD3\xD8\xDB\xBC\xBA\xC2\xEA\x89\x07\xD6\xDF\xDA\xA3\xC0\xC7\xFD\xD4\xDC\xE6\xE5\xE6\xC3\x9B\xF9\xD9\xCB\xD1\xE9\xEA\xEA\xD3\xD2\xC1\xF8", + "\xEB\xEA\xEF\xE4\xEB\xD9\xD7\xC9\x8A\x06\xE0\xE8\xEF\xEF\xE7\xE6\xDE\xEA\xF2\xF5\xF5\xF1\xF7\xDD\xEE\xF1\xF0\xF8\xF3\xF7\x05\xF2\x0E\xA6\x8A\x8D\x05\xF6\x05\xF3\xE7\x0F\x3F\x79\x73\x80\xA5\x50\x05\x79\x04\x02\xA5\x60\x47\x65\xEB\x4F\x7E\x80\x81\xA7\x4F\x85\x6A\x84\x11\x90\x89\x6A\x85\xBF\x58\x88\x73\x84\x1A\x8E\x7D\x84\x78\xF3\x61\x81\x43\x04\x09\x95\x8C\x87\x89\x26\xA9\x87\x84\x8A\xA1\x54\x05\x8B\x8A\x2A\x99\x8C\x8A\x8C\x31\x9B\x85\x8E\x87\x33\xB6\x80\x8F\x8E\x34\xBC\x8A\x8D\x8F\x40\xBF\x82\x90\x8E\x37\xA0\x85\x7E\x7C\x47\xB4\x70\x01\x05\x2F\x81\x94\x92\x8F\x4F\xB3\x66\x05\x93\x43\x86\x9C\x7A\x92\x14\x90\x96\x95\x96\x4E\x96\x97\x04\x95\xCC\x52\x4C\x80\x92\x57\xA2\x85\x99\x92\x66\x9C\x95\x95\x7A\x6A\x91\x9B\x99\x83\x1F\xAC\x93\x69\x06\x60\x96\x9A\x05\x9D\x72\xB9\x8E\x9B\x9E\x5B\xB1\x90\x9D\x69\x1B\x38\x9F\x9D\x91\x79\x84\xA3\xA2\x96\x85\x88\xA7\xA1\x97\x89\x8C\xAB\xA3\x9B\x06\x5C\x05\x78\x45\x63\x83\x4E\x05\x79\x1F\x02\xA6\x40\x08\xE5\x61\x0A\xA6\x92\x22\x25\x73\x0B\xA7\x69\xA3\x64\x09\x79\x25\x25\x76\x09\x79", + "\x27\x24\xA1\x40\x0A\xAE\xA7\x92\xAD\x0A\xE5\x6A\x01\xAF\x0A\xB1\xAD\x9D\x9E\x9E\xBB\x86\xA4\x9A\xAE\x8D\x90\xA8\x96\x9F\xBF\x84\xB3\x40\x0B\xE5\x6D\x09\xAE\xB1\xA5\xBC\xAA\x42\x0B\xE5\x6F\x05\x78\x0C\xE5\x71\x01\xAE\x0C\xCB\x8E\xB9\x43\x0C\xE5\x74\x09\xB6\xAF\xC3\x9A\xB5\xB2\xB8\xE1\xA0\xBD\xB2\xB9\x01\x75\x0F\xB6\xA2\xE3\xA8\xB2\xAC\xB0\x8F\xBC\x99\x7A\x0D\xEB\x8E\xAD\xB8\xBB\xE5\xB8\xB7\xBA\xBE\x68\x81\x47\x0D\xBD\xC2\xBB\xB6\xBD\xBE\x03\xC2\xC1\xC1\xBF\xEF\x8C\xB8\xC3\x73\x38\x31\xA9\x0C\xC0\xF2\xB1\xBD\xAC\xBF\x09\xE4\xB6\xC1\xC4\xF7\x85\xCB\xC2\xC2\x00\x3A\x00\xC7\xC4\x1A\xD5\xCE\xB8\xBC\x19\xC7\xC0\x03\x0E\x1F\xC1\xB8\xC4\xC1\x26\xE4\xCC\xCB\xCA\x02\x7D\x1A\x41\x4A\x95\xBC\x64\xCE\x7E\x57\x77\xC3\x43\x4A\xCB\x7A\xC2\x40\x4F\xF1\xB3\x4E\x69\x42\x3E\xFD\xCA\x40\x42\x25\xF3\x4F\x3F\xD0\x06\x48\xD7\x6C\xCF\x00\x10\xD2\xD0\x98\x4E\xFC\x63\x4C\xD4\x45\xCD\x7C\xD3\xCE\x6C\x55\xDB\x73\xD5\x21\x57\x5B\xD6\x40\x52\xF0\x4E\xD5\x73\x33\x67\xDA\xD2\xD9\x6C\x73\x49\xD4\x58\x41\xF0\x43\xD9\x40\x3F\x57\x55\xDF\x6A\x6E", + "\xE0\x97\xDF\x6D\x79\xF5\xCB\x73\xDE\x56\xF0\x49\xD5\xD9\x2D\x40\xEF\xD6\xE0\x3E\x6C\x56\xE0\xDA\x88\xE1\xD7\x6F\xE2\x6B\xED\x49\xD4\xD0\x49\xD3\xD4\xD2\xE2\x6D\xCD\xED\xD2\xCA\x96\xDB\xE7\x56\xDA\x91\xDB\x49\xD4\xE4\x9A\xC3\x40\xDD\xE5\x72\xC9\xE9\xCE\x42\xA7\xEF\xCD\xE7\x40\xA4\xED\x40\xE9\xE8\x19\x59\xDA\x6D\xEC\xB4\xC3\xE8\xE7\x55\x7D\xF8\xCB\x68\xEE\xA1\xFA\xE6\xDD\xE6\x92\xEA\xEF\xEC\xF1\x1F\x76\xEB\xEC\xDE\xA5\xFF\xCC\xE5\xEA\x97\xC3\xFC\xED\xF3\x01\x73\xE7\x8F\xEB\x7B\x52\xFC\xF1\xF1\x7E\xCD\x70\xF1\xE4\xC2\xC7\xF3\xF4\xF7\xBE\xCF\xE8\xF2\xE8\xC6\xE6\xF3\xF9\xF2\x8E\xEA\xFB\xF4\xFB\x09\x54\xEE\xE8\xF4\x06\x59\xD3\x4F\xF7\x6B\xD9\xD6\xF4\x94\xD8\xD5\xFD\xD7\xF9\x1A\x38\x7E\xD2\x61\x7E\x7C\xBE\x54\x79\x6A\xCB\x66\x80\xF9\x5C\x6A\x7A\x05\xB0\x7E\x20\x02\x82\x81\xEF\x6D\x77\x7E\x00\xB5\x72\x21\xF2\x77\x61\xFF\x00\x06\x7E\x98\x12\x87\x80\xFB\x6E\x4B\x06\xA1\x89\x22\x12\x8A\x6E\x84\x69\x76\x83\x3F\x1F\x8B\x80\x81\x11\x82\x85\xCA\x7F\x72\x0A\xA8\x84\x7E\xD3\x6C\x2D\x75\x81\x6D\x24\x0E\x87\x7A\x86\x15\xB3\x68", + "\x00\x19\x8B\x3B\x0F\xC1\x8A\x6B\xF6\x7C\x37\x87\xBA\x3B\x84\xE3\x3D\x8B\x7D\x8D\x2A\x5E\x88\x08\x90\x88\xD4\x22\x20\x8A\x0E\x95\x8C\x88\x54\x92\x89\xFA\x02\x2A\x89\xB3\x50\x6E\x8B\x47\x65\x3F\xD9\x7A\x78\x83\x30\x9D\x78\x8C\x09\x36\x31\xF9\x0B\x25\x3C\x35\x8C\x86\x20\x6E\x82\x21\xD6\x71\x81\x20\x22\xB4\x89\x8A\x70\x85\x3C\xD4\x7B\x83\x67\x32\x9D\x78\x6A\x3F\x85\x3B\x78\x5B\x81\x20\xF2\x10\x8B\x0E\xE5\x3D\x21\xA0\x50\x84\x0F\xF2\x19\x6A\x52\x50\x95\x0D\x79\x44\x87\x4E\x28\xB6\x0A\x8F\x0A\x28\x40\x14\xF7\x08\x93\x84\x1A\x96\x88\x78\x05\x3F\xE2\x5F\x40\x8B\x3C\x22\x92\x21\xA4\x86\x8A\x1E\x0E\x9A\x20\x4E\x50\x8B\x0F\x93\x8A\x21\xA6\x50\x8C\x0F\xF2\x3C\x05\x8A\x8B\x75\x88\x1E\xAF\x6A\x97\x18\xAB\x89\x20\x84\x6E\x5F\x4E\x55\x84\x81\x8B\x7A\x92\x89\xC3\x9D\x7B\xE2\x1D\x85\x35\x8E\x27\x6E\x99\x6D\x9D\x8F\x7A\x45\x91\x6C\x41\x86\x24\x88\x2E\x6E\x79\xF7\x1D\x29\x3F\x81\x18\x9C\x63\x8B\x73\x8A\x42\x01\x41\x7E\x95\x5D\x22\x89\xE2\x8F\x21\xCA\x09\x28\x8C\x23\xA4\x45\x7B\xD9\x95\x32\x42\x77\x30\x8A\x17\x5D\x7C\x49\xD1\x64", + "\x4E\x35\xB0\x75\x8B\x54\xA8\x21\x3D\x1D\x39\x6B\x3E\xF2\x85\x8A\x3A\x79\x9A\x49\x59\x62\xA2\x1F\xC6\x8B\x91\xFA\x69\x3B\x99\xC4\x2A\x22\x7F\x50\x84\x52\x87\xAB\x3B\x8C\x11\xA9\x22\x3D\xC6\x83\x96\x8B\xA4\x4F\x87\x0A\xA9\x20\x32\x8A\x2E\x53\x83\x82\x23\x54\x26\xA5\x92\x34\x86\x23\xA0\xFF\x50\x89\x55\x29\xA0\x01\xAB\x31\xAD\x9A\x82\x83\x91\x21\x48\x8A\x20\xAD\x70\x9C\x62\x7A\xAC\xA5\x8A\xF1\x92\x55\x4D\x81\x23\xA2\x23\xB6\x54\xA7\x16\x64\xAA\x42\x06\x40\x8B\xA0\x8F\x3D\xA8\x03\x3E\xA5\xFB\x38\x5D\x7A\x64\x71\xA0\xAA\x64\x63\x9F\x3C\xD5\x80\x5B\xEE\x52\x59\xA6\xE4\x9F\x94\x00\x4C\xA6\x20\xFE\x10\x8E\x5A\x48\xAE\x5F\x27\x83\x24\xAC\x0A\x9C\x67\x39\x6B\xA2\x21\x58\xEE\xA9\xA8\x59\x4B\x46\x20\x1B\xAD\x7C\xB6\x69\xA4\x63\xBC\xAE\x85\x8A\xDC\x51\xA7\x73\x6D\xA6\xA6\xBC\xAB\xA5\x7D\x4F\x9E\xA2\x92\x77\xAF\x9E\x8D\x8B\xA5\x7D\xFF\x42\xB3\x68\x7E\xA1\x21\xAC\x54\xB0\x00\x58\xA1\x6F\xC3\x12\xB5\x35\x29\x71\xA7\xB2\x97\xBD\x20\xCA\x1C\xB7\x34\x31\x4A\xB2\x20\x97\xBE\xB2\x11\xCE\xA3\xB2\xD6\x55\x8D\x07\x87\xA2\x23\x0F\x31", + "\xB1\x21\x4A\xA7\xB1\x20\x97\xAF\x9A\x42\x41\x04\xB6\x00\x03\x0D\xB7\x90\x97\xB7\x92\x04\x91\x25\x22\x3D\xB7\x39\x97\x51\xA4\x3E\xC2\xBD\x23\x23\x07\xBB\x34\xAE\x82\xBB\x72\xDE\x95\x8B\x24\x0F\xBD\x34\xA1\x4A\xBA\x44\xD5\x8B\x09\xEB\xA7\x37\x54\xDA\xAE\xB0\x14\xCD\x0E\xBB\xD0\x2B\x51\xBC\x5F\x35\x8B\x13\x3D\xB1\x0B\xDE\xB0\x50\xBD\x03\x3A\xB5\x42\x53\x0D\xB7\x2A\x3D\xB7\xA8\xC2\xAA\xB7\x40\x6F\x96\x89\x2B\x2B\x9E\x20\xFE\x82\x22\x7E\x8E\x7C\xB5\xD2\x01\xC1\x20\xD3\xA4\xC3\x5B\xA3\x36\xB4\x7E\x90\x88\x0B\xE5\xB3\x36\x55\xE2\xAD\xC1\xC2\xAD\x7A\x0B\x11\xD1\x36\xB2\x5D\x75\xC3\x3A\x95\x8C\x0B\x19\xCC\x39\x57\x94\xCB\xBA\x28\x9E\x09\xC4\x1D\x3F\xA8\x89\xE2\xB6\x88\x30\x28\xC2\x21\xD4\x5C\xC2\x6B\xD0\x82\x0D\xDE\xA4\x0D\xB7\x68\xAB\xC6\xE7\x46\x86\x0D\xDE\xA8\x0D\xB7\x7B\xA2\xAE\x6D\x83\x26\xA0\x23\xAA\x0F\xBF\x03\x2D\xA0\x91\xD5\x8B\x0C\x24\xC2\x21\xB8\x4B\xD0\x88\x1B\x4E\xC1\x21\x8A\x83\x21\xB3\x21\x2D\x0F\x8B\xDB\x53\x52\x85\x21\xB2\x21\x6F\x1B\xCA\x41\x5E\x5D\x7B\x8E\x96\x55\x8A\x71\x14\xC8\x00\x51\xB7\xCC\x28", + "\xB2\x0A\xCD\x25\xAB\xB7\x68\x68\x69\x98\x28\xB9\x91\xA0\xBA\x89\x9D\x15\xC1\x90\x24\x3E\xDB\x22\xCF\x62\xA1\x24\xA0\x8D\xB5\x3A\x66\xAD\x86\x71\xBE\x8C\xB8\x9E\xD7\x8A\x31\x6F\xB0\x20\x8B\x75\xC6\x88\xA4\x8F\xBD\x7C\x01\x80\x02\x82\x10\xA4\xB9\x48\x61\x97\x9C\xC5\x0A\x8A\x69\xE8\x9D\xD1\x15\x80", + }; + vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); + } + + const wchar_t* ParserRuleName(vl::vint index) + { + static const wchar_t* results[] = { + L"JLiteral", + L"JField", + L"JObject", + L"JArray", + L"JValue", + L"JRoot", + }; + return results[index]; + } + + const wchar_t* ParserStateLabel(vl::vint index) + { + static const wchar_t* results[] = { + L"[0][JLiteral] BEGIN ", + L"[1][JLiteral] END [ENDING]", + L"[2][JLiteral]< \"false\" @ >", + L"[3][JLiteral]< \"null\" @ >", + L"[4][JLiteral]< \"true\" @ >", + L"[5][JLiteral]< NUMBER @ >", + L"[6][JLiteral]< STRING @ >", + L"[7][JField] BEGIN ", + L"[8][JField] END [ENDING]", + L"[9][JField]< STRING \":\" @ JValue >", + L"[10][JField]< STRING \":\" JValue @ >", + L"[11][JField]< STRING @ \":\" JValue >", + L"[12][JObject] BEGIN ", + L"[13][JObject] END [ENDING]", + L"[14][JObject]< \"{\" @ { JField ; \",\" } \"}\" >", + L"[15][JObject]< \"{\" { JField ; \",\" @ } \"}\" >", + L"[16][JObject]< \"{\" { JField ; \",\" } \"}\" @ >", + L"[17][JObject]< \"{\" { JField @ ; \",\" } \"}\" >", + L"[18][JArray] BEGIN ", + L"[19][JArray] END [ENDING]", + L"[20][JArray]< \"[\" @ { JValue ; \",\" } \"]\" >", + L"[21][JArray]< \"[\" { JValue ; \",\" @ } \"]\" >", + L"[22][JArray]< \"[\" { JValue ; \",\" } \"]\" @ >", + L"[23][JArray]< \"[\" { JValue @ ; \",\" } \"]\" >", + L"[24][JValue] BEGIN ", + L"[25][JValue] END [ENDING]", + L"[26][JValue]<< !JArray @ >>", + L"[27][JValue]<< !JLiteral @ >>", + L"[28][JValue]<< !JObject @ >>", + L"[29][JRoot] BEGIN ", + L"[30][JRoot] END [ENDING]", + L"[31][JRoot]<< !JArray @ >>", + L"[32][JRoot]<< !JObject @ >>", + }; + return results[index]; + } + + Parser::Parser() + : vl::glr::ParserBase(&JsonTokenDeleter, &JsonLexerData, &JsonParserData) + { + }; + + vl::vint32_t Parser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const + { + return -1; + }; + + vl::Ptr Parser::ParseJRoot(const vl::WString& input, vl::vint codeIndex) const + { + return Parse(input, this, codeIndex); + }; + + vl::Ptr Parser::ParseJRoot(vl::collections::List& tokens, vl::vint codeIndex) const + { + return Parse(tokens, this, codeIndex); + }; + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSON_ASSEMBLER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Json +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + +/*********************************************************************** +JsonAstInsReceiver : public vl::glr::AstInsReceiverBase +***********************************************************************/ + + vl::Ptr JsonAstInsReceiver::CreateAstNode(vl::vint32_t type) + { + auto cppTypeName = JsonCppTypeName((JsonClasses)type); + switch((JsonClasses)type) + { + case JsonClasses::Array: + return new vl::glr::json::JsonArray(); + case JsonClasses::Literal: + return new vl::glr::json::JsonLiteral(); + case JsonClasses::Number: + return new vl::glr::json::JsonNumber(); + case JsonClasses::Object: + return new vl::glr::json::JsonObject(); + case JsonClasses::ObjectField: + return new vl::glr::json::JsonObjectField(); + case JsonClasses::String: + return new vl::glr::json::JsonString(); + default: + return vl::glr::AssemblyThrowCannotCreateAbstractType(type, cppTypeName); + } + } + + void JsonAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value) + { + auto cppFieldName = JsonCppFieldName((JsonFields)field); + switch((JsonFields)field) + { + case JsonFields::Array_items: + return vl::glr::AssemblerSetObjectField(&vl::glr::json::JsonArray::items, object, field, value, cppFieldName); + case JsonFields::Object_fields: + return vl::glr::AssemblerSetObjectField(&vl::glr::json::JsonObject::fields, object, field, value, cppFieldName); + case JsonFields::ObjectField_value: + return vl::glr::AssemblerSetObjectField(&vl::glr::json::JsonObjectField::value, object, field, value, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName); + } + } + + void JsonAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) + { + auto cppFieldName = JsonCppFieldName((JsonFields)field); + switch((JsonFields)field) + { + case JsonFields::Number_content: + return vl::glr::AssemblerSetTokenField(&vl::glr::json::JsonNumber::content, object, field, token, tokenIndex, cppFieldName); + case JsonFields::ObjectField_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::json::JsonObjectField::name, object, field, token, tokenIndex, cppFieldName); + case JsonFields::String_content: + return vl::glr::AssemblerSetTokenField(&vl::glr::json::JsonString::content, object, field, token, tokenIndex, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName); + } + } + + void JsonAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem) + { + auto cppFieldName = JsonCppFieldName((JsonFields)field); + switch((JsonFields)field) + { + case JsonFields::Literal_value: + return vl::glr::AssemblerSetEnumField(&vl::glr::json::JsonLiteral::value, object, field, enumItem, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName); + } + } + + const wchar_t* JsonTypeName(JsonClasses type) + { + const wchar_t* results[] = { + L"Array", + L"Literal", + L"Node", + L"Number", + L"Object", + L"ObjectField", + L"String", + }; + vl::vint index = (vl::vint)type; + return 0 <= index && index < 7 ? results[index] : nullptr; + } + + const wchar_t* JsonCppTypeName(JsonClasses type) + { + const wchar_t* results[] = { + L"vl::glr::json::JsonArray", + L"vl::glr::json::JsonLiteral", + L"vl::glr::json::JsonNode", + L"vl::glr::json::JsonNumber", + L"vl::glr::json::JsonObject", + L"vl::glr::json::JsonObjectField", + L"vl::glr::json::JsonString", + }; + vl::vint index = (vl::vint)type; + return 0 <= index && index < 7 ? results[index] : nullptr; + } + + const wchar_t* JsonFieldName(JsonFields field) + { + const wchar_t* results[] = { + L"Array::items", + L"Literal::value", + L"Number::content", + L"Object::fields", + L"ObjectField::name", + L"ObjectField::value", + L"String::content", + }; + vl::vint index = (vl::vint)field; + return 0 <= index && index < 7 ? results[index] : nullptr; + } + + const wchar_t* JsonCppFieldName(JsonFields field) + { + const wchar_t* results[] = { + L"vl::glr::json::JsonArray::items", + L"vl::glr::json::JsonLiteral::value", + L"vl::glr::json::JsonNumber::content", + L"vl::glr::json::JsonObject::fields", + L"vl::glr::json::JsonObjectField::name", + L"vl::glr::json::JsonObjectField::value", + L"vl::glr::json::JsonString::content", + }; + vl::vint index = (vl::vint)field; + return 0 <= index && index < 7 ? results[index] : nullptr; + } + + vl::Ptr JsonAstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates) + { + auto cppTypeName = JsonCppTypeName((JsonClasses)type); + return vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName); + } + } + } +} + + +/*********************************************************************** +.\JSON\GENERATED\JSON_LEXER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Json +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace json + { + bool JsonTokenDeleter(vl::vint token) + { + switch((JsonTokens)token) + { + case JsonTokens::SPACE: + return true; + default: + return false; + } + } + + const wchar_t* JsonTokenId(JsonTokens token) + { + static const wchar_t* results[] = { + L"TRUE_VALUE", + L"FALSE_VALUE", + L"NULL_VALUE", + L"OBJOPEN", + L"OBJCLOSE", + L"ARROPEN", + L"ARRCLOSE", + L"COMMA", + L"COLON", + L"NUMBER", + L"STRING", + L"SPACE", + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < JsonTokenCount ? results[index] : nullptr; + } + + const wchar_t* JsonTokenDisplayText(JsonTokens token) + { + static const wchar_t* results[] = { + L"true", + L"false", + L"null", + L"{", + L"}", + L"[", + L"]", + L",", + L":", + nullptr, + nullptr, + nullptr, + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < JsonTokenCount ? results[index] : nullptr; + } + + const wchar_t* JsonTokenRegex(JsonTokens token) + { + static const wchar_t* results[] = { + L"true", + L"false", + L"null", + L"\\{", + L"\\}", + L"\\[", + L"\\]", + L",", + L":", + L"[\\-]?\\d+(.\\d+)?([eE][+\\-]?\\d+)?", + L"\"([^\\\\\"]|\\\\[^u]|\\\\u\\d{4})*\"", + L"\\s+", + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < JsonTokenCount ? results[index] : nullptr; + } + + void JsonLexerData(vl::stream::IStream& outputStream) + { + static const vl::vint dataLength = 690; // 7754 bytes before compressing + static const vl::vint dataBlock = 256; + static const vl::vint dataRemain = 178; + static const vl::vint dataSolidRows = 2; + static const vl::vint dataRows = 3; + static const char* compressed[] = { + "\x4A\x1E\x00\x00\xAA\x02\x00\x00\x2A\x00\x01\xAB\x01\x84\x81\x80\x81\x80\x01\x04\x88\x04\x89\x04\x84\x82\x05\x0F\x84\x8B\x04\x8C\x04\x81\x06\x8B\x04\x8E\x04\x9F\x04\x80\x11\x8E\x82\x21\x20\x84\x82\x13\x94\x83\x10\x82\x07\x80\x03\x82\x84\x84\x15\x96\x82\x2D\x30\x84\x8E\x13\x9C\x83\x16\x9B\x04\xB0\x04\x99\x14\x82\x1D\x9E\x82\x3B\x04\x84\x24\x85\x24\xA0\x82\x23\x04\xDA\x04\x9B\x2B\xA4\x80\x2E\xA7\x04\xDD\x11\xA4\x8E\x2C\x80\x30\x82\x61\x58\x84\x82\x34\x84\x30\x83\x32\x5F\x84\xA6\x22\xB4\x87\x30\x83\x35\x04\xEC\x29\xA4\x8D\x34\xB4\x82\x37\x6F\x84\xAF\x24\x81\x3C\x82\x38\xBB\x04\xF3\x39\xA4\x84\x3C\xBC\x83\x3A\x7F\x84\xB6\x24\x8A\x3C\x83\x3C\xC3\x04\xFC\x09\xC4\x8D\x3C\xC4\x82\x3F\x04\xFF\x7F\x70\x00\x02\xCA\xC9\x8B\x01\x98\xD5\xD6\xCA\xCE\xCB\x7F\xCE\x96\x95\x81\x9E\xCE\xCB\x85\x80\x88\xA3\xA4\xD2\xD3\x81\x85\x85\xD4\xD5\x9E\x86\x11\xD6\xC7\x03\xD8\xD8\xD8\x02\x36\xF7\xDF\x73\x02\xDF\xDB\x84\xAF\xA4\xC4\x1A\xD5\x06\xDF\xDD\xE3\xC8\xC9\xCA\xEB\xEC\xE5\xE6\xE7\xE7\x1A\xC1\xCF\xF3\xE4\xED\xEA\xEB\xEB\xA4\x8F\x06\xF8", + "\xEC\xED\xEE\xEF\xEF\xE0\xE1\xD5\xF4\xC2\xEA\xF2\xF3\xF3\xE8\xE9\xEA\xEB\xFC\xF5\xF6\xF7\xF7\xF0\xF1\xF2\xF3\xF4\xFD\xFA\xFB\xFB\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xF4\xD6\x9B\x7E\x72\x83\x7C\x12\x3A\x61\x07\x76\xFF\x13\x08\x80\x75\x0A\xA5\x73\x80\x05\x04\x50\x81\x42\x84\x00\x14\x86\x85\x84\x18\x81\x46\x05\x86\x15\x9C\x87\x87\x84\x1E\xA1\x80\x8B\x88\x00\x15\x02\x89\x87\x24\x9F\x88\x8B\x8A\x2A\xAD\x87\x8A\x8B\x29\x88\x87\x04\x41\x33\x81\x75\x8D\x80\xFF\x37\x83\x83\x8E\x3C\xBD\x88\x7C\x06\x0B\xBE\x82\x92\x6A\x19\x01\x93\x93\x91\xE0\x5A\x06\x90\x92\xDE\x45\x81\x73\x81\x0E\x89\x8B\x91\x73\x0D\xB8\x8C\x93\x7E\x1B\x13\x97\x94\x93\x1C\x3A\x6D\x95\x94\x1D\x1A\x9B\x94\x77\x30\xAC\x8F\x88\x41\x1B\xB1\x8A\x9A\x99\x6B\xA5\x94\x86\x89\x6D\xA7\x91\x9F\x9C\x6C\xB5\x9E\x9A\x6E\x1E\x04\x49\x9D\x40\x7B\x80\x0D\x9F\x9F\x7A\x81\xAC\x9E\xA0\x7E\x84\xA0\xA3\xA0\x88\x85\xA9\xA3\xA1\x8A\x8D\xAC\xA3\xA3\x86\x91\xAB\xA2\xA4\x8D\x9C\x43\xA7\xA5\x8D\xA3\x9A\xA5\x7B\x37\xBA\x86\x66\xA7\x92\x60\xAB\xA7\xA8\xA4\x9D\x7E\x45\x94\xA5\xA9\xAF\x79\x48", + "\xA8\xAA\xAE\x8C\x49\xAD\xAE\xA8\x77\x49\x51\x95\x9F\x76\xAD\xB2\xB2\x71\x99\xAC\xB9\xAA\xA4\x0A\x98\xBD\x89\x77\x9C\x9D\x14\xA9\x96\x9E\x9C\xC7\xB4\x90\x9D\xB2\xCC\x83\xBD\xB0\xB2\x65\x83\x95\x08\xB0\xC1\x95\xB6\xB7\xB5\xE8\x66\x04\xB4\xB6\xDC\x9D\xBF\x70\xAD\x56\x96\x68\xAD\x77\xE3\x9E\xB6\x7B\xAF\xBC\xA6\xB8\x93\x09\xDB\xAA\xBE\xBB\xBB\xF4\x68\x0D\xB8\xBC\xFD\x69\x03\xBD\xB7\xCE\x8E\xB6\xB1\xBE\xD0\x88\xBB\xB0\xBF\xC4\xBD\xB1\xC0\x9D\x9E\x70\x3B\x0A\x30\x28\x12\x59\x49\x41\xA2\x40\x0D\xC1\xC3\xBD\x41\x43\x71\x40\xC5\x41\x42\x6D\x40\xB5\x41\x46\x6A\xC3\x0E\x41\x4D\xC0\x80\x0F\xD4\x4D\xC4\xC7\x1E\xE2\xC5\xCB\x69\x12\x66\xC4\xCB\xCA\xAE\x6C\xCA\xC9\xC3\x0C\xC4\x49\x6D\x6B\x23\xCD\xC0\x73\xCA\x21\xC1\x40", + }; + vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); + } + } + } +} + + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace automaton + { + +/*********************************************************************** +TraceManager +***********************************************************************/ + + void TraceManager::BeginSwap() + { + concurrentCount = 0; + } + + void TraceManager::AddTrace(Trace* trace) + { + if (concurrentCount < backupTraces->Count()) + { + backupTraces->Set(concurrentCount, trace); + } + else + { + backupTraces->Add(trace); + } + concurrentCount++; + } + + void TraceManager::EndSwap() + { + auto t = concurrentTraces; + concurrentTraces = backupTraces; + backupTraces = t; + } + + void TraceManager::AddTraceToCollection(Trace* owner, Trace* element, TraceCollection(Trace::* collection)) + { + auto errorMessage = L"vl::glr::automaton::TraceManager::AddTraceToCollection(Trace*, Trace*, TraceCollection(Trace::*))#Multiple to multiple predecessor-successor relationship is not supported."; + auto&& elementCollection = element->*collection; + if (elementCollection.siblingNext == -1 && elementCollection.siblingPrev == -1) + { + auto&& ownerCollection = owner->*collection; + if (ownerCollection.first == -1) + { + ownerCollection.first = element->allocatedIndex; + ownerCollection.last = element->allocatedIndex; + } + else + { + auto sibling = GetTrace(ownerCollection.last); + auto&& siblingCollection = sibling->*collection; + CHECK_ERROR(siblingCollection.siblingNext == -1, errorMessage); + + siblingCollection.siblingNext = element->allocatedIndex; + elementCollection.siblingPrev = sibling->allocatedIndex; + ownerCollection.last = element->allocatedIndex; + } + } + else if (collection == &Trace::predecessors) + { + // there is a valid scenario when + // B(ending) ---+ + // | + // O(origin) -+-> A(ending) -+-+-> C(merged) + // | + // +---> D(token) + + // in this case, we need to copy A(ending) to avoid the multiple to multiple relationship + // the reason we cannot have such relationship is that + // TraceCollection::(siblingPrev|siblingNext) is a linked list + // it represents a predecessor collections of owner + // if a trace is shared in two predecessor collections + // there is no place for a second linked list + // the data structure is not able to represent such relationship + + // but this it is not doable if A also has multiple predecessors + // because copying A replaces a new multiple to multiple relationship to an old one like this + // O1(origin) -+-+ B(ending) -+ + // | | | + // O2(origin) -+-+-> A(ending) -+-> C(merged) + // | + // +---> X(ending) ---> D(token) + CHECK_ERROR(element->predecessors.first == element->predecessors.last, errorMessage); + + auto copiedElement = AllocateTrace(); + { + vint32_t copiedId = copiedElement->allocatedIndex; + *copiedElement = *element; + copiedElement->allocatedIndex = copiedId; + } + + // clear sibilingPrev and sibilingNext because it belongs to no collection at this moment + // keep first and last so that it still knows its predecessors + copiedElement->predecessors.siblingPrev = -1; + copiedElement->predecessors.siblingNext = -1; + + // now it becomes + // B(ending) -+ + // | + // O(origin) -+-> A(ending) -+-> C(merged) + // | + // +-> X(ending) ---> D(token) + AddTraceToCollection(owner, copiedElement, collection); + } + else + { + // Trace::predecessors is filled by Input + // Trace::successors is filled by PrepareTraceRoute + // if Input and EndOfInput succeeded + // there should not be any multiple to multiple relationship + CHECK_FAIL(errorMessage); + } + } + + TraceManager::TraceManager(Executable& _executable, const ITypeCallback* _typeCallback) + : executable(_executable) + , typeCallback(_typeCallback) + { + } + + ReturnStack* TraceManager::GetReturnStack(vint32_t index) + { + return returnStacks.Get(index); + } + + ReturnStack* TraceManager::AllocateReturnStack() + { + return returnStacks.Get(returnStacks.Allocate()); + } + + Trace* TraceManager::GetTrace(vint32_t index) + { + return traces.Get(index); + } + + Trace* TraceManager::AllocateTrace() + { + return traces.Get(traces.Allocate()); + } + + Competition* TraceManager::GetCompetition(vint32_t index) + { + return competitions.Get(index); + } + + Competition* TraceManager::AllocateCompetition() + { + return competitions.Get(competitions.Allocate()); + } + + AttendingCompetitions* TraceManager::GetAttendingCompetitions(vint32_t index) + { + return attendingCompetitions.Get(index); + } + + AttendingCompetitions* TraceManager::AllocateAttendingCompetitions() + { + return attendingCompetitions.Get(attendingCompetitions.Allocate()); + } + + void TraceManager::Initialize(vint32_t startState) + { + state = TraceManagerState::WaitingForInput; + + returnStacks.Clear(); + traces.Clear(); + competitions.Clear(); + attendingCompetitions.Clear(); + + traces1.Clear(); + traces2.Clear(); + concurrentTraces = &traces1; + backupTraces = &traces2; + + activeCompetitions = -1; + initialReturnStackSuccessors = {}; + + initialTrace = AllocateTrace(); + initialTrace->state = startState; + concurrentCount = 1; + concurrentTraces->Add(initialTrace); + } + } + } +} + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER_EXECUTETRACE.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace automaton + { +/*********************************************************************** +TraceManager::ExecuteTrace +***********************************************************************/ + + struct TraceManagerSubmitter + { + // AccumulatedDfa + vint32_t adfaCount = 0; + vint32_t adfaIndex = -1; + regex::RegexToken* adfaToken = nullptr; + + // AccumulatedEoRo + vint32_t aeoroCount = 0; + vint32_t aeoroIndex = -1; + regex::RegexToken* aeoroToken = nullptr; + + // Caching + AstIns cachedIns; + vint32_t cachedIndex = -1; + regex::RegexToken* cachedToken = nullptr; + + IAstInsReceiver* receiver = nullptr; + + void Submit(AstIns& ins, regex::RegexToken& token, vint32_t tokenIndex) + { + // multiple DelayFieldAssignment are compressed to single AccumulatedDfa + // multiple EndObject+ReopenObject are compressed to single AccumulatedEoRo + + switch (ins.type) + { + case AstInsType::DelayFieldAssignment: + if (aeoroToken == nullptr && cachedToken == nullptr && (adfaToken == nullptr || adfaToken == &token)) + { + adfaCount++; + adfaIndex = tokenIndex; + adfaToken = &token; + } + else + { + ExecuteSubmitted(); + adfaCount = 1; + adfaIndex = tokenIndex; + adfaToken = &token; + } + break; + case AstInsType::EndObject: + if (adfaToken == nullptr && cachedToken == nullptr) + { + cachedIns = ins; + cachedIndex = tokenIndex; + cachedToken = &token; + } + else + { + ExecuteSubmitted(); + cachedIns = ins; + cachedIndex = tokenIndex; + cachedToken = &token; + } + break; + case AstInsType::ReopenObject: + if (adfaToken != nullptr || cachedToken == nullptr || cachedIns.type != AstInsType::EndObject) + { + ExecuteSubmitted(); + receiver->Execute(ins, token, tokenIndex); + } + else if ((aeoroToken == nullptr || aeoroToken == &token) && cachedToken == &token) + { + aeoroCount++; + aeoroIndex = tokenIndex; + aeoroToken = &token; + cachedToken = nullptr; + } + else if (cachedToken == &token) + { + cachedToken = nullptr; + ExecuteSubmitted(); + aeoroCount = 1; + aeoroIndex = tokenIndex; + aeoroToken = &token; + } + else + { + ExecuteSubmitted(); + receiver->Execute(ins, token, tokenIndex); + } + break; + default: + ExecuteSubmitted(); + receiver->Execute(ins, token, tokenIndex); + } + } + + void ExecuteSubmitted() + { + if (adfaToken) + { + if (adfaCount == 1) + { + AstIns ins = { AstInsType::DelayFieldAssignment }; + receiver->Execute(ins, *adfaToken, adfaIndex); + } + else + { + AstIns ins = { AstInsType::AccumulatedDfa,-1,adfaCount }; + receiver->Execute(ins, *adfaToken, adfaIndex); + } + adfaCount = 0; + adfaToken = nullptr; + } + if (aeoroToken) + { + AstIns ins = { AstInsType::AccumulatedEoRo,-1,aeoroCount }; + receiver->Execute(ins, *aeoroToken, aeoroIndex); + aeoroCount = 0; + aeoroToken = nullptr; + } + if (cachedToken) + { + receiver->Execute(cachedIns, *cachedToken, aeoroIndex); + cachedToken = nullptr; + } + } + }; + + Ptr TraceManager::ExecuteTrace(Trace* trace, IAstInsReceiver& receiver, collections::List& tokens) + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::ExecuteTrace(Trace*, IAstInsReceiver&, List&)#" + CHECK_ERROR(state == TraceManagerState::PreparedTraceRoute, ERROR_MESSAGE_PREFIX L"Wrong timing to call this function."); + + TraceManagerSubmitter submitter; + submitter.receiver = &receiver; + + // execute from the root trace + + vint32_t startIns = 0; + while (trace) + { + TraceInsLists insLists; + ReadInstructionList(trace, insLists); + + vint32_t minIns = 0; + vint32_t maxIns = insLists.c3 - 1; + if (trace->ambiguityMergeInsPostfix != -1) + { + minIns = insLists.c3 - trace->ambiguityMergeInsPostfix; + } + if (trace->ambiguityBranchInsPostfix != -1) + { + maxIns = insLists.c3 - trace->ambiguityBranchInsPostfix - 1; + } + + // if the current trace is an ambiguity resolving trace + // we check if all predecessors has been visited + // if yes, we continue + // if no, we jump to the BeginObject and repeat it again + + if (trace->ambiguity.traceBeginObject != -1 && trace->ambiguityRouting.predecessorCount == -1) + { + // we need to know how many predecessors there + // the number is calculated and cached when an ambiguity resolving trace is visited for the first time + trace->ambiguityRouting.predecessorCount = 0; + auto predecessorId = trace->predecessors.first; + while (predecessorId != -1) + { + trace->ambiguityRouting.predecessorCount++; + predecessorId = GetTrace(predecessorId)->predecessors.siblingNext; + } + } + + if (trace->ambiguity.traceBeginObject != -1) + { + if (0 <= trace->ambiguity.insEndObject && trace->ambiguity.insEndObject < insLists.c3) + { + // execute from the beginning to EndObject instruction if it exists + // if ambiguityMergeInsPostfix exists + // then insEndObject will be the last instruction in the prefix + // so it is skipped and this loop does nothing + // the EndObject instruction has already been executed by its predecessors + for (vint32_t i = minIns; i <= trace->ambiguity.insEndObject; i++) + { + auto& ins = ReadInstruction(i, insLists); + auto& token = tokens[trace->currentTokenIndex]; + submitter.Submit(ins, token, trace->currentTokenIndex); + } + } + else + { + // otherwise this must be the trace created by CreateLastMergingTrace + CHECK_ERROR(insLists.c3 == 0 && trace->successors.first == -1 && trace->successors.last == -1, ERROR_MESSAGE_PREFIX L"Instruction index out of range."); + } + + // for any ambiguity resolving trace + // we check all predecessors has been visited + trace->ambiguityRouting.branchVisited++; + auto traceBeginObject = GetTrace(trace->ambiguity.traceBeginObject); + + if (trace->ambiguityRouting.branchVisited == trace->ambiguityRouting.predecessorCount) + { + // if all predecessors has been visited + // we reset the number to 0 + // because TraceManager::ExecuteTrace could be called multiple time + trace->ambiguityRouting.branchVisited = 0; + { + // submit a ResolveAmbiguity instruction + auto& token = tokens[trace->currentTokenIndex]; + AstIns insResolve = { AstInsType::ResolveAmbiguity,trace->ambiguity.ambiguityType,trace->ambiguityRouting.predecessorCount }; + submitter.Submit(insResolve, token, trace->currentTokenIndex); + } + + // execute all instructions after EndObject + // these part should not be repeated + for (vint32_t i = trace->ambiguity.insEndObject + 1; i <= maxIns; i++) + { + auto& ins = ReadInstruction(i, insLists); + auto& token = tokens[trace->currentTokenIndex]; + submitter.Submit(ins, token, trace->currentTokenIndex); + } + } + else + { + // if there are unvisited predecessors + // we jump to the BeginObject instruction and repeat it again + startIns = trace->ambiguity.insBeginObject; + trace = traceBeginObject; + goto FOUND_NEXT_TRACE; + } + } + else + { + // otherwise, just submit instructions + CHECK_ERROR(minIns <= startIns, ERROR_MESSAGE_PREFIX L"startIns corrupted."); + for (vint32_t i = startIns; i <= maxIns; i++) + { + auto& ins = ReadInstruction(i, insLists); + auto& token = tokens[trace->currentTokenIndex]; + submitter.Submit(ins, token, trace->currentTokenIndex); + } + } + + if (trace->successors.first == -1) + { + trace = nullptr; + startIns = 0; + } + else if (trace->successors.first == trace->successors.last) + { + trace = GetTrace(trace->successors.first); + startIns = 0; + } + else + { + // if there are multiple successors + // whenever this trace is visited + // we pick a different successor to continue + auto nextSuccessorId = trace->successors.first; + Trace* successor = nullptr; + for (vint i = 0; i <= trace->ambiguityRouting.branchVisited; i++) + { + CHECK_ERROR(nextSuccessorId != -1, ERROR_MESSAGE_PREFIX L"branchVisited corrupted."); + successor = GetTrace(nextSuccessorId); + nextSuccessorId = successor->successors.siblingNext; + } + + if (nextSuccessorId == -1) + { + trace->ambiguityRouting.branchVisited = 0; + } + else + { + trace->ambiguityRouting.branchVisited++; + } + + // this could happen when all BeginObject are in successors + // if the current successor is the first successor + // then we need to execute the prefix + if (startIns >= insLists.c3) + { + startIns -= insLists.c3; + if (trace->successors.first == successor->allocatedIndex) + { + ReadInstructionList(successor, insLists); + for (vint32_t i = 0; i < startIns; i++) + { + auto& ins = ReadInstruction(i, insLists); + auto& token = tokens[successor->currentTokenIndex]; + submitter.Submit(ins, token, trace->currentTokenIndex); + } + } + } + else + { + startIns = 0; + } + trace = successor; + } + FOUND_NEXT_TRACE:; + } + + submitter.ExecuteSubmitted(); + return receiver.Finished(); +#undef ERROR_MESSAGE_PREFIX + } + } + } +} + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER_INPUT.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace automaton + { + +/*********************************************************************** +Input +***********************************************************************/ + + void TraceManager::Input(vint32_t currentTokenIndex, vint32_t token, vint32_t lookAhead) + { + CHECK_ERROR(state == TraceManagerState::WaitingForInput, L"vl::glr::automaton::TraceManager::Input(vint, vint)#Wrong timing to call this function."); + vint32_t traceCount = concurrentCount; + vint32_t input = Executable::TokenBegin + token; + + BeginSwap(); + + // for each surviving trace + // step one TokenInput transition + // followed by multiple and EndingInput, LeftrecInput and their combination + // one surviving trace could create multiple surviving trace + for (vint32_t traceIndex = 0; traceIndex < traceCount; traceIndex++) + { + auto trace = concurrentTraces->Get(traceIndex); + vint32_t transitionIndex = executable.GetTransitionIndex(trace->state, input); + auto&& edgeArray = executable.transitions[transitionIndex]; + WalkAlongTokenEdges(currentTokenIndex, input, lookAhead, trace, edgeArray); + } + + // if competitions happen between new surviving traces + // remove traces that known to have lost the competition + CheckBackupTracesBeforeSwapping(currentTokenIndex); + + EndSwap(); + + // if there are unused spaces in concurrentTraces + // set them to nullptr to clear out traces from the last round + for (vint32_t traceIndex = concurrentCount; traceIndex < concurrentTraces->Count(); traceIndex++) + { + concurrentTraces->Set(traceIndex, nullptr); + } + } + +/*********************************************************************** +EndOfInput +***********************************************************************/ + + void TraceManager::EndOfInput() + { + CHECK_ERROR(state == TraceManagerState::WaitingForInput, L"vl::glr::automaton::TraceManager::EndOfInput()#Wrong timing to call this function."); + state = TraceManagerState::Finished; + + vint32_t traceCount = concurrentCount; + BeginSwap(); + + // check all surviving traces and remove all that + // 1) does not stay in an ending state + // 2) return stack is not empty + // the remaining are all traces that successfully walked to the ending state of the root rule + for (vint32_t traceIndex = 0; traceIndex < traceCount; traceIndex++) + { + auto trace = concurrentTraces->Get(traceIndex); + auto& stateDesc = executable.states[trace->state]; + if (trace->returnStack == -1 && stateDesc.endingState) + { + AddTrace(trace); + } + } + + EndSwap(); + } + } + } +} + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER_INPUT_AMBIGUITY.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace automaton + { + +/*********************************************************************** +AreTwoTraceEqual +***********************************************************************/ + + bool TraceManager::AreTwoEndingInputTraceEqual(vint32_t state, vint32_t returnStack, vint32_t executedReturnStack, vint32_t acId, Trace* candidate) + { + // two traces equal to each other if + // 1) they are in the same state + // 2) they have the same executedReturnStack (and therefore the same returnStack) + // 3) they are attending same competitions + // 4) the candidate has an ending input + // TODO: verify if we can do "acId == candidate->runtimeRouting.attendingCompetitions" or not + + if (state != candidate->state) return false; + if (acId != candidate->competitionRouting.attendingCompetitions) return false; + if (candidate->byInput != Executable::EndingInput) return false; + + if (executedReturnStack != candidate->executedReturnStack) return false; + if (returnStack != candidate->returnStack) return false; + return true; + } + +/*********************************************************************** +GetInstructionPostfix +***********************************************************************/ + + vint32_t TraceManager::GetInstructionPostfix(EdgeDesc& oldEdge, EdgeDesc& newEdge) + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::GetInstructionPostfix(EdgeDesc&, EdgeDesc&)#" + // given two equal traces, calculate their common instruction postfix length in insBeforeInput + // EndObject is the last instruction of the prefix + + // EndObject may not be the first instruction in both edges + // and instructions before EndObject could be different + // the most common case is different {field = value} before EndObject + // if the ambiguity is created by two left recursive clauses which consume the same series of tokens + + CHECK_ERROR(oldEdge.insAfterInput.count == 0, ERROR_MESSAGE_PREFIX L"EndingInput edge is not allowed to have insAfterInput."); + CHECK_ERROR(newEdge.insAfterInput.count == 0, ERROR_MESSAGE_PREFIX L"EndingInput edge is not allowed to have insAfterInput."); + + // find the first EndObject instruction + vint32_t i1 = -1; + vint32_t i2 = -1; + + for (vint32_t insRef = 0; insRef < oldEdge.insBeforeInput.count; insRef++) + { + auto&& ins = executable.instructions[oldEdge.insBeforeInput.start + insRef]; + if (ins.type == AstInsType::EndObject) + { + i1 = insRef; + break; + } + } + + for (vint32_t insRef = 0; insRef < newEdge.insBeforeInput.count; insRef++) + { + auto&& ins = executable.instructions[newEdge.insBeforeInput.start + insRef]; + if (ins.type == AstInsType::EndObject) + { + i2 = insRef; + break; + } + } + + CHECK_ERROR(i1 != -1, ERROR_MESSAGE_PREFIX L"EndObject from oldEdge not found."); + CHECK_ERROR(i2 != -1, ERROR_MESSAGE_PREFIX L"EndObject from newEdge not found."); + + // ensure they have the same instruction postfix starting from EndObject + CHECK_ERROR(oldEdge.insBeforeInput.count - i1 == newEdge.insBeforeInput.count - i2, L"Two instruction postfix after EndObject not equal."); + + vint32_t postfix = oldEdge.insBeforeInput.count - i1 - 1; + for (vint32_t postfixRef = 0; postfixRef < postfix; postfixRef++) + { + auto&& ins1 = executable.instructions[oldEdge.insBeforeInput.start + i1 + 1 + postfixRef]; + auto&& ins2 = executable.instructions[newEdge.insBeforeInput.start + i2 + 1 + postfixRef]; + CHECK_ERROR(ins1 == ins2, L"Two instruction postfix after EndObject not equal."); + } + return postfix; +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +MergeTwoEndingInputTrace +***********************************************************************/ + + void TraceManager::MergeTwoEndingInputTrace( + Trace* trace, + Trace* ambiguityTraceToMerge, + vint32_t currentTokenIndex, + vint32_t input, + vint32_t byEdge, + EdgeDesc& edgeDesc, + vint32_t state, + vint32_t returnStack, + vint32_t attendingCompetitions, + vint32_t carriedCompetitions, + vint32_t executedReturnStack) + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::MergeTwoEndingInputTrace(...)#" + // if ambiguity resolving happens + // find the instruction postfix + // the instruction prefix ends at EndObject of a trace + // and both instruction postfix should equal + + // old == ambiguityTraceToMerge + // new == the trace that is being created (could skip) + auto& oldEdge = executable.edges[ambiguityTraceToMerge->byEdge]; + vint32_t oldInsCount = oldEdge.insBeforeInput.count + oldEdge.insAfterInput.count; + vint32_t newInsCount = edgeDesc.insBeforeInput.count + edgeDesc.insAfterInput.count; + vint32_t returnInsCount = 0; + vint32_t postfix = GetInstructionPostfix(oldEdge, edgeDesc); + + // if two state can merge + // then executedReturnStack == ambiguityTraceToMerge.executedReturnStack + // so two ReturnDesc.insAfterInput.count are identical + // and also instructions + if (executedReturnStack != -1) + { + auto rs = GetReturnStack(executedReturnStack); + auto& rd = executable.returns[rs->returnIndex]; + returnInsCount = rd.insAfterInput.count; + postfix += returnInsCount; + oldInsCount += returnInsCount; + newInsCount += returnInsCount; + } + + // a trace needs to be cut if EndObject is not its first instruction + bool needCut = oldInsCount > postfix + 1 || newInsCount > postfix + 1; + + if (ambiguityTraceToMerge->ambiguityMergeInsPostfix == -1 && needCut) + { + // append an extra trace after predecessors of ambiguityTraceToMerge + Trace* firstFormer = nullptr; + Trace* lastFormer = nullptr; + vint32_t predecessorId = ambiguityTraceToMerge->predecessors.first; + while (predecessorId != -1) + { + auto predecessor = GetTrace(predecessorId); + predecessorId = predecessor->predecessors.siblingNext; + + auto formerTrace = AllocateTrace(); + { + vint32_t formerId = formerTrace->allocatedIndex; + *formerTrace = *ambiguityTraceToMerge; + formerTrace->allocatedIndex = formerId; + } + + // connect predecessor and formerTrace + formerTrace->predecessors.first = predecessor->allocatedIndex; + formerTrace->predecessors.last = predecessor->allocatedIndex; + formerTrace->predecessors.siblingPrev = -1; + formerTrace->predecessors.siblingNext = -1; + + // connect ambiguityTraceToMerge and formerTrace + if (firstFormer == nullptr) + { + firstFormer = formerTrace; + lastFormer = formerTrace; + } + else + { + lastFormer->predecessors.siblingNext = formerTrace->allocatedIndex; + formerTrace->predecessors.siblingPrev = lastFormer->allocatedIndex; + lastFormer = formerTrace; + } + + // executedReturnStack is from the EndObject instruction + // which is available in the instruction postfix + // so formerTrace->executedReturnStack should be -1 and keep the previous return stack + formerTrace->executedReturnStack = -1; + formerTrace->returnStack = predecessor->returnStack; + + // ambiguity is filled by PrepareTraceRoute, skipped + // runtimeRouting.holdingCompetition always belong to the second trace + // runtimeRouting.attendingCompetitions is inherited + // runtimeRouting.carriedCompetitions is inherited + formerTrace->competitionRouting = {}; + formerTrace->competitionRouting.attendingCompetitions = ambiguityTraceToMerge->competitionRouting.attendingCompetitions; + formerTrace->competitionRouting.carriedCompetitions = ambiguityTraceToMerge->competitionRouting.carriedCompetitions; + + // both traces need to have the same postfix + // since formerTrace doesn't have executedReturnStack but ambiguityTraceToMerge has + // the amount of returnInsCount need to cut from the postfix + formerTrace->ambiguityBranchInsPostfix = postfix - returnInsCount; + } + + ambiguityTraceToMerge->ambiguityMergeInsPostfix = postfix; + ambiguityTraceToMerge->predecessors.first = firstFormer->allocatedIndex; + ambiguityTraceToMerge->predecessors.last = lastFormer->allocatedIndex; + } + + if (needCut) + { + // otherwise, create a new trace with the instruction prefix + auto newTrace = AllocateTrace(); + AddTraceToCollection(newTrace, trace, &Trace::predecessors); + newTrace->state = state; + newTrace->returnStack = returnStack; + newTrace->byEdge = byEdge; + newTrace->byInput = input; + newTrace->currentTokenIndex = currentTokenIndex; + + // executedReturnStack == ambiguityTraceToMerge->executedReturnStack is ensured + // so no need to assign executedReturnStack to newTrace + // acid == ambiguityTraceToMerge->runtimeRouting.attendingCompetitions is ensure + // this is affected by TODO: in TraceManager::AreTwoEndingInputTraceEqual + // and ambiguityTraceToMerge is supposed to inherit this value + newTrace->competitionRouting.attendingCompetitions = attendingCompetitions; + newTrace->competitionRouting.carriedCompetitions = carriedCompetitions; + + // both traces need to have the same postfix + // since newTrace doesn't have executedReturnStack but ambiguityTraceToMerge has + // the amount of returnInsCount need to cut from the postfix + newTrace->ambiguityBranchInsPostfix = postfix - returnInsCount; + + AddTraceToCollection(ambiguityTraceToMerge, newTrace, &Trace::predecessors); + } + else + { + // if EndObject is the first instruction of the new trace + // then no need to create the new trace + AddTraceToCollection(ambiguityTraceToMerge, trace, &Trace::predecessors); + } +#undef ERROR_MESSAGE_PREFIX + } + } + } +} + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER_INPUT_COMPETITION.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace automaton + { + +/*********************************************************************** +AttendCompetition +***********************************************************************/ + + void TraceManager::AttendCompetition(Trace* trace, vint32_t& newAttendingCompetitions, vint32_t& newCarriedCompetitions, vint32_t returnStack, vint32_t ruleId, vint32_t clauseId, bool forHighPriority) + { + // a competition is defined by its rule, clause and the owner trace + // but we don't need to compare the trace + // since only transitions starting from that trace will search competitions in that trace + // we only create a new Competition object if it has not been created for the trace yet + Competition* competition = nullptr; + { + vint32_t cid = trace->competitionRouting.holdingCompetitions; + while (cid != -1) + { + auto cpt = GetCompetition(cid); + if (cpt->ruleId == ruleId && cpt->clauseId == clauseId) + { + competition = cpt; + break; + } + cid = cpt->nextHoldCompetition; + } + } + + if (!competition) + { + // create a Competition object + competition = AllocateCompetition(); + competition->nextHoldCompetition = trace->competitionRouting.holdingCompetitions; + trace->competitionRouting.holdingCompetitions = competition->allocatedIndex; + + competition->currentTokenIndex = trace->currentTokenIndex; + competition->ruleId = ruleId; + competition->clauseId = clauseId; + + competition->nextActiveCompetition = activeCompetitions; + activeCompetitions = competition->allocatedIndex; + } + + // target traces from the current trace could attend different competitions + // but they also inherit all attending competitions from the current trace + // it is fine for different traces share all or part of AttendingCompetitions in their RuntimeRouting::attendingCompetitions linked list + // because if a competition is settled in the future + // AttendingCompetitions objects for this competition is going to be removed anyway + // sharing a linked list doesn't change the result + + auto ac = AllocateAttendingCompetitions(); + ac->competition = competition->allocatedIndex; + ac->forHighPriority = forHighPriority; + ac->returnStack = returnStack; + + ac->nextActiveAC = newAttendingCompetitions; + newAttendingCompetitions = ac->allocatedIndex; + + ac->nextCarriedAC = newCarriedCompetitions; + newCarriedCompetitions = ac->allocatedIndex; + } + +/*********************************************************************** +AttendCompetitionIfNecessary +***********************************************************************/ + + ReturnStack* TraceManager::PushReturnStack(vint32_t base, vint32_t returnIndex, vint32_t currentTokenIndex) + { + auto siblings = base == -1 ? &initialReturnStackSuccessors : &GetReturnStack(base)->successors; + + if (siblings->successorTokenIndex == -1 && currentTokenIndex - siblings->createdTokenIndex <= 1) + { + siblings->successorTokenIndex = currentTokenIndex; + } + + if (siblings->successorTokenIndex == currentTokenIndex) + { + vint32_t successorId = siblings->first; + while (successorId != -1) + { + auto successor = GetReturnStack(successorId); + successorId = successor->successors.next; + + if (successor->returnIndex == returnIndex) + { + return successor; + } + } + } + + auto returnStack = AllocateReturnStack(); + returnStack->previous = base; + returnStack->returnIndex = returnIndex; + returnStack->successors.createdTokenIndex = currentTokenIndex; + + if (siblings->successorTokenIndex == currentTokenIndex) + { + if (siblings->first == -1) + { + siblings->first = returnStack->allocatedIndex; + siblings->last = returnStack->allocatedIndex; + } + else + { + GetReturnStack(siblings->last)->successors.next = returnStack->allocatedIndex; + returnStack->successors.prev = siblings->last; + siblings->last = returnStack->allocatedIndex; + } + } + return returnStack; + } + +/*********************************************************************** +AttendCompetitionIfNecessary +***********************************************************************/ + + void TraceManager::AttendCompetitionIfNecessary(Trace* trace, vint32_t currentTokenIndex, EdgeDesc& edgeDesc, vint32_t& newAttendingCompetitions, vint32_t& newCarriedCompetitions, vint32_t& newReturnStack) + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::AttendCompetitionIfNecessary(Trace*, EdgeDesc&, vint32_t&, vint32_t&)#" + newAttendingCompetitions = trace->competitionRouting.attendingCompetitions; + newCarriedCompetitions = trace->competitionRouting.carriedCompetitions; + newReturnStack = trace->returnStack; + + // visit each compact transition in order + // 1) returns + token + // 2) ending + // 3) leftrec + // find out if any of them attends a competition + + vint32_t edgeFromState = edgeDesc.fromState; + for (vint32_t returnRef = 0; returnRef < edgeDesc.returnIndices.count; returnRef++) + { + auto returnIndex = executable.returnIndices[edgeDesc.returnIndices.start + returnRef]; + auto&& returnDesc = executable.returns[returnIndex]; + + if (returnDesc.priority != EdgePriority::NoCompetition) + { + // attend a competition from a ReturnDesc edge + // find out the rule id and the clause id for this competition + // a ReturnDesc is a compact transition which consumes a rule + // so it does not points to the ending state + // therefore we just need the toState of this ReturnDesc for reference + auto&& stateForClause = executable.states[returnDesc.returnState]; + vint32_t competitionRule = stateForClause.rule; + vint32_t competitionClause = stateForClause.clause; + CHECK_ERROR(competitionRule != -1 && competitionClause != -1, ERROR_MESSAGE_PREFIX L"Illegal rule or clause id."); + AttendCompetition(trace, newAttendingCompetitions, newCarriedCompetitions, newReturnStack, competitionRule, competitionClause, returnDesc.priority == EdgePriority::HighPriority); + } + + // push this ReturnDesc to the ReturnStack + newReturnStack = PushReturnStack(newReturnStack, returnIndex, currentTokenIndex)->allocatedIndex; + edgeFromState = executable.ruleStartStates[returnDesc.consumedRule]; + } + + if (edgeDesc.priority != EdgePriority::NoCompetition) + { + // attend a competition from a EdgeDesc edge + // find out the rule id and the clause id for this competition + auto&& fromState = executable.states[edgeFromState]; + auto&& toState = executable.states[edgeDesc.toState]; + vint32_t competitionRule = toState.rule; + vint32_t competitionClause = toState.clause; + if (toState.endingState) + { + competitionRule = fromState.rule; + competitionClause = fromState.clause; + } + CHECK_ERROR(competitionRule != -1 && competitionClause != -1, ERROR_MESSAGE_PREFIX L"Illegal rule or clause id."); + AttendCompetition(trace, newAttendingCompetitions, newCarriedCompetitions, newReturnStack, competitionRule, competitionClause, edgeDesc.priority == EdgePriority::HighPriority); + } +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +CheckAttendingCompetitionsOnEndingEdge +***********************************************************************/ + + void TraceManager::CheckAttendingCompetitionsOnEndingEdge(Trace* trace, EdgeDesc& edgeDesc, vint32_t acId, vint32_t returnStack) + { + while (acId != -1) + { + // when executing an EndingInput transition, we announce high priority win a competition if + // 1) such EndingInput transitions ends the clause, and the state of the trace holding competition belongs to the same clause + // we ensure this by comparing rule id, clause id in Competition + // and compare ReturnStack object (not content) in AttendingCompetitions + // the reason returnStack is not in Competition is that + // different transitions always create new ReturnStack objects + // 2) this trace bets high + // 3) the competition has not been settled + auto ac = GetAttendingCompetitions(acId); + if (ac->returnStack == returnStack) + { + auto cpt = GetCompetition(ac->competition); + // ensure that this EndingInput edge and the competition belong to the same clause + auto&& stateDesc = executable.states[edgeDesc.fromState]; + if (cpt->ruleId == stateDesc.rule && cpt->clauseId == stateDesc.clause) + { + // check if it is a high bet + if (ac->forHighPriority && cpt->status == CompetitionStatus::Holding) + { + cpt->status = CompetitionStatus::HighPriorityWin; + } + } + } + acId = ac->nextActiveAC; + } + } + +/*********************************************************************** +CheckBackupTracesBeforeSwapping +***********************************************************************/ + + void TraceManager::CheckBackupTracesBeforeSwapping(vint32_t currentTokenIndex) + { + // try to find if any competition could be settled at this moment + + { + // reset highCounter and lowCounter for any active competitions + auto cId = activeCompetitions; + while (cId != -1) + { + auto cpt = GetCompetition(cId); + cpt->highCounter = 0; + cpt->lowCounter = 0; + cId = cpt->nextActiveCompetition; + } + } + + // for any surviving traces + // add itself to the appriopriate counter for all attending competitions + for (vint i = 0; i < concurrentCount; i++) + { + auto trace = backupTraces->Get(i); + auto acId = trace->competitionRouting.attendingCompetitions; + while (acId != -1) + { + auto ac = GetAttendingCompetitions(acId); + auto cpt = GetCompetition(ac->competition); + (ac->forHighPriority ? cpt->highCounter : cpt->lowCounter)++; + acId = ac->nextActiveAC; + } + } + + // revisit all active competitions + // some competitions could have been settled + // but settled competitions will only be removed before consuming the next token + { + auto cId = activeCompetitions; + while (cId != -1) + { + auto cpt = GetCompetition(cId); + if (cpt->status == CompetitionStatus::Holding) + { + if (cpt->highCounter > 0 && cpt->lowCounter == 0) + { + // if only high bet traces survive, high priority win + cpt->status = CompetitionStatus::HighPriorityWin; + } + else if (cpt->highCounter == 0 && cpt->lowCounter > 0) + { + // if only low bet traces survive + // low priority win after at least one token is consumed from when the competition is created + // low priority epsilon transitions could have been visited right after a competition is created + // but high priority token transitions could only be visited when consuming the next token + // if all high priority transitions are token transitions + // and all low priority transitions are epsilon transitions + // closing the competition too early will direct to a wrong result + // so we need to wait at least one step to see if any trace will visit the high priority transition in the future + if (cpt->currentTokenIndex != currentTokenIndex) + { + cpt->status = CompetitionStatus::LowPriorityWin; + } + } + } + cId = cpt->nextActiveCompetition; + } + } + + // for any surviving traces + // if it loses any one of its attending competitions + // this trace will be removed + for (vint i = concurrentCount - 1; i >= 0; i--) + { + auto trace = backupTraces->Get(i); + auto acId = trace->competitionRouting.attendingCompetitions; + while (acId != -1) + { + auto ac = GetAttendingCompetitions(acId); + auto cpt = GetCompetition(ac->competition); + if (cpt->status != CompetitionStatus::Holding) + { + ac->closed = true; + if (ac->forHighPriority != (cpt->status == CompetitionStatus::HighPriorityWin)) + { + concurrentCount--; + backupTraces->RemoveAt(i); + goto TRACE_REMOVED; + } + } + acId = ac->nextActiveAC; + } + TRACE_REMOVED:; + } + + // remove all settled competition from the active competitions linked list + { + vint32_t* pnext = &activeCompetitions; + while (*pnext != -1) + { + auto cpt = GetCompetition(*pnext); + if (cpt->status != CompetitionStatus::Holding || (cpt->highCounter == 0 && cpt->lowCounter == 0)) + { + *pnext = cpt->nextActiveCompetition; + } + else + { + pnext = &cpt->nextActiveCompetition; + } + } + } + + // remove all settled AttendingCompetitions object from linked lists of any surviving trace + for (vint i = 0; i < concurrentCount; i++) + { + auto trace = backupTraces->Get(i); + vint32_t* pnext = &trace->competitionRouting.attendingCompetitions; + while (*pnext != -1) + { + auto ac = GetAttendingCompetitions(*pnext); + if (ac->closed) + { + *pnext = ac->nextActiveAC; + } + else + { + pnext = &ac->nextActiveAC; + } + } + } + } + } + } +} + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER_INPUT_WALK.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace automaton + { + +/*********************************************************************** +TraceManager::WalkAlongSingleEdge +***********************************************************************/ + + Trace* TraceManager::WalkAlongSingleEdge( + vint32_t currentTokenIndex, + vint32_t input, + Trace* trace, + vint32_t byEdge, + EdgeDesc& edgeDesc + ) + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::WalkAlongSingleEdge(vint, vint, vint, Trace*, vint, EdgeDesc&)#" + vint32_t state = edgeDesc.toState; + vint32_t returnStack = -1; + vint32_t attendingCompetitions = -1; + vint32_t carriedCompetitions = -1; + vint32_t executedReturnStack = -1; + Trace* ambiguityTraceToMerge = nullptr; + + // attend a competition hold by the current trace if the priority is set for this output transition + AttendCompetitionIfNecessary(trace, currentTokenIndex, edgeDesc, attendingCompetitions, carriedCompetitions, returnStack); + + if (input == Executable::EndingInput) + { + // an EndingInput transition consume return record in the return stack + // such return will be popped from the return stack and stored in Trace::executedReturnStack + CHECK_ERROR(edgeDesc.returnIndices.count == 0, ERROR_MESSAGE_PREFIX L"Ending input edge is not allowed to push something into the return stack."); + if (returnStack != -1) + { + executedReturnStack = returnStack; + auto rs = GetReturnStack(returnStack); + returnStack = rs->previous; + state = executable.returns[rs->returnIndex].returnState; + } + + // an EndingInput transition also settle a competition if + // 1) there is a competition + // 2) the returnStack of the trace holding the competition is the same to the current returnStack + // 3) the target trace bets high priority + // in this case, high priority traces wins the competition + // but no traces are being removed for now, just mark the competition + CheckAttendingCompetitionsOnEndingEdge(trace, edgeDesc, attendingCompetitions, trace->returnStack); + + // if the target trace has exactly the same to another surviving trace + // stop creating a Trace instance for the target trace + // instead connect the correct trace to that surviving trace and form a ambiguity resolving structure + for (vint i = 0; i < concurrentCount; i++) + { + auto candidate = backupTraces->Get(i); + if (AreTwoEndingInputTraceEqual(state, returnStack, executedReturnStack, attendingCompetitions, candidate)) + { + ambiguityTraceToMerge = candidate; + break; + } + } + } + + if (ambiguityTraceToMerge) + { + MergeTwoEndingInputTrace( + trace, + ambiguityTraceToMerge, + currentTokenIndex, + input, + byEdge, + edgeDesc, + state, + returnStack, + attendingCompetitions, + carriedCompetitions, + executedReturnStack); + + // return nullptr so that there is no WalkAlongEpsilonEdges following WalkAlongSingleEdge + return nullptr; + } + else + { + // if ambiguity resolving doesn't happen + // create an instance of the target trace + // and connect the current trace to this target trace + auto newTrace = AllocateTrace(); + AddTrace(newTrace); + AddTraceToCollection(newTrace, trace, &Trace::predecessors); + newTrace->state = state; + newTrace->returnStack = returnStack; + newTrace->executedReturnStack = executedReturnStack; + newTrace->byEdge = byEdge; + newTrace->byInput = input; + newTrace->currentTokenIndex = currentTokenIndex; + newTrace->competitionRouting.attendingCompetitions = attendingCompetitions; + newTrace->competitionRouting.carriedCompetitions = carriedCompetitions; + + return newTrace; + } +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +TraceManager::WalkAlongEpsilonEdges +***********************************************************************/ + + void TraceManager::WalkAlongLeftrecEdges( + vint32_t currentTokenIndex, + vint32_t lookAhead, + Trace* trace, + EdgeArray& edgeArray + ) + { + // if there is no more token + // then it is not possible for more left recursions + if (lookAhead == -1) return; + + for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++) + { + vint32_t byEdge = edgeArray.start + edgeRef; + auto& edgeDesc = executable.edges[byEdge]; + + // see if the target state could consume that token + vint32_t lookAheadTransitionIndex = executable.GetTransitionIndex(edgeDesc.toState, Executable::TokenBegin + lookAhead); + auto& lookAheadEdgeArray = executable.transitions[lookAheadTransitionIndex]; + if (lookAheadEdgeArray.count == 0) continue; + + // proceed only if it can + WalkAlongSingleEdge(currentTokenIndex, Executable::LeftrecInput, trace, byEdge, edgeDesc); + + // A LeftrecInput transition points to a non ending state in another clause + // so there is no need to find other epsilon transitions after LeftrecInput + } + } + + void TraceManager::WalkAlongEpsilonEdges( + vint32_t currentTokenIndex, + vint32_t lookAhead, + Trace* trace + ) + { + // if we could walk along multiple EndingInput transition + // but the last several transition will fail + // then creating them is wasting the performance + // so we count how many EndingInput transition we could walk along first + + vint32_t endingCount = -1; + + if (lookAhead == -1) + { + // if there is no more tokens + // then we have to go all the way to the end anyway + vint32_t currentState = trace->state; + vint32_t currentReturnStack = trace->returnStack; + + while (currentState != -1) + { + vint32_t transitionIndex = executable.GetTransitionIndex(currentState, Executable::EndingInput); + auto&& edgeArray = executable.transitions[transitionIndex]; + + // at most one EndingInput transition could exist from any state + CHECK_ERROR(edgeArray.count < 2, L"vl::glr::automaton::TraceManager::WalkAlongEpsilonEdges(vint32_t, vint32_t, Trace*)#Too many EndingInput transitions."); + + if (edgeArray.count == 0) + { + // if there is no more EndingInput to go + // and the current state is not an ending state + // then we just give up + + auto&& stateDesc = executable.states[currentState]; + if (stateDesc.endingState) + { + currentState = -1; + } + else + { + return; + } + } + else if (currentReturnStack == -1) + { + vint32_t byEdge = edgeArray.start; + auto& edgeDesc = executable.edges[byEdge]; + currentState = edgeDesc.toState; + } + else + { + auto rs = GetReturnStack(currentReturnStack); + currentReturnStack = rs->previous; + currentState = executable.returns[rs->returnIndex].returnState; + } + } + } + else + { + // otherwise we see how many EndingInput transition we need to walk along + vint32_t currentCount = 0; + vint32_t currentState = trace->state; + vint32_t currentReturnStack = trace->returnStack; + + while (currentState != -1) + { + currentCount++; + + // try LeftrecInput + lookAhead + { + vint32_t transitionIndex = executable.GetTransitionIndex(currentState, Executable::LeftrecInput); + auto&& edgeArray = executable.transitions[transitionIndex]; + for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++) + { + vint32_t byEdge = edgeArray.start + edgeRef; + auto& edgeDesc = executable.edges[byEdge]; + vint32_t lookAheadTransitionIndex = executable.GetTransitionIndex(edgeDesc.toState, Executable::TokenBegin + lookAhead); + auto& lookAheadEdgeArray = executable.transitions[lookAheadTransitionIndex]; + + // mark this EndingInput if any LeftrecInput + lookAhead transition exists + if (lookAheadEdgeArray.count > 0) + { + endingCount = currentCount; + goto TRY_ENDING_INPUT; + } + } + } + + // try lookAhead + { + vint32_t transitionIndex = executable.GetTransitionIndex(currentState, Executable::TokenBegin + lookAhead); + auto&& edgeArray = executable.transitions[transitionIndex]; + + // mark this EndingInput if lookAhead transition exists + if (edgeArray.count > 0) + { + endingCount = currentCount; + } + } + + // try EndingInput + TRY_ENDING_INPUT: + { + vint32_t transitionIndex = executable.GetTransitionIndex(currentState, Executable::EndingInput); + auto&& edgeArray = executable.transitions[transitionIndex]; + + // at most one EndingInput transition could exist from any state + CHECK_ERROR(edgeArray.count < 2, L"vl::glr::automaton::TraceManager::WalkAlongEpsilonEdges(vint32_t, vint32_t, Trace*)#Too many EndingInput transitions."); + + if (edgeArray.count == 0 || currentReturnStack == -1) + { + // currentReturnStack == -1 means this is the last possible EndingInput + // no need to test forward + // because if the current EndingInput is doable + // it would have already been marked + currentState = -1; + } + else + { + auto rs = GetReturnStack(currentReturnStack); + currentReturnStack = rs->previous; + currentState = executable.returns[rs->returnIndex].returnState; + } + } + } + } + + for (vint32_t i = 0; trace && (i < endingCount || endingCount == -1); i++) + { + { + // LeftrecInput transition is an epsilon transition + vint32_t transitionIndex = executable.GetTransitionIndex(trace->state, Executable::LeftrecInput); + auto&& edgeArray = executable.transitions[transitionIndex]; + WalkAlongLeftrecEdges(currentTokenIndex, lookAhead, trace, edgeArray); + } + + // EndingInput transition is an epsilon transition + vint32_t transitionIndex = executable.GetTransitionIndex(trace->state, Executable::EndingInput); + auto&& edgeArray = executable.transitions[transitionIndex]; + + // it has been ensured that edgeArray.count < 2 + if (edgeArray.count == 0) + { + trace = nullptr; + } + else + { + vint32_t byEdge = edgeArray.start; + auto& edgeDesc = executable.edges[byEdge]; + trace = WalkAlongSingleEdge(currentTokenIndex, Executable::EndingInput, trace, byEdge, edgeDesc); + + // EndingInput could be followed by EndingInput or LeftrecInput + } + } + } + +/*********************************************************************** +TraceManager::WalkAlongTokenEdges +***********************************************************************/ + + void TraceManager::WalkAlongTokenEdges( + vint32_t currentTokenIndex, + vint32_t input, + vint32_t lookAhead, + Trace* trace, + EdgeArray& edgeArray + ) + { + // find all transitions that has the expected input + // there could be multiple transitions with the same input + // but with different instructions and destinations + for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++) + { + vint32_t byEdge = edgeArray.start + edgeRef; + auto& edgeDesc = executable.edges[edgeArray.start + edgeRef]; + if (auto newTrace = WalkAlongSingleEdge(currentTokenIndex, input, trace, byEdge, edgeDesc)) + { + // continue with as much EndingInput and LeftrecInput transitions as possible + // TokenInput could be followed by EndingInput or LeftrecInput + WalkAlongEpsilonEdges(currentTokenIndex, lookAhead, newTrace); + } + } + } + } + } +} + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER_PREPARETRACEROUTE.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace automaton + { + using namespace collections; + +/*********************************************************************** +ReadInstructionList +***********************************************************************/ + + void TraceManager::ReadInstructionList(Trace* trace, TraceInsLists& insLists) + { + // this function collects the following instructions in order: + // 1) byEdge.insBeforeInput + // 2) byEdge.insAfterInput + // 3) executedReturnStack.returnIndex.insAfterInput in order + if (trace->byEdge != -1) + { + auto& edgeDesc = executable.edges[trace->byEdge]; + insLists.edgeInsBeforeInput = edgeDesc.insBeforeInput; + insLists.edgeInsAfterInput = edgeDesc.insAfterInput; + } + else + { + insLists.edgeInsBeforeInput = {}; + insLists.edgeInsAfterInput = {}; + } + if (trace->executedReturnStack != -1) + { + auto returnStack = GetReturnStack(trace->executedReturnStack); + auto& returnDesc = executable.returns[returnStack->returnIndex]; + insLists.returnInsAfterInput = returnDesc.insAfterInput; + } + else + { + insLists.returnInsAfterInput = {}; + } + + insLists.c1 = (vint32_t)(insLists.edgeInsBeforeInput.count); + insLists.c2 = (vint32_t)(insLists.c1 + insLists.edgeInsAfterInput.count); + insLists.c3 = (vint32_t)(insLists.c2 + insLists.returnInsAfterInput.count); + } + +/*********************************************************************** +ReadInstruction +***********************************************************************/ + + AstIns& TraceManager::ReadInstruction(vint32_t instruction, TraceInsLists& insLists) + { + // access the instruction object from a trace + // the index is the instruction in a virtual instruction array + // defined by all InstructionArray in TraceInsLists combined together +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::ReadInstruction(vint, TraceInsLists&)#" + CHECK_ERROR(0 <= instruction && instruction <= insLists.c3, ERROR_MESSAGE_PREFIX L"Instruction index out of range."); + + vint insRef = -1; + if (instruction < insLists.c1) + { + insRef = insLists.edgeInsBeforeInput.start + instruction; + } + else if (instruction < insLists.c2) + { + insRef = insLists.edgeInsAfterInput.start + (instruction - insLists.c1); + } + else if (instruction < insLists.c3) + { + insRef = insLists.returnInsAfterInput.start + (instruction - insLists.c2); + } + else + { + CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Instruction index out of range."); + } + + return executable.instructions[insRef]; +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +RunInstruction +***********************************************************************/ + + bool TraceManager::RunInstruction(vint32_t instruction, TraceInsLists& insLists, vint32_t& objectCount, vint32_t& reopenCount) + { + // run an instruction to simulate the number of extra constructing AST objects in the stack +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::SearchSingleTraceForBeginObject(Trace*&, vint&, vint&)#" + auto& ins = ReadInstruction(instruction, insLists); + switch (ins.type) + { + case AstInsType::EndObject: + objectCount++; + break; + case AstInsType::ReopenObject: + case AstInsType::BeginObject: + case AstInsType::BeginObjectLeftRecursive: + CHECK_ERROR(objectCount > 0, ERROR_MESSAGE_PREFIX L"Encountered unbalanced instructions."); + objectCount--; + break; + } + + switch (ins.type) + { + case AstInsType::ReopenObject: + reopenCount++; + break; + case AstInsType::DelayFieldAssignment: + reopenCount--; + break; + } + + // if we found a ReopenObject + // we should continue to search until we reach BeginObject or BeginObjectLeftRecursive + return objectCount == 0 && (ins.type == AstInsType::BeginObject || ins.type == AstInsType::BeginObjectLeftRecursive); +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +AdjustToRealTrace +***********************************************************************/ + + void TraceManager::AdjustToRealTrace(SharedBeginObject& shared) + { + TraceInsLists insLists; + ReadInstructionList(shared.traceBeginObject, insLists); + if (shared.insBeginObject >= insLists.c3) + { + shared.traceBeginObject = GetTrace(shared.traceBeginObject->successors.first); + shared.insBeginObject -= insLists.c3; + } + } + +/*********************************************************************** +FindBalancedBoOrBolr +***********************************************************************/ + + void TraceManager::FindBalancedBoOrBolr(SharedBeginObject& balanced, vint32_t& objectCount, vint32_t& reopenCount) + { + // given the current instruction and the current constructing AST objects + // find the nearlest BeginObject or BeginObjectLeftRecursive before the current instruction + // that creates the bottom object +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::FindBalancedBoOrBolr(Trace*&, vint&, vint&)#" + TraceInsLists insLists; + ReadInstructionList(balanced.traceBeginObject, insLists); + + while (true) + { + if (balanced.traceBeginObject->predecessors.first != balanced.traceBeginObject->predecessors.last) + { + // if there are multiple predecessors + // then this is a ambiguity resolving trace + auto ambiguityBegin = FillAmbiguityInfoForMergingTrace(balanced.traceBeginObject); + + // execute all instructions until it reaches the first EndObject instruction + // and this EndObject instruction is not executed + for (auto i = balanced.insBeginObject; i > balanced.traceBeginObject->ambiguity.insEndObject; i--) + { + if (RunInstruction(i, insLists, objectCount, reopenCount)) + { + balanced.insBeginObject = i; + return; + } + } + + // since the BeginObject instruction for this EndObject instruction will be executed after calling FillAmbiguityInfoForMergingTrace + // must jump to the instruction before that BeginObject instruction + + balanced = ambiguityBegin; + if (objectCount == 0) + { + return; + } + else + { + AdjustToRealTrace(balanced); + balanced.insBeginObject--; + ReadInstructionList(balanced.traceBeginObject, insLists); + } + } + else + { + // if there is only one predecessor + // run all instructions until we find the correct BeginObject or BeginObjectLeftRecursive instruction + + vint32_t minIns = 0; + vint32_t maxIns = insLists.c3; + if (balanced.traceBeginObject->ambiguityMergeInsPostfix != -1) + { + minIns = insLists.c3 - balanced.traceBeginObject->ambiguityMergeInsPostfix; + } + if (balanced.traceBeginObject->ambiguityBranchInsPostfix != -1) + { + maxIns = insLists.c3 - balanced.traceBeginObject->ambiguityBranchInsPostfix - 1; + } + if (balanced.insBeginObject > maxIns) + { + balanced.insBeginObject = maxIns; + } + + for (auto i = balanced.insBeginObject; i >= minIns; i--) + { + if (RunInstruction(i, insLists, objectCount, reopenCount)) + { + balanced.insBeginObject = i; + return; + } + } + + // if not found, then we continue searching in the predecessor trace + CHECK_ERROR(balanced.traceBeginObject->predecessors.first != -1, ERROR_MESSAGE_PREFIX L"Encountered unbalanced instructions."); + + balanced.traceBeginObject = GetTrace(balanced.traceBeginObject->predecessors.first); + ReadInstructionList(balanced.traceBeginObject, insLists); + balanced.insBeginObject = insLists.c3 - 1; + } + } +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +FindBalancedBoOrDfa +***********************************************************************/ + + void TraceManager::FindBalancedBoOrDfa(Trace* trace, vint32_t objectCount, SharedBeginObject& branch) + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::FindBalancedBoOrDfa(Trace*, vint32_t, Trace*&, vint32_t&, vint32_t&)#" + // find the first balanced BeginObject or BeginObjectLeftRecursive + TraceInsLists branchInsLists; + ReadInstructionList(trace, branchInsLists); + branch.traceBeginObject = trace; + branch.insBeginObject = branchInsLists.c3 - 1; + vint32_t branchObjectCount = objectCount; + vint32_t branchReopenCount = 0; + FindBalancedBoOrBolr(branch, branchObjectCount, branchReopenCount); + + // no matter if we found BeginObject or BeginObjectLeftRecursive + // we now know what type of the AST we need to resolve + AdjustToRealTrace(branch); + ReadInstructionList(branch.traceBeginObject, branchInsLists); + auto ins = ReadInstruction(branch.insBeginObject, branchInsLists); + branch.type = ins.param; + + // if we found a BeginObjectLeftRecursive which creates the bottom object in stack + // then we should continue until we reach the BeginObject + // because such BeginObject creates objects that eventually become part of BeginObjectLeftRecursive created objects + // we cannot allow sharing the same child AST object in different parent AST objects. + while (ins.type == AstInsType::BeginObjectLeftRecursive) + { + branch.insBeginObject--; + FindBalancedBoOrBolr(branch, branchObjectCount, branchReopenCount); + AdjustToRealTrace(branch); + ReadInstructionList(branch.traceBeginObject, branchInsLists); + ins = ReadInstruction(branch.insBeginObject, branchInsLists); + } + + // if branchReopenCount > 0 + // it means there must be this amount of DelayFieldAssignment instruction before BeginOpen + // the first DelayFieldAssignment must be located + if (branchReopenCount > 0) + { + ReadInstructionList(branch.traceBeginObject, branchInsLists); + while (true) + { + branch.insBeginObject--; + if (branch.insBeginObject == -1) + { + // a merging trace must at least have one EndObject before the balanced BeginObject + // so it is not possible to see it here + + CHECK_ERROR( + branch.traceBeginObject->predecessors.first == branch.traceBeginObject->predecessors.last, + ERROR_MESSAGE_PREFIX L"Unexpected merging trace when searching for DelayFieldAssignment." + ); + CHECK_ERROR( + branch.traceBeginObject->predecessors.first != -1, + ERROR_MESSAGE_PREFIX L"Unexpected root trace when searching for DelayFieldAssignment." + ); + + branch.traceBeginObject = GetTrace(branch.traceBeginObject->predecessors.first); + ReadInstructionList(branch.traceBeginObject, branchInsLists); + branch.insBeginObject = branchInsLists.c3; + } + else + { + auto& ins = ReadInstruction(branch.insBeginObject, branchInsLists); + switch (ins.type) + { + case AstInsType::EndObject: + // if we see EndObject, find its balanced BeginObject or BeginObjectLeftRecursive + FindBalancedBoOrBolr(branch, branchObjectCount, branchReopenCount); + AdjustToRealTrace(branch); + ReadInstructionList(branch.traceBeginObject, branchInsLists); + break; + case AstInsType::ReopenObject: + branchReopenCount++; + break; + case AstInsType::DelayFieldAssignment: + branchReopenCount--; + if (branchReopenCount == 0) + { + return; + } + break; + } + } + } + } +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +MergeAmbiguityType +***********************************************************************/ + + void TraceManager::MergeAmbiguityType(vint32_t& ambiguityType, vint32_t branchType) + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::MergeAmbiguityType(vint32_t&, vint32_t)#" + if (ambiguityType == -1) + { + ambiguityType = branchType; + } + else if (typeCallback) + { + vint32_t newType = typeCallback->FindCommonBaseClass(ambiguityType, branchType); + CHECK_ERROR(newType != -1, ERROR_MESSAGE_PREFIX L"Failed to merge from ambiguity types."); + ambiguityType = newType; + } + else + { + CHECK_ERROR(ambiguityType == branchType, ERROR_MESSAGE_PREFIX L"TraceManager::ITypeCallback is not installed, unable to merge from ambiguity types."); + } +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +MergeSharedBeginObjectsSingleRoot +***********************************************************************/ + + TraceManager::SharedBeginObject TraceManager::MergeSharedBeginObjectsSingleRoot(Trace* trace, collections::Dictionary& predecessorToBranches) + { + // predecessorToBranches.Count() == 1 + // it means all values in predecessorToBranches must be identical + +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::MergeSharedBeginObjectsSingleRoot(Trace*, Dictionary&)#" + SharedBeginObject shared; + vint32_t predecessorId = trace->predecessors.first; + while (predecessorId != -1) + { + auto predecessor = GetTrace(predecessorId); + auto branch = predecessorToBranches[predecessor]; + predecessorId = predecessor->predecessors.siblingNext; + + // BeginObject found from different predecessors must be the same + if (shared.traceBeginObject == nullptr) + { + shared = branch; + } + else + { + CHECK_ERROR(shared.traceBeginObject == branch.traceBeginObject && shared.insBeginObject == branch.insBeginObject, ERROR_MESSAGE_PREFIX L"BeginObject searched from different branches are not the same."); + } + } + + shared.type = -1; + return shared; +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +MergeSharedBeginObjectsMultipleRoot +***********************************************************************/ + + TraceManager::SharedBeginObject TraceManager::MergeSharedBeginObjectsMultipleRoot(Trace* trace, collections::Dictionary& predecessorToBranches) + { + // predecessorToBranches.Count() == number of predecessors + // it means all values in predecessorToBranches must be identical + // after they are adjusted to locate in the common predecessor + +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::MergeSharedBeginObjectsMultipleRoot(Trace*, Dictionary&)#" + SharedBeginObject shared; + vint32_t predecessorId = trace->predecessors.first; + + Trace* firstBranch = nullptr; + while (predecessorId != -1) + { + auto predecessor = GetTrace(predecessorId); + auto branch = predecessorToBranches[predecessor]; + predecessorId = predecessor->predecessors.siblingNext; + + if (firstBranch == nullptr) + { + firstBranch = branch.traceBeginObject; + } + Trace* currentBranch = branch.traceBeginObject; + + // adjust branch to locate in its predecessor + { + TraceInsLists parentInsLists; + Trace* parentTrace = GetTrace(branch.traceBeginObject->predecessors.first); + + ReadInstructionList(parentTrace, parentInsLists); + branch.traceBeginObject = parentTrace; + branch.insBeginObject += parentInsLists.c3; + } + + // multiple BeginObject must belong to successors of the same trace + // and the instructions prefix before these BeginObject must be identical + if (shared.traceBeginObject == nullptr) + { + shared = branch; + } + else + { +#define ERROR_MESSAGE ERROR_MESSAGE_PREFIX L"Failed to merge prefix from BeginObject of multiple successors." + CHECK_ERROR(shared.traceBeginObject == branch.traceBeginObject && shared.insBeginObject == branch.insBeginObject, ERROR_MESSAGE); + + TraceInsLists sharedInsLists, firstInsLists, currentInsLists; + ReadInstructionList(shared.traceBeginObject, sharedInsLists); + ReadInstructionList(firstBranch, firstInsLists); + ReadInstructionList(currentBranch, currentInsLists); + + vint32_t insBeginObject = shared.insBeginObject - sharedInsLists.c3; + CHECK_ERROR(insBeginObject < firstInsLists.c3, ERROR_MESSAGE); + CHECK_ERROR(insBeginObject < currentInsLists.c3, ERROR_MESSAGE); + + for (vint32_t i = 0; i < insBeginObject; i++) + { + auto& ins1 = ReadInstruction(i, firstInsLists); + auto& ins2 = ReadInstruction(i, currentInsLists); + CHECK_ERROR(ins1 == ins2, ERROR_MESSAGE); + } +#undef ERROR_MESSAGE + } + } + + shared.type = -1; + return shared; +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +MergeSharedBeginObjectsMultipleRoot +***********************************************************************/ + + TraceManager::SharedBeginObject TraceManager::MergeSharedBeginObjectsPartialMultipleRoot(Trace* trace, vint32_t ambiguityType, collections::Group& beginToPredecessors, collections::Dictionary& predecessorToBranches) + { + // some values in predecessorToBranches are the same but some are not + // the result is the same to one when all values in predecessorToBranches are different + // but we need to merge subset of predecessors which share the same value + +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::MergeSharedBeginObjectsPartialMultipleRoot(Trace*, vint32_t, Group&, Dictionary&)#" + vint32_t predecessorId = trace->predecessors.first; + while (predecessorId != -1) + { + auto predecessor = GetTrace(predecessorId); + auto branch = predecessorToBranches[predecessor]; + predecessorId = predecessor->predecessors.siblingNext; + + // we start with the first predecessor from all subset + auto& subset = beginToPredecessors[branch.traceBeginObject]; + if (subset.Count()==1 || predecessor != subset[0]) continue; + +#define ERROR_MESSAGE ERROR_MESSAGE_PREFIX L"Failed to merge prefix from BeginObject of multiple successors." + // ensure all value in the subset are identical + for (vint i = 1; i < subset.Count(); i++) + { + auto anotherBranch = predecessorToBranches[subset[i]]; + CHECK_ERROR(branch.traceBeginObject == anotherBranch.traceBeginObject && branch.insBeginObject == anotherBranch.insBeginObject, ERROR_MESSAGE); + } + + // ensure all predecessor in the subset are identical in their critical content + TraceInsLists insLists; + ReadInstructionList(predecessor, insLists); + for (vint i = 1; i < subset.Count(); i++) + { + auto anotherPredecessor = subset[i]; + CHECK_ERROR(predecessor->state == anotherPredecessor->state, ERROR_MESSAGE); + CHECK_ERROR(predecessor->byInput == anotherPredecessor->byInput, ERROR_MESSAGE); + CHECK_ERROR(predecessor->currentTokenIndex == anotherPredecessor->currentTokenIndex, ERROR_MESSAGE); + CHECK_ERROR(predecessor->returnStack == anotherPredecessor->returnStack, ERROR_MESSAGE); + + TraceInsLists anotherInsLists; + ReadInstructionList(anotherPredecessor, anotherInsLists); + CHECK_ERROR(insLists.c3 == anotherInsLists.c3, ERROR_MESSAGE); + for (vint32_t j = 0; j < insLists.c3; j++) + { + auto& ins1 = ReadInstruction(j, insLists); + auto& ins2 = ReadInstruction(j, anotherInsLists); + CHECK_ERROR(ins1 == ins2, ERROR_MESSAGE); + } + } + + // ensure all predecessor in the subset has only one predecessor + // otherwise we are replacing the current issue with another same issue + for (vint i = 0; i < subset.Count(); i++) + { + auto anotherPredecessor = subset[i]; + CHECK_ERROR(anotherPredecessor->predecessors.first == anotherPredecessor->predecessors.last, ERROR_MESSAGE); + } + + // connect all predecessors of predecessors in the subset to the first one + for (vint i = 1; i < subset.Count(); i++) + { + auto p1 = subset[i]; + auto p2 = GetTrace(p1->predecessors.first); + p2->successors = {}; + AddTraceToCollection(predecessor, p2, &Trace::predecessors); + AddTraceToCollection(p2, predecessor, &Trace::successors); + } + + // remove all predecessors in the subset except the first one + for (vint i = 1; i < subset.Count(); i++) + { + auto p = subset[i]; + if (p->predecessors.siblingPrev != -1) + { + GetTrace(p->predecessors.siblingPrev)->predecessors.siblingNext = p->predecessors.siblingNext; + } + if (p->predecessors.siblingNext != -1) + { + GetTrace(p->predecessors.siblingNext)->predecessors.siblingPrev = p->predecessors.siblingPrev; + } + if (trace->predecessors.first == p->allocatedIndex) + { + trace->predecessors.first = p->predecessors.siblingNext; + } + if (trace->predecessors.last == p->allocatedIndex) + { + trace->predecessors.last = p->predecessors.siblingPrev; + } + } + + // fix predecessor->ambiguity + predecessor->ambiguity.traceBeginObject = branch.traceBeginObject->allocatedIndex; + predecessor->ambiguity.insBeginObject = branch.insBeginObject; + predecessor->ambiguity.ambiguityType = ambiguityType; + + for (vint32_t i = 0; i < insLists.c3; i++) + { + auto& ins = ReadInstruction(i, insLists); + if (ins.type == AstInsType::EndObject) + { + predecessor->ambiguity.insEndObject = i; + break; + } + } + CHECK_ERROR(predecessor->ambiguity.insEndObject != -1, ERROR_MESSAGE); +#undef ERROR_MESSAGE + } + return MergeSharedBeginObjectsMultipleRoot(trace, predecessorToBranches); +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +FillAmbiguityInfoForMergingTrace +***********************************************************************/ + + TraceManager::SharedBeginObject TraceManager::FillAmbiguityInfoForMergingTrace(Trace* trace) + { + // assuming that this is a ambiguity resolving trace + // find the first instruction that accesses the object which is closed by the first EndObject in this trace + // such instruction must be BeginObject + // it is possible that the object closed by EndObject is created by a BeginObjectLeftRecursive + // in this case we need to keep searching + // until we find the BeginObject which creates the object that is consumed by BeginObjectLeftRecursive + // by executing from such BeginObject instead of BeginObjectLeftRecursive for all branches + // we prevent the object created by such BeginObject to be shared in multiple other objects + +#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::FillAmbiguityInfoForMergingTrace(Trace*)#" + // skip if the instruction has been found + if (trace->ambiguity.traceBeginObject != -1) + { + SharedBeginObject shared; + shared.traceBeginObject = GetTrace(trace->ambiguity.traceBeginObject); + shared.insBeginObject = trace->ambiguity.insBeginObject; + shared.type = trace->ambiguity.ambiguityType; + return shared; + } + + CHECK_ERROR(trace->predecessors.first != trace->predecessors.last, L"This function is not allowed to run on non-merging traces."); + + // find the first EndObject instruction + TraceInsLists insLists; + ReadInstructionList(trace, insLists); + + vint32_t insEndObject = -1; + for (vint32_t i = 0; i < insLists.c3; i++) + { + auto& ins = ReadInstruction(i, insLists); + if (ins.type == AstInsType::EndObject) + { + insEndObject = i; + break; + } + } + CHECK_ERROR(insEndObject != -1, ERROR_MESSAGE_PREFIX L"Cannot find EndObject instruction in the merging trace."); + if (trace->ambiguityMergeInsPostfix != -1) + { + CHECK_ERROR(insEndObject == insLists.c3 - trace->ambiguityMergeInsPostfix - 1, L"ambiguityMergeInsPostfix and insEndObject does not match."); + } + + vint32_t ambiguityType = -1; + Group beginToPredecessors; + Dictionary predecessorToBranches; + + // call FindBalancedBoOrBolr on all predecessors + auto predecessorId = trace->predecessors.first; + vint predecessorCount = 0; + while (predecessorId != -1) + { + predecessorCount++; + auto predecessor = GetTrace(predecessorId); + + SharedBeginObject branch; + if (trace->ambiguityMergeInsPostfix == -1) + { + // theoretically we need to run from EndObject to the first instruction + // but there will be nothing interested before EndObject + // so just set objectCount to 1 + FindBalancedBoOrDfa(predecessor, 1, branch); + } + else + { + // having a postfix means the predecessor is another half of this trace + // the EndObject instruction is in the predecessor + FindBalancedBoOrDfa(predecessor, 0, branch); + } + + beginToPredecessors.Add(branch.traceBeginObject, predecessor); + predecessorToBranches.Add(predecessor, branch); + + // if EndObject is not the first instruction + // then the all instruction prefix are stored in predecessors + // so no need to really touch the prefix in this trace. + + MergeAmbiguityType(ambiguityType, branch.type); + + predecessorId = predecessor->predecessors.siblingNext; + } + + SharedBeginObject shared; + if (beginToPredecessors.Count() == 1) + { + shared = MergeSharedBeginObjectsSingleRoot(trace, predecessorToBranches); + } + else if (beginToPredecessors.Count() == predecessorCount) + { + shared = MergeSharedBeginObjectsMultipleRoot(trace, predecessorToBranches); + } + else + { + shared = MergeSharedBeginObjectsPartialMultipleRoot(trace, ambiguityType, beginToPredecessors, predecessorToBranches); + } + + trace->ambiguity.insEndObject = insEndObject; + trace->ambiguity.insBeginObject = shared.insBeginObject; + trace->ambiguity.traceBeginObject = shared.traceBeginObject->allocatedIndex; + trace->ambiguity.ambiguityType = ambiguityType; + return shared; +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +FillAmbiguityInfoForPredecessorTraces +***********************************************************************/ + + void TraceManager::FillAmbiguityInfoForPredecessorTraces(Trace* trace) + { + // fill Trace::ambiguity in any traces that could be reached by the current trace + while (trace) + { + if (trace->predecessors.first != trace->predecessors.last) + { + // if an ambiguity resolving trace has been filled + // then we could stop here + // because a previous call should have visited from this trace all the way to the root trace + if (trace->ambiguity.traceBeginObject == -1) + { + FillAmbiguityInfoForMergingTrace(trace); + trace = GetTrace(trace->ambiguity.traceBeginObject); + } + else + { + break; + } + } + else + { + if (trace->predecessors.first == -1) break; + trace = GetTrace(trace->predecessors.first); + } + } + } + +/*********************************************************************** +CreateLastMergingTrace +***********************************************************************/ + + void TraceManager::CreateLastMergingTrace(Trace* rootTraceCandidate) + { + // if there are multiple surviving traces + // they are all EndingInput transition to the ending state + // and their last instruction are EndObject + // so we could merge every surviving trace to one + + // first, we need to determine the ambiguity type + vint32_t ambiguityType = -1; + for (vint i = 0; i < concurrentCount; i++) + { + auto trace = concurrentTraces->Get(i); + if (trace->predecessors.first == trace->predecessors.last) + { + // if this trace has only one predecessor + // find its BeginObject or BeginObjectLeftRecursive instruction for the type + TraceInsLists insLists; + ReadInstructionList(trace, insLists); + + SharedBeginObject balanced; + balanced.traceBeginObject = trace; + balanced.insBeginObject = insLists.c3 - 1; + vint32_t objectCount = 0; + vint32_t reopenCount = 0; + FindBalancedBoOrBolr(balanced, objectCount, reopenCount); + + AdjustToRealTrace(balanced); + ReadInstructionList(balanced.traceBeginObject, insLists); + auto ins = ReadInstruction(balanced.insBeginObject, insLists); + MergeAmbiguityType(ambiguityType, ins.param); + } + else + { + // otherwise, the type has been calculated before + MergeAmbiguityType(ambiguityType, trace->ambiguity.ambiguityType); + } + } + + // second, create a merging ending trace + // such merging ending trace has no instruction + // it just merges all ending traces + auto mergingTrace = AllocateTrace(); + for (vint i = 0; i < concurrentCount; i++) + { + auto trace = concurrentTraces->Get(i); + if (i == 0) + { + // copy data from the first one + mergingTrace->state = trace->state; + mergingTrace->byInput = trace->byInput; + mergingTrace->currentTokenIndex = trace->currentTokenIndex; + + // set the ambiguity data + // rootTraceCandidate has no instruction + // the first instructions of all successors are all we need + TraceInsLists insLists; + ReadInstructionList(mergingTrace, insLists); + mergingTrace->ambiguity.traceBeginObject = rootTraceCandidate->allocatedIndex; + mergingTrace->ambiguity.insBeginObject = 0; + mergingTrace->ambiguity.insEndObject = 0; + mergingTrace->ambiguity.ambiguityType = ambiguityType; + } + + AddTraceToCollection(mergingTrace, trace, &Trace::predecessors); + AddTraceToCollection(trace, mergingTrace, &Trace::successors); + } + + // finally, the new merging trace should be the only surviving trace + concurrentCount = 1; + concurrentTraces->Set(0, mergingTrace); + for (vint i = 1; i < concurrentTraces->Count(); i++) + { + concurrentTraces->Set(i, nullptr); + } + } + +/*********************************************************************** +PrepareTraceRoute +***********************************************************************/ + + Trace* TraceManager::PrepareTraceRoute() + { + if (state == TraceManagerState::PreparedTraceRoute) return initialTrace; + CHECK_ERROR(state == TraceManagerState::Finished, L"vl::glr::automaton::TraceManager::PrepareTraceRoute()#Wrong timing to call this function."); + state = TraceManagerState::PreparedTraceRoute; + + // we starts from all surviving traces + // and visit all predecessors + // until we reach the end + // so that we could skip all failed traces + + SortedList available; + List visited; + + for (vint i = 0; i < concurrentCount; i++) + { + auto trace = concurrentTraces->Get(i); + visited.Add(trace); + } + + for (vint i = 0; i < visited.Count(); i++) + { + auto visiting = visited[i]; + if (available.Contains(visiting)) continue; + available.Add(visiting); + + // add the current trace to its predecessors' successors collection + // so that a succeeded trace only have other succeeded successors in its successor collection + auto predecessorId = visiting->predecessors.first; + while (predecessorId != -1) + { + auto predecessor = GetTrace(predecessorId); + AddTraceToCollection(predecessor, visiting, &Trace::successors); + predecessorId = predecessor->predecessors.siblingNext; + visited.Add(predecessor); + } + } + + // find all ambiguity resolving traces and fill their Trace::ambiguity + for (vint i = 0; i < concurrentCount; i++) + { + auto trace = concurrentTraces->Get(i); + FillAmbiguityInfoForPredecessorTraces(trace); + } + + // if there are multiple surviving traces + // check if the ambiguity happens in the root AST + if (concurrentCount > 1) + { + CreateLastMergingTrace(initialTrace); + } + + return initialTrace; + } + } + } +} + +/*********************************************************************** +.\XML\GLRXML.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace xml + { + using namespace stream; + using namespace collections; + using namespace regex; + +/*********************************************************************** +XmlUnescapeVisitor +***********************************************************************/ + + class XmlUnescapeVisitor : public traverse_visitor::AstVisitor + { + protected: + List& tokens; + + public: + XmlUnescapeVisitor(List& _tokens) + :tokens(_tokens) + { + } + + protected: + void Traverse(XmlAttribute* node) override + { + node->value.value = XmlUnescapeValue(node->value.value.Sub(1, node->value.value.Length() - 2)); + } + + void Traverse(XmlCData* node) override + { + node->content.value = XmlUnescapeCData(node->content.value); + } + + void Traverse(XmlComment* node) override + { + node->content.value = XmlUnescapeComment(node->content.value); + } + + void Traverse(XmlElement* node) override + { + vint begin = -1; + vint end = -1; + for (vint i = node->subNodes.Count() - 1; i >= -1; i--) + { + if (i == -1) + { + if (end != -1) begin = 0; + } + else if (node->subNodes[i].Cast()) + { + if (end == -1) end = i; + } + else + { + if (end != -1) begin = i + 1; + } + if (begin != -1 && end != -1) + { + vint beginTokenIndex = node->subNodes[begin].Cast()->content.index; + vint endTokenIndex = node->subNodes[end].Cast()->content.index; + + auto& beginToken = tokens[beginTokenIndex]; + auto& endToken = tokens[endTokenIndex]; + + auto textBegin = beginToken.reading; + auto textEnd = endToken.reading + endToken.length; + + if (beginTokenIndex > 0) + { + auto& previousToken = tokens[beginTokenIndex - 1]; + textBegin = previousToken.reading + previousToken.length; + } + + if (endTokenIndex < tokens.Count() - 1) + { + auto& nextToken = tokens[endTokenIndex + 1]; + textEnd = nextToken.reading; + } + + WString text = WString::CopyFrom(textBegin, vint(textEnd - textBegin)); + ParsingTextRange range(&beginToken, &endToken); + + Ptr xmlText = new XmlText; + xmlText->codeRange = range; + xmlText->content.codeRange = range; + xmlText->content.value = XmlUnescapeValue(text); + + node->subNodes.RemoveRange(begin, end - begin + 1); + node->subNodes.Insert(begin, xmlText); + + begin = -1; + end = -1; + } + } + } + }; + +/*********************************************************************** +XmlPrintVisitor +***********************************************************************/ + + class XmlPrintVisitor : public Object, public XmlNode::IVisitor + { + public: + TextWriter& writer; + + XmlPrintVisitor(TextWriter& _writer) + :writer(_writer) + { + } + + void Visit(XmlText* node) + { + writer.WriteString(XmlEscapeValue(node->content.value)); + } + + void Visit(XmlCData* node) + { + writer.WriteString(XmlEscapeCData(node->content.value)); + } + + void Visit(XmlAttribute* node) + { + writer.WriteString(node->name.value); + writer.WriteString(L"=\""); + writer.WriteString(XmlEscapeValue(node->value.value)); + writer.WriteString(L"\""); + } + + void Visit(XmlComment* node) + { + writer.WriteString(XmlEscapeComment(node->content.value)); + } + + void Visit(XmlElement* node) + { + writer.WriteChar(L'<'); + writer.WriteString(node->name.value); + for (auto att : node->attributes) + { + writer.WriteChar(L' '); + Visit(att.Obj()); + } + if(node->subNodes.Count()==0) + { + writer.WriteString(L"/>"); + } + else + { + writer.WriteChar(L'>'); + for (auto subNode : node->subNodes) + { + subNode->Accept(this); + } + writer.WriteString(L"name.value); + writer.WriteChar(L'>'); + } + } + + void Visit(XmlInstruction* node) + { + writer.WriteString(L"name.value); + for (auto att : node->attributes) + { + writer.WriteChar(L' '); + Visit(att.Obj()); + } + writer.WriteString(L"?>"); + } + + void Visit(XmlDocument* node) + { + for (auto prolog : node->prologs) + { + prolog->Accept(this); + } + node->rootElement->Accept(this); + } + }; + +/*********************************************************************** +Escaping and Unescaping +***********************************************************************/ + + WString XmlEscapeValue(const WString& value) + { + WString result; + const wchar_t* reading = value.Buffer(); + while (wchar_t c = *reading++) + { + switch (c) + { + case L'<': + result += L"<"; + break; + case L'>': + result += L">"; + break; + case L'&': + result += L"&"; + break; + case L'\'': + result += L"'"; + break; + case L'\"': + result += L"""; + break; + default: + result += WString::FromChar(c); + } + } + return result; + } + + WString XmlUnescapeValue(const WString& value) + { + WString result; + const wchar_t* reading = value.Buffer(); + while (*reading) + { + if (wcsncmp(reading, L"<", 4) == 0) + { + result += WString::FromChar(L'<'); + reading += 4; + } + else if (wcsncmp(reading, L">", 4) == 0) + { + result += WString::FromChar(L'>'); + reading += 4; + } + else if (wcsncmp(reading, L"&", 5) == 0) + { + result += WString::FromChar(L'&'); + reading += 5; + } + else if (wcsncmp(reading, L"'", 6) == 0) + { + result += WString::FromChar(L'\''); + reading += 6; + } + else if (wcsncmp(reading, L""", 6) == 0) + { + result += WString::FromChar(L'\"'); + reading += 6; + } + else + { + result += WString::FromChar(*reading++); + } + } + return result; + } + + WString XmlEscapeCData(const WString& value) + { + return L""; + } + + WString XmlUnescapeCData(const WString& value) + { + return value.Sub(9, value.Length() - 12); + } + + WString XmlEscapeComment(const WString& value) + { + return L""; + } + + WString XmlUnescapeComment(const WString& value) + { + return value.Sub(4, value.Length() - 7); + } + +/*********************************************************************** +Parsing and Printing +***********************************************************************/ + + Ptr XmlParseDocument(const WString& input, const Parser& parser) + { + List tokens; + parser.Tokenize(input, tokens); + auto ast = parser.ParseXDocument(tokens); + XmlUnescapeVisitor(tokens).InspectInto(ast.Obj()); + return ast; + } + + Ptr XmlParseElement(const WString& input, const Parser& parser) + { + List tokens; + parser.Tokenize(input, tokens); + auto ast = parser.ParseXElement(tokens); + XmlUnescapeVisitor(tokens).InspectInto(ast.Obj()); + return ast; + } + + void XmlPrint(Ptr node, stream::TextWriter& writer) + { + XmlPrintVisitor visitor(writer); + node->Accept(&visitor); + } + + void XmlPrintContent(Ptr element, stream::TextWriter& writer) + { + XmlPrintVisitor visitor(writer); + for (auto node : element->subNodes) + { + node->Accept(&visitor); + } + } + + WString XmlToString(Ptr node) + { + return GenerateToStream([&](StreamWriter& writer) + { + XmlPrint(node, writer); + }); + } + +/*********************************************************************** +Utility +***********************************************************************/ + + Ptr XmlGetAttribute(Ptr element, const WString& name) + { + return XmlGetAttribute(element.Obj(), name); + } + + Ptr XmlGetElement(Ptr element, const WString& name) + { + return XmlGetElement(element.Obj(), name); + } + + collections::LazyList> XmlGetElements(Ptr element) + { + return XmlGetElements(element.Obj()); + } + + collections::LazyList> XmlGetElements(Ptr element, const WString& name) + { + return XmlGetElements(element.Obj(), name); + } + + WString XmlGetValue(Ptr element) + { + return XmlGetValue(element.Obj()); + } + + Ptr XmlGetAttribute(XmlElement* element, const WString& name) + { + for (auto att : element->attributes) + { + if (att->name.value == name) + { + return att; + } + } + return nullptr; + } + + Ptr XmlGetElement(XmlElement* element, const WString& name) + { + for (auto node : element->subNodes) + { + Ptr subElement = node.Cast(); + if (subElement && subElement->name.value == name) + { + return subElement; + } + } + return nullptr; + } + + collections::LazyList> XmlGetElements(XmlElement* element) + { + return From(element->subNodes).FindType(); + } + + collections::LazyList> XmlGetElements(XmlElement* element, const WString& name) + { + return XmlGetElements(element) + .Where([name](auto&& e) {return e->name.value == name; }); + } + + WString XmlGetValue(XmlElement* element) + { + WString result; + for (auto node : element->subNodes) + { + if (auto text = node.Cast()) + { + result += text->content.value; + } + else if (auto text = node.Cast()) + { + result += text->content.value; + } + } + return result; + } + +/*********************************************************************** +XmlElementWriter +***********************************************************************/ + + XmlElementWriter::XmlElementWriter(Ptr _element, const XmlElementWriter* _previousWriter) + : element(_element) + , previousWriter(_previousWriter) + { + } + + XmlElementWriter::~XmlElementWriter() + { + } + + const XmlElementWriter& XmlElementWriter::Attribute(const WString& name, const WString& value)const + { + Ptr node = new XmlAttribute; + node->name.value = name; + node->value.value = value; + element->attributes.Add(node); + return *this; + } + + XmlElementWriter XmlElementWriter::Element(const WString& name)const + { + Ptr node = new XmlElement; + node->name.value = name; + element->subNodes.Add(node); + return XmlElementWriter(node, this); + } + + const XmlElementWriter& XmlElementWriter::End()const + { + return *previousWriter; + } + + const XmlElementWriter& XmlElementWriter::Text(const WString& value)const + { + Ptr node = new XmlText; + node->content.value = value; + element->subNodes.Add(node); + return *this; + } + + const XmlElementWriter& XmlElementWriter::CData(const WString& value)const + { + Ptr node = new XmlCData; + node->content.value = value; + element->subNodes.Add(node); + return *this; + } + + const XmlElementWriter& XmlElementWriter::Comment(const WString& value)const + { + Ptr node = new XmlComment; + node->content.value = value; + element->subNodes.Add(node); + return *this; + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XMLAST.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { +/*********************************************************************** +Visitor Pattern Implementation +***********************************************************************/ + + void XmlText::Accept(XmlNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void XmlCData::Accept(XmlNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void XmlComment::Accept(XmlNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void XmlElement::Accept(XmlNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void XmlInstruction::Accept(XmlNode::IVisitor* visitor) + { + visitor->Visit(this); + } + + void XmlDocument::Accept(XmlNode::IVisitor* visitor) + { + visitor->Visit(this); + } + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlNode, system::xml::XmlNode) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlNode::IVisitor, system::xml::XmlNode::IVisitor) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlText, system::xml::XmlText) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlCData, system::xml::XmlCData) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlAttribute, system::xml::XmlAttribute) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlComment, system::xml::XmlComment) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlElement, system::xml::XmlElement) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlInstruction, system::xml::XmlInstruction) + IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlDocument, system::xml::XmlDocument) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlNode) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + END_CLASS_MEMBER(vl::glr::xml::XmlNode) + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlText) + CLASS_MEMBER_BASE(vl::glr::xml::XmlNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(content) + END_CLASS_MEMBER(vl::glr::xml::XmlText) + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlCData) + CLASS_MEMBER_BASE(vl::glr::xml::XmlNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(content) + END_CLASS_MEMBER(vl::glr::xml::XmlCData) + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlAttribute) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + CLASS_MEMBER_FIELD(value) + END_CLASS_MEMBER(vl::glr::xml::XmlAttribute) + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlComment) + CLASS_MEMBER_BASE(vl::glr::xml::XmlNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(content) + END_CLASS_MEMBER(vl::glr::xml::XmlComment) + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlElement) + CLASS_MEMBER_BASE(vl::glr::xml::XmlNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + CLASS_MEMBER_FIELD(closingName) + CLASS_MEMBER_FIELD(attributes) + CLASS_MEMBER_FIELD(subNodes) + END_CLASS_MEMBER(vl::glr::xml::XmlElement) + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlInstruction) + CLASS_MEMBER_BASE(vl::glr::xml::XmlNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + CLASS_MEMBER_FIELD(attributes) + END_CLASS_MEMBER(vl::glr::xml::XmlInstruction) + + BEGIN_CLASS_MEMBER(vl::glr::xml::XmlDocument) + CLASS_MEMBER_BASE(vl::glr::xml::XmlNode) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(prologs) + CLASS_MEMBER_FIELD(rootElement) + END_CLASS_MEMBER(vl::glr::xml::XmlDocument) + + BEGIN_INTERFACE_MEMBER(vl::glr::xml::XmlNode::IVisitor) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlText* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlCData* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlComment* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlElement* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlInstruction* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlDocument* node)) + END_INTERFACE_MEMBER(vl::glr::xml::XmlNode) + +#endif + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + class XmlAstTypeLoader : public vl::Object, public ITypeLoader + { + public: + void Load(ITypeManager* manager) + { + ADD_TYPE_INFO(vl::glr::xml::XmlNode) + ADD_TYPE_INFO(vl::glr::xml::XmlNode::IVisitor) + ADD_TYPE_INFO(vl::glr::xml::XmlText) + ADD_TYPE_INFO(vl::glr::xml::XmlCData) + ADD_TYPE_INFO(vl::glr::xml::XmlAttribute) + ADD_TYPE_INFO(vl::glr::xml::XmlComment) + ADD_TYPE_INFO(vl::glr::xml::XmlElement) + ADD_TYPE_INFO(vl::glr::xml::XmlInstruction) + ADD_TYPE_INFO(vl::glr::xml::XmlDocument) + } + + void Unload(ITypeManager* manager) + { + } + }; +#endif +#endif + + bool XmlAstLoadTypes() + { +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + if (auto manager = GetGlobalTypeManager()) + { + Ptr loader = new XmlAstTypeLoader; + return manager->AddTypeLoader(loader); + } +#endif + return false; + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XMLAST_BUILDER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace builder + { + +/*********************************************************************** +MakeAttribute +***********************************************************************/ + + MakeAttribute& MakeAttribute::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + + MakeAttribute& MakeAttribute::value(const vl::WString& value) + { + node->value.value = value; + return *this; + } + +/*********************************************************************** +MakeCData +***********************************************************************/ + + MakeCData& MakeCData::content(const vl::WString& value) + { + node->content.value = value; + return *this; + } + +/*********************************************************************** +MakeComment +***********************************************************************/ + + MakeComment& MakeComment::content(const vl::WString& value) + { + node->content.value = value; + return *this; + } + +/*********************************************************************** +MakeDocument +***********************************************************************/ + + MakeDocument& MakeDocument::prologs(const vl::Ptr& value) + { + node->prologs.Add(value); + return *this; + } + + MakeDocument& MakeDocument::rootElement(const vl::Ptr& value) + { + node->rootElement = value; + return *this; + } + +/*********************************************************************** +MakeElement +***********************************************************************/ + + MakeElement& MakeElement::attributes(const vl::Ptr& value) + { + node->attributes.Add(value); + return *this; + } + + MakeElement& MakeElement::closingName(const vl::WString& value) + { + node->closingName.value = value; + return *this; + } + + MakeElement& MakeElement::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + + MakeElement& MakeElement::subNodes(const vl::Ptr& value) + { + node->subNodes.Add(value); + return *this; + } + +/*********************************************************************** +MakeInstruction +***********************************************************************/ + + MakeInstruction& MakeInstruction::attributes(const vl::Ptr& value) + { + node->attributes.Add(value); + return *this; + } + + MakeInstruction& MakeInstruction::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + +/*********************************************************************** +MakeText +***********************************************************************/ + + MakeText& MakeText::content(const vl::WString& value) + { + node->content.value = value; + return *this; + } + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XMLAST_COPY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace copy_visitor + { + void AstVisitor::CopyFields(XmlAttribute* from, XmlAttribute* to) + { + to->name = from->name; + to->value = from->value; + } + + void AstVisitor::CopyFields(XmlCData* from, XmlCData* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->content = from->content; + } + + void AstVisitor::CopyFields(XmlComment* from, XmlComment* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->content = from->content; + } + + void AstVisitor::CopyFields(XmlDocument* from, XmlDocument* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->prologs) + { + to->prologs.Add(CopyNode(listItem.Obj())); + } + to->rootElement = CopyNode(from->rootElement.Obj()); + } + + void AstVisitor::CopyFields(XmlElement* from, XmlElement* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->attributes) + { + to->attributes.Add(CopyNode(listItem.Obj())); + } + to->closingName = from->closingName; + to->name = from->name; + for (auto&& listItem : from->subNodes) + { + to->subNodes.Add(CopyNode(listItem.Obj())); + } + } + + void AstVisitor::CopyFields(XmlInstruction* from, XmlInstruction* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->attributes) + { + to->attributes.Add(CopyNode(listItem.Obj())); + } + to->name = from->name; + } + + void AstVisitor::CopyFields(XmlNode* from, XmlNode* to) + { + } + + void AstVisitor::CopyFields(XmlText* from, XmlText* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->content = from->content; + } + + void AstVisitor::Visit(XmlAttribute* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(XmlText* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(XmlCData* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(XmlComment* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(XmlElement* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(XmlInstruction* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void AstVisitor::Visit(XmlDocument* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + vl::Ptr AstVisitor::CopyNode(XmlNode* node) + { + if (!node) return nullptr; + node->Accept(static_cast(this)); + return this->result.Cast(); + } + + vl::Ptr AstVisitor::CopyNode(XmlAttribute* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr AstVisitor::CopyNode(XmlCData* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(XmlComment* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(XmlDocument* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(XmlElement* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(XmlInstruction* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr AstVisitor::CopyNode(XmlText* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XMLAST_EMPTY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace empty_visitor + { + +/*********************************************************************** +NodeVisitor +***********************************************************************/ + + // Visitor Members ----------------------------------- + + void NodeVisitor::Visit(XmlText* node) + { + } + + void NodeVisitor::Visit(XmlCData* node) + { + } + + void NodeVisitor::Visit(XmlComment* node) + { + } + + void NodeVisitor::Visit(XmlElement* node) + { + } + + void NodeVisitor::Visit(XmlInstruction* node) + { + } + + void NodeVisitor::Visit(XmlDocument* node) + { + } + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XMLAST_JSON.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace json_visitor + { + void AstVisitor::PrintFields(XmlAttribute* node) + { + BeginField(L"name"); + WriteToken(node->name); + EndField(); + BeginField(L"value"); + WriteToken(node->value); + EndField(); + } + void AstVisitor::PrintFields(XmlCData* node) + { + BeginField(L"content"); + WriteToken(node->content); + EndField(); + } + void AstVisitor::PrintFields(XmlComment* node) + { + BeginField(L"content"); + WriteToken(node->content); + EndField(); + } + void AstVisitor::PrintFields(XmlDocument* node) + { + BeginField(L"prologs"); + BeginArray(); + for (auto&& listItem : node->prologs) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + BeginField(L"rootElement"); + Print(node->rootElement.Obj()); + EndField(); + } + void AstVisitor::PrintFields(XmlElement* node) + { + BeginField(L"attributes"); + BeginArray(); + for (auto&& listItem : node->attributes) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + BeginField(L"closingName"); + WriteToken(node->closingName); + EndField(); + BeginField(L"name"); + WriteToken(node->name); + EndField(); + BeginField(L"subNodes"); + BeginArray(); + for (auto&& listItem : node->subNodes) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + } + void AstVisitor::PrintFields(XmlInstruction* node) + { + BeginField(L"attributes"); + BeginArray(); + for (auto&& listItem : node->attributes) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + BeginField(L"name"); + WriteToken(node->name); + EndField(); + } + void AstVisitor::PrintFields(XmlNode* node) + { + } + void AstVisitor::PrintFields(XmlText* node) + { + BeginField(L"content"); + WriteToken(node->content); + EndField(); + } + + void AstVisitor::Visit(XmlText* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Text", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(XmlCData* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"CData", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(XmlComment* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Comment", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(XmlElement* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Element", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(XmlInstruction* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Instruction", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void AstVisitor::Visit(XmlDocument* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Document", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + AstVisitor::AstVisitor(vl::stream::StreamWriter& _writer) + : vl::glr::JsonVisitorBase(_writer) + { + } + + void AstVisitor::Print(XmlNode* node) + { + if (!node) + { + WriteNull(); + return; + } + node->Accept(static_cast(this)); + } + + void AstVisitor::Print(XmlAttribute* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Attribute", node); + PrintFields(static_cast(node)); + EndObject(); + } + + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XMLAST_TRAVERSE.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace traverse_visitor + { + void AstVisitor::Traverse(vl::glr::ParsingToken& token) {} + void AstVisitor::Traverse(vl::glr::ParsingAstBase* node) {} + void AstVisitor::Traverse(XmlAttribute* node) {} + void AstVisitor::Traverse(XmlCData* node) {} + void AstVisitor::Traverse(XmlComment* node) {} + void AstVisitor::Traverse(XmlDocument* node) {} + void AstVisitor::Traverse(XmlElement* node) {} + void AstVisitor::Traverse(XmlInstruction* node) {} + void AstVisitor::Traverse(XmlNode* node) {} + void AstVisitor::Traverse(XmlText* node) {} + + void AstVisitor::Finishing(vl::glr::ParsingAstBase* node) {} + void AstVisitor::Finishing(XmlAttribute* node) {} + void AstVisitor::Finishing(XmlCData* node) {} + void AstVisitor::Finishing(XmlComment* node) {} + void AstVisitor::Finishing(XmlDocument* node) {} + void AstVisitor::Finishing(XmlElement* node) {} + void AstVisitor::Finishing(XmlInstruction* node) {} + void AstVisitor::Finishing(XmlNode* node) {} + void AstVisitor::Finishing(XmlText* node) {} + + void AstVisitor::Visit(XmlText* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->content); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(XmlCData* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->content); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(XmlComment* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->content); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(XmlElement* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->attributes) + { + InspectInto(listItem.Obj()); + } + Traverse(node->closingName); + Traverse(node->name); + for (auto&& listItem : node->subNodes) + { + InspectInto(listItem.Obj()); + } + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(XmlInstruction* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->attributes) + { + InspectInto(listItem.Obj()); + } + Traverse(node->name); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::Visit(XmlDocument* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->prologs) + { + InspectInto(listItem.Obj()); + } + InspectInto(node->rootElement.Obj()); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void AstVisitor::InspectInto(XmlNode* node) + { + if (!node) return; + node->Accept(static_cast(this)); + } + + void AstVisitor::InspectInto(XmlAttribute* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->name); + Traverse(node->value); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XMLPARSER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Xml +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + void XmlParserData(vl::stream::IStream& outputStream) + { + static const vl::vint dataLength = 2446; // 22181 bytes before compressing + static const vl::vint dataBlock = 256; + static const vl::vint dataRemain = 142; + static const vl::vint dataSolidRows = 9; + static const vl::vint dataRows = 10; + static const char* compressed[] = { + "\xA5\x56\x00\x00\x86\x09\x00\x00\x0D\x00\x01\x82\x80\x08\x03\x82\x81\x82\x06\x89\x82\x85\x0A\x83\x06\x84\x07\x0A\x91\x0A\x9C\x0A\x82\x12\x84\x14\x0A\xA3\x42\x09\x8F\x7D\x8E\x8F\x8E\x0A\x80\x1F\x9F\x81\x93\x92\x8F\x92\x26\xFF\x68\x86\x9B\x93\x91\x96\x92\x0A\xA9\xAA\x91\x99\x91\x91\x91\x00\x34\xAC\xB9\x8E\x9B\x98\x98\x8F\x9A\x3D\xA7\x81\xA0\x93\xA3\x9B\x9E\x9D\x47\xBC\x89\xBE\x96\x82\x9B\x96\xA1\x4B\xD0\x8D\xA0\xA1\xAC\xA1\xAA\xA3\x53\xC8\x99\xAA\xAB\xAC\xA7\x80\xA7\x45\xCF\x96\xBD\xA2\xAF\xAC\xAA\xB2\x63\xE6\x9A\xAA\xBC\xAC\xB6\xAE\x81\x60\xD7\xB7\x8A\x88\x9A\xB9\xB1\xBB\x76\x89\x9B\x89\x85\xB8\xB4\xAC\xB7\x65\xF0\xA7\xA0\xC9\xB2\xC3\xB4\xC3\x6D\x88\xEF\xA1\x81\xBE\xBE\xB1\xBF\x8A\x81\xCC\xC3\xC1\xCD\xC3\xC9\xC3\x97\x89\xD9\xCB\xC2\x94\xCB\xCC\xC9\x9D\x98\xE1\xDA\xC3\xD4\xCD\xC7\x81\x03\x74\xB8\xAE\xCB\xD4\xC0\xC9\xCF\x96\xA5\xE0\xC7\xD5\xCF\xD6\xD9\xD8\xB4\xB0\xF6\xD9\xD7\xDB\xDE\xCE\x00\x04\x2A\xC9\x8C\x8C\xBA\x86\x02\xE1\xAC\xF9\x86\x87\x08\xE6\xD7\xC7\xE7\xAD\xB5\xD0\xEA\xEE\xE1\xEA\xDD\xE9\xC9\xD9\xD5\xF4", + "\xE2\xEA\x84\x84\x83\x7D\xDB\xDA\xFD\xEC\xEF\xEA\xEB\xDE\xD8\xE2\xEA\xE4\xF3\xF6\xF1\xF2\x00\x09\x4D\xEC\xEB\xFE\xF5\xF4\xF5\xF3\xBC\xF9\xFF\xDA\xF2\xD4\xFC\xD2\xDE\x0A\x32\x75\x7C\x7D\xF7\x6F\x7E\x7E\x69\xFB\x49\x8D\x7E\x82\xFF\x4C\x88\x82\x68\x0E\x45\x76\x82\x83\xB3\x54\x88\x6E\x85\xBE\x4B\x8A\x85\x83\x1B\x8F\x8C\x87\x87\x1E\xA1\x85\x85\x87\x23\xA0\x85\x8A\x88\x17\xA4\x89\x88\x69\x0C\x02\x85\x82\x7D\x07\xA7\x82\x8F\x8A\x28\x99\x86\x88\x8D\x33\xB6\x85\x8D\x7A\xF3\x7D\x81\x40\x40\x12\xB0\x88\x84\x8F\x03\xBE\x8F\x88\x81\x31\xB8\x8A\x92\x8E\x39\x84\x97\x92\x91\x49\x8C\x9B\x92\x93\x51\x8E\x90\x45\x90\x48\x83\x98\x7E\x96\x13\xAA\x82\x97\x97\x54\x9C\x92\x92\x97\x4E\x8F\x0E\x89\x95\x5B\xA4\x99\x9B\x8D\x60\xAB\x9B\x8E\x9B\x4D\xB0\x93\x96\x9C\xB6\x50\x07\x9A\x98\x59\xAA\x9D\x94\x9B\x61\xBA\x93\x98\x9F\x74\xBD\x90\xA3\x9E\x6F\x84\xA1\x9E\xA1\x73\x88\xAD\x9B\x7B\x12\x58\x90\x94\x9E\x8F\xBE\x99\x9F\xA0\xF6\x52\x07\x9E\x68\x13\x17\xA4\x68\x05\x9A\x85\xAF\x9E\xA7\x93\xA0\xA1\xA4\x69\x15\x1D\xA0\x6A\x05\xA6\xB1\x67\x05\xAA", + "\x8B\x9F\xA7\xA2\x41\x18\x2C\xA2\xA2\xA8\x45\xB5\xAF\x92\xAD\x68\x8A\xA3\xAF\xAB\xA1\xBC\xA2\x41\x06\xB2\x8A\x4A\x05\xB0\x09\x5B\x0E\x88\x45\x8E\x81\x4D\x06\x8B\x1E\x2E\x8F\x06\x8B\x20\x04\xBE\xA9\xA2\xF6\x61\x02\xB7\x40\x16\x49\xB7\xAC\x00\x23\x2E\x84\x0A\x8B\x25\x2E\x86\x0A\x8B\x27\x2E\x88\x46\xB6\xB9\x93\xBD\xA9\xAF\xD4\xAC\xB6\x6D\x0A\xD7\xA3\xA4\xAF\xB6\x2A\x31\xB8\xAC\xA4\xF7\x92\xA2\xBE\xAF\xF9\x94\xAE\xBB\xAE\xED\xBB\xB1\xC1\x40\x2B\x36\xBB\xB5\xBA\xFF\x81\xAA\xC2\xAE\xE7\x6C\x06\xC1\x0B\x2E\xAE\x0E\x8B\x0B\x2E\xB0\x0E\x89\x0C\x2E\xB2\x06\xC0\xC2\x02\xEB\xBD\xC4\xC0\x1E\xFD\xB3\xBC\xC7\x01\x73\x0B\xC4\xBE\x07\xE8\xC4\xC9\xCA\xFA\xA2\xCC\xBC\x00\x34\x27\xCD\xC8\xCB\xFE\x9F\xCB\xC2\xBA\x20\xE1\x45\x0E\xCC\x35\xEE\xC3\xC0\xCD\x23\xEA\xC2\xD2\x68\x36\x3C\xC1\xD3\xCC\x2B\xC9\xD3\xD1\xCF\x40\xEF\xC7\x0E\xD1\x2F\xCA\xD8\xD3\xD2\x47\xCC\xD2\xD6\xD5\x54\xD1\xD9\xD7\xCF\x57\xD5\xDE\xD6\xD6\x53\xE2\x68\x0C\xD4\x5C\xDB\xD1\xCB\xB6\x39\x24\xD7\xDB\xCA\x3A\x2A\xD9\xCF\xCD\x09\xC9\x4B\x0E\xDB\x70\xC6\x9C\x0C\xDD\x0C", + "\xEF\x7D\x0C\xDE\x38\xF5\xDE\xCF\xDA\x66\xEF\xD9\xDE\x41\x3E\x3C\xD4\x83\x0F\x86\xF6\xC9\x40\x10\x89\xFF\xD2\xE1\xDF\x83\xF1\xD0\xE7\xE4\x92\xD5\xE2\x41\x10\x8D\xDB\xB2\x11\xE6\x2B\xC3\x1C\xE7\x6F\x44\x1F\xE1\xD8\xD6\xA3\xDF\xD5\xD9\xE9\x2F\xC5\x12\xE8\x69\x46\x2B\xE3\xBF\x11\xAE\xE0\x6D\x2A\x42\x7B\x76\x4E\xBA\x4C\xDF\x76\xEF\xDC\xEE\xAC\x87\x77\x56\x4C\xB5\xC3\x4C\x72\xA2\xBC\xC9\x4D\x8B\x55\xC1\xC2\x43\xF2\xBA\xC5\xC6\x47\xF2\x5F\xC9\xC1\x4B\xF3\xED\x29\x79\xE2\x43\xF3\xAE\x51\xF0\x03\xF4\x1D\xCD\xF3\x40\xF6\xB5\x7E\xEE\x5E\x4C\xE2\xEE\x64\xF9\x51\xE7\xFF\xE9\x4A\xF6\xE1\x5D\xF5\xF4\xED\x45\x65\xF5\x6C\xF0\xF0\xC4\xFF\xF9\x42\xA9\x57\x52\xFE\x6E\xF4\xC9\x41\x72\xFD\x26\x36\x79\x40\x02\x8D\x36\xED\x60\x66\x7B\xBA\x7D\x7E\xEE\x3B\x77\x7F\x05\xBD\x33\x7F\xBD\x32\x27\xFF\x63\x7B\x7C\x85\x13\x86\x35\x17\x93\x7D\x05\x89\x2C\x7A\x06\x81\x82\x21\xE0\x7A\x35\x06\xFC\x7B\x83\xE5\x34\x48\x81\x01\x21\x85\x6F\x23\x81\x83\x12\x82\x7F\x84\x0D\x9F\x79\x51\x2C\x82\x26\x05\x83\x22\x7B\x51\x48\x84\x00\x79\x7E\x2E\x1A\xB5\x86", + "\x24\xEC\x70\x87\x07\xFA\x23\x86\xF4\x6E\x82\x79\x42\x83\x24\x01\xAA\x82\x82\x23\x80\x8E\x82\x45\x8A\x7F\x13\x9C\x89\x89\x8F\x0B\x89\x8A\x14\x93\x8A\x09\x80\x8A\x88\x10\x98\x8E\x7C\x47\x92\x79\x15\x9E\x27\x8B\xAB\x3E\x87\x87\x1F\x3A\x78\x0E\x98\x4A\x86\x1E\x98\x86\x89\x23\x21\x88\x17\xD6\x85\x7F\x1E\xB0\x89\x8D\x0A\x3D\x81\xD3\x3F\x85\x8C\xE6\x71\x80\x89\xFA\x77\x8E\x47\x67\x88\x8D\x8E\x1A\x7C\x90\x1F\x28\x90\x1A\xDA\x7A\x8F\x1C\xBF\x89\x85\x5F\x9A\x82\x16\xAF\x83\x8E\x32\x9E\x8E\x8C\x82\x86\x91\x1E\xE3\x8D\x23\x3E\xAF\x8A\x8A\x71\x95\x8C\xF5\x43\x86\x20\x37\xB5\x32\x91\x3F\x92\x8E\x1F\xA4\x97\x87\x48\xA4\x83\x92\x80\x8B\x95\x17\xC6\x71\x7F\x4C\xBF\x18\x82\x85\x9F\x20\x2E\xB9\x9D\x23\x5D\xBC\x92\x7B\xC4\x32\x94\x1D\x89\x21\x42\xE8\x4E\x86\x83\xB3\x8E\x82\x0D\x89\x8C\x8D\x47\xB6\x21\x7D\x59\x81\x94\xFE\x45\x20\x98\x6A\x8A\x26\x94\xBA\x27\x92\x35\xD3\x98\x78\x51\xAE\x7C\x95\x02\x38\x99\x01\x8A\x21\x99\xEC\x50\x8D\x9B\x44\x95\x91\x27\xD7\x95\x96\x50\xB8\x8B\x38\xDB\x86\x20\x2A\xFF\x1A\x8C\x4E\xBF\x1C\x80\xE2\x9A", + "\x86\x2F\xC9\x93\x21\x7D\x83\x9E\x20\xF1\x37\x29\x39\x92\x93\x25\x81\xAF\x95\xA0\xB6\x86\xA1\x0B\xE0\x91\x21\x80\xBE\x2C\x80\x01\x57\x28\x44\xC5\x24\x81\x79\x84\x82\xA1\x3A\x96\xA3\x39\x8F\xA4\x9C\x8A\x9B\xA6\x35\x15\xBE\xA0\x3C\x92\xAF\xA3\xDA\x16\x67\x98\xED\x61\x22\xF6\x62\x9A\x9B\x74\xB2\x9E\x9B\x01\x2C\x85\x35\xAE\xAD\x9E\x98\x80\x3B\x93\xDC\x9B\x8B\x4B\xD4\x8E\x7E\x9C\xBB\xA2\xA7\x03\x2A\xA2\x1E\x90\x8A\x8E\x16\xA2\x9C\x85\x48\xBD\xA1\x42\x10\x8C\x84\x02\x8E\xA3\x20\x11\xA6\x21\x31\xB2\x89\x20\x20\x46\x27\x4A\x06\x26\x4D\x42\x76\x49\x21\x46\x46\x26\x52\x09\x39\x53\x31\xA5\x57\x98\x4D\x2E\x41\x24\x64\xAE\x83\x26\x2E\x4A\xA1\x58\x47\x9C\x13\x2E\x4C\x87\xB3\x47\x9D\x12\x17\x69\xA0\x00\xCD\x47\x9A\x27\x2E\x42\x9D\x68\x47\x9F\x13\x2E\x5A\x7A\xB5\x47\x90\x14\xB6\x8A\x26\xAD\x0E\x81\x17\x59\x8A\x23\x5D\x63\xA2\x13\xB1\x09\x2D\xB2\x03\xA3\x1E\x44\x08\xB5\x5F\x98\xA4\x11\xAE\x42\x05\x67\x99\x52\x3C\xAA\x21\x0E\x67\x9A\x29\x15\xBA\x21\xCB\x8E\x87\x14\x9A\xA9\x20\x67\x8E\x88\x15\xCF\x89\x21\xB4\x0E\x89\x14\x69\x89", + "\x26\xB5\x05\xAA\x11\xB5\x06\x2B\xB7\x02\xAB\x1E\xB4\x83\x30\xB3\x81\xAC\x0E\x44\x12\x47\x97\xA6\xE2\xB6\xAE\xA6\xBC\x2B\xA4\x71\xBC\x3C\xA5\xF3\x22\x9F\xAE\x21\x2A\xA3\x5D\xAB\x62\xA7\xE5\x81\x72\xA9\x40\xBA\x74\x04\xF7\xAA\x8F\x35\xA2\x32\xA1\x4F\xBA\x75\x78\x81\x27\xAF\xA8\xAD\x97\x3D\x0A\xA4\x81\x48\x2A\x87\xAE\xAB\xA7\xBE\x3E\x0A\xA6\xBE\xEE\x5A\xA0\x3C\x85\x1C\xAE\x20\xDE\xA4\x37\x50\xC4\xB0\xAD\xFA\x91\x77\x20\xC6\x24\xBA\x58\xFE\xB4\x72\x81\x23\xB8\x00\x10\x81\x24\xA7\x68\x58\x64\xF9\x81\x21\xC1\x0A\x29\xAF\x40\x53\xB8\x65\xA9\x82\x26\xBD\xBA\x68\x56\xB6\x2B\x54\xA6\x23\x58\xC0\x92\xC7\x80\x58\x83\xB3\x68\xAB\x81\x37\xBB\x81\xC3\x5A\x5A\xB1\x1D\xC6\x57\x13\xC2\x24\xBE\x0B\x8B\x5B\x88\xCC\x6E\xAB\x81\x03\xC3\x81\x79\xA4\xC2\xE5\x01\x27\xC6\x81\x0B\xC2\x99\xBF\x33\xAC\x7E\xE7\x3F\xC7\x81\x1A\xC0\xC8\xA8\x71\x35\x91\x82\x2C\xC2\x24\xE4\x73\x53\x25\xB6\x77\x60\xBA\xC2\x21\x6C\x43\xC8\xA5\x11\xCA\x23\x91\x8B\x8D\x6A\xD0\x12\xC4\xC9\xD6\xA9\xCA\x6D\x5F\xC1\xA6\xE2\x9F\x5A\x5B\xE1\x4C\xC4\x00\x77\xA7\xAF\x2D", + "\xC2\x25\xBF\x0B\x85\x5F\x8C\xF3\x5D\xC9\x81\x22\xC6\xC9\xA6\x76\x35\x9D\x82\x2D\xC6\xDB\x67\x5F\xCA\xF6\x35\x9D\x42\x7B\xC2\x8D\x63\xB5\xB2\x20\xDA\x7F\xB4\xA2\xD1\xC0\x00\xED\x44\xD0\x3E\xC4\xB2\x62\x9A\xA7\xA0\xD1\x9A\xAA\xCF\xD1\xEA\xAA\x22\xC6\x6A\xC1\x66\x35\xC4\x86\xD1\xF6\xA4\xB9\xD1\x6A\xC3\x6C\x35\xCE\xC5\xD1\x0A\x2F\xD3\x87\xB6\x2D\x6C\x35\xF7\x6A\xCD\x2A\x80\xD5\x42\x27\xD1\x25\xC2\x6A\xCC\x71\x6A\xC5\xC7\xA2\x89\x28\xB0\x3B\xE1\xCF\xC9\x9C\x3D\xD4\x9F\xC4\xBB\x72\x35\xFC\x36\xC5\x2A\xA7\xB2\x4F\x8B\x81\x74\x35\xED\x72\xCD\x70\xDB\xD4\xAC\x0A\x27\xC1\x90\x03\xBA\xCD\x4A\x16\xA7\x92\xC9\xDC\xD6\xEF\x04\xBC\x09\x36\xAE\x0A\x4D\xEE\xCC\xDB\x69\xDB\xAC\xB8\x50\x16\xA6\x14\x36\xA2\xD9\x72\xC3\x25\xDD\x00\x0B\xD5\x48\x54\x06\xA6\x2B\x36\xA1\xC5\x95\xC2\x20\xBC\xB4\xDA\x20\x2C\x36\xA2\x0B\x36\xA8\x59\xBE\x81\x27\xCF\x81\x2B\xC0\xCF\xA0\x3C\x08\x72\xBF\x38\xDF\x81\x11\xDE\x76\x5E\x19\x73\xC1\x83\x2D\xE0\x66\xA2\xC9\x24\x02\xF6\xC4\x71\xDF\x0B\xE0\xD1\x39\xC3\xC2\x13\x2B\xDA\xEE\x61\x06\xA7\x31\x36\xA2\xC8", + "\x20\xE9\x21\xC6\x86\xC4\xB9\x32\x36\xA7\x0C\x36\xBE\xAC\x95\x81\x2B\xE5\x01\x84\xB9\x0D\x36\xAB\x0E\x4D\xD3\xC9\xE4\x83\x35\xE0\x00\xC8\xD6\x25\x1B\x36\xAF\x0C\x9B\x96\xCD\xE7\x03\x3F\xE6\xBC\x8A\x21\x0E\x9B\xB3\x0E\xA6\xDD\x5A\x5B\xCF\xFC\xD9\x21\x3A\x36\xA7\x0E\x36\xA7\xCF\xCC\xF8\xAA\x20\x19\xCE\x81\x0F\x99\x68\xE6\x40\x5E\xEB\x80\x3D\x19\x72\xE6\x03\x24\xEE\xEE\x7B\x09\x72\x9E\xE3\xEC\xB8\x7C\x19\x73\xD1\x82\x2A\xEB\x05\xBD\x09\x73\x75\xE2\x21\x9A\x88\xE1\x36\x3F\x1D\xE4\x34\x7B\xE3\x22\x9C\xFC\xE0\x70\xD1\x01\xF2\x20\x2C\x81\x24\x20\x2E\x41\x10\x9B\x87\xF4\xBC\x8C\xAA\x23\xE0\xDC\xC7\xBB\xC8\x8C\xD1\x24\x83\x0E\x44\x21\x36\xA2\xB2\xA4\xC2\x23\xF2\x02\x31\xEA\x03\x86\x19\x73\x3F\xC3\x21\xEF\xB6\x67\x13\xDF\x9C\x30\xF4\xC8\xC9\x26\xF4\xC3\xC7\x99\x22\x2B\xF0\x34\xD8\xEE\xF6\x20\xB6\xE0\xE8\x71\x8B\x16\xA7\x46\x36\xA0\x5E\xDA\x47\xD1\x40\x28\xF6\x27\x47\x06\x62\xF8\x6B\xC5\xB6\x42\x7D\xC6\x26\x48\x06\x62\xB7\x02\x37\xAC\xF2\xC1\xE1\x25\x48\x2E\x42\x12\x36\xAA\xD3\xED\x83\x20\xFB\x80\x00\xFE\x81\x94\x19\x72", + "\xF6\x80\x04\xF9\x90\x15\x17\x61\x2E\x43\xFC\xF3\xA1\x26\x12\x83\x52\xD3\xEB\xE3\xF4\xFA\x42\x17\x1E\x44\x4C\x36\xA4\x62\xDA\x50\x63\x31\xBC\x31\x82\xE3\xBE\xFF\xFF\x14\x6C\x12\x01\x86\x12\x6C\x63\x17\x6A\x69\x7C\xC4\x57\x57\xE2\x48\x6A\x72\x19\x5F\xD2\x47\x4C\xF9\x45\x13\x11\x89\x12\x0B\x81\x12\xF3\x45\x5C\xE3\x39\x78\x16\x86\x5C\x1A\x87\x79\x1B\x84\x5C\x1D\x8D\x53\x20\x8C\x81\xC6\x58\x51\x35\x16\x82\x29\x1A\x50\x36\x1A\x82\xD1\x55\x82\xC6\x5E\x4F\x27\x10\x83\x1E\x10\x61\x01\x64\x5C\x34\x8B\x54\xC6\x5D\x48\x35\x1A\x83\x29\x1A\x47\x36\x1E\x83\x21\x10\x84\x0A\x10", + }; + vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); + } + + const wchar_t* ParserRuleName(vl::vint index) + { + static const wchar_t* results[] = { + L"XAttribute", + L"XText", + L"XCData", + L"XComment", + L"XElement", + L"XSubNode", + L"XInstruction", + L"XDocument", + }; + return results[index]; + } + + const wchar_t* ParserStateLabel(vl::vint index) + { + static const wchar_t* results[] = { + L"[0][XAttribute] BEGIN ", + L"[1][XAttribute] END [ENDING]", + L"[2][XAttribute]< NAME \"=\" @ ATTVALUE >", + L"[3][XAttribute]< NAME \"=\" ATTVALUE @ >", + L"[4][XAttribute]< NAME @ \"=\" ATTVALUE >", + L"[5][XText] BEGIN ", + L"[6][XText] END [ENDING]", + L"[7][XText]< \"=\" @ >", + L"[8][XText]< ATTVALUE @ >", + L"[9][XText]< NAME @ >", + L"[10][XText]< TEXT @ >", + L"[11][XCData] BEGIN ", + L"[12][XCData] END [ENDING]", + L"[13][XCData]< CDATA @ >", + L"[14][XComment] BEGIN ", + L"[15][XComment] END [ENDING]", + L"[16][XComment]< COMMENT @ >", + L"[17][XElement] BEGIN ", + L"[18][XElement] END [ENDING]", + L"[19][XElement]< \"<\" @ NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"\" ) >", + L"[20][XElement]< \"<\" NAME @ { XAttribute } ( \"/>\" | \">\" { XSubNode } \"\" ) >", + L"[21][XElement]< \"<\" NAME { XAttribute @ } ( \"/>\" | \">\" { XSubNode } \"\" ) >", + L"[22][XElement]< \"<\" NAME { XAttribute } ( \"/>\" @ | \">\" { XSubNode } \"\" ) >", + L"[23][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" @ { XSubNode } \"\" ) >", + L"[24][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode @ } \"\" ) >", + L"[25][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"\" ) >", + L"[26][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"\" @ ) >", + L"[27][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"\" ) >", + L"[28][XSubNode] BEGIN ", + L"[29][XSubNode] END [ENDING]", + L"[30][XSubNode]<< ( ( ( !XText @ | !XCData ) | !XComment ) | !XElement ) >>", + L"[31][XSubNode]<< ( ( ( !XText | !XCData ) | !XComment ) | !XElement @ ) >>", + L"[32][XSubNode]<< ( ( ( !XText | !XCData ) | !XComment @ ) | !XElement ) >>", + L"[33][XSubNode]<< ( ( ( !XText | !XCData @ ) | !XComment ) | !XElement ) >>", + L"[34][XInstruction] BEGIN ", + L"[35][XInstruction] END [ENDING]", + L"[36][XInstruction]< \"\" >", + L"[37][XInstruction]< \"\" >", + L"[38][XInstruction]< \"\" >", + L"[39][XInstruction]< \"\" @ >", + L"[40][XDocument] BEGIN ", + L"[41][XDocument] END [ENDING]", + L"[42][XDocument]< { ( XInstruction @ | XComment ) } XElement >", + L"[43][XDocument]< { ( XInstruction | XComment ) } XElement @ >", + L"[44][XDocument]< { ( XInstruction | XComment @ ) } XElement >", + }; + return results[index]; + } + + Parser::Parser() + : vl::glr::ParserBase(&XmlTokenDeleter, &XmlLexerData, &XmlParserData) + { + }; + + vl::vint32_t Parser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const + { + return -1; + }; + + vl::Ptr Parser::ParseXElement(const vl::WString& input, vl::vint codeIndex) const + { + return Parse(input, this, codeIndex); + }; + + vl::Ptr Parser::ParseXElement(vl::collections::List& tokens, vl::vint codeIndex) const + { + return Parse(tokens, this, codeIndex); + }; + + vl::Ptr Parser::ParseXDocument(const vl::WString& input, vl::vint codeIndex) const + { + return Parse(input, this, codeIndex); + }; + + vl::Ptr Parser::ParseXDocument(vl::collections::List& tokens, vl::vint codeIndex) const + { + return Parse(tokens, this, codeIndex); + }; + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XML_ASSEMBLER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Xml +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + +/*********************************************************************** +XmlAstInsReceiver : public vl::glr::AstInsReceiverBase +***********************************************************************/ + + vl::Ptr XmlAstInsReceiver::CreateAstNode(vl::vint32_t type) + { + auto cppTypeName = XmlCppTypeName((XmlClasses)type); + switch((XmlClasses)type) + { + case XmlClasses::Attribute: + return new vl::glr::xml::XmlAttribute(); + case XmlClasses::CData: + return new vl::glr::xml::XmlCData(); + case XmlClasses::Comment: + return new vl::glr::xml::XmlComment(); + case XmlClasses::Document: + return new vl::glr::xml::XmlDocument(); + case XmlClasses::Element: + return new vl::glr::xml::XmlElement(); + case XmlClasses::Instruction: + return new vl::glr::xml::XmlInstruction(); + case XmlClasses::Text: + return new vl::glr::xml::XmlText(); + default: + return vl::glr::AssemblyThrowCannotCreateAbstractType(type, cppTypeName); + } + } + + void XmlAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value) + { + auto cppFieldName = XmlCppFieldName((XmlFields)field); + switch((XmlFields)field) + { + case XmlFields::Document_prologs: + return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlDocument::prologs, object, field, value, cppFieldName); + case XmlFields::Document_rootElement: + return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlDocument::rootElement, object, field, value, cppFieldName); + case XmlFields::Element_attributes: + return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlElement::attributes, object, field, value, cppFieldName); + case XmlFields::Element_subNodes: + return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlElement::subNodes, object, field, value, cppFieldName); + case XmlFields::Instruction_attributes: + return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlInstruction::attributes, object, field, value, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName); + } + } + + void XmlAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) + { + auto cppFieldName = XmlCppFieldName((XmlFields)field); + switch((XmlFields)field) + { + case XmlFields::Attribute_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlAttribute::name, object, field, token, tokenIndex, cppFieldName); + case XmlFields::Attribute_value: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlAttribute::value, object, field, token, tokenIndex, cppFieldName); + case XmlFields::CData_content: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlCData::content, object, field, token, tokenIndex, cppFieldName); + case XmlFields::Comment_content: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlComment::content, object, field, token, tokenIndex, cppFieldName); + case XmlFields::Element_closingName: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlElement::closingName, object, field, token, tokenIndex, cppFieldName); + case XmlFields::Element_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlElement::name, object, field, token, tokenIndex, cppFieldName); + case XmlFields::Instruction_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlInstruction::name, object, field, token, tokenIndex, cppFieldName); + case XmlFields::Text_content: + return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlText::content, object, field, token, tokenIndex, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName); + } + } + + void XmlAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem) + { + auto cppFieldName = XmlCppFieldName((XmlFields)field); + return vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName); + } + + const wchar_t* XmlTypeName(XmlClasses type) + { + const wchar_t* results[] = { + L"Attribute", + L"CData", + L"Comment", + L"Document", + L"Element", + L"Instruction", + L"Node", + L"Text", + }; + vl::vint index = (vl::vint)type; + return 0 <= index && index < 8 ? results[index] : nullptr; + } + + const wchar_t* XmlCppTypeName(XmlClasses type) + { + const wchar_t* results[] = { + L"vl::glr::xml::XmlAttribute", + L"vl::glr::xml::XmlCData", + L"vl::glr::xml::XmlComment", + L"vl::glr::xml::XmlDocument", + L"vl::glr::xml::XmlElement", + L"vl::glr::xml::XmlInstruction", + L"vl::glr::xml::XmlNode", + L"vl::glr::xml::XmlText", + }; + vl::vint index = (vl::vint)type; + return 0 <= index && index < 8 ? results[index] : nullptr; + } + + const wchar_t* XmlFieldName(XmlFields field) + { + const wchar_t* results[] = { + L"Attribute::name", + L"Attribute::value", + L"CData::content", + L"Comment::content", + L"Document::prologs", + L"Document::rootElement", + L"Element::attributes", + L"Element::closingName", + L"Element::name", + L"Element::subNodes", + L"Instruction::attributes", + L"Instruction::name", + L"Text::content", + }; + vl::vint index = (vl::vint)field; + return 0 <= index && index < 13 ? results[index] : nullptr; + } + + const wchar_t* XmlCppFieldName(XmlFields field) + { + const wchar_t* results[] = { + L"vl::glr::xml::XmlAttribute::name", + L"vl::glr::xml::XmlAttribute::value", + L"vl::glr::xml::XmlCData::content", + L"vl::glr::xml::XmlComment::content", + L"vl::glr::xml::XmlDocument::prologs", + L"vl::glr::xml::XmlDocument::rootElement", + L"vl::glr::xml::XmlElement::attributes", + L"vl::glr::xml::XmlElement::closingName", + L"vl::glr::xml::XmlElement::name", + L"vl::glr::xml::XmlElement::subNodes", + L"vl::glr::xml::XmlInstruction::attributes", + L"vl::glr::xml::XmlInstruction::name", + L"vl::glr::xml::XmlText::content", + }; + vl::vint index = (vl::vint)field; + return 0 <= index && index < 13 ? results[index] : nullptr; + } + + vl::Ptr XmlAstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates) + { + auto cppTypeName = XmlCppTypeName((XmlClasses)type); + return vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName); + } + } + } +} + + +/*********************************************************************** +.\XML\GENERATED\XML_LEXER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Xml +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace xml + { + bool XmlTokenDeleter(vl::vint token) + { + switch((XmlTokens)token) + { + case XmlTokens::SPACE: + return true; + default: + return false; + } + } + + const wchar_t* XmlTokenId(XmlTokens token) + { + static const wchar_t* results[] = { + L"INSTRUCTION_OPEN", + L"INSTRUCTION_CLOSE", + L"COMPLEX_ELEMENT_OPEN", + L"SINGLE_ELEMENT_CLOSE", + L"ELEMENT_OPEN", + L"ELEMENT_CLOSE", + L"EQUAL", + L"NAME", + L"ATTVALUE", + L"COMMENT", + L"CDATA", + L"TEXT", + L"SPACE", + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < XmlTokenCount ? results[index] : nullptr; + } + + const wchar_t* XmlTokenDisplayText(XmlTokens token) + { + static const wchar_t* results[] = { + L"", + L"", + L"<", + L">", + L"=", + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < XmlTokenCount ? results[index] : nullptr; + } + + const wchar_t* XmlTokenRegex(XmlTokens token) + { + static const wchar_t* results[] = { + L"/", + L"/", + L"/<", + L"/>", + L"/=", + L"[a-zA-Z0-9:._/-]+", + L"\"[^<>\"]*\"|\'[^<>\']*\'", + L"/])*--/>", + L"/])*/]/]/>", + L"([^<>=\"\' /r/n/ta-zA-Z0-9:._/-])+|\"|\'", + L"/s+", + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < XmlTokenCount ? results[index] : nullptr; + } + + void XmlLexerData(vl::stream::IStream& outputStream) + { + static const vl::vint dataLength = 1076; // 7370 bytes before compressing + static const vl::vint dataBlock = 256; + static const vl::vint dataRemain = 52; + static const vl::vint dataSolidRows = 4; + static const vl::vint dataRows = 5; + static const char* compressed[] = { + "\xCA\x1C\x00\x00\x2C\x04\x00\x00\x2C\x00\x01\xA7\x01\x84\x81\x82\x12\x82\x01\x04\x88\x04\x89\x04\x84\x82\x05\x0F\x84\x8B\x04\x8C\x04\x81\x06\x8B\x04\x8E\x04\x9F\x04\x80\x11\x8E\x82\x21\x20\x84\x82\x13\x94\x83\x10\x82\x07\x82\x84\x83\x81\x80\x14\x82\x80\x01\xAD\x04\x92\x91\x86\x14\x82\x9B\x01\xAF\x04\x9A\x91\x80\x18\x83\x1C\x04\xBA\x01\xA4\x8B\x1C\xA0\x82\x1E\x47\x84\xBD\x0A\xA4\x86\x1D\xA6\x82\x3F\x50\x84\x80\x23\xAC\x81\x20\xAB\x04\xC2\x19\xA4\x83\x24\xAC\x82\x22\x5F\x84\x85\x24\x83\x2C\x80\x2A\xB3\x04\xD5\x04\x9A\x24\x83\x2D\xB6\x82\x5C\x70\x84\x9D\x23\xBC\x82\x2E\xBB\x04\xDF\x39\xA4\x80\x34\xBC\x83\x30\x04\xFA\x04\x9B\x34\x87\x7F\x7E\x08\x00\x0D\x81\x90\x8B\xC6\x85\xC7\x80\x8A\x80\x0C\xC9\xC4\x87\x02\xC6\x00\x0B\x90\xC4\x86\x0B\xCC\x83\x01\xCE\x01\x9C\xDA\xC1\x89\x81\x81\x02\x82\x04\x04\x82\x17\xC2\xD0\x01\xD7\xD7\xA0\xAE\xF1\xD1\xC4\xDC\xD6\xDB\xD1\x00\x06\xFA\xDB\xDC\xDD\xDE\xDE\xDE\x17\x81\xBF\xC3\xEE\xDD\x8A\xE0\xE2\xC8\x86\xD3\x87\xE9\xE5\xE6\xE7\xE7\xC9\x8F\x05\xDE\xD2\xEC\xE7\x7F\xEA\xB9\xBA\xD8\xFB", + "\xDB\xEA\xEF\xE9\xDE\xDD\xE0\xDF\xFC\xDA\x89\x80\xED\xF0\xD0\xC3\xE7\xE4\x8B\xF6\xE8\xF5\xF7\xE3\xDC\xE3\xF0\xFE\xF3\xF9\xF8\xEF\xD6\xF2\xF9\xFA\xD8\xC6\xF0\xF7\xFB\xE9\x7C\x6D\x78\x00\x03\xBA\x79\x76\x61\xE8\x41\x8A\x83\x82\x0C\x8D\x8E\x83\x83\x10\x91\x82\x87\x84\x14\x95\x86\x85\x7A\x11\x04\x49\x86\x75\x1B\x80\x0D\x87\x83\x1D\xA1\x8A\x87\x88\x01\x62\x8B\x7C\x71\x1F\xBA\x69\x89\x6F\x12\x04\x4D\x89\x40\x2F\x80\x01\x8F\x8C\x2E\xB5\x81\x43\x04\x36\xB2\x89\x8C\x8D\x30\xBB\x89\x8F\x6E\x31\x80\x9E\x8D\x8F\x44\xBA\x85\x90\x8F\x46\x89\x98\x93\x92\x3F\xBA\x64\x04\x41\x4F\x81\x41\x94\x00\x53\x95\x90\x97\x95\x52\x98\x90\x01\x05\x5A\x96\x99\x97\x97\x54\x9A\x9B\x6F\x94\x63\x9D\x96\x98\x98\x5E\xA1\x98\x9B\x99\x6A\xAD\x99\x9A\x81\xBF\x74\x77\x83\x75\xF6\x75\x77\x88\x9D\x77\x89\x84\x77\x7F\x77\x8B\x83\x81\x81\xF8\x73\x9A\x9E\x61\x16\x04\x45\xA2\x75\x87\xB3\x99\xA3\x85\x8C\x8D\xAE\xA3\xA3\x90\x91\xA2\xA7\xA4\x94\x95\xA6\xA5\xA4\x17\x00\x87\xA5\x7A\x18\x1A\xAB\xA7\xA7\xA0\x95\xA3\xA0\x9E\x82\xB5\x95\xAA\x9D\x73\xB0\x9B\x9D\x9F", + "\x81\xA3\xAE\x9C\x9F\x04\xB0\xAA\xA8\x82\x9E\xA1\xA6\xAF\xAD\xB8\xBF\x36\x8B\x9C\xBB\xA0\x84\x8A\x87\xBF\xBB\xAB\x89\x73\xC3\x83\xB2\x93\x91\x43\x8A\x99\x8C\x8E\xC8\x8D\xBA\xB2\xB3\x41\xBA\x61\xB6\x61\x4C\x90\xB9\xB1\xB5\xCF\x99\xB8\x91\xAE\xDC\x9D\xBF\x3D\x9A\xE0\xAC\x91\xB9\x40\x5C\xAB\x96\xBA\x9B\x62\x8E\x93\x7B\xB8\xE8\xA7\xBC\xBB\xBB\xE2\xB5\xAE\xB7\xBC\x96\x89\xAB\xA2\x6E\xF7\x84\xA2\xBC\xBD\xFC\xB7\xA9\x07\xBE\xFD\x81\xC2\xC1\x72\x1A\x00\xC2\xA7\x06\x04\x48\xC1\x42\xC2\x00\x0C\xCE\xC1\xC2\x10\xCB\xC1\xC5\xC3\x13\xDC\x03\xC7\xC3\x12\xD9\xC4\xC6\xC6\x18\xDB\xCE\xC5\xC7\x20\xD7\xC2\xC8\xC7\x23\xDE\xC3\xC3\xA7\x1D\x06\xCD\xA1\xC8\x24\xED\xCF\xC5\xC9\x0C\xD6\xCE\xC8\xCB\x2F\xF3\xC0\xCF\xCD\x36\xF9\xC5\xCE\xC9\xBA\x5E\x04\x42\xCF\x01\x40\xD0\x02\xD0\x44\xFF\xC6\xD1\xD0\x47\xC3\xD9\xD0\x47\x48\xCD\xDA\xD2\xD3\x45\xD0\xD9\xD1\xD4\x4F\xD5\xD4\xD7\xD5\x53\xD9\xD2\xD6\xD3\x27\xCC\xAE\x44\xAB\xB7\xB4\xC2\xD8\xCE\x3B\xF2\xCB\xCF\xD8\x3A\xE8\xD7\xD8\xD9\x6A\xDD\xCB\x6D\x48\x01\x70\xD0\x02\xDC\x74\xE2\x41\xDE\xDD\x73", + "\xF8\xD5\xDF\xDD\x7C\xF9\xDD\xDF\xDE\x7E\xC1\xE4\x4B\xDF\x7A\xC5\xE4\xE3\xE1\x81\xC0\xEA\xE0\xDE\x5D\xF9\xA7\x48\xD8\x14\xAD\xDC\xD8\xD9\x66\xD2\xE9\xDB\xE4\x97\xD9\xEB\xDA\xC6\x8D\xDD\xEE\xE5\xB7\x24\x2A\xCF\xE7\xE8\x13\xA5\x02\xE8\x74\x29\x40\x09\xEB\xEA\x28\x6D\xE6\x42\xEB\xAA\xF0\xEC\xEB\xEB\xB4\xF1\xE5\xEF\xEC\xB6\xF9\xE8\xEF\xEE\xB2\xFD\xE7\xEC\xEC\x2C\x7A\xEE\xED\xEE\xBB\x7C\xEF\xEF\xF1\xC2\xC8\xF6\xF1\xF2\xCC\xCB\xFE\xF3\xF0\xCF\xF5\xE1\xF1\xF4\xC4\xFA\x6E\x49\x4B\x04\x57\xF0\x02\xF6\xDC\xD9\xFE\xF4\xF6\xE0\xDB\xFF\xF6\xF8\xE1\xDD\xF5\xFB\xF8\xE6\xE4\xFA\xF9\xFA\xEC\xE8\xFE\xF9\x40\x29\x2F\xFB\xFB\xF8\xC5\xD0\xF6\xFE\xF2\xF7\xCD\xF9\xFC\xF5\xFC\xFB\xFB\x4A\xFF\xB5\x7B\x36\x0A\x04\x23\x81\x80\x05\x80\x00\x07\x89\x80\x01\x8B\x86\x80\x06\x88\x86\x81\x0A\x8D\x82\x04\x8F\x83\x83\x08\x80\x03\x05\x10\x99\x81\x05\x9A\x84\x83\x0E\x96\x87\x83\x1C\x95\x7C\xFE\x23\x8A\x7E\x12\xBD\x7E\x84\x00\x85\x86\x0A\xD3\x79\x84\xD2\x6E\x82\x41\xFE\x1F\x1B\x1A\x00\x04\x00\x04\x30\x25\x20\x34\x92\x22\x0E\xA6\x31\x36\xCB\x01\x23", + "\x39\x00\x00\x88\x10\xC6\x38\x87\xD5\x01\x21\x38\x00\x05\x35\x10\x9E\x35\x32\x8C\x01\x21\x33\x00\x08\x88\x14\xC4\x88\x89\x2A\x8E\x89\x8A\x57\x96\x8B\x11\xD9\x87\x32\x2D\x98\x8B\x8B\x60\x9F\x8A\x18\xC8\x83\x32", + }; + vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); + } + } + } +} + diff --git a/Import/VlppGlrParser.h b/Import/VlppGlrParser.h new file mode 100644 index 00000000..97a04122 --- /dev/null +++ b/Import/VlppGlrParser.h @@ -0,0 +1,2822 @@ +/*********************************************************************** +THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY +DEVELOPER: Zihan Chen(vczh) +***********************************************************************/ +#include "VlppReflection.h" +#include "VlppOS.h" +#include "Vlpp.h" +#include "VlppRegex.h" + +/*********************************************************************** +.\ASTBASE.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_ASTBASE +#define VCZH_PARSER2_ASTBASE + + +namespace vl +{ + namespace glr + { +/*********************************************************************** +ParsingTextPos +***********************************************************************/ + + /// A type representing text position. + struct ParsingTextPos + { + static const vint UnknownValue = -2; + /// Character index, begins at 0. + vint index; + /// Row number, begins at 0. + vint row; + /// Column number, begins at 0. + vint column; + + ParsingTextPos() + :index(UnknownValue) + , row(UnknownValue) + , column(UnknownValue) + { + } + + ParsingTextPos(vint _index) + :index(_index) + , row(UnknownValue) + , column(UnknownValue) + { + } + + ParsingTextPos(vint _row, vint _column) + :index(UnknownValue) + , row(_row) + , column(_column) + { + } + + ParsingTextPos(vint _index, vint _row, vint _column) + :index(_index) + , row(_row) + , column(_column) + { + } + + /// Test if this position a valid position. + /// Returns true if this position is a valid position. + bool IsInvalid()const + { + return index < 0 && row < 0 && column < 0; + } + + static ParsingTextPos Start(const regex::RegexToken* token) + { + return { token->start,token->rowStart,token->columnStart }; + } + + static ParsingTextPos End(const regex::RegexToken* token) + { + return { token->start + token->length - 1,token->rowEnd,token->columnEnd }; + } + + static vint Compare(const ParsingTextPos& a, const ParsingTextPos& b) + { + if (a.IsInvalid() && b.IsInvalid()) + { + return 0; + } + else if (a.IsInvalid()) + { + return -1; + } + else if (b.IsInvalid()) + { + return 1; + } + else if (a.index >= 0 && b.index >= 0) + { + return a.index - b.index; + } + else if (a.row >= 0 && a.column >= 0 && b.row >= 0 && b.column >= 0) + { + if (a.row == b.row) + { + return a.column - b.column; + } + else + { + return a.row - b.row; + } + } + else + { + return 0; + } + } + + bool operator==(const ParsingTextPos& pos)const { return Compare(*this, pos) == 0; } + bool operator!=(const ParsingTextPos& pos)const { return Compare(*this, pos) != 0; } + bool operator<(const ParsingTextPos& pos)const { return Compare(*this, pos) < 0; } + bool operator<=(const ParsingTextPos& pos)const { return Compare(*this, pos) <= 0; } + bool operator>(const ParsingTextPos& pos)const { return Compare(*this, pos) > 0; } + bool operator>=(const ParsingTextPos& pos)const { return Compare(*this, pos) >= 0; } + }; + +/*********************************************************************** +ParsingTextRange +***********************************************************************/ + + /// A type representing text range. + struct ParsingTextRange + { + /// Text position for the first character. + ParsingTextPos start; + /// Text position for the last character. + ParsingTextPos end; + /// Code index, refer to [F:vl.regex.RegexToken.codeIndex] + vint codeIndex = -1; + + ParsingTextRange() = default; + + ParsingTextRange(const ParsingTextPos& _start, const ParsingTextPos& _end, vint _codeIndex = -1) + : start(_start) + , end(_end) + , codeIndex(_codeIndex) + { + } + + ParsingTextRange(const regex::RegexToken* startToken, const regex::RegexToken* endToken) + : start(ParsingTextPos::Start(startToken)) + , end(ParsingTextPos::End(endToken)) + , codeIndex(startToken->codeIndex) + { + } + + bool operator==(const ParsingTextRange& range)const { return start == range.start && end == range.end; } + bool operator!=(const ParsingTextRange& range)const { return start != range.start || end != range.end; } + bool Contains(const ParsingTextPos& pos)const { return start <= pos && pos <= end; } + bool Contains(const ParsingTextRange& range)const { return start <= range.start && range.end <= end; } + }; + +/*********************************************************************** +ParsingError +***********************************************************************/ + + class ParsingAstBase; + + struct ParsingError + { + ParsingAstBase* node = nullptr; + ParsingTextRange codeRange; + WString message; + }; + +/*********************************************************************** +AST +***********************************************************************/ + + /// Base type of all strong typed syntax tree. Normally all strong typed syntax tree are generated from a grammar file using ParserGen.exe in Tools project. + class ParsingAstBase : public Object, public reflection::Description + { + public: + /// Range of all tokens that form this object. + ParsingTextRange codeRange; + }; + + /// Strong typed token syntax node, for all class fields of type "token" in the grammar file. See [T:vl.parsing.tabling.ParsingTable] for details. + struct ParsingToken + { + public: + /// Range of all tokens that form this object. + ParsingTextRange codeRange; + /// Index of the token in the token list provided to the parser. + vint index = -1; + /// Type of the token, representing the index of a regular expression that creates this token in the regular expression list in the grammar file. + vint token = -1; + /// Content of the token. + WString value; + + operator bool() const { return value.Length() > 0; } + }; + +/*********************************************************************** +AST (Builder) +***********************************************************************/ + + template + class ParsingAstBuilder + { + protected: + Ptr node = MakePtr(); + ParsingAstBuilder() {} + public: + + template + operator Ptr() const + { + return node; + } + }; + +/*********************************************************************** +AST (Visitor) +***********************************************************************/ + + class CopyVisitorBase : public Object + { + protected: + Ptr result; + }; + + class JsonVisitorBase : public Object + { + private: + stream::StreamWriter& writer; + vint indentation = 0; + collections::List indices; + + protected: + + void BeginObject(); + void BeginField(const WString& field); + void EndField(); + void EndObject(); + void BeginArray(); + void BeginArrayItem(); + void EndArrayItem(); + void EndArray(); + void WriteIndent(); + void WriteRange(const ParsingTextRange& range); + void WriteToken(const ParsingToken& token); + void WriteType(const WString& type, ParsingAstBase* node); + void WriteString(const WString& text); + void WriteNull(); + public: + bool printTokenCodeRange = true; + bool printAstCodeRange = true; + bool printAstType = true; + + JsonVisitorBase(stream::StreamWriter& _writer); + }; + + extern void JsonEscapeString(const WString& text, stream::TextWriter& writer); + extern void JsonUnescapeString(const WString& text, stream::TextWriter& writer); + +/*********************************************************************** +Instructions +***********************************************************************/ + + enum class AstInsType + { + Token, // Token() : Push the current token as a value. + EnumItem, // EnumItem(Value) : Push an enum item. + BeginObject, // BeginObject(Type) : Begin creating an AST node. + BeginObjectLeftRecursive, // BeginObjectLeftRecursive(Type) : Begin creating an AST node, taking the ownership of the last pushed object. + DelayFieldAssignment, // DelayFieldAssignment() : An object will be created later by ReopenObject, delay future field assignments to this object before ReopenObject. + ReopenObject, // ReopenObject() : Move the last pushed object back to creating status. + EndObject, // EndObject() : Finish creating an AST node, all objects pushed after BeginObject are supposed to be its fields. + DiscardValue, // DiscardValue() : Remove a pushed value. + Field, // Field(Field) : Associate a field name with the top object. + ResolveAmbiguity, // ResolveAmbiguity(Type, Count) : Combine several top objects to one using an ambiguity node. Type is the type of each top object. + + AccumulatedDfa, // AccumulatedDfa(Count) : Multiple DelayFieldAssignment + AccumulatedEoRo, // AccumulatedEoRo(Count) : Multiple EndObject + ReopenObject + }; + + struct AstIns + { + AstInsType type = AstInsType::Token; + vint32_t param = -1; + vint count = -1; + + vint Compare(const AstIns& ins) const + { + auto result = (vint)type - (vint)ins.type; + if (result != 0) return result; + result = (vint)param - (vint)ins.param; + if (result != 0) return result; + return count - ins.count; + } + + bool operator==(const AstIns& ins) const { return Compare(ins) == 0; } + bool operator!=(const AstIns& ins) const { return Compare(ins) != 0; } + bool operator< (const AstIns& ins) const { return Compare(ins) < 0; } + bool operator<=(const AstIns& ins) const { return Compare(ins) <= 0; } + bool operator> (const AstIns& ins) const { return Compare(ins) > 0; } + bool operator>=(const AstIns& ins) const { return Compare(ins) >= 0; } + }; + + enum class AstInsErrorType + { + UnknownType, // UnknownType(Type) : The type id does not exist. + UnknownField, // UnknownField(Field) : The field id does not exist. + UnsupportedAbstractType, // UnsupportedAbstractType(Type) : Unable to create abstract class. + UnsupportedAmbiguityType, // UnsupportedAmbiguityType(Type) : The type is not configured to allow ambiguity. + UnexpectedAmbiguousCandidate, // UnexpectedAmbiguousCandidate(Type) : The type of the ambiguous candidate is not compatible to the required type. + FieldNotExistsInType, // FieldNotExistsInType(Field) : The type doesn't have such field. + FieldReassigned, // FieldReassigned(Field) : An object is assigned to a field but this field has already been assigned. + ObjectTypeMismatchedToField, // ObjectTypeMismatchedToField(Field) : Unable to assign an object to a field because the type does not match. + + NoRootObject, // NoRootObject() : There is no created objects. + NoRootObjectAfterDfa, // NoRootObjectAfterDfa() : There is no created objects after DelayFieldAssignment. + MissingLeftRecursiveValue, // MissingLeftRecursiveValue() : There is no pushed value to create left recursive object. + LeftRecursiveValueIsNotObject, // LeftRecursiveValueIsNotObject() : The pushed value to create left recursive object is not an object. + TooManyUnassignedValues, // LeavingUnassignedValues() : The value to reopen is not the only unassigned value. + MissingDfaBeforeReopen, // MissingDfaBeforeReopen() : DelayFieldAssignment is not submitted before ReopenObject. + MissingValueToReopen, // MissingValueToReopen() : There is no pushed value to reopen. + ReopenedValueIsNotObject, // ReopenedValueIsNotObject() : The pushed value to reopen is not an object. + MissingValueToDiscard, // MissingValueToDiscard() : There is no pushed value to discard. + LeavingUnassignedValues, // LeavingUnassignedValues() : There are still values to assign to fields before finishing an object. + MissingFieldValue, // MissingFieldValue() : There is no pushed value to be assigned to a field. + MissingAmbiguityCandidate, // MissingAmbiguityCandidate() : There are not enough candidates to create an ambiguity node. + AmbiguityCandidateIsNotObject, // AmbiguityCandidateIsNotObject() : Tokens or enum items cannot be ambiguity candidates. + InstructionNotComplete, // InstructionNotComplete() : No more instruction but the root object has not been completed yet. + Corrupted, // Corrupted() : An exception has been thrown therefore this receiver cannot be used anymore. + Finished, // Finished() : The finished instruction has been executed therefore this receiver cannot be used anymore. + }; + + class AstInsException : public Exception + { + public: + AstInsErrorType error = AstInsErrorType::Corrupted; + vint32_t paramTypeOrField = -1; + + AstInsException(const WString& message, AstInsErrorType _error, vint32_t _typeOrField = -1) + : Exception(message) + , error(_error) + , paramTypeOrField(_typeOrField) + { + } + }; + +/*********************************************************************** +IAstInsReceiver +***********************************************************************/ + + class IAstInsReceiver : public virtual Interface + { + public: + virtual void Execute(AstIns instruction, const regex::RegexToken& token, vint32_t tokenIndex) = 0; + virtual Ptr Finished() = 0; + }; + + class AstInsReceiverBase : public Object, public virtual IAstInsReceiver + { + private: + struct ObjectOrToken + { + Ptr object; + vint32_t enumItem = -1; + regex::RegexToken token = {}; + vint32_t tokenIndex = -1; + + explicit ObjectOrToken(Ptr _object) : object(_object) {} + explicit ObjectOrToken(vint32_t _enumItem) : enumItem(_enumItem) {} + explicit ObjectOrToken(const regex::RegexToken& _token, vint32_t _tokenIndex) : token(_token), tokenIndex(_tokenIndex) {} + }; + + struct FieldAssignment + { + ObjectOrToken value; + vint32_t field; + }; + + struct CreatedObject + { + Ptr object; + vint pushedCount; + + regex::RegexToken delayedToken; + collections::List delayedFieldAssignments; + vint extraEmptyDfaBelow = 0; + + CreatedObject(Ptr _object, vint _pushedCount) + : object(_object) + , pushedCount(_pushedCount) + { + } + + CreatedObject(Ptr _object, vint _pushedCount, const regex::RegexToken& _delayedToken) + : object(_object) + , pushedCount(_pushedCount) + , delayedToken(_delayedToken) + { + } + }; + + collections::List created; + collections::List pushed; + bool finished = false; + bool corrupted = false; + + void EnsureContinuable(); + void SetField(ParsingAstBase* object, vint32_t field, const ObjectOrToken& value); + + CreatedObject& PushCreated(CreatedObject&& createdObject); + const CreatedObject& TopCreated(); + void PopCreated(); + void DelayAssign(FieldAssignment&& fa); + protected: + virtual Ptr CreateAstNode(vint32_t type) = 0; + virtual void SetField(ParsingAstBase* object, vint32_t field, Ptr value) = 0; + virtual void SetField(ParsingAstBase* object, vint32_t field, const regex::RegexToken& token, vint32_t tokenIndex) = 0; + virtual void SetField(ParsingAstBase* object, vint32_t field, vint32_t enumValue) = 0; + virtual Ptr ResolveAmbiguity(vint32_t type, collections::Array>& candidates) = 0; + + public: + AstInsReceiverBase() = default; + ~AstInsReceiverBase() = default; + + void Execute(AstIns instruction, const regex::RegexToken& token, vint32_t tokenIndex) override; + Ptr Finished() override; + }; + +/*********************************************************************** +IAstInsReceiver (Code Generation Templates) +***********************************************************************/ + + template + void AssemblerSetObjectField(Ptr(TClass::* member), ParsingAstBase* object, vint32_t field, Ptr value, const wchar_t* cppFieldName) + { + auto typedObject = dynamic_cast(object); + if (!typedObject) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" does not exist in the current object."), + AstInsErrorType::FieldNotExistsInType, field); + } + if ((typedObject->*member)) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" has already been assigned."), + AstInsErrorType::FieldReassigned, field); + } + + auto typedValue = value.Cast(); + if (!typedValue) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" cannot be assigned with an uncompatible value."), + AstInsErrorType::ObjectTypeMismatchedToField, field); + } + (typedObject->*member) = typedValue; + } + + template + void AssemblerSetObjectField(collections::List>(TClass::* member), ParsingAstBase* object, vint32_t field, Ptr value, const wchar_t* cppFieldName) + { + auto typedObject = dynamic_cast(object); + if (!typedObject) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" does not exist in the current object."), + AstInsErrorType::FieldNotExistsInType, field); + } + + auto typedValue = value.Cast(); + if (!typedValue) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" cannot be assigned with an uncompatible value."), + AstInsErrorType::ObjectTypeMismatchedToField, field); + } + (typedObject->*member).Add(typedValue); + } + + template + void AssemblerSetTokenField(ParsingToken(TClass::* member), ParsingAstBase* object, vint32_t field, const regex::RegexToken& token, vint32_t tokenIndex, const wchar_t* cppFieldName) + { + auto typedObject = dynamic_cast(object); + if (!typedObject) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" does not exist in the current object."), + AstInsErrorType::FieldNotExistsInType, field); + } + if ((typedObject->*member).value.Length() != 0) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" has already been assigned."), + AstInsErrorType::FieldReassigned, field); + } + + ParsingToken& tokenField = typedObject->*member; + tokenField.codeRange = { &token,&token }; + tokenField.index = tokenIndex; + tokenField.token = token.token; + tokenField.value = WString::CopyFrom(token.reading, token.length); + } + + template + void AssemblerSetEnumField(TField(TClass::* member), ParsingAstBase* object, vint32_t field, vint32_t enumItem, const wchar_t* cppFieldName) + { + auto typedObject = dynamic_cast(object); + if (!typedObject) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" does not exist in the current object."), + AstInsErrorType::FieldNotExistsInType, field); + } + if ((typedObject->*member) != TField::UNDEFINED_ENUM_ITEM_VALUE) + { + throw AstInsException( + WString::Unmanaged(L"Field \"") + + WString::Unmanaged(cppFieldName) + + WString::Unmanaged(L"\" has already been assigned."), + AstInsErrorType::FieldReassigned, field); + } + (typedObject->*member) = (TField)enumItem; + } + + template + Ptr AssemblerResolveAmbiguity(vint32_t type, collections::Array>& candidates, const wchar_t* cppTypeName) + { + Ptr ast = new TAmbiguity(); + for (auto candidate : candidates) + { + if (auto typedAst = candidate.Cast()) + { + ast->candidates.Add(typedAst); + } + else if (auto ambiguityAst = candidate.Cast()) + { + CopyFrom(ast->candidates, ambiguityAst->candidates, true); + } + else + { + throw AstInsException( + WString::Unmanaged(L"The type of the ambiguous candidate is not compatible to the required type \"") + + WString::Unmanaged(cppTypeName) + + WString::Unmanaged(L"\"."), + AstInsErrorType::UnexpectedAmbiguousCandidate, type); + } + } + return ast; + } + + template + vint32_t AssemblerFindCommonBaseClass(vint32_t class1, vint32_t class2, vint32_t(&matrix)[Size][Size]) + { + if (class1 < 0 || class1 >= Size) throw glr::AstInsException(L"The type id does not exist.", glr::AstInsErrorType::UnknownType, class1); + if (class2 < 0 || class2 >= Size) throw glr::AstInsException(L"The type id does not exist.", glr::AstInsErrorType::UnknownType, class2); + return matrix[class1][class2]; + } + +/*********************************************************************** +IAstInsReceiver (Code Generation Error Templates) +***********************************************************************/ + + extern Ptr AssemblyThrowCannotCreateAbstractType(vint32_t type, const wchar_t* cppTypeName); + extern void AssemblyThrowFieldNotObject(vint32_t field, const wchar_t* cppFieldName); + extern void AssemblyThrowFieldNotToken(vint32_t field, const wchar_t* cppFieldName); + extern void AssemblyThrowFieldNotEnum(vint32_t field, const wchar_t* cppFieldName); + extern Ptr AssemblyThrowTypeNotAllowAmbiguity(vint32_t type, const wchar_t* cppTypeName); + +/*********************************************************************** +Compression +***********************************************************************/ + + extern void DecompressSerializedData(const char** buffer, bool decompress, vint solidRows, vint rows, vint block, vint remain, stream::IStream& outputStream); + } + +/*********************************************************************** +Reflection +***********************************************************************/ + + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + DECL_TYPE_INFO(vl::glr::ParsingTextPos) + DECL_TYPE_INFO(vl::glr::ParsingTextRange) + DECL_TYPE_INFO(vl::glr::ParsingToken) + DECL_TYPE_INFO(vl::glr::ParsingAstBase) +#endif + extern bool LoadParsing2Types(); + } + } +} + +#endif + +/*********************************************************************** +.\ASTPRINT.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_ASTPRINT +#define VCZH_PARSER2_ASTPRINT + + +namespace vl +{ + namespace glr + { +/*********************************************************************** +IParsingPrintNodeRecorder +***********************************************************************/ + + class IParsingPrintNodeRecorder : public virtual Interface + { + public: + virtual void Record(ParsingAstBase* node, const ParsingTextRange& range) = 0; + }; + + class ParsingEmptyPrintNodeRecorder : public Object, public virtual IParsingPrintNodeRecorder + { + public: + ParsingEmptyPrintNodeRecorder(); + ~ParsingEmptyPrintNodeRecorder(); + + void Record(ParsingAstBase* node, const ParsingTextRange& range)override; + }; + + class ParsingMultiplePrintNodeRecorder : public Object, public virtual IParsingPrintNodeRecorder + { + typedef collections::List> RecorderList; + protected: + RecorderList recorders; + + public: + ParsingMultiplePrintNodeRecorder(); + ~ParsingMultiplePrintNodeRecorder(); + + void AddRecorder(Ptr recorder); + void Record(ParsingAstBase* node, const ParsingTextRange& range)override; + }; + + class ParsingOriginalLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder + { + protected: + Ptr recorder; + + public: + ParsingOriginalLocationRecorder(Ptr _recorder); + ~ParsingOriginalLocationRecorder(); + + void Record(ParsingAstBase* node, const ParsingTextRange& range)override; + }; + + class ParsingGeneratedLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder + { + typedef collections::Dictionary RangeMap; + protected: + RangeMap& rangeMap; + + public: + ParsingGeneratedLocationRecorder(RangeMap& _rangeMap); + ~ParsingGeneratedLocationRecorder(); + + void Record(ParsingAstBase* node, const ParsingTextRange& range)override; + }; + + class ParsingUpdateLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder + { + public: + ParsingUpdateLocationRecorder(); + ~ParsingUpdateLocationRecorder(); + + void Record(ParsingAstBase* node, const ParsingTextRange& range)override; + }; + +/*********************************************************************** +ParsingWriter +***********************************************************************/ + + class ParsingWriter : public stream::TextWriter + { + typedef collections::Pair NodePosPair; + typedef collections::List NodePosList; + protected: + stream::TextWriter& writer; + Ptr recorder; + vint codeIndex; + ParsingTextPos lastPos; + ParsingTextPos currentPos; + NodePosList nodePositions; + + void HandleChar(wchar_t c); + public: + ParsingWriter(stream::TextWriter& _writer, Ptr _recorder = nullptr, vint _codeIndex = -1); + ~ParsingWriter(); + + using stream::TextWriter::WriteString; + void WriteChar(wchar_t c)override; + void WriteString(const wchar_t* string, vint charCount)override; + void BeforePrint(ParsingAstBase* node); + void AfterPrint(ParsingAstBase* node); + }; + } +} + +#endif + +/*********************************************************************** +.\EXECUTABLE.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_EXECUTABLE +#define VCZH_PARSER2_EXECUTABLE + + +namespace vl +{ + namespace glr + { + namespace automaton + { +/*********************************************************************** +Executable +***********************************************************************/ + + struct InstructionArray + { + vint32_t start = -1; + vint32_t count = 0; + }; + + struct ReturnIndexArray + { + vint32_t start = -1; + vint32_t count = -1; + }; + + struct EdgeArray + { + vint32_t start = -1; + vint32_t count = 0; + }; + + enum class EdgePriority + { + NoCompetition, + HighPriority, + LowPriority, + }; + + struct ReturnDesc + { + vint32_t consumedRule = -1; + vint32_t returnState = -1; + EdgePriority priority = EdgePriority::NoCompetition; + InstructionArray insAfterInput; + }; + + struct EdgeDesc + { + vint32_t fromState = -1; + vint32_t toState = -1; + EdgePriority priority = EdgePriority::NoCompetition; + InstructionArray insBeforeInput; + InstructionArray insAfterInput; + ReturnIndexArray returnIndices; + }; + + struct StateDesc + { + vint32_t rule = -1; + vint32_t clause = -1; + bool endingState = false; + }; + + struct Executable + { + static constexpr vint32_t EndOfInputInput = -1; + static constexpr vint32_t EndingInput = 0; + static constexpr vint32_t LeftrecInput = 1; + static constexpr vint32_t TokenBegin = 2; + + vint32_t tokenCount = 0; + vint32_t ruleCount = 0; + collections::Array ruleStartStates; // ruleStartStates[rule] = the start state of this rule. + collections::Array transitions; // transitions[state * (TokenBegin + tokenCount) + input] = edges from state with specified input. + collections::Array instructions; // referenced by InstructionArray + collections::Array returnIndices; // referenced by ReturnIndexArray + collections::Array returns; // referenced by Executable::returnIndices + collections::Array edges; // referenced by EdgeArray + collections::Array states; // refereced by returnState/fromState/toState + + Executable() = default; + Executable(stream::IStream& inputStream); + + void Serialize(stream::IStream& outputStream); + + vint32_t GetTransitionIndex(vint32_t state, vint32_t input) + { + return state * (TokenBegin + tokenCount) + input; + } + }; + + struct Metadata + { + collections::Array ruleNames; + collections::Array stateLabels; + }; + } + } +} + +#endif + +/*********************************************************************** +.\TRACEMANAGER\TRACEMANAGER.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_TRACEMANAGER_TRACEMANAGER +#define VCZH_PARSER2_TRACEMANAGER_TRACEMANAGER + + +namespace vl +{ + namespace glr + { + namespace automaton + { +/*********************************************************************** +AllocateOnly +***********************************************************************/ + + template + class AllocateOnly : public Object + { + protected: + vint blockSize; + vint remains; + collections::List>> buffers; + + public: + AllocateOnly(vint _blockSize = 65536) + : blockSize(_blockSize) + , remains(0) + { + } + + T* Get(vint32_t index) + { + vint row = index / blockSize; + vint column = index % blockSize; + CHECK_ERROR(0 <= row && row < buffers.Count(), L"vl::glr::automaton::AllocateOnly::Get(vint)#Index out of range."); + if (row == buffers.Count() - 1) + { + CHECK_ERROR(0 <= column && column < (blockSize - remains), L"vl::glr::automaton::AllocateOnly::Get(vint)#Index out of range."); + } + else + { + CHECK_ERROR(0 <= column && column < blockSize, L"vl::glr::automaton::AllocateOnly::Get(vint)#Index out of range."); + } + return &buffers[row]->operator[](column); + } + + vint32_t Allocate() + { + if (remains == 0) + { + buffers.Add(new collections::Array(blockSize)); + remains = blockSize; + } + vint index = blockSize * (buffers.Count() - 1) + (blockSize - remains); + buffers[buffers.Count() - 1]->operator[](blockSize - remains).allocatedIndex = (vint32_t)index; + remains--; + return (vint32_t)index; + } + + void Clear() + { + remains = 0; + buffers.Clear(); + } + }; + +/*********************************************************************** +TraceManager (Data Structures) +***********************************************************************/ + + struct ReturnStackSuccessors + { + vint32_t createdTokenIndex = -1; // index of the token when this ReturnStack is created + vint32_t successorTokenIndex = -1; // index of the token when this ReturnStack has its first successor + // the following members records all successors + // that is created at the token index + + vint32_t first = -1; // first successor + vint32_t last = -1; // last successor + vint32_t prev = -1; // previous successor of ReturnStack::previous + vint32_t next = -1; // next successor of ReturnStack::previous + }; + + struct ReturnStack + { + vint32_t allocatedIndex = -1; // id of this ReturnStack + vint32_t previous = -1; // id of the previous ReturnStack + vint32_t returnIndex = -1; // index of ReturnDesc + ReturnStackSuccessors successors; + }; + + struct TraceCollection + { + vint32_t first = -1; // first trace in the collection + vint32_t last = -1; // last trace in the collection + vint32_t siblingPrev = -1; // previous trace in the collection of the owned trace + vint32_t siblingNext = -1; // next trace in the collection of the owned trace + }; + + struct TraceAmbiguity + { + vint32_t insEndObject = -1; // the index of the first EndObject instruction + // in {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined + // when this member is valid, the trace should satisfies: + // trace.ambiguity.insEndObject == trace.byEdge.insBeforeInput.count - trace.ambiguityInsPostfix + + vint32_t traceBeginObject = -1; // id of the trace containing BeginObject or DelayFieldAssignment + // that ends by the above EndObject + + vint32_t insBeginObject = -1; // the index of the BeginObject instruction + // from traceBeginObject + // in {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined + // if insBeginObject is larger than the number of instructions in traceBeginObject + // then the branches begin from the (insBeginObject - instruction-count(traceBeginObject))-th instruction (starting from 0) in all successors + + vint32_t ambiguityType = -1; // when the BeginObject creates an object that later be consumed by BeginObjectLeftRecursive + // than the correct type is the type in BeginObjectLeftRecursive + }; + + enum class CompetitionStatus + { + Holding, + HighPriorityWin, + LowPriorityWin, + }; + + struct Competition + { + vint32_t allocatedIndex = -1; + vint32_t nextActiveCompetition = -1; // next active Competition + vint32_t nextHoldCompetition = -1; // next Competition hold by this trace + + CompetitionStatus status = CompetitionStatus::Holding; // if predecessors from this trace have different priority, the competition begins + // when the competition is over, it will be changed to HighPriorityWin or LowPriorityWin + // if all candidates fail, it could be Holding forever + + vint32_t currentTokenIndex = -1; // currentTokenIndex from the trace that creates this competition + vint32_t ruleId = -1; // the rule id of state, when an edge starts this competition + vint32_t clauseId = -1; // the clause id of the state, when an edge starts this competition + // an state must be picked up and ensure that, the syntax creating the priority and the state belong to the same clause + + vint32_t highCounter = 0; // temporary counter for all existing high bets + // in the current step of input + vint32_t lowCounter = 0; // temporary counter for all existing low bets + // in the current step of input + }; + + struct AttendingCompetitions + { + vint32_t allocatedIndex = -1; // id of this AttendingCompetitions + vint32_t nextActiveAC = -1; // the next AttendingCompetitions for RuntimeRouting::attendingCompetitions + vint32_t nextCarriedAC = -1; // the next AttendingCompetitions for RuntimeRouting::carriedCompetitions + vint32_t competition = -1; // the id of the Competition + bool forHighPriority = false; // bet of this competition + + vint32_t returnStack = -1; // the ReturnStack object for the competition + // if the competition is attended by a ReturnDesc + // then the ReturnStack object is the one before a ReturnDesc transition happens + + bool closed = false; // true if the competition has been closed + // this flag is not always updated for discarded AttendingCompetitions objects + }; + + struct CompetitionRouting + { + vint32_t holdingCompetitions = -1; // the id of the active Competition + + vint32_t attendingCompetitions = -1; // a linked list containing all AttendingCompetitions that this trace is attending + // predecessors could share and modify the same linked list + // if a competition is over, node could be removed from the linked list + // one competition only creates two AttendingCompetitions, traces with the same bet share the object + + vint32_t carriedCompetitions = -1; // all attended competitions regardless of the status of the competition + }; + + struct AmbiguityRouting + { + vint32_t predecessorCount = -1; // the number of predecessors + // (filled by ExecuteTrace) + + vint32_t branchVisited = 0; // the number of visited branches in the current loop. + // if these branches are contained in a larger ambiguity resolving loop, all branches could be visited multiple times + // (filled by ExecuteTrace) + }; + + struct Trace + { + vint32_t allocatedIndex = -1; // id of this Trace + TraceCollection predecessors; // id of the predecessor Trace + TraceCollection successors; // successors (filled by PrepareTraceRoute) + + vint32_t state = -1; // id of the current StateDesc + vint32_t returnStack = -1; // id of the current ReturnStack + vint32_t executedReturnStack = -1; // id of the executed ReturnStack that contains the ReturnDesc being executed + vint32_t byEdge = -1; // id of the last EdgeDesc that make this trace + vint32_t byInput = -1; // the last input that make this trace + vint32_t currentTokenIndex = -1; // the index of the token that is byInput + + TraceAmbiguity ambiguity; // where to end resolving ambiguity in instructions from this trace + // this member is useful when it has multiple predecessors + // (filled by PrepareTraceRoute) + + vint32_t ambiguityBranchInsPostfix = -1; // this member is useful when it is not -1 and the trace has multiple successors + // specifying the length of the postfix + // of {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined + // only execute the specified prefix of instructions + // usually EndObject is the last instruction in the prefix + + vint32_t ambiguityMergeInsPostfix = -1; // this member is useful when it is not -1 and the trace has multiple predecessors + // specifying the length of the postfix + // of {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined + // only execute the specified postfix of instructions + // usually EndObject is the last instruction in the prefix + + CompetitionRouting competitionRouting; // a data structure carrying priority and competition information + + AmbiguityRouting ambiguityRouting; // a data structure guiding instruction execution when a trace need to be executed multiple times + // this member is useful when it has multiple predecessors or successors + }; + + enum class TraceManagerState + { + Uninitialized, + WaitingForInput, + Finished, + PreparedTraceRoute, + }; + + struct TraceInsLists + { + InstructionArray edgeInsBeforeInput; + InstructionArray edgeInsAfterInput; + InstructionArray returnInsAfterInput; + vint32_t c1; + vint32_t c2; + vint32_t c3; + }; + +/*********************************************************************** +TraceManager +***********************************************************************/ + + class TraceManager : public Object + { + public: + class ITypeCallback : public virtual Interface + { + public: + virtual vint32_t FindCommonBaseClass(vint32_t class1, vint32_t class2) const= 0; + }; + + protected: + Executable& executable; + const ITypeCallback* typeCallback = nullptr; + + TraceManagerState state = TraceManagerState::Uninitialized; + AllocateOnly returnStacks; + AllocateOnly traces; + AllocateOnly competitions; + AllocateOnly attendingCompetitions; + + collections::List traces1; + collections::List traces2; + + Trace* initialTrace = nullptr; + vint32_t activeCompetitions = -1; + ReturnStackSuccessors initialReturnStackSuccessors; + + void BeginSwap(); + void AddTrace(Trace* trace); + void EndSwap(); + void AddTraceToCollection(Trace* owner, Trace* element, TraceCollection(Trace::* collection)); + + // Ambiguity + bool AreTwoEndingInputTraceEqual(vint32_t state, vint32_t returnStack, vint32_t executedReturnStack, vint32_t acId, Trace* candidate); + vint32_t GetInstructionPostfix(EdgeDesc& oldEdge, EdgeDesc& newEdge); + void MergeTwoEndingInputTrace( + Trace* trace, + Trace* ambiguityTraceToMerge, + vint32_t currentTokenIndex, + vint32_t input, + vint32_t byEdge, + EdgeDesc& edgeDesc, + vint32_t state, + vint32_t returnStack, + vint32_t attendingCompetitions, + vint32_t carriedCompetitions, + vint32_t executedReturnStack); + + // Competition + void AttendCompetition(Trace* trace, vint32_t& newAttendingCompetitions, vint32_t& newCarriedCompetitions, vint32_t returnStack, vint32_t ruleId, vint32_t clauseId, bool forHighPriority); + ReturnStack* PushReturnStack(vint32_t base, vint32_t returnIndex, vint32_t currentTokenIndex); + void AttendCompetitionIfNecessary(Trace* trace, vint32_t currentTokenIndex, EdgeDesc& edgeDesc, vint32_t& newAttendingCompetitions, vint32_t& newCarriedCompetitions, vint32_t& newReturnStack); + void CheckAttendingCompetitionsOnEndingEdge(Trace* trace, EdgeDesc& edgeDesc, vint32_t acId, vint32_t returnStack); + void CheckBackupTracesBeforeSwapping(vint32_t currentTokenIndex); + + // Walk + Trace* WalkAlongSingleEdge(vint32_t currentTokenIndex, vint32_t input, Trace* trace, vint32_t byEdge, EdgeDesc& edgeDesc); + void WalkAlongLeftrecEdges(vint32_t currentTokenIndex, vint32_t lookAhead, Trace* trace, EdgeArray& edgeArray); + void WalkAlongEpsilonEdges(vint32_t currentTokenIndex, vint32_t lookAhead, Trace* trace); + void WalkAlongTokenEdges(vint32_t currentTokenIndex, vint32_t input, vint32_t lookAhead, Trace* trace, EdgeArray& edgeArray); + + // PrepareTraceRoute + struct SharedBeginObject + { + Trace* traceBeginObject = nullptr; + vint32_t insBeginObject = -1; + vint32_t type = -1; + }; + + void ReadInstructionList(Trace* trace, TraceInsLists& insLists); + AstIns& ReadInstruction(vint32_t instruction, TraceInsLists& insLists); + bool RunInstruction(vint32_t instruction, TraceInsLists& insLists, vint32_t& objectCount, vint32_t& reopenCount); + void AdjustToRealTrace(SharedBeginObject& shared); + + void FindBalancedBoOrBolr(SharedBeginObject& balanced, vint32_t& objectCount, vint32_t& reopenCount); + void FindBalancedBoOrDfa(Trace* trace, vint32_t objectCount, SharedBeginObject& branch); + + void MergeAmbiguityType(vint32_t& ambiguityType, vint32_t branchType); + SharedBeginObject MergeSharedBeginObjectsSingleRoot(Trace* trace, collections::Dictionary& predecessorToBranches); + SharedBeginObject MergeSharedBeginObjectsMultipleRoot(Trace* trace, collections::Dictionary& predecessorToBranches); + SharedBeginObject MergeSharedBeginObjectsPartialMultipleRoot(Trace* trace, vint32_t ambiguityType, collections::Group& beginToPredecessors, collections::Dictionary& predecessorToBranches); + + SharedBeginObject FillAmbiguityInfoForMergingTrace(Trace* trace); + void FillAmbiguityInfoForPredecessorTraces(Trace* trace); + void CreateLastMergingTrace(Trace* rootTraceCandidate); + public: + TraceManager(Executable& _executable, const ITypeCallback* _typeCallback = nullptr); + + vint32_t concurrentCount = 0; + collections::List* concurrentTraces = nullptr; + collections::List* backupTraces = nullptr; + + ReturnStack* GetReturnStack(vint32_t index); + ReturnStack* AllocateReturnStack(); + Trace* GetTrace(vint32_t index); + Trace* AllocateTrace(); + Competition* GetCompetition(vint32_t index); + Competition* AllocateCompetition(); + AttendingCompetitions* GetAttendingCompetitions(vint32_t index); + AttendingCompetitions* AllocateAttendingCompetitions(); + + void Initialize(vint32_t startState); + void Input(vint32_t currentTokenIndex, vint32_t token, vint32_t lookAhead); + void EndOfInput(); + Trace* PrepareTraceRoute(); + Ptr ExecuteTrace(Trace* trace, IAstInsReceiver& receiver, collections::List& tokens); + }; + } + } +} + +#endif + +/*********************************************************************** +.\SYNTAXBASE.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_SYNTAXBASE +#define VCZH_PARSER2_SYNTAXBASE + + +namespace vl +{ + namespace glr + { +/*********************************************************************** +ParserBase +***********************************************************************/ + + enum class ErrorType + { + UnrecognizedToken, // (token) the token is not recognizable to the tokenizer + InvalidToken, // (token, tokens, executable, traceManager) the token cause the parser to stop + InputIncomplete, // (tokens, executable, traceManager) all traces do not reach the end + UnexpectedAstType, // (tokens, executable, traceManager, ast) unexpected type of the created AST + }; + + struct EndOfInputArgs + { + collections::List& tokens; + automaton::Executable& executable; + automaton::TraceManager& traceManager; + automaton::Trace* rootTrace; + }; + + struct ErrorArgs + { + bool throwError; + ErrorType error; + vint codeIndex; + regex::RegexToken& token; + collections::List& tokens; + automaton::Executable& executable; + automaton::TraceManager& traceManager; + Ptr ast; + + static ErrorArgs UnrecognizedToken (const regex::RegexToken& token); + static ErrorArgs InvalidToken (regex::RegexToken& token, collections::List& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager); + static ErrorArgs InputIncomplete (vint codeIndex, collections::List& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager); + static ErrorArgs UnexpectedAstType (collections::List& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager, Ptr ast); + + ParsingError ToParsingError(); + }; + + template + Ptr InstallDefaultErrorMessageGenerator(TParser& parser, collections::List& errors) + { + return parser.OnError.Add([&errors](ErrorArgs& args) + { + args.throwError = false; + errors.Add(args.ToParsingError()); + }); + } + + template< + typename TTokens, + typename TStates, + typename TReceiver, + template class TStateTypes + > + class ParserBase : public Object + { + static_assert(std::is_enum_v); + static_assert(std::is_enum_v); + static_assert(std::is_convertible_v); + + using Deleter = bool(*)(vint); + using TokenList = collections::List; + using EndOfInputCallback = void(EndOfInputArgs&); + using ErrorCallback = void(ErrorArgs&); + protected: + Deleter deleter; + Ptr lexer; + Ptr executable; + + public: + Event OnEndOfInput; + Event OnError; + + ParserBase( + Deleter _deleter, + void(*_lexerData)(stream::IStream&), + void(*_parserData)(stream::IStream&) + ) : deleter(_deleter) + { + { + stream::MemoryStream data; + _lexerData(data); + data.SeekFromBegin(0); + lexer = new regex::RegexLexer(data); + } + { + stream::MemoryStream data; + _parserData(data); + data.SeekFromBegin(0); + executable = new automaton::Executable(data); + } + } + + regex::RegexLexer& Lexer() const + { + return *lexer.Obj(); + } + + Deleter LexerDeleter() const + { + return deleter; + } + + void Tokenize(const WString& input, TokenList& tokens, vint codeIndex = -1) const + { + auto enumerable = lexer->Parse(input, {}, codeIndex); + Ptr> enumerator = enumerable.CreateEnumerator(); + while (enumerator->Next()) + { + auto&& token = enumerator->Current(); + if (token.token == -1) + { + auto args = ErrorArgs::UnrecognizedToken(token); + args.throwError = false; + OnError(args); + if (args.throwError) + { + CHECK_FAIL(L"vl::glr::ParserBase<...>::Tokenize(const WString&, List&, vint)#Unrecognized token."); + } + } + else if (!deleter(token.token)) + { + tokens.Add(token); + } + } + } + + protected: + template + auto Parse(TokenList& tokens, const automaton::TraceManager::ITypeCallback* typeCallback, vint codeIndex) const -> Ptr::Type> + { +#define ERROR_MESSAGE_PREFIX L"vl::glr::ParserBase<...>::Parse(List&, TraceManager::ITypeCallback*)#" + if (codeIndex == -1 && tokens.Count() > 0) + { + codeIndex = tokens[0].codeIndex; + } + + automaton::TraceManager tm(*executable.Obj(), typeCallback); + tm.Initialize((vint32_t)State); + for (vint32_t i = 0; i < tokens.Count(); i++) + { + auto&& token = tokens[i]; + auto lookAhead = i == tokens.Count() - 1 ? -1 : tokens[i + 1].token; + tm.Input(i, (vint32_t)token.token, (vint32_t)lookAhead); + + if (tm.concurrentCount == 0) + { + auto args = ErrorArgs::InvalidToken(token, tokens, *executable.Obj(), tm); + OnError(args); + if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Error happens during parsing."); + return nullptr; + } + } + + tm.EndOfInput(); + if (tm.concurrentCount == 0) + { + auto args = ErrorArgs::InputIncomplete(codeIndex, tokens, *executable.Obj(), tm); + OnError(args); + if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Input is incomplete."); + return nullptr; + } + + auto rootTrace = tm.PrepareTraceRoute(); + { + EndOfInputArgs args = { tokens, *executable.Obj(), tm, rootTrace }; + OnEndOfInput(args); + } + + TReceiver receiver; + auto ast = tm.ExecuteTrace(rootTrace, receiver, tokens); + auto typedAst = ast.Cast::Type>(); + + if (!typedAst) + { + auto args = ErrorArgs::UnexpectedAstType(tokens, *executable.Obj(), tm, ast); + OnError(args); + if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unexpected type of the created AST."); + return nullptr; + } + return typedAst; + +#undef ERROR_MESSAGE_PREFIX + } + + template + auto Parse(const WString& input, const automaton::TraceManager::ITypeCallback* typeCallback, vint codeIndex) const + { + TokenList tokens; + Tokenize(input, tokens, codeIndex); + return Parse(tokens, typeCallback, codeIndex); + } + }; + } +} + +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSONAST.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST +#define VCZH_PARSER2_BUILTIN_JSON_AST_AST + + +namespace vl +{ + namespace glr + { + namespace json + { + class JsonArray; + class JsonLiteral; + class JsonNode; + class JsonNumber; + class JsonObject; + class JsonObjectField; + class JsonString; + + enum class JsonLiteralValue + { + UNDEFINED_ENUM_ITEM_VALUE = -1, + True = 0, + False = 1, + Null = 2, + }; + + class JsonNode abstract : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + class IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description + { + public: + virtual void Visit(JsonLiteral* node) = 0; + virtual void Visit(JsonString* node) = 0; + virtual void Visit(JsonNumber* node) = 0; + virtual void Visit(JsonArray* node) = 0; + virtual void Visit(JsonObject* node) = 0; + }; + + virtual void Accept(JsonNode::IVisitor* visitor) = 0; + + }; + + class JsonLiteral : public JsonNode, vl::reflection::Description + { + public: + JsonLiteralValue value = JsonLiteralValue::UNDEFINED_ENUM_ITEM_VALUE; + + void Accept(JsonNode::IVisitor* visitor) override; + }; + + class JsonString : public JsonNode, vl::reflection::Description + { + public: + vl::glr::ParsingToken content; + + void Accept(JsonNode::IVisitor* visitor) override; + }; + + class JsonNumber : public JsonNode, vl::reflection::Description + { + public: + vl::glr::ParsingToken content; + + void Accept(JsonNode::IVisitor* visitor) override; + }; + + class JsonArray : public JsonNode, vl::reflection::Description + { + public: + vl::collections::List> items; + + void Accept(JsonNode::IVisitor* visitor) override; + }; + + class JsonObjectField : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + vl::Ptr value; + }; + + class JsonObject : public JsonNode, vl::reflection::Description + { + public: + vl::collections::List> fields; + + void Accept(JsonNode::IVisitor* visitor) override; + }; + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + DECL_TYPE_INFO(vl::glr::json::JsonNode) + DECL_TYPE_INFO(vl::glr::json::JsonNode::IVisitor) + DECL_TYPE_INFO(vl::glr::json::JsonLiteralValue) + DECL_TYPE_INFO(vl::glr::json::JsonLiteral) + DECL_TYPE_INFO(vl::glr::json::JsonString) + DECL_TYPE_INFO(vl::glr::json::JsonNumber) + DECL_TYPE_INFO(vl::glr::json::JsonArray) + DECL_TYPE_INFO(vl::glr::json::JsonObjectField) + DECL_TYPE_INFO(vl::glr::json::JsonObject) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::glr::json::JsonNode::IVisitor) + void Visit(vl::glr::json::JsonLiteral* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::json::JsonString* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::json::JsonNumber* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::json::JsonArray* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::json::JsonObject* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + END_INTERFACE_PROXY(vl::glr::json::JsonNode::IVisitor) + +#endif +#endif + /// Load all reflectable AST types, only available when VCZH_DEBUG_NO_REFLECTION is off. + /// Returns true if this operation succeeded. + extern bool JsonAstLoadTypes(); + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_BUILDER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_BUILDER +#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_BUILDER + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace builder + { + class MakeArray : public vl::glr::ParsingAstBuilder + { + public: + MakeArray& items(const vl::Ptr& value); + }; + + class MakeLiteral : public vl::glr::ParsingAstBuilder + { + public: + MakeLiteral& value(JsonLiteralValue value); + }; + + class MakeNumber : public vl::glr::ParsingAstBuilder + { + public: + MakeNumber& content(const vl::WString& value); + }; + + class MakeObject : public vl::glr::ParsingAstBuilder + { + public: + MakeObject& fields(const vl::Ptr& value); + }; + + class MakeObjectField : public vl::glr::ParsingAstBuilder + { + public: + MakeObjectField& name(const vl::WString& value); + MakeObjectField& value(const vl::Ptr& value); + }; + + class MakeString : public vl::glr::ParsingAstBuilder + { + public: + MakeString& content(const vl::WString& value); + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_COPY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_COPY_VISITOR +#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_COPY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace copy_visitor + { + /// A copy visitor, overriding all abstract methods with AST copying code. + class AstVisitor + : public virtual vl::glr::CopyVisitorBase + , protected virtual JsonNode::IVisitor + { + protected: + void CopyFields(JsonArray* from, JsonArray* to); + void CopyFields(JsonLiteral* from, JsonLiteral* to); + void CopyFields(JsonNode* from, JsonNode* to); + void CopyFields(JsonNumber* from, JsonNumber* to); + void CopyFields(JsonObject* from, JsonObject* to); + void CopyFields(JsonObjectField* from, JsonObjectField* to); + void CopyFields(JsonString* from, JsonString* to); + + protected: + virtual void Visit(JsonObjectField* node); + + void Visit(JsonLiteral* node) override; + void Visit(JsonString* node) override; + void Visit(JsonNumber* node) override; + void Visit(JsonArray* node) override; + void Visit(JsonObject* node) override; + + public: + virtual vl::Ptr CopyNode(JsonNode* node); + virtual vl::Ptr CopyNode(JsonObjectField* node); + + vl::Ptr CopyNode(JsonArray* node); + vl::Ptr CopyNode(JsonLiteral* node); + vl::Ptr CopyNode(JsonNumber* node); + vl::Ptr CopyNode(JsonObject* node); + vl::Ptr CopyNode(JsonString* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_EMPTY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_EMPTY_VISITOR +#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_EMPTY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace empty_visitor + { + /// An empty visitor, overriding all abstract methods with empty implementations. + class NodeVisitor : public vl::Object, public JsonNode::IVisitor + { + protected: + // Dispatch (virtual) -------------------------------- + + public: + // Visitor Members ----------------------------------- + void Visit(JsonLiteral* node) override; + void Visit(JsonString* node) override; + void Visit(JsonNumber* node) override; + void Visit(JsonArray* node) override; + void Visit(JsonObject* node) override; + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_JSON.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_JSON_VISITOR +#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_JSON_VISITOR + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace json_visitor + { + /// A JSON visitor, overriding all abstract methods with AST to JSON serialization code. + class AstVisitor + : public vl::glr::JsonVisitorBase + , protected virtual JsonNode::IVisitor + { + protected: + virtual void PrintFields(JsonArray* node); + virtual void PrintFields(JsonLiteral* node); + virtual void PrintFields(JsonNode* node); + virtual void PrintFields(JsonNumber* node); + virtual void PrintFields(JsonObject* node); + virtual void PrintFields(JsonObjectField* node); + virtual void PrintFields(JsonString* node); + + protected: + void Visit(JsonLiteral* node) override; + void Visit(JsonString* node) override; + void Visit(JsonNumber* node) override; + void Visit(JsonArray* node) override; + void Visit(JsonObject* node) override; + + public: + AstVisitor(vl::stream::StreamWriter& _writer); + + void Print(JsonNode* node); + void Print(JsonObjectField* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSONAST_TRAVERSE.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_TRAVERSE_VISITOR +#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_TRAVERSE_VISITOR + + +namespace vl +{ + namespace glr + { + namespace json + { + namespace traverse_visitor + { + /// A traverse visitor, overriding all abstract methods with AST visiting code. + class AstVisitor + : public vl::Object + , protected virtual JsonNode::IVisitor + { + protected: + virtual void Traverse(vl::glr::ParsingToken& token); + virtual void Traverse(vl::glr::ParsingAstBase* node); + virtual void Traverse(JsonArray* node); + virtual void Traverse(JsonLiteral* node); + virtual void Traverse(JsonNode* node); + virtual void Traverse(JsonNumber* node); + virtual void Traverse(JsonObject* node); + virtual void Traverse(JsonObjectField* node); + virtual void Traverse(JsonString* node); + + protected: + virtual void Finishing(vl::glr::ParsingAstBase* node); + virtual void Finishing(JsonArray* node); + virtual void Finishing(JsonLiteral* node); + virtual void Finishing(JsonNode* node); + virtual void Finishing(JsonNumber* node); + virtual void Finishing(JsonObject* node); + virtual void Finishing(JsonObjectField* node); + virtual void Finishing(JsonString* node); + + protected: + void Visit(JsonLiteral* node) override; + void Visit(JsonString* node) override; + void Visit(JsonNumber* node) override; + void Visit(JsonArray* node) override; + void Visit(JsonObject* node) override; + + public: + void InspectInto(JsonNode* node); + void InspectInto(JsonObjectField* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSON_ASSEMBLER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Json +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_ASSEMBLER +#define VCZH_PARSER2_BUILTIN_JSON_AST_ASSEMBLER + + +namespace vl +{ + namespace glr + { + namespace json + { + enum class JsonClasses : vl::vint32_t + { + Array = 0, + Literal = 1, + Node = 2, + Number = 3, + Object = 4, + ObjectField = 5, + String = 6, + }; + + enum class JsonFields : vl::vint32_t + { + Array_items = 0, + Literal_value = 1, + Number_content = 2, + Object_fields = 3, + ObjectField_name = 4, + ObjectField_value = 5, + String_content = 6, + }; + + extern const wchar_t* JsonTypeName(JsonClasses type); + extern const wchar_t* JsonCppTypeName(JsonClasses type); + extern const wchar_t* JsonFieldName(JsonFields field); + extern const wchar_t* JsonCppFieldName(JsonFields field); + + class JsonAstInsReceiver : public vl::glr::AstInsReceiverBase + { + protected: + vl::Ptr CreateAstNode(vl::vint32_t type) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem) override; + vl::Ptr ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates) override; + }; + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSON_LEXER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Json +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_LEXER +#define VCZH_PARSER2_BUILTIN_JSON_LEXER + + +namespace vl +{ + namespace glr + { + namespace json + { + enum class JsonTokens : vl::vint32_t + { + TRUE_VALUE = 0, + FALSE_VALUE = 1, + NULL_VALUE = 2, + OBJOPEN = 3, + OBJCLOSE = 4, + ARROPEN = 5, + ARRCLOSE = 6, + COMMA = 7, + COLON = 8, + NUMBER = 9, + STRING = 10, + SPACE = 11, + }; + + constexpr vl::vint JsonTokenCount = 12; + extern bool JsonTokenDeleter(vl::vint token); + extern const wchar_t* JsonTokenId(JsonTokens token); + extern const wchar_t* JsonTokenDisplayText(JsonTokens token); + extern const wchar_t* JsonTokenRegex(JsonTokens token); + extern void JsonLexerData(vl::stream::IStream& outputStream); + } + } +} +#endif + +/*********************************************************************** +.\JSON\GENERATED\JSONPARSER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Json +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON_PARSER_SYNTAX +#define VCZH_PARSER2_BUILTIN_JSON_PARSER_SYNTAX + + +namespace vl +{ + namespace glr + { + namespace json + { + enum class ParserStates + { + JLiteral = 0, + JField = 7, + JObject = 12, + JArray = 18, + JValue = 24, + JRoot = 29, + }; + + template struct ParserStateTypes; + template<> struct ParserStateTypes { using Type = vl::glr::json::JsonNode; }; + + const wchar_t* ParserRuleName(vl::vint index); + const wchar_t* ParserStateLabel(vl::vint index); + extern void JsonParserData(vl::stream::IStream& outputStream); + + class Parser + : public vl::glr::ParserBase + , protected vl::glr::automaton::TraceManager::ITypeCallback + { + protected: + vl::vint32_t FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const override; + public: + Parser(); + + vl::Ptr ParseJRoot(const vl::WString& input, vl::vint codeIndex = -1) const; + vl::Ptr ParseJRoot(vl::collections::List& tokens, vl::vint codeIndex = -1) const; + }; + } + } +} +#endif + +/*********************************************************************** +.\JSON\GLRJSON.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +Parser::ParsingJson_Parser + +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_JSON +#define VCZH_PARSER2_BUILTIN_JSON + + +namespace vl +{ + namespace glr + { + namespace json + { + /// Deserialize JSON from string. + /// The deserialized JSON node. + /// The JSON code. + /// The generated parser. + extern Ptr JsonParse(const WString& input, const Parser& parser); + + /// Serialize JSON to string. + /// The JSON node to serialize. + /// The text writer to receive the string. + extern void JsonPrint(Ptr node, stream::TextWriter& writer); + + /// Serialize JSON to string. + /// The serialized string. + /// The JSON node to serialize. + extern WString JsonToString(Ptr node); + } + } +} + +#endif + +/*********************************************************************** +.\XML\GENERATED\XMLAST.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST +#define VCZH_PARSER2_BUILTIN_XML_AST_AST + + +namespace vl +{ + namespace glr + { + namespace xml + { + class XmlAttribute; + class XmlCData; + class XmlComment; + class XmlDocument; + class XmlElement; + class XmlInstruction; + class XmlNode; + class XmlText; + + class XmlNode abstract : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + class IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description + { + public: + virtual void Visit(XmlText* node) = 0; + virtual void Visit(XmlCData* node) = 0; + virtual void Visit(XmlComment* node) = 0; + virtual void Visit(XmlElement* node) = 0; + virtual void Visit(XmlInstruction* node) = 0; + virtual void Visit(XmlDocument* node) = 0; + }; + + virtual void Accept(XmlNode::IVisitor* visitor) = 0; + + }; + + class XmlText : public XmlNode, vl::reflection::Description + { + public: + vl::glr::ParsingToken content; + + void Accept(XmlNode::IVisitor* visitor) override; + }; + + class XmlCData : public XmlNode, vl::reflection::Description + { + public: + vl::glr::ParsingToken content; + + void Accept(XmlNode::IVisitor* visitor) override; + }; + + class XmlAttribute : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + vl::glr::ParsingToken value; + }; + + class XmlComment : public XmlNode, vl::reflection::Description + { + public: + vl::glr::ParsingToken content; + + void Accept(XmlNode::IVisitor* visitor) override; + }; + + class XmlElement : public XmlNode, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + vl::glr::ParsingToken closingName; + vl::collections::List> attributes; + vl::collections::List> subNodes; + + void Accept(XmlNode::IVisitor* visitor) override; + }; + + class XmlInstruction : public XmlNode, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + vl::collections::List> attributes; + + void Accept(XmlNode::IVisitor* visitor) override; + }; + + class XmlDocument : public XmlNode, vl::reflection::Description + { + public: + vl::collections::List> prologs; + vl::Ptr rootElement; + + void Accept(XmlNode::IVisitor* visitor) override; + }; + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + DECL_TYPE_INFO(vl::glr::xml::XmlNode) + DECL_TYPE_INFO(vl::glr::xml::XmlNode::IVisitor) + DECL_TYPE_INFO(vl::glr::xml::XmlText) + DECL_TYPE_INFO(vl::glr::xml::XmlCData) + DECL_TYPE_INFO(vl::glr::xml::XmlAttribute) + DECL_TYPE_INFO(vl::glr::xml::XmlComment) + DECL_TYPE_INFO(vl::glr::xml::XmlElement) + DECL_TYPE_INFO(vl::glr::xml::XmlInstruction) + DECL_TYPE_INFO(vl::glr::xml::XmlDocument) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::glr::xml::XmlNode::IVisitor) + void Visit(vl::glr::xml::XmlText* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::xml::XmlCData* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::xml::XmlComment* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::xml::XmlElement* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::xml::XmlInstruction* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::xml::XmlDocument* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + END_INTERFACE_PROXY(vl::glr::xml::XmlNode::IVisitor) + +#endif +#endif + /// Load all reflectable AST types, only available when VCZH_DEBUG_NO_REFLECTION is off. + /// Returns true if this operation succeeded. + extern bool XmlAstLoadTypes(); + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XMLAST_BUILDER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_BUILDER +#define VCZH_PARSER2_BUILTIN_XML_AST_AST_BUILDER + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace builder + { + class MakeAttribute : public vl::glr::ParsingAstBuilder + { + public: + MakeAttribute& name(const vl::WString& value); + MakeAttribute& value(const vl::WString& value); + }; + + class MakeCData : public vl::glr::ParsingAstBuilder + { + public: + MakeCData& content(const vl::WString& value); + }; + + class MakeComment : public vl::glr::ParsingAstBuilder + { + public: + MakeComment& content(const vl::WString& value); + }; + + class MakeDocument : public vl::glr::ParsingAstBuilder + { + public: + MakeDocument& prologs(const vl::Ptr& value); + MakeDocument& rootElement(const vl::Ptr& value); + }; + + class MakeElement : public vl::glr::ParsingAstBuilder + { + public: + MakeElement& attributes(const vl::Ptr& value); + MakeElement& closingName(const vl::WString& value); + MakeElement& name(const vl::WString& value); + MakeElement& subNodes(const vl::Ptr& value); + }; + + class MakeInstruction : public vl::glr::ParsingAstBuilder + { + public: + MakeInstruction& attributes(const vl::Ptr& value); + MakeInstruction& name(const vl::WString& value); + }; + + class MakeText : public vl::glr::ParsingAstBuilder + { + public: + MakeText& content(const vl::WString& value); + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XMLAST_COPY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_COPY_VISITOR +#define VCZH_PARSER2_BUILTIN_XML_AST_AST_COPY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace copy_visitor + { + /// A copy visitor, overriding all abstract methods with AST copying code. + class AstVisitor + : public virtual vl::glr::CopyVisitorBase + , protected virtual XmlNode::IVisitor + { + protected: + void CopyFields(XmlAttribute* from, XmlAttribute* to); + void CopyFields(XmlCData* from, XmlCData* to); + void CopyFields(XmlComment* from, XmlComment* to); + void CopyFields(XmlDocument* from, XmlDocument* to); + void CopyFields(XmlElement* from, XmlElement* to); + void CopyFields(XmlInstruction* from, XmlInstruction* to); + void CopyFields(XmlNode* from, XmlNode* to); + void CopyFields(XmlText* from, XmlText* to); + + protected: + virtual void Visit(XmlAttribute* node); + + void Visit(XmlText* node) override; + void Visit(XmlCData* node) override; + void Visit(XmlComment* node) override; + void Visit(XmlElement* node) override; + void Visit(XmlInstruction* node) override; + void Visit(XmlDocument* node) override; + + public: + virtual vl::Ptr CopyNode(XmlNode* node); + virtual vl::Ptr CopyNode(XmlAttribute* node); + + vl::Ptr CopyNode(XmlCData* node); + vl::Ptr CopyNode(XmlComment* node); + vl::Ptr CopyNode(XmlDocument* node); + vl::Ptr CopyNode(XmlElement* node); + vl::Ptr CopyNode(XmlInstruction* node); + vl::Ptr CopyNode(XmlText* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XMLAST_EMPTY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_EMPTY_VISITOR +#define VCZH_PARSER2_BUILTIN_XML_AST_AST_EMPTY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace empty_visitor + { + /// An empty visitor, overriding all abstract methods with empty implementations. + class NodeVisitor : public vl::Object, public XmlNode::IVisitor + { + protected: + // Dispatch (virtual) -------------------------------- + + public: + // Visitor Members ----------------------------------- + void Visit(XmlText* node) override; + void Visit(XmlCData* node) override; + void Visit(XmlComment* node) override; + void Visit(XmlElement* node) override; + void Visit(XmlInstruction* node) override; + void Visit(XmlDocument* node) override; + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XMLAST_JSON.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_JSON_VISITOR +#define VCZH_PARSER2_BUILTIN_XML_AST_AST_JSON_VISITOR + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace json_visitor + { + /// A JSON visitor, overriding all abstract methods with AST to JSON serialization code. + class AstVisitor + : public vl::glr::JsonVisitorBase + , protected virtual XmlNode::IVisitor + { + protected: + virtual void PrintFields(XmlAttribute* node); + virtual void PrintFields(XmlCData* node); + virtual void PrintFields(XmlComment* node); + virtual void PrintFields(XmlDocument* node); + virtual void PrintFields(XmlElement* node); + virtual void PrintFields(XmlInstruction* node); + virtual void PrintFields(XmlNode* node); + virtual void PrintFields(XmlText* node); + + protected: + void Visit(XmlText* node) override; + void Visit(XmlCData* node) override; + void Visit(XmlComment* node) override; + void Visit(XmlElement* node) override; + void Visit(XmlInstruction* node) override; + void Visit(XmlDocument* node) override; + + public: + AstVisitor(vl::stream::StreamWriter& _writer); + + void Print(XmlNode* node); + void Print(XmlAttribute* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XMLAST_TRAVERSE.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Ast +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_TRAVERSE_VISITOR +#define VCZH_PARSER2_BUILTIN_XML_AST_AST_TRAVERSE_VISITOR + + +namespace vl +{ + namespace glr + { + namespace xml + { + namespace traverse_visitor + { + /// A traverse visitor, overriding all abstract methods with AST visiting code. + class AstVisitor + : public vl::Object + , protected virtual XmlNode::IVisitor + { + protected: + virtual void Traverse(vl::glr::ParsingToken& token); + virtual void Traverse(vl::glr::ParsingAstBase* node); + virtual void Traverse(XmlAttribute* node); + virtual void Traverse(XmlCData* node); + virtual void Traverse(XmlComment* node); + virtual void Traverse(XmlDocument* node); + virtual void Traverse(XmlElement* node); + virtual void Traverse(XmlInstruction* node); + virtual void Traverse(XmlNode* node); + virtual void Traverse(XmlText* node); + + protected: + virtual void Finishing(vl::glr::ParsingAstBase* node); + virtual void Finishing(XmlAttribute* node); + virtual void Finishing(XmlCData* node); + virtual void Finishing(XmlComment* node); + virtual void Finishing(XmlDocument* node); + virtual void Finishing(XmlElement* node); + virtual void Finishing(XmlInstruction* node); + virtual void Finishing(XmlNode* node); + virtual void Finishing(XmlText* node); + + protected: + void Visit(XmlText* node) override; + void Visit(XmlCData* node) override; + void Visit(XmlComment* node) override; + void Visit(XmlElement* node) override; + void Visit(XmlInstruction* node) override; + void Visit(XmlDocument* node) override; + + public: + void InspectInto(XmlNode* node); + void InspectInto(XmlAttribute* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XML_ASSEMBLER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Xml +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_AST_ASSEMBLER +#define VCZH_PARSER2_BUILTIN_XML_AST_ASSEMBLER + + +namespace vl +{ + namespace glr + { + namespace xml + { + enum class XmlClasses : vl::vint32_t + { + Attribute = 0, + CData = 1, + Comment = 2, + Document = 3, + Element = 4, + Instruction = 5, + Node = 6, + Text = 7, + }; + + enum class XmlFields : vl::vint32_t + { + Attribute_name = 0, + Attribute_value = 1, + CData_content = 2, + Comment_content = 3, + Document_prologs = 4, + Document_rootElement = 5, + Element_attributes = 6, + Element_closingName = 7, + Element_name = 8, + Element_subNodes = 9, + Instruction_attributes = 10, + Instruction_name = 11, + Text_content = 12, + }; + + extern const wchar_t* XmlTypeName(XmlClasses type); + extern const wchar_t* XmlCppTypeName(XmlClasses type); + extern const wchar_t* XmlFieldName(XmlFields field); + extern const wchar_t* XmlCppFieldName(XmlFields field); + + class XmlAstInsReceiver : public vl::glr::AstInsReceiverBase + { + protected: + vl::Ptr CreateAstNode(vl::vint32_t type) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem) override; + vl::Ptr ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates) override; + }; + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XML_LEXER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Xml +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_LEXER +#define VCZH_PARSER2_BUILTIN_XML_LEXER + + +namespace vl +{ + namespace glr + { + namespace xml + { + enum class XmlTokens : vl::vint32_t + { + INSTRUCTION_OPEN = 0, + INSTRUCTION_CLOSE = 1, + COMPLEX_ELEMENT_OPEN = 2, + SINGLE_ELEMENT_CLOSE = 3, + ELEMENT_OPEN = 4, + ELEMENT_CLOSE = 5, + EQUAL = 6, + NAME = 7, + ATTVALUE = 8, + COMMENT = 9, + CDATA = 10, + TEXT = 11, + SPACE = 12, + }; + + constexpr vl::vint XmlTokenCount = 13; + extern bool XmlTokenDeleter(vl::vint token); + extern const wchar_t* XmlTokenId(XmlTokens token); + extern const wchar_t* XmlTokenDisplayText(XmlTokens token); + extern const wchar_t* XmlTokenRegex(XmlTokens token); + extern void XmlLexerData(vl::stream::IStream& outputStream); + } + } +} +#endif + +/*********************************************************************** +.\XML\GENERATED\XMLPARSER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:Xml +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML_PARSER_SYNTAX +#define VCZH_PARSER2_BUILTIN_XML_PARSER_SYNTAX + + +namespace vl +{ + namespace glr + { + namespace xml + { + enum class ParserStates + { + XAttribute = 0, + XText = 5, + XCData = 11, + XComment = 14, + XElement = 17, + XSubNode = 28, + XInstruction = 34, + XDocument = 40, + }; + + template struct ParserStateTypes; + template<> struct ParserStateTypes { using Type = vl::glr::xml::XmlElement; }; + template<> struct ParserStateTypes { using Type = vl::glr::xml::XmlDocument; }; + + const wchar_t* ParserRuleName(vl::vint index); + const wchar_t* ParserStateLabel(vl::vint index); + extern void XmlParserData(vl::stream::IStream& outputStream); + + class Parser + : public vl::glr::ParserBase + , protected vl::glr::automaton::TraceManager::ITypeCallback + { + protected: + vl::vint32_t FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const override; + public: + Parser(); + + vl::Ptr ParseXElement(const vl::WString& input, vl::vint codeIndex = -1) const; + vl::Ptr ParseXElement(vl::collections::List& tokens, vl::vint codeIndex = -1) const; + vl::Ptr ParseXDocument(const vl::WString& input, vl::vint codeIndex = -1) const; + vl::Ptr ParseXDocument(vl::collections::List& tokens, vl::vint codeIndex = -1) const; + }; + } + } +} +#endif + +/*********************************************************************** +.\XML\GLRXML.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +Parser::ParsingXml + +***********************************************************************/ + +#ifndef VCZH_PARSER2_BUILTIN_XML +#define VCZH_PARSER2_BUILTIN_XML + + +namespace vl +{ + namespace glr + { + namespace xml + { + extern WString XmlEscapeValue(const WString& value); + extern WString XmlUnescapeValue(const WString& value); + extern WString XmlEscapeCData(const WString& value); + extern WString XmlUnescapeCData(const WString& value); + extern WString XmlEscapeComment(const WString& value); + extern WString XmlUnescapeComment(const WString& value); + + /// Deserialize XML document from string. + /// The deserialized XML node. + /// The XML code. + /// The generated parser. + extern Ptr XmlParseDocument(const WString& input, const Parser& parser); + + /// Deserialize XML element from string. + /// The deserialized XML node. + /// The XML code. + /// The generated parser. + extern Ptr XmlParseElement(const WString& input, const Parser& parser); + + /// Serialize XML to string. + /// The XML node to serialize. + /// The text writer to receive the string. + extern void XmlPrint(Ptr node, stream::TextWriter& writer); + + /// Serialize sub nodes in an XML element to string. + /// The XML element in which sub nodes are to be serialized. + /// The text writer to receive the string. + extern void XmlPrintContent(Ptr element, stream::TextWriter& writer); + + /// Serialize XML to string. + /// The serialized string. + /// The XML node to serialize. + extern WString XmlToString(Ptr node); + + /// Try to read an attribute in an XML element. + /// The expected attribute. Returns null if it doesn't exist. + /// The element to find the attribute. + /// The name of the attribute. + extern Ptr XmlGetAttribute(Ptr element, const WString& name); + + /// Try to read a sub element in an XML element. + /// The expected sub element. Returns null if it doesn't exist. If there are multiple elements of the expected name, returns the first one. + /// The element to find the sub element. + /// The name of the sub element. + extern Ptr XmlGetElement(Ptr element, const WString& name); + + /// Get all sub elements in an XML element. + /// All sub elements in an XML element. + /// The container XML element. + extern collections::LazyList> XmlGetElements(Ptr element); + + /// Try to read sub elements in an XML element. + /// Expected sub elements. All sub elements of the expected name will be returned. + /// The element to find sub elements. + /// The name of sub elements. + extern collections::LazyList> XmlGetElements(Ptr element, const WString& name); + + /// Serialize contents in an XML element. + /// The serialized contents in an XML element. + /// The XML element in which contents are to be serialized. + extern WString XmlGetValue(Ptr element); + + extern Ptr XmlGetAttribute(XmlElement* element, const WString& name); + extern Ptr XmlGetElement(XmlElement* element, const WString& name); + extern collections::LazyList> XmlGetElements(XmlElement* element); + extern collections::LazyList> XmlGetElements(XmlElement* element, const WString& name); + extern WString XmlGetValue(XmlElement* element); + + class XmlElementWriter : public Object + { + protected: + Ptr element; + const XmlElementWriter* previousWriter; + + public: + XmlElementWriter(Ptr _element, const XmlElementWriter* _previousWriter=0); + ~XmlElementWriter(); + + const XmlElementWriter& Attribute(const WString& name, const WString& value)const; + XmlElementWriter Element(const WString& name)const; + const XmlElementWriter& End()const; + const XmlElementWriter& Text(const WString& value)const; + const XmlElementWriter& CData(const WString& value)const; + const XmlElementWriter& Comment(const WString& value)const; + }; + } + } +} + +#endif diff --git a/Import/VlppGlrParserCompiler.cpp b/Import/VlppGlrParserCompiler.cpp new file mode 100644 index 00000000..34fafe7d --- /dev/null +++ b/Import/VlppGlrParserCompiler.cpp @@ -0,0 +1,10172 @@ +/*********************************************************************** +THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY +DEVELOPER: Zihan Chen(vczh) +***********************************************************************/ +#include "VlppGlrParserCompiler.h" + +/*********************************************************************** +.\AST\ASTCPPGEN.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + +/*********************************************************************** +GenerateAstFileNames +***********************************************************************/ + + void GenerateAstFileNames(AstSymbolManager& manager, Ptr parserOutput) + { + for (auto file : manager.Files().Values()) + { + auto astOutput = MakePtr(); + astOutput->astH = file->Owner()->Global().name + file->Name() + L".h"; + astOutput->astCpp = file->Owner()->Global().name + file->Name() + L".cpp"; + astOutput->builderH = file->Owner()->Global().name + file->Name() + L"_Builder.h"; + astOutput->builderCpp = file->Owner()->Global().name + file->Name() + L"_Builder.cpp"; + astOutput->emptyH = file->Owner()->Global().name + file->Name() + L"_Empty.h"; + astOutput->emptyCpp = file->Owner()->Global().name + file->Name() + L"_Empty.cpp"; + astOutput->copyH = file->Owner()->Global().name + file->Name() + L"_Copy.h"; + astOutput->copyCpp = file->Owner()->Global().name + file->Name() + L"_Copy.cpp"; + astOutput->traverseH = file->Owner()->Global().name + file->Name() + L"_Traverse.h"; + astOutput->traverseCpp = file->Owner()->Global().name + file->Name() + L"_Traverse.cpp"; + astOutput->jsonH = file->Owner()->Global().name + file->Name() + L"_Json.h"; + astOutput->jsonCpp = file->Owner()->Global().name + file->Name() + L"_Json.cpp"; + parserOutput->astOutputs.Add(file, astOutput); + } + } + +/*********************************************************************** +Utility +***********************************************************************/ + + void CollectVisitorsAndConcreteClasses(AstDefFile* file, List& visitors, List& concreteClasses) + { + for (auto name : file->SymbolOrder()) + { + if (auto classSymbol = dynamic_cast(file->Symbols()[name])) + { + if (classSymbol->derivedClasses.Count() > 0) + { + visitors.Add(classSymbol); + } + if (!classSymbol->baseClass && classSymbol->derivedClasses.Count() == 0) + { + concreteClasses.Add(classSymbol); + } + } + } + } + +/*********************************************************************** +Forward Declarations +***********************************************************************/ + + extern void WriteTypeForwardDefinitions(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer); + extern void WriteTypeDefinitions(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer); + extern void WriteVisitorImpl(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer); + extern void WriteTypeReflectionDeclaration(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer); + extern void WriteTypeReflectionImplementation(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer); + +/*********************************************************************** +WriteAstHeaderFile +***********************************************************************/ + + void WriteAstHeaderFile(AstDefFile* file, stream::StreamWriter& writer) + { + WriteFileComment(file->Name(), writer); + auto&& headerGuard = file->Owner()->Global().headerGuard; + if (headerGuard != L"") + { + writer.WriteString(L"#ifndef "); + writer.WriteLine(headerGuard + L"_" + wupper(file->Name()) + L"_AST"); + writer.WriteString(L"#define "); + writer.WriteLine(headerGuard + L"_" + wupper(file->Name()) + L"_AST"); + } + else + { + writer.WriteLine(L"#pragma once"); + } + writer.WriteLine(L""); + for (auto include : file->Owner()->Global().includes) + { + if (include.Length() > 0 && include[0] == L'<') + { + writer.WriteLine(L"#include " + include); + } + else + { + writer.WriteLine(L"#include \"" + include + L"\""); + } + } + writer.WriteLine(L""); + + { + WString prefix = WriteNssBegin(file->cppNss, writer); + WriteTypeForwardDefinitions(file, prefix, writer); + WriteTypeDefinitions(file, prefix, writer); + WriteNssEnd(file->cppNss, writer); + } + { + List refNss; + refNss.Add(L"vl"); + refNss.Add(L"reflection"); + refNss.Add(L"description"); + WString prefix = WriteNssBegin(refNss, writer); + WriteTypeReflectionDeclaration(file, prefix, writer); + WriteNssEnd(refNss, writer); + } + + if (headerGuard != L"") + { + writer.WriteString(L"#endif"); + } + } + +/*********************************************************************** +WriteAstCppFile +***********************************************************************/ + + void WriteAstCppFile(AstDefFile* file, const WString& astHeaderName, stream::StreamWriter& writer) + { + WriteFileComment(file->Name(), writer); + writer.WriteLine(L"#include \"" + astHeaderName + L"\""); + writer.WriteLine(L""); + { + WString prefix = WriteNssBegin(file->cppNss, writer); + writer.WriteLine(L"/***********************************************************************"); + writer.WriteLine(L"Visitor Pattern Implementation"); + writer.WriteLine(L"***********************************************************************/"); + WriteVisitorImpl(file, prefix, writer); + WriteNssEnd(file->cppNss, writer); + } + { + List refNss; + refNss.Add(L"vl"); + refNss.Add(L"reflection"); + refNss.Add(L"description"); + WString prefix = WriteNssBegin(refNss, writer); + WriteTypeReflectionImplementation(file, prefix, writer); + WriteNssEnd(refNss, writer); + } + } + +/*********************************************************************** +WriteAstUtilityHeaderFile +***********************************************************************/ + + void WriteAstUtilityHeaderFile( + AstDefFile* file, + Ptr output, + const WString& extraNss, + stream::StreamWriter& writer, + Func callback + ) + { + WriteFileComment(file->Name(), writer); + auto&& headerGuard = file->Owner()->Global().headerGuard; + if (headerGuard != L"") + { + writer.WriteString(L"#ifndef "); + writer.WriteLine(headerGuard + L"_" + wupper(file->Name()) + L"_AST_" + wupper(extraNss)); + writer.WriteString(L"#define "); + writer.WriteLine(headerGuard + L"_" + wupper(file->Name()) + L"_AST_" + wupper(extraNss)); + } + else + { + writer.WriteLine(L"#pragma once"); + } + writer.WriteLine(L""); + writer.WriteLine(L"#include \"" + output->astH + L"\""); + writer.WriteLine(L""); + { + List cppNss; + CopyFrom(cppNss, file->cppNss); + cppNss.Add(extraNss); + WString prefix = WriteNssBegin(cppNss, writer); + callback(prefix); + WriteNssEnd(cppNss, writer); + } + if (headerGuard != L"") + { + writer.WriteString(L"#endif"); + } + } + +/*********************************************************************** +WriteAstUtilityCppFile +***********************************************************************/ + + void WriteAstUtilityCppFile( + AstDefFile* file, + const WString& utilityHeaderFile, + const WString& extraNss, + stream::StreamWriter& writer, + Func callback + ) + { + WriteFileComment(file->Name(), writer); + writer.WriteLine(L"#include \"" + utilityHeaderFile + L"\""); + writer.WriteLine(L""); + { + List cppNss; + CopyFrom(cppNss, file->cppNss); + cppNss.Add(extraNss); + WString prefix = WriteNssBegin(cppNss, writer); + callback(prefix); + WriteNssEnd(cppNss, writer); + } + } + +/*********************************************************************** +WriteParserUtilityHeaderFile +***********************************************************************/ + + void WriteParserUtilityHeaderFile( + AstSymbolManager& manager, + Ptr output, + const WString& guardPostfix, + stream::StreamWriter& writer, + Func callback + ) + { + WriteFileComment(manager.Global().name, writer); + if (manager.Global().headerGuard != L"") + { + writer.WriteString(L"#ifndef "); + writer.WriteLine(manager.Global().headerGuard + L"_AST_" + guardPostfix); + writer.WriteString(L"#define "); + writer.WriteLine(manager.Global().headerGuard + L"_AST_" + guardPostfix); + } + else + { + writer.WriteLine(L"#pragma once"); + } + + writer.WriteLine(L""); + for (auto file : manager.Files().Values()) + { + writer.WriteLine(L"#include \"" + output->astOutputs[file]->astH + L"\""); + } + + writer.WriteLine(L""); + WString prefix = WriteNssBegin(manager.Global().cppNss, writer); + callback(prefix); + WriteNssEnd(manager.Global().cppNss, writer); + + if (manager.Global().headerGuard != L"") + { + writer.WriteString(L"#endif"); + } + } + +/*********************************************************************** +WriteParserUtilityCppFile +***********************************************************************/ + + void WriteParserUtilityCppFile( + AstSymbolManager& manager, + const WString& utilityHeaderFile, + stream::StreamWriter& writer, + Func callback + ) + { + WriteFileComment(manager.Global().name, writer); + writer.WriteLine(L"#include \"" + utilityHeaderFile + L"\""); + writer.WriteLine(L""); + WString prefix = WriteNssBegin(manager.Global().cppNss, writer); + callback(prefix); + WriteNssEnd(manager.Global().cppNss, writer); + } + +/*********************************************************************** +WriteAstFiles +***********************************************************************/ + + void WriteAstFiles(AstDefFile* file, Ptr output, collections::Dictionary& files) + { + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteAstHeaderFile(file, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteAstCppFile(file, output->astH, writer); + }); + + files.Add(output->astH, fileH); + files.Add(output->astCpp, fileCpp); + } + + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteAstBuilderHeaderFile(file, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteAstBuilderCppFile(file, output, writer); + }); + + files.Add(output->builderH, fileH); + files.Add(output->builderCpp, fileCpp); + } + + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteEmptyVisitorHeaderFile(file, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteEmptyVisitorCppFile(file, output, writer); + }); + + files.Add(output->emptyH, fileH); + files.Add(output->emptyCpp, fileCpp); + } + + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteCopyVisitorHeaderFile(file, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteCopyVisitorCppFile(file, output, writer); + }); + + files.Add(output->copyH, fileH); + files.Add(output->copyCpp, fileCpp); + } + + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteTraverseVisitorHeaderFile(file, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteTraverseVisitorCppFile(file, output, writer); + }); + + files.Add(output->traverseH, fileH); + files.Add(output->traverseCpp, fileCpp); + } + + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteJsonVisitorHeaderFile(file, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteJsonVisitorCppFile(file, output, writer); + }); + + files.Add(output->jsonH, fileH); + files.Add(output->jsonCpp, fileCpp); + } + } + + void WriteAstFiles(AstSymbolManager& manager, Ptr output, collections::Dictionary& files) + { + for (auto file : manager.Files().Values()) + { + WriteAstFiles(file, output->astOutputs[file], files); + } + + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteAstAssemblerHeaderFile(manager, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteAstAssemblerCppFile(manager, output, writer); + }); + + files.Add(output->assemblyH, fileH); + files.Add(output->assemblyCpp, fileCpp); + } + } + } + } +} + +/*********************************************************************** +.\AST\ASTCPPGEN_ASSEMBLER.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + + extern void PrintCppType(AstDefFile* fileContext, AstSymbol* propSymbol, stream::StreamWriter& writer); + +/*********************************************************************** +WriteAstAssemblerHeaderFile +***********************************************************************/ + + void WriteAstAssemblerHeaderFile(AstSymbolManager& manager, Ptr output, stream::StreamWriter& writer) + { + WriteParserUtilityHeaderFile(manager, output, L"ASSEMBLER", writer, [&](const WString& prefix) + { + { + vint index = 0; + writer.WriteLine(prefix + L"enum class " + manager.Global().name + L"Classes : vl::vint32_t"); + writer.WriteLine(prefix + L"{"); + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + output->classIds.Add(classSymbol, (vint32_t)index); + writer.WriteLine(prefix + L"\t" + classSymbol->Name() + L" = " + itow(index) + L","); + index++; + } + } + writer.WriteLine(prefix + L"};"); + } + { + vint index = 0; + writer.WriteLine(L""); + writer.WriteLine(prefix + L"enum class " + manager.Global().name + L"Fields : vl::vint32_t"); + writer.WriteLine(prefix + L"{"); + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + for (auto propSymbol : classSymbol->Props().Values()) + { + output->fieldIds.Add(propSymbol, (vint32_t)index); + writer.WriteLine(prefix + L"\t" + classSymbol->Name() + L"_" + propSymbol->Name() + L" = " + itow(index) + L","); + index++; + } + } + } + writer.WriteLine(prefix + L"};"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"extern const wchar_t* " + manager.Global().name + L"TypeName(" + manager.Global().name + L"Classes type);"); + writer.WriteLine(prefix + L"extern const wchar_t* " + manager.Global().name + L"CppTypeName(" + manager.Global().name + L"Classes type);"); + writer.WriteLine(prefix + L"extern const wchar_t* " + manager.Global().name + L"FieldName(" + manager.Global().name + L"Fields field);"); + writer.WriteLine(prefix + L"extern const wchar_t* " + manager.Global().name + L"CppFieldName(" + manager.Global().name + L"Fields field);"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"class " + manager.Global().name + L"AstInsReceiver : public vl::glr::AstInsReceiverBase"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"protected:"); + writer.WriteLine(prefix + L"\tvl::Ptr CreateAstNode(vl::vint32_t type) override;"); + writer.WriteLine(prefix + L"\tvoid SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value) override;"); + writer.WriteLine(prefix + L"\tvoid SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) override;"); + writer.WriteLine(prefix + L"\tvoid SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem) override;"); + writer.WriteLine(prefix + L"\tvl::Ptr ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates) override;"); + writer.WriteLine(prefix + L"};"); + } + }); + } + +/*********************************************************************** +WriteAstAssemblerCppFile +***********************************************************************/ + + void WriteAstAssemblerCppFile(AstSymbolManager& manager, Ptr output, stream::StreamWriter& writer) + { + WriteParserUtilityCppFile(manager, output->assemblyH, writer, [&](const WString& prefix) + { + writer.WriteLine(L""); + writer.WriteLine(L"/***********************************************************************"); + writer.WriteLine(manager.Global().name + L"AstInsReceiver : public vl::glr::AstInsReceiverBase"); + writer.WriteLine(L"***********************************************************************/"); + + /*********************************************************************** + CreateAstNode + ***********************************************************************/ + + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"vl::Ptr " + manager.Global().name + L"AstInsReceiver::CreateAstNode(vl::vint32_t type)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tauto cppTypeName = " + manager.Global().name + L"CppTypeName((" + manager.Global().name + L"Classes)type);"); + writer.WriteLine(prefix + L"\tswitch((" + manager.Global().name + L"Classes)type)"); + writer.WriteLine(prefix + L"\t{"); + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + if (classSymbol->derivedClasses.Count() == 0) + { + writer.WriteLine(prefix + L"\tcase " + manager.Global().name + L"Classes::" + classSymbol->Name() + L":"); + writer.WriteString(prefix + L"\t\treturn new "); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L"();"); + } + } + } + writer.WriteLine(prefix + L"\tdefault:"); + writer.WriteLine(prefix + L"\t\treturn vl::glr::AssemblyThrowCannotCreateAbstractType(type, cppTypeName);"); + writer.WriteLine(prefix + L"\t}"); + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + SetField(Object) + ***********************************************************************/ + + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"void " + manager.Global().name + L"AstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tauto cppFieldName = " + manager.Global().name + L"CppFieldName((" + manager.Global().name + L"Fields)field);"); + + List props; + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + for (auto [propSymbol, index] : indexed(classSymbol->Props().Values())) + { + if (propSymbol->propType != AstPropType::Token) + { + if (dynamic_cast(propSymbol->propSymbol)) + { + props.Add(propSymbol); + } + } + } + } + } + + if (props.Count() > 0) + { + writer.WriteLine(prefix + L"\tswitch((" + manager.Global().name + L"Fields)field)"); + writer.WriteLine(prefix + L"\t{"); + for (auto propSymbol : props) + { + auto classSymbol = propSymbol->Parent(); + writer.WriteLine(prefix + L"\tcase " + manager.Global().name + L"Fields::" + classSymbol->Name() + L"_" + propSymbol->Name() + L":"); + writer.WriteString(prefix + L"\t\treturn vl::glr::AssemblerSetObjectField(&"); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteString(L"::"); + writer.WriteString(propSymbol->Name()); + writer.WriteLine(L", object, field, value, cppFieldName);"); + } + writer.WriteLine(prefix + L"\tdefault:"); + writer.WriteLine(prefix + L"\t\treturn vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName);"); + writer.WriteLine(prefix + L"\t}"); + } + else + { + writer.WriteLine(prefix + L"\treturn vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName);"); + } + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + SetField(Token) + ***********************************************************************/ + + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"void " + manager.Global().name + L"AstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tauto cppFieldName = " + manager.Global().name + L"CppFieldName((" + manager.Global().name + L"Fields)field);"); + + List props; + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + for (auto [propSymbol, index] : indexed(classSymbol->Props().Values())) + { + if (propSymbol->propType == AstPropType::Token) + { + props.Add(propSymbol); + } + } + } + } + + if (props.Count() > 0) + { + writer.WriteLine(prefix + L"\tswitch((" + manager.Global().name + L"Fields)field)"); + writer.WriteLine(prefix + L"\t{"); + for (auto propSymbol : props) + { + auto classSymbol = propSymbol->Parent(); + writer.WriteLine(prefix + L"\tcase " + manager.Global().name + L"Fields::" + classSymbol->Name() + L"_" + propSymbol->Name() + L":"); + writer.WriteString(prefix + L"\t\treturn vl::glr::AssemblerSetTokenField(&"); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteString(L"::"); + writer.WriteString(propSymbol->Name()); + writer.WriteLine(L", object, field, token, tokenIndex, cppFieldName);"); + } + writer.WriteLine(prefix + L"\tdefault:"); + writer.WriteLine(prefix + L"\t\treturn vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName);"); + writer.WriteLine(prefix + L"\t}"); + } + else + { + writer.WriteLine(prefix + L"\treturn vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName);"); + } + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + SetField(Enum) + ***********************************************************************/ + + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"void " + manager.Global().name + L"AstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tauto cppFieldName = " + manager.Global().name + L"CppFieldName((" + manager.Global().name + L"Fields)field);"); + + List props; + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + for (auto [propSymbol, index] : indexed(classSymbol->Props().Values())) + { + if (propSymbol->propType == AstPropType::Type) + { + if (dynamic_cast(propSymbol->propSymbol)) + { + props.Add(propSymbol); + } + } + } + } + } + + if (props.Count() > 0) + { + writer.WriteLine(prefix + L"\tswitch((" + manager.Global().name + L"Fields)field)"); + writer.WriteLine(prefix + L"\t{"); + for (auto propSymbol : props) + { + auto classSymbol = propSymbol->Parent(); + writer.WriteLine(prefix + L"\tcase " + manager.Global().name + L"Fields::" + classSymbol->Name() + L"_" + propSymbol->Name() + L":"); + writer.WriteString(prefix + L"\t\treturn vl::glr::AssemblerSetEnumField(&"); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteString(L"::"); + writer.WriteString(propSymbol->Name()); + writer.WriteLine(L", object, field, enumItem, cppFieldName);"); + } + writer.WriteLine(prefix + L"\tdefault:"); + writer.WriteLine(prefix + L"\t\treturn vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName);"); + writer.WriteLine(prefix + L"\t}"); + } + else + { + writer.WriteLine(prefix + L"\treturn vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName);"); + } + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + TypeName + ***********************************************************************/ + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.Global().name + L"TypeName(" + manager.Global().name + L"Classes type)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tconst wchar_t* results[] = {"); + + Array idToClasses(output->classIds.Count()); + for (auto [k, v] : output->classIds) + { + idToClasses[v] = k; + } + + for (auto classSymbol : idToClasses) + { + writer.WriteLine(prefix + L"\t\tL\"" + classSymbol->Name() + L"\","); + } + + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::vint index = (vl::vint)type;"); + writer.WriteLine(prefix + L"\treturn 0 <= index && index < " + itow(idToClasses.Count()) + L" ? results[index] : nullptr;"); + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + CppTypeName + ***********************************************************************/ + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.Global().name + L"CppTypeName(" + manager.Global().name + L"Classes type)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tconst wchar_t* results[] = {"); + + Array idToClasses(output->classIds.Count()); + for (auto [k, v] : output->classIds) + { + idToClasses[v] = k; + } + + for (auto classSymbol : idToClasses) + { + writer.WriteString(prefix + L"\t\tL\""); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L"\","); + } + + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::vint index = (vl::vint)type;"); + writer.WriteLine(prefix + L"\treturn 0 <= index && index < " + itow(idToClasses.Count()) + L" ? results[index] : nullptr;"); + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + FieldName + ***********************************************************************/ + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.Global().name + L"FieldName(" + manager.Global().name + L"Fields field)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tconst wchar_t* results[] = {"); + + Array idToFields(output->fieldIds.Count()); + for (auto [k, v] : output->fieldIds) + { + idToFields[v] = k; + } + + for (auto propSymbol : idToFields) + { + auto classSymbol = propSymbol->Parent(); + writer.WriteLine(prefix + L"\t\tL\"" + classSymbol->Name() + L"::" + propSymbol->Name() + L"\","); + } + + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::vint index = (vl::vint)field;"); + writer.WriteLine(prefix + L"\treturn 0 <= index && index < " + itow(idToFields.Count()) + L" ? results[index] : nullptr;"); + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + CppFieldName + ***********************************************************************/ + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.Global().name + L"CppFieldName(" + manager.Global().name + L"Fields field)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tconst wchar_t* results[] = {"); + + Array idToFields(output->fieldIds.Count()); + for (auto [k, v] : output->fieldIds) + { + idToFields[v] = k; + } + + for (auto propSymbol : idToFields) + { + auto classSymbol = propSymbol->Parent(); + writer.WriteString(prefix + L"\t\tL\""); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L"::" + propSymbol->Name() + L"\","); + } + + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::vint index = (vl::vint)field;"); + writer.WriteLine(prefix + L"\treturn 0 <= index && index < " + itow(idToFields.Count()) + L" ? results[index] : nullptr;"); + writer.WriteLine(prefix + L"}"); + } + + /*********************************************************************** + ResolveAmbiguity + ***********************************************************************/ + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"vl::Ptr " + manager.Global().name + L"AstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tauto cppTypeName = " + manager.Global().name + L"CppTypeName((" + manager.Global().name + L"Classes)type);"); + + Dictionary resolvables; + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + auto current = classSymbol; + while (current) + { + if (current->ambiguousDerivedClass) + { + resolvables.Add(classSymbol, current->ambiguousDerivedClass); + break; + } + current = current->baseClass; + } + } + } + + if (resolvables.Count() > 0) + { + writer.WriteLine(prefix + L"\tswitch((" + manager.Global().name + L"Classes)type)"); + writer.WriteLine(prefix + L"\t{"); + + for (auto typeSymbol : manager.Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + if (resolvables.Keys().Contains(classSymbol)) + { + auto ambiguousClassSymbol = resolvables[classSymbol]; + writer.WriteLine(prefix + L"\tcase " + manager.Global().name + L"Classes::" + classSymbol->Name() + L":"); + writer.WriteString(prefix + L"\t\treturn vl::glr::AssemblerResolveAmbiguity<"); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteString(L", "); + PrintCppType(nullptr, ambiguousClassSymbol, writer); + writer.WriteLine(L">(type, candidates, cppTypeName);"); + } + } + } + + writer.WriteLine(prefix + L"\tdefault:"); + writer.WriteLine(prefix + L"\t\treturn vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName);"); + writer.WriteLine(prefix + L"\t}"); + } + else + { + writer.WriteLine(prefix + L"\treturn vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName);"); + } + writer.WriteLine(prefix + L"}"); + } + }); + } + } + } +} + +/*********************************************************************** +.\AST\ASTCPPGEN_BUILDER.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + + extern void PrintCppType(AstDefFile* fileContext, AstSymbol* propSymbol, stream::StreamWriter& writer); + +/*********************************************************************** +WriteAstBuilderHeaderFile +***********************************************************************/ + + void WriteAstBuilderHeaderFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityHeaderFile(file, output, L"builder", writer, [&](const WString& prefix) + { + for(auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + if (classSymbol->Props().Count() > 0) + { + WString className = L"Make" + classSymbol->Name(); + writer.WriteString(prefix + L"class " + className); + writer.WriteString(L" : public vl::glr::ParsingAstBuilder<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L">"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"public:"); + + auto currentClass = classSymbol; + while (currentClass) + { + for (auto propSymbol : currentClass->Props().Values()) + { + switch (propSymbol->propType) + { + case AstPropType::Token: + writer.WriteLine(prefix + L"\t" + className + L"& " + propSymbol->Name() + L"(const vl::WString& value);"); + break; + case AstPropType::Type: + if (dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteString(prefix + L"\t" + className + L"& " + propSymbol->Name() + L"("); + PrintCppType(file, propSymbol->propSymbol, writer); + writer.WriteLine(L" value);"); + break; + } + case AstPropType::Array: + writer.WriteString(prefix + L"\t" + className + L"& " + propSymbol->Name() + L"(const vl::Ptr<"); + PrintCppType(file, propSymbol->propSymbol, writer); + writer.WriteLine(L">& value);"); + break; + } + } + currentClass = currentClass->baseClass; + } + writer.WriteLine(prefix + L"};"); + writer.WriteLine(L""); + } + } + } + }); + } + +/*********************************************************************** +WriteAstBuilderCppFile +***********************************************************************/ + + void WriteAstBuilderCppFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityCppFile(file, output->builderH, L"builder", writer, [&](const WString& prefix) + { + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + if (classSymbol->Props().Count() > 0) + { + WString className = L"Make" + classSymbol->Name(); + writer.WriteLine(L""); + writer.WriteLine(L"/***********************************************************************"); + writer.WriteLine(className); + writer.WriteLine(L"***********************************************************************/"); + + auto currentClass = classSymbol; + while (currentClass) + { + for (auto propSymbol : currentClass->Props().Values()) + { + writer.WriteLine(L""); + switch (propSymbol->propType) + { + case AstPropType::Token: + writer.WriteLine(prefix + className + L"& " + className + L"::" + propSymbol->Name() + L"(const vl::WString& value)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tnode->" + propSymbol->Name() + L".value = value;"); + writer.WriteLine(prefix + L"\treturn *this;"); + writer.WriteLine(prefix + L"}"); + break; + case AstPropType::Type: + if (dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteString(prefix + className + L"& " + className + L"::" + propSymbol->Name() + L"("); + PrintCppType(file, propSymbol->propSymbol, writer); + writer.WriteLine(L" value)"); + } + if (dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteString(prefix + className + L"& " + className + L"::" + propSymbol->Name() + L"(const vl::Ptr<"); + PrintCppType(file, propSymbol->propSymbol, writer); + writer.WriteLine(L">& value)"); + } + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tnode->" + propSymbol->Name() + L" = value;"); + writer.WriteLine(prefix + L"\treturn *this;"); + writer.WriteLine(prefix + L"}"); + break; + case AstPropType::Array: + writer.WriteString(prefix + className + L"& " + className + L"::" + propSymbol->Name() + L"(const vl::Ptr<"); + PrintCppType(file, propSymbol->propSymbol, writer); + writer.WriteLine(L">& value)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tnode->" + propSymbol->Name() + L".Add(value);"); + writer.WriteLine(prefix + L"\treturn *this;"); + writer.WriteLine(prefix + L"}"); + break; + } + } + currentClass = currentClass->baseClass; + } + } + } + } + }); + } + } + } +} + +/*********************************************************************** +.\AST\ASTCPPGEN_CLASSES.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + +/*********************************************************************** +WriteTypeForwardDefinitions +***********************************************************************/ + + void WriteTypeForwardDefinitions(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer) + { + for (auto [name, index] : indexed(file->Symbols().Keys())) + { + if (dynamic_cast(file->Symbols().Values()[index])) + { + writer.WriteString(prefix); + writer.WriteString(L"class "); + writer.WriteString(file->classPrefix); + writer.WriteString(name); + writer.WriteLine(L";"); + } + } + } + +/*********************************************************************** +PrintCppType +***********************************************************************/ + + void PrintNss(List& nss, stream::StreamWriter& writer) + { + for (auto&& ns : nss) + { + writer.WriteString(ns); + writer.WriteString(L"::"); + } + } + + enum class PrintTypePurpose + { + TypeName, + ReflectionName, + Value, + }; + + void PrintAstType(AstDefFile* fileContext, AstPropType propType, AstSymbol* propSymbol, PrintTypePurpose purpose, stream::StreamWriter& writer) + { + if (propType == AstPropType::Token) + { + writer.WriteString(L"vl::glr::ParsingToken"); + return; + } + + if (propType == AstPropType::Array) + { + writer.WriteString(L"vl::collections::List(propSymbol)) + { + writer.WriteString(L"vl::Ptr<"); + } + + auto file = propSymbol->Owner(); + if (purpose == PrintTypePurpose::ReflectionName) + { + PrintNss(file->refNss, writer); + } + else + { + if (fileContext != file) + { + PrintNss(file->cppNss, writer); + } + } + writer.WriteString(file->classPrefix); + writer.WriteString(propSymbol->Name()); + + if (propType == AstPropType::Array) + { + writer.WriteString(L">>"); + } + else if (purpose == PrintTypePurpose::Value && dynamic_cast(propSymbol)) + { + writer.WriteString(L">"); + } + } + + void PrintFieldType(AstDefFile* fileContext, AstPropType propType, AstSymbol* propSymbol, stream::StreamWriter& writer) + { + PrintAstType(fileContext, propType, propSymbol, PrintTypePurpose::Value, writer); + } + + void PrintCppType(AstDefFile* fileContext, AstSymbol* propSymbol, stream::StreamWriter& writer) + { + PrintAstType(fileContext, AstPropType::Type, propSymbol, PrintTypePurpose::TypeName, writer); + } + +/*********************************************************************** +WriteTypeDefinitions +***********************************************************************/ + + void WriteTypeDefinitions(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer) + { + for (auto name : file->SymbolOrder()) + { + auto typeSymbol = file->Symbols()[name]; + if (auto enumSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteString(L"enum class "); + writer.WriteString(file->classPrefix); + writer.WriteLine(name); + writer.WriteString(prefix); + writer.WriteLine(L"{"); + + { + writer.WriteString(prefix); + writer.WriteLine(L"\tUNDEFINED_ENUM_ITEM_VALUE = -1,"); + } + + for (auto itemName : enumSymbol->ItemOrder()) + { + auto itemSymbol = enumSymbol->Items()[itemName]; + writer.WriteString(prefix); + writer.WriteString(L"\t"); + writer.WriteString(itemName); + writer.WriteString(L" = "); + writer.WriteString(itow(itemSymbol->value)); + writer.WriteLine(L","); + } + + writer.WriteString(prefix); + writer.WriteLine(L"};"); + } + } + + for (auto name : file->SymbolOrder()) + { + auto typeSymbol = file->Symbols()[name]; + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteString(L"class "); + writer.WriteString(file->classPrefix); + writer.WriteString(name); + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteString(L" abstract"); + } + writer.WriteString(L" : public "); + if (classSymbol->baseClass) + { + PrintCppType(file, classSymbol->baseClass, writer); + } + else + { + writer.WriteString(L"vl::glr::ParsingAstBase"); + } + writer.WriteString(L", vl::reflection::Description<"); + writer.WriteString(file->classPrefix); + writer.WriteString(name); + writer.WriteLine(L">"); + + writer.WriteString(prefix); + writer.WriteLine(L"{"); + writer.WriteString(prefix); + writer.WriteLine(L"public:"); + + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteString(prefix); + writer.WriteLine(L"\tclass IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description"); + writer.WriteString(prefix); + writer.WriteLine(L"\t{"); + writer.WriteString(prefix); + writer.WriteLine(L"\tpublic:"); + + for (auto childSymbol : classSymbol->derivedClasses) + { + writer.WriteString(prefix); + writer.WriteString(L"\t\tvirtual void Visit("); + PrintCppType(file, childSymbol, writer); + writer.WriteLine(L"* node) = 0;"); + } + + writer.WriteString(prefix); + writer.WriteLine(L"\t};"); + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteString(L"\tvirtual void Accept("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor* visitor) = 0;"); + writer.WriteLine(L""); + } + + for (auto propName : classSymbol->PropOrder()) + { + auto propSymbol = classSymbol->Props()[propName]; + writer.WriteString(prefix); + writer.WriteString(L"\t"); + PrintFieldType(file, propSymbol->propType, propSymbol->propSymbol, writer); + writer.WriteString(L" "); + writer.WriteString(propName); + if (dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteString(L" = "); + PrintCppType(file, propSymbol->propSymbol, writer); + writer.WriteString(L"::UNDEFINED_ENUM_ITEM_VALUE"); + } + writer.WriteLine(L";"); + } + + if (classSymbol->baseClass) + { + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteString(L"\tvoid Accept("); + PrintCppType(file, classSymbol->baseClass, writer); + writer.WriteLine(L"::IVisitor* visitor) override;"); + } + + writer.WriteString(prefix); + writer.WriteLine(L"};"); + } + } + } + +/*********************************************************************** +WriteVisitorImpl +***********************************************************************/ + + void WriteVisitorImpl(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer) + { + for (auto name : file->SymbolOrder()) + { + if (auto classSymbol = dynamic_cast(file->Symbols()[name])) + { + if (classSymbol->baseClass) + { + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteString(L"void "); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"::Accept("); + PrintCppType(file, classSymbol->baseClass, writer); + writer.WriteLine(L"::IVisitor* visitor)"); + writer.WriteString(prefix); + writer.WriteLine(L"{"); + writer.WriteString(prefix); + writer.WriteLine(L"\tvisitor->Visit(this);"); + writer.WriteString(prefix); + writer.WriteLine(L"}"); + } + } + } + } + +/*********************************************************************** +WriteTypeReflectionDeclaration +***********************************************************************/ + + void WriteTypeReflectionDeclaration(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer) + { + writer.WriteLine(L"#ifndef VCZH_DEBUG_NO_REFLECTION"); + + for (auto&& name : file->SymbolOrder()) + { + auto typeSymbol = file->Symbols()[name]; + writer.WriteString(prefix); + writer.WriteString(L"DECL_TYPE_INFO("); + PrintCppType(nullptr, typeSymbol, writer); + writer.WriteLine(L")"); + + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteString(prefix); + writer.WriteString(L"DECL_TYPE_INFO("); + PrintCppType(nullptr, typeSymbol, writer); + writer.WriteLine(L"::IVisitor)"); + } + } + } + + writer.WriteLine(L""); + writer.WriteLine(L"#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA"); + writer.WriteLine(L""); + for (auto&& name : file->SymbolOrder()) + { + if (auto classSymbol = dynamic_cast(file->Symbols()[name])) + { + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteString(prefix); + writer.WriteString(L"BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L"::IVisitor)"); + + for (auto childSymbol : classSymbol->derivedClasses) + { + writer.WriteString(prefix); + writer.WriteString(L"\tvoid Visit("); + PrintCppType(nullptr, childSymbol, writer); + writer.WriteLine(L"* node) override"); + writer.WriteString(prefix); + writer.WriteLine(L"\t{"); + writer.WriteString(prefix); + writer.WriteLine(L"\t\tINVOKE_INTERFACE_PROXY(Visit, node);"); + writer.WriteString(prefix); + writer.WriteLine(L"\t}"); + writer.WriteLine(L""); + } + + writer.WriteString(prefix); + writer.WriteString(L"END_INTERFACE_PROXY("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L"::IVisitor)"); + writer.WriteLine(L""); + } + } + } + + writer.WriteLine(L"#endif"); + writer.WriteLine(L"#endif"); + + writer.WriteString(prefix); + writer.WriteLine(L"/// Load all reflectable AST types, only available when VCZH_DEBUG_NO_REFLECTION is off."); + writer.WriteString(prefix); + writer.WriteLine(L"/// Returns true if this operation succeeded."); + + writer.WriteString(prefix); + writer.WriteString(L"extern bool "); + writer.WriteString(file->Owner()->Global().name); + writer.WriteString(file->Name()); + writer.WriteLine(L"LoadTypes();"); + } + +/*********************************************************************** +WriteTypeReflectionImplementation +***********************************************************************/ + + void WriteTypeReflectionImplementation(AstDefFile* file, const WString& prefix, stream::StreamWriter& writer) + { + writer.WriteLine(L"#ifndef VCZH_DEBUG_NO_REFLECTION"); + + writer.WriteLine(L""); + + for (auto&& name : file->SymbolOrder()) + { + auto typeSymbol = file->Symbols()[name]; + writer.WriteString(prefix); + writer.WriteString(L"IMPL_TYPE_INFO_RENAME("); + PrintCppType(nullptr, typeSymbol, writer); + writer.WriteString(L", "); + PrintAstType(nullptr, AstPropType::Type, typeSymbol, PrintTypePurpose::ReflectionName, writer); + writer.WriteLine(L")"); + + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteString(prefix); + writer.WriteString(L"IMPL_TYPE_INFO_RENAME("); + PrintCppType(nullptr, typeSymbol, writer); + writer.WriteString(L"::IVisitor"); + writer.WriteString(L", "); + PrintAstType(nullptr, AstPropType::Type, typeSymbol, PrintTypePurpose::ReflectionName, writer); + writer.WriteLine(L"::IVisitor)"); + } + } + } + + writer.WriteLine(L""); + writer.WriteLine(L"#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA"); + + for (auto&& name : file->SymbolOrder()) + { + auto typeSymbol = file->Symbols()[name]; + writer.WriteLine(L""); + + if (auto enumSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix); + writer.WriteString(L"BEGIN_ENUM_ITEM("); + PrintCppType(nullptr, enumSymbol, writer); + writer.WriteLine(L")"); + + writer.WriteString(prefix); + writer.WriteString(L"\tENUM_ITEM_NAMESPACE("); + PrintCppType(nullptr, enumSymbol, writer); + writer.WriteLine(L")"); + + for (auto itemName : enumSymbol->ItemOrder()) + { + writer.WriteString(prefix); + writer.WriteString(L"\tENUM_NAMESPACE_ITEM("); + writer.WriteString(itemName); + writer.WriteLine(L")"); + } + + writer.WriteString(prefix); + writer.WriteString(L"END_ENUM_ITEM("); + PrintCppType(nullptr, enumSymbol, writer); + writer.WriteLine(L")"); + } + + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix); + writer.WriteString(L"BEGIN_CLASS_MEMBER("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L")"); + + if (classSymbol->baseClass) + { + writer.WriteString(prefix); + writer.WriteString(L"\tCLASS_MEMBER_BASE("); + PrintCppType(nullptr, classSymbol->baseClass, writer); + writer.WriteLine(L")"); + } + else + { + writer.WriteLine(prefix + L"\tCLASS_MEMBER_BASE(vl::glr::ParsingAstBase)"); + } + writer.WriteLine(L""); + + if (classSymbol->derivedClasses.Count() == 0) + { + writer.WriteString(prefix); + writer.WriteString(L"\tCLASS_MEMBER_CONSTRUCTOR(vl::Ptr<"); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L">(), NO_PARAMETER)"); + writer.WriteLine(L""); + } + + for (auto propName : classSymbol->PropOrder()) + { + auto propSymbol = classSymbol->Props()[propName]; + writer.WriteString(prefix); + writer.WriteString(L"\tCLASS_MEMBER_FIELD("); + writer.WriteString(propSymbol->Name()); + writer.WriteLine(L")"); + } + + writer.WriteString(prefix); + writer.WriteString(L"END_CLASS_MEMBER("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L")"); + } + } + + for (auto&& name : file->SymbolOrder()) + { + if (auto classSymbol = dynamic_cast(file->Symbols()[name])) + { + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteString(L"BEGIN_INTERFACE_MEMBER("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L"::IVisitor)"); + + for (auto childSymbol : classSymbol->derivedClasses) + { + writer.WriteString(prefix); + writer.WriteString(L"\tCLASS_MEMBER_METHOD_OVERLOAD(Visit, {L\"node\"}, void("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteString(L"::IVisitor::*)("); + PrintCppType(nullptr, childSymbol, writer); + writer.WriteLine(L"* node))"); + } + + writer.WriteString(prefix); + writer.WriteString(L"END_INTERFACE_MEMBER("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L")"); + } + } + } + + writer.WriteLine(L""); + writer.WriteLine(L"#endif"); + + writer.WriteLine(L""); + writer.WriteLine(L"#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA"); + writer.WriteString(prefix); + writer.WriteString(L"class "); + writer.WriteString(file->Owner()->Global().name); + writer.WriteString(file->Name()); + writer.WriteLine(L"TypeLoader : public vl::Object, public ITypeLoader"); + writer.WriteString(prefix); + writer.WriteLine(L"{"); + writer.WriteString(prefix); + writer.WriteLine(L"public:"); + + writer.WriteString(prefix); + writer.WriteLine(L"\tvoid Load(ITypeManager* manager)"); + writer.WriteString(prefix); + writer.WriteLine(L"\t{"); + + for (auto&& name : file->SymbolOrder()) + { + auto typeSymbol = file->Symbols()[name]; + writer.WriteString(prefix); + writer.WriteString(L"\t\tADD_TYPE_INFO("); + PrintCppType(nullptr, typeSymbol, writer); + writer.WriteLine(L")"); + + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteString(prefix); + writer.WriteString(L"\t\tADD_TYPE_INFO("); + PrintCppType(nullptr, classSymbol, writer); + writer.WriteLine(L"::IVisitor)"); + } + } + } + + writer.WriteString(prefix); + writer.WriteLine(L"\t}"); + + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteLine(L"\tvoid Unload(ITypeManager* manager)"); + writer.WriteString(prefix); + writer.WriteLine(L"\t{"); + writer.WriteString(prefix); + writer.WriteLine(L"\t}"); + + writer.WriteString(prefix); + writer.WriteLine(L"};"); + writer.WriteLine(L"#endif"); + + writer.WriteLine(L"#endif"); + + writer.WriteLine(L""); + writer.WriteString(prefix); + writer.WriteString(L"bool "); + writer.WriteString(file->Owner()->Global().name); + writer.WriteString(file->Name()); + writer.WriteLine(L"LoadTypes()"); + writer.WriteString(prefix); + writer.WriteLine(L"{"); + writer.WriteLine(L"#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA"); + + writer.WriteString(prefix); + writer.WriteLine(L"\tif (auto manager = GetGlobalTypeManager())"); + writer.WriteString(prefix); + writer.WriteLine(L"\t{"); + writer.WriteString(prefix); + writer.WriteString(L"\t\tPtr loader = new "); + writer.WriteString(file->Owner()->Global().name); + writer.WriteString(file->Name()); + writer.WriteLine(L"TypeLoader;"); + writer.WriteString(prefix); + writer.WriteLine(L"\t\treturn manager->AddTypeLoader(loader);"); + writer.WriteString(prefix); + writer.WriteLine(L"\t}"); + + writer.WriteLine(L"#endif"); + writer.WriteString(prefix); + writer.WriteLine(L"\treturn false;"); + writer.WriteString(prefix); + writer.WriteLine(L"}"); + } + } + } +} + +/*********************************************************************** +.\AST\ASTCPPGEN_COPYVISITOR.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + + extern void PrintCppType(AstDefFile* fileContext, AstSymbol* propSymbol, stream::StreamWriter& writer); + extern void CollectVisitorsAndConcreteClasses(AstDefFile* file, List& visitors, List& concreteClasses); + +/*********************************************************************** +WriteCopyFieldFunctionBody +***********************************************************************/ + + void WriteCopyFieldFunctionBody(AstDefFile* file, AstClassSymbol* fieldSymbol, const WString& prefix, stream::StreamWriter& writer) + { + if (fieldSymbol->baseClass) + { + writer.WriteString(prefix + L"\tCopyFields(static_cast<"); + PrintCppType(file, fieldSymbol->baseClass, writer); + writer.WriteString(L"*>(from), static_cast<"); + PrintCppType(file, fieldSymbol->baseClass, writer); + writer.WriteLine(L"*>(to));"); + } + + for (auto propSymbol : fieldSymbol->Props().Values()) + { + switch (propSymbol->propType) + { + case AstPropType::Token: + writer.WriteLine(prefix + L"\tto->" + propSymbol->Name() + L" = from->" + propSymbol->Name() + L";"); + break; + case AstPropType::Array: + writer.WriteLine(prefix + L"\tfor (auto&& listItem : from->" + propSymbol->Name() + L")"); + writer.WriteLine(prefix + L"\t{"); + writer.WriteLine(prefix + L"\t\tto->" + propSymbol->Name() + L".Add(CopyNode(listItem.Obj()));"); + writer.WriteLine(prefix + L"\t}"); + break; + case AstPropType::Type: + if (dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteLine(prefix + L"\tto->" + propSymbol->Name() + L" = CopyNode(from->" + propSymbol->Name() + L".Obj());"); + } + else + { + writer.WriteLine(prefix + L"\tto->" + propSymbol->Name() + L" = from->" + propSymbol->Name() + L";"); + } + break; + } + } + } + +/*********************************************************************** +WriteCopyVisitorHeaderFile +***********************************************************************/ + + void WriteCopyVisitorHeaderFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityHeaderFile(file, output, L"copy_visitor", writer, [&](const WString& prefix) + { + List visitors, concreteClasses; + CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses); + + writer.WriteLine(prefix + L"/// A copy visitor, overriding all abstract methods with AST copying code."); + writer.WriteLine(prefix + L"class " + file->Name() + L"Visitor"); + writer.WriteLine(prefix + L"\t: public virtual vl::glr::CopyVisitorBase"); + for (auto visitorSymbol : visitors) + { + writer.WriteString(prefix + L"\t, protected virtual "); + PrintCppType(file, visitorSymbol, writer); + writer.WriteLine(L"::IVisitor"); + } + writer.WriteLine(prefix + L"{"); + + writer.WriteLine(prefix + L"protected:"); + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"\tvoid CopyFields("); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"* from, "); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* to);"); + } + } + writer.WriteLine(L""); + + writer.WriteLine(prefix + L"protected:"); + for (auto classSymbol : concreteClasses) + { + writer.WriteString(prefix + L"\tvirtual void Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + writer.WriteLine(L""); + for (auto visitorSymbol : visitors) + { + for (auto classSymbol : visitorSymbol->derivedClasses) + { + writer.WriteString(prefix + L"\tvoid Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node) override;"); + } + writer.WriteLine(L""); + } + + writer.WriteLine(prefix + L"public:"); + for (auto classSymbol : + From(visitors) + .Where([](AstClassSymbol* visitor) { return visitor->baseClass == nullptr; }) + .Concat(concreteClasses) + ) + { + writer.WriteString(prefix + L"\tvirtual vl::Ptr<"); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"> CopyNode("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + + writer.WriteLine(L""); + for (auto classSymbol : + From(file->Symbols().Values()) + .Select([](AstSymbol* derivedClass) { return dynamic_cast(derivedClass); }) + .Where([](AstClassSymbol* derivedClass) { return derivedClass && derivedClass->baseClass != nullptr; }) + ) + { + writer.WriteString(prefix + L"\tvl::Ptr<"); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"> CopyNode("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + writer.WriteLine(prefix + L"};"); + }); + } + +/*********************************************************************** +WriteCopyVisitorCppFile +***********************************************************************/ + + void WriteCopyVisitorCppFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityCppFile(file, output->copyH, L"copy_visitor", writer, [&](const WString& prefix) + { + List visitors, concreteClasses; + CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses); + + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::CopyFields("); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"* from, "); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* to)"); + writer.WriteLine(prefix + L"{"); + WriteCopyFieldFunctionBody(file, classSymbol, prefix, writer); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + } + + for (auto classSymbol : concreteClasses) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + writer.WriteString(prefix + L"\tauto newNode = vl::MakePtr<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L">();"); + writer.WriteLine(prefix + L"\tCopyFields(node, newNode.Obj());"); + writer.WriteLine(prefix + L"\tthis->result = newNode;"); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + + for (auto visitorSymbol : visitors) + { + for (auto classSymbol : visitorSymbol->derivedClasses) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + if (classSymbol->derivedClasses.Count() == 0) + { + writer.WriteString(prefix + L"\tauto newNode = vl::MakePtr<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L">();"); + writer.WriteLine(prefix + L"\tCopyFields(node, newNode.Obj());"); + writer.WriteLine(prefix + L"\tthis->result = newNode;"); + } + else + { + writer.WriteString(prefix + L"\tnode->Accept(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor*>(this));"); + } + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + } + + for (auto classSymbol : visitors) + { + if (!classSymbol->baseClass) + { + writer.WriteString(prefix + L"vl::Ptr<"); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"> " + file->Name() + L"Visitor::CopyNode("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tif (!node) return nullptr;"); + writer.WriteString(prefix + L"\tnode->Accept(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor*>(this));"); + writer.WriteString(prefix + L"\treturn this->result.Cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L">();"); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + } + + for (auto classSymbol : concreteClasses) + { + writer.WriteString(prefix + L"vl::Ptr<"); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"> " + file->Name() + L"Visitor::CopyNode("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tif (!node) return nullptr;"); + writer.WriteLine(prefix + L"\tVisit(node);"); + writer.WriteString(prefix + L"\treturn this->result.Cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L">();"); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + + for (auto classSymbol : + From(file->Symbols().Values()) + .Select([](AstSymbol* derivedClass) { return dynamic_cast(derivedClass); }) + .Where([](AstClassSymbol* derivedClass) { return derivedClass && derivedClass->baseClass != nullptr; }) + ) + { + auto rootBaseClass = classSymbol; + while (rootBaseClass->baseClass) + { + rootBaseClass = rootBaseClass->baseClass; + } + + writer.WriteString(prefix + L"vl::Ptr<"); + PrintCppType(file, classSymbol, writer); + writer.WriteString(L"> " + file->Name() + L"Visitor::CopyNode("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tif (!node) return nullptr;"); + writer.WriteString(prefix + L"\treturn CopyNode(static_cast<"); + PrintCppType(file, rootBaseClass, writer); + writer.WriteString(L"*>(node)).Cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L">();"); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + }); + } + } + } +} + +/*********************************************************************** +.\AST\ASTCPPGEN_EMPTYVISITOR.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + + extern void PrintCppType(AstDefFile* fileContext, AstSymbol* propSymbol, stream::StreamWriter& writer); + +/*********************************************************************** +WriteEmptyVisitorHeaderFile +***********************************************************************/ + + void WriteEmptyVisitorHeaderFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityHeaderFile(file, output, L"empty_visitor", writer, [&](const WString& prefix) + { + for (auto name : file->SymbolOrder()) + { + if (auto classSymbol = dynamic_cast(file->Symbols()[name])) + { + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteLine(prefix + L"/// An empty visitor, overriding all abstract methods with empty implementations."); + writer.WriteString(prefix + L"class " + name + L"Visitor : public vl::Object, public "); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor"); + writer.WriteLine(prefix + L"{"); + + writer.WriteLine(prefix + L"protected:"); + writer.WriteLine(prefix + L"\t// Dispatch (virtual) --------------------------------"); + for (auto childSymbol : classSymbol->derivedClasses) + { + if (childSymbol->derivedClasses.Count() > 0) + { + writer.WriteString(prefix + L"\tvirtual void Dispatch("); + PrintCppType(file, childSymbol, writer); + writer.WriteLine(L"* node) = 0;"); + } + } + writer.WriteLine(L""); + + writer.WriteLine(prefix + L"public:"); + writer.WriteLine(prefix + L"\t// Visitor Members -----------------------------------"); + for (auto childSymbol : classSymbol->derivedClasses) + { + writer.WriteString(prefix + L"\tvoid Visit("); + PrintCppType(file, childSymbol, writer); + writer.WriteLine(L"* node) override;"); + } + + writer.WriteLine(prefix + L"};"); + writer.WriteLine(L""); + } + } + } + }); + } + +/*********************************************************************** +WriteEmptyVisitorCppFile +***********************************************************************/ + + void WriteEmptyVisitorCppFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityCppFile(file, output->emptyH, L"empty_visitor", writer, [&](const WString& prefix) + { + for (auto name : file->SymbolOrder()) + { + if (auto classSymbol = dynamic_cast(file->Symbols()[name])) + { + if (classSymbol->derivedClasses.Count() > 0) + { + writer.WriteLine(L""); + writer.WriteLine(L"/***********************************************************************"); + writer.WriteLine(classSymbol->Name() + L"Visitor"); + writer.WriteLine(L"***********************************************************************/"); + + writer.WriteLine(L""); + writer.WriteLine(prefix + L"// Visitor Members -----------------------------------"); + for (auto childSymbol : classSymbol->derivedClasses) + { + writer.WriteLine(L""); + writer.WriteString(prefix + L"void " + classSymbol->Name() + L"Visitor::Visit("); + PrintCppType(file, childSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + if (childSymbol->derivedClasses.Count() > 0) + { + writer.WriteLine(prefix + L"\tDispatch(node);"); + } + writer.WriteLine(prefix + L"}"); + } + } + } + } + }); + } + } + } +} + +/*********************************************************************** +.\AST\ASTCPPGEN_JSONVISITOR.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + + extern void PrintCppType(AstDefFile* fileContext, AstSymbol* propSymbol, stream::StreamWriter& writer); + extern void CollectVisitorsAndConcreteClasses(AstDefFile* file, List& visitors, List& concreteClasses); + +/*********************************************************************** +WriteVisitFieldFunctionBody +***********************************************************************/ + + void WritePrintFieldsFunctionBody(AstDefFile* file, AstClassSymbol* fieldSymbol, const WString& prefix, stream::StreamWriter& writer) + { + for (auto propSymbol : fieldSymbol->Props().Values()) + { + writer.WriteLine(prefix + L"\tBeginField(L\"" + propSymbol->Name() + L"\");"); + switch (propSymbol->propType) + { + case AstPropType::Token: + writer.WriteLine(prefix + L"\tWriteToken(node->" + propSymbol->Name() + L");"); + break; + case AstPropType::Array: + writer.WriteLine(prefix + L"\tBeginArray();"); + writer.WriteLine(prefix + L"\tfor (auto&& listItem : node->" + propSymbol->Name() + L")"); + writer.WriteLine(prefix + L"\t{"); + writer.WriteLine(prefix + L"\t\tBeginArrayItem();"); + writer.WriteLine(prefix + L"\t\tPrint(listItem.Obj());"); + writer.WriteLine(prefix + L"\t\tEndArrayItem();"); + writer.WriteLine(prefix + L"\t}"); + writer.WriteLine(prefix + L"\tEndArray();"); + break; + case AstPropType::Type: + if (auto enumPropSymbol = dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteLine(prefix + L"\tswitch (node->" + propSymbol->Name() + L")"); + writer.WriteLine(prefix + L"\t{"); + for (auto enumItemSymbol : enumPropSymbol->Items().Values()) + { + writer.WriteString(prefix + L"\tcase "); + PrintCppType(nullptr, enumPropSymbol, writer); + writer.WriteLine(L"::" + enumItemSymbol->Name() + L":"); + writer.WriteLine(prefix + L"\t\tWriteString(L\"" + enumItemSymbol->Name() + L"\");"); + writer.WriteLine(prefix + L"\t\tbreak;"); + } + writer.WriteLine(prefix + L"\tdefault:"); + writer.WriteLine(prefix + L"\t\tWriteNull();"); + writer.WriteLine(prefix + L"\t}"); + } + if (dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteLine(prefix + L"\tPrint(node->" + propSymbol->Name() + L".Obj());"); + } + break; + } + writer.WriteLine(prefix + L"\tEndField();"); + } + } + + void WriteNullAndReturn(const WString& prefix, stream::StreamWriter& writer) + { + writer.WriteLine(prefix + L"\tif (!node)"); + writer.WriteLine(prefix + L"\t{"); + writer.WriteLine(prefix + L"\t\tWriteNull();"); + writer.WriteLine(prefix + L"\t\treturn;"); + writer.WriteLine(prefix + L"\t}"); + } + + void WriteVisitFunctionBody(AstDefFile* file, AstClassSymbol* fieldSymbol, const WString& prefix, stream::StreamWriter& writer) + { + WriteNullAndReturn(prefix, writer); + List order; + { + auto current = fieldSymbol; + while (current) + { + order.Add(current); + current = current->baseClass; + } + } + + writer.WriteLine(prefix + L"\tBeginObject();"); + writer.WriteLine(prefix + L"\tWriteType(L\"" + fieldSymbol->Name() + L"\", node);"); + for (auto classSymbol : From(order).Reverse()) + { + writer.WriteString(prefix + L"\tPrintFields(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"*>(node));"); + } + writer.WriteLine(prefix + L"\tEndObject();"); + } + +/*********************************************************************** +WriteJsonVisitorHeaderFile +***********************************************************************/ + + void WriteJsonVisitorHeaderFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityHeaderFile(file, output, L"json_visitor", writer, [&](const WString& prefix) + { + List visitors, concreteClasses; + CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses); + + writer.WriteLine(prefix + L"/// A JSON visitor, overriding all abstract methods with AST to JSON serialization code."); + writer.WriteLine(prefix + L"class " + file->Name() + L"Visitor"); + writer.WriteLine(prefix + L"\t: public vl::glr::JsonVisitorBase"); + for (auto visitorSymbol : visitors) + { + writer.WriteString(prefix + L"\t, protected virtual "); + PrintCppType(file, visitorSymbol, writer); + writer.WriteLine(L"::IVisitor"); + } + writer.WriteLine(prefix + L"{"); + + writer.WriteLine(prefix + L"protected:"); + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"\tvirtual void PrintFields("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + } + writer.WriteLine(L""); + + writer.WriteLine(prefix + L"protected:"); + for (auto visitorSymbol : visitors) + { + for (auto classSymbol : visitorSymbol->derivedClasses) + { + writer.WriteString(prefix + L"\tvoid Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node) override;"); + } + writer.WriteLine(L""); + } + + writer.WriteLine(prefix + L"public:"); + writer.WriteLine(prefix + L"\t" + file->Name() + L"Visitor(vl::stream::StreamWriter& _writer);"); + writer.WriteLine(L""); + for (auto classSymbol : + From(visitors) + .Where([](AstClassSymbol* visitor) { return !visitor->baseClass; }) + .Concat(concreteClasses) + ) + { + writer.WriteString(prefix + L"\tvoid Print("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + writer.WriteLine(prefix + L"};"); + }); + } + +/*********************************************************************** +WriteJsonVisitorCppFile +***********************************************************************/ + + void WriteJsonVisitorCppFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityCppFile(file, output->jsonH, L"json_visitor", writer, [&](const WString& prefix) + { + List visitors, concreteClasses; + CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses); + + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::PrintFields("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + WritePrintFieldsFunctionBody(file, classSymbol, prefix, writer); + writer.WriteLine(prefix + L"}"); + } + } + writer.WriteLine(L""); + + for (auto visitorSymbol : visitors) + { + for (auto classSymbol : visitorSymbol->derivedClasses) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + if (classSymbol->derivedClasses.Count() == 0) + { + WriteVisitFunctionBody(file, classSymbol, prefix, writer); + } + else + { + writer.WriteString(prefix + L"\tnode->Accept(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor*>(this));"); + } + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + } + + writer.WriteLine(prefix + file->Name() + L"Visitor::" + file->Name() + L"Visitor(vl::stream::StreamWriter& _writer)"); + writer.WriteLine(prefix + L"\t: vl::glr::JsonVisitorBase(_writer)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + + for (auto classSymbol : visitors) + { + if (!classSymbol->baseClass) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Print("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + WriteNullAndReturn(prefix, writer); + writer.WriteString(prefix + L"\tnode->Accept(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor*>(this));"); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + } + + for (auto classSymbol : concreteClasses) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Print("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + WriteVisitFunctionBody(file, classSymbol, prefix, writer); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + }); + } + } + } +} + +/*********************************************************************** +.\AST\ASTCPPGEN_TRAVERSEVISITOR.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + + extern void PrintCppType(AstDefFile* fileContext, AstSymbol* propSymbol, stream::StreamWriter& writer); + extern void CollectVisitorsAndConcreteClasses(AstDefFile* file, List& visitors, List& concreteClasses); + +/*********************************************************************** +WriteVisitFieldFunctionBody +***********************************************************************/ + + void WriteVisitFieldFunctionBody(AstDefFile* file, AstClassSymbol* fieldSymbol, const WString& prefix, stream::StreamWriter& writer) + { + writer.WriteLine(prefix + L"\tif (!node) return;"); + List order; + { + auto current = fieldSymbol; + while (current) + { + order.Add(current); + current = current->baseClass; + } + } + + writer.WriteLine(prefix + L"\tTraverse(static_cast(node));"); + for (auto classSymbol : From(order).Reverse()) + { + writer.WriteString(prefix + L"\tTraverse(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"*>(node));"); + } + + { + auto current = fieldSymbol; + while (current) + { + for (auto propSymbol : current->Props().Values()) + { + switch (propSymbol->propType) + { + case AstPropType::Token: + writer.WriteLine(prefix + L"\tTraverse(node->" + propSymbol->Name() + L");"); + break; + case AstPropType::Array: + writer.WriteLine(prefix + L"\tfor (auto&& listItem : node->" + propSymbol->Name() + L")"); + writer.WriteLine(prefix + L"\t{"); + writer.WriteLine(prefix + L"\t\tInspectInto(listItem.Obj());"); + writer.WriteLine(prefix + L"\t}"); + break; + case AstPropType::Type: + if (dynamic_cast(propSymbol->propSymbol)) + { + writer.WriteLine(prefix + L"\tInspectInto(node->" + propSymbol->Name() + L".Obj());"); + } + break; + } + } + current = current->baseClass; + } + } + + for (auto classSymbol : order) + { + writer.WriteString(prefix + L"\tFinishing(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"*>(node));"); + } + writer.WriteLine(prefix + L"\tFinishing(static_cast(node));"); + } + +/*********************************************************************** +WriteTraverseVisitorHeaderFile +***********************************************************************/ + + void WriteTraverseVisitorHeaderFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityHeaderFile(file, output, L"traverse_visitor", writer, [&](const WString& prefix) + { + List visitors, concreteClasses; + CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses); + + writer.WriteLine(prefix + L"/// A traverse visitor, overriding all abstract methods with AST visiting code."); + writer.WriteLine(prefix + L"class " + file->Name() + L"Visitor"); + writer.WriteLine(prefix + L"\t: public vl::Object"); + for (auto visitorSymbol : visitors) + { + writer.WriteString(prefix + L"\t, protected virtual "); + PrintCppType(file, visitorSymbol, writer); + writer.WriteLine(L"::IVisitor"); + } + writer.WriteLine(prefix + L"{"); + + writer.WriteLine(prefix + L"protected:"); + writer.WriteLine(prefix + L"\tvirtual void Traverse(vl::glr::ParsingToken& token);"); + writer.WriteLine(prefix + L"\tvirtual void Traverse(vl::glr::ParsingAstBase* node);"); + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"\tvirtual void Traverse("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + } + writer.WriteLine(L""); + + writer.WriteLine(prefix + L"protected:"); + writer.WriteLine(prefix + L"\tvirtual void Finishing(vl::glr::ParsingAstBase* node);"); + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"\tvirtual void Finishing("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + } + writer.WriteLine(L""); + + writer.WriteLine(prefix + L"protected:"); + for (auto visitorSymbol : visitors) + { + for (auto classSymbol : visitorSymbol->derivedClasses) + { + writer.WriteString(prefix + L"\tvoid Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node) override;"); + } + writer.WriteLine(L""); + } + + writer.WriteLine(prefix + L"public:"); + for (auto classSymbol : + From(visitors) + .Where([](AstClassSymbol* visitor) { return !visitor->baseClass; }) + .Concat(concreteClasses) + ) + { + writer.WriteString(prefix + L"\tvoid InspectInto("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node);"); + } + writer.WriteLine(prefix + L"};"); + }); + } + +/*********************************************************************** +WriteTraverseVisitorCppFile +***********************************************************************/ + + void WriteTraverseVisitorCppFile(AstDefFile* file, Ptr output, stream::StreamWriter& writer) + { + WriteAstUtilityCppFile(file, output->traverseH, L"traverse_visitor", writer, [&](const WString& prefix) + { + List visitors, concreteClasses; + CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses); + + writer.WriteLine(prefix + L"void " + file->Name() + L"Visitor::Traverse(vl::glr::ParsingToken& token) {}"); + writer.WriteLine(prefix + L"void " + file->Name() + L"Visitor::Traverse(vl::glr::ParsingAstBase* node) {}"); + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Traverse("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node) {}"); + } + } + writer.WriteLine(L""); + + writer.WriteLine(prefix + L"void " + file->Name() + L"Visitor::Finishing(vl::glr::ParsingAstBase* node) {}"); + for (auto typeSymbol : file->Symbols().Values()) + { + if (auto classSymbol = dynamic_cast(typeSymbol)) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Finishing("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node) {}"); + } + } + writer.WriteLine(L""); + + for (auto visitorSymbol : visitors) + { + for (auto classSymbol : visitorSymbol->derivedClasses) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::Visit("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + if (classSymbol->derivedClasses.Count() == 0) + { + WriteVisitFieldFunctionBody(file, classSymbol, prefix, writer); + } + else + { + writer.WriteString(prefix + L"\tnode->Accept(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor*>(this));"); + } + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + } + + for (auto classSymbol : visitors) + { + if (!classSymbol->baseClass) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::InspectInto("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tif (!node) return;"); + writer.WriteString(prefix + L"\tnode->Accept(static_cast<"); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"::IVisitor*>(this));"); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + } + + for (auto classSymbol : concreteClasses) + { + writer.WriteString(prefix + L"void " + file->Name() + L"Visitor::InspectInto("); + PrintCppType(file, classSymbol, writer); + writer.WriteLine(L"* node)"); + writer.WriteLine(prefix + L"{"); + WriteVisitFieldFunctionBody(file, classSymbol, prefix, writer); + writer.WriteLine(prefix + L"}"); + writer.WriteLine(L""); + } + }); + } + } + } +} + +/*********************************************************************** +.\AST\ASTSYMBOL.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +AstSymbol +***********************************************************************/ + + AstSymbol::AstSymbol(AstDefFile* _file, const WString& _name) + : ownerFile(_file) + , name(_name) + { + } + +/*********************************************************************** +AstEnumItemSymbol +***********************************************************************/ + + AstEnumItemSymbol::AstEnumItemSymbol(AstEnumSymbol* _parent, const WString& name) + : AstSymbol(_parent->Owner(), name) + , parent(_parent) + { + } + +/*********************************************************************** +AstEnumSymbol +***********************************************************************/ + + AstEnumSymbol::AstEnumSymbol(AstDefFile* _file, const WString& _name) + : AstSymbol(_file, _name) + { + } + + AstEnumItemSymbol* AstEnumSymbol::CreateItem(const WString& itemName, ParsingTextRange codeRange) + { + auto symbol = new AstEnumItemSymbol(this, itemName); + symbol->value = items.items.Count(); + if (!items.Add(itemName, symbol)) + { + ownerFile->AddError( + ParserErrorType::DuplicatedEnumItem, + codeRange, + ownerFile->Name(), + name, + itemName + ); + } + return symbol; + } + +/*********************************************************************** +AstClassPropSymbol +***********************************************************************/ + + AstClassPropSymbol::AstClassPropSymbol(AstClassSymbol* _parent, const WString& name) + : AstSymbol(_parent->Owner(), name) + , parent(_parent) + { + } + + bool AstClassPropSymbol::SetPropType(AstPropType _type, const WString& typeName, ParsingTextRange codeRange) + { + propType = _type; + if (_type == AstPropType::Token) return true; + + auto& symbols = parent->Owner()->Symbols(); + vint index = symbols.Keys().IndexOf(typeName); + if (index == -1) + { + ownerFile->AddError( + ParserErrorType::FieldTypeNotExists, + codeRange, + ownerFile->Name(), + parent->Name(), + name + ); + return false; + } + + propSymbol = symbols.Values()[index]; + if (_type == AstPropType::Type) return true; + + if (!dynamic_cast(propSymbol)) + { + ownerFile->AddError( + ParserErrorType::FieldTypeNotClass, + codeRange, + parent->Owner()->Name(), + parent->Name(), + name + ); + return false; + } + return true; + } + +/*********************************************************************** +AstClassSymbol +***********************************************************************/ + + AstClassSymbol::AstClassSymbol(AstDefFile* _file, const WString& _name) + : AstSymbol(_file, _name) + { + } + + bool AstClassSymbol::SetBaseClass(const WString& typeName, ParsingTextRange codeRange) + { + auto& symbols = ownerFile->Symbols(); + vint index = symbols.Keys().IndexOf(typeName); + if (index == -1) + { + ownerFile->AddError( + ParserErrorType::BaseClassNotExists, + codeRange, + ownerFile->Name(), + name, + typeName + ); + return false; + } + + auto newBaseClass = dynamic_cast(symbols.Values()[index]); + if (!newBaseClass) + { + ownerFile->AddError( + ParserErrorType::BaseClassNotClass, + codeRange, + ownerFile->Name(), + name, + typeName + ); + return false; + } + + List visited; + visited.Add(newBaseClass); + for (vint i = 0; i < visited.Count(); i++) + { + auto currentSymbol = visited[i]; + if (currentSymbol == this) + { + ownerFile->AddError( + ParserErrorType::BaseClassCyclicDependency, + codeRange, + ownerFile->Name(), + name + ); + return false; + } + + if (currentSymbol->baseClass) + { + visited.Add(currentSymbol->baseClass); + } + } + + baseClass = newBaseClass; + newBaseClass->derivedClasses.Add(this); + return true; + } + + AstClassSymbol* AstClassSymbol::CreateAmbiguousDerivedClass(ParsingTextRange codeRange) + { + if (!ambiguousDerivedClass) + { + auto derived = ownerFile->CreateClass(name + L"ToResolve", codeRange); + derived->baseClass = this; + derivedClasses.Add(derived); + + auto prop = derived->CreateProp(L"candidates", codeRange); + prop->propType = AstPropType::Array; + prop->propSymbol = this; + + ambiguousDerivedClass = derived; + } + return ambiguousDerivedClass; + } + + AstClassPropSymbol* AstClassSymbol::CreateProp(const WString& propName, ParsingTextRange codeRange) + { + auto symbol = new AstClassPropSymbol(this, propName); + if (!props.Add(propName, symbol)) + { + ownerFile->AddError( + ParserErrorType::DuplicatedClassProp, + codeRange, + ownerFile->Name(), + name, + propName + ); + } + return symbol; + } + +/*********************************************************************** +FindCommonBaseClass +***********************************************************************/ + + AstClassSymbol* FindCommonBaseClass(AstClassSymbol* c1, AstClassSymbol* c2) + { + if (c1 == c2) return c1; + if (!c1) return c2; + if (!c2) return c1; + + // find common base classes + vint n1 = 0, n2 = 0; + { + auto c = c1; + while (c) + { + n1++; + c = c->baseClass; + } + } + { + auto c = c2; + while (c) + { + n2++; + c = c->baseClass; + } + } + + while (n1 > n2) + { + n1--; + c1 = c1->baseClass; + } + while (n2 > n1) + { + n2--; + c2 = c2->baseClass; + } + + while (c1 && c2) + { + if (c1 == c2) return c1; + c1 = c1->baseClass; + c2 = c2->baseClass; + } + return nullptr; + } + +/*********************************************************************** +FindPropSymbol +***********************************************************************/ + + AstClassPropSymbol* FindPropSymbol(AstClassSymbol*& type, const WString& name) + { + auto currentType = type; + while (currentType) + { + vint index = currentType->Props().Keys().IndexOf(name); + if (index != -1) + { + return currentType->Props().Values()[index]; + } + currentType = currentType->baseClass; + } + return nullptr; + } + +/*********************************************************************** +AstDefFile +***********************************************************************/ + + template + T* AstDefFile::CreateSymbol(const WString& symbolName, ParsingTextRange codeRange) + { + auto symbol = new T(this, symbolName); + if (!symbols.Add(symbolName, symbol)) + { + AddError( + ParserErrorType::DuplicatedSymbol, + codeRange, + name, + symbolName + ); + } + else if (!ownerManager->symbolMap.Keys().Contains(symbolName)) + { + ownerManager->symbolMap.Add(symbolName, symbol); + } + else + { + AddError( + ParserErrorType::DuplicatedSymbolGlobally, + codeRange, + name, + symbolName, + ownerManager->symbolMap[symbolName]->Owner()->name + ); + } + + return symbol; + } + + AstDefFile::AstDefFile(ParserSymbolManager* _global, AstSymbolManager* _ownerManager, const WString& _name) + : global(_global) + , ownerManager(_ownerManager) + , name(_name) + { + } + + bool AstDefFile::AddDependency(const WString& dependency, ParsingTextRange codeRange) + { + if (dependencies.Contains(dependency)) return true; + if (!ownerManager->Files().Keys().Contains(dependency)) + { + AddError( + ParserErrorType::FileDependencyNotExists, + codeRange, + name, + dependency + ); + return false; + } + + List visited; + visited.Add(dependency); + for (vint i = 0; i < visited.Count(); i++) + { + auto currentName = visited[i]; + if (currentName == name) + { + AddError( + ParserErrorType::FileCyclicDependency, + codeRange, + name, + dependency + ); + return false; + } + auto current = ownerManager->Files()[currentName]; + for (vint j = 0; j < current->dependencies.Count(); j++) + { + auto dep = current->dependencies[j]; + if (!visited.Contains(dep)) + { + visited.Add(dep); + } + } + } + + dependencies.Add(dependency); + return true; + } + + AstEnumSymbol* AstDefFile::CreateEnum(const WString& symbolName, ParsingTextRange codeRange) + { + return CreateSymbol(symbolName, codeRange); + } + + AstClassSymbol* AstDefFile::CreateClass(const WString& symbolName, ParsingTextRange codeRange) + { + return CreateSymbol(symbolName, codeRange); + } + +/*********************************************************************** +AstSymbolManager +***********************************************************************/ + + AstSymbolManager::AstSymbolManager(ParserSymbolManager& _global) + : global(_global) + { + } + + AstDefFile* AstSymbolManager::CreateFile(const WString& name) + { + auto file = new AstDefFile(&global, this, name); + if (!files.Add(name, file)) + { + file->AddError( + ParserErrorType::DuplicatedFile, + {}, + name + ); + } + return file; + } + } + } +} + +/*********************************************************************** +.\AST\ASTSYMBOL_CREATEPARSERGENRULEAST.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +CreateParserGenRuleAst +***********************************************************************/ + + AstDefFile* CreateParserGenRuleAst(AstSymbolManager& manager) + { + auto _ast = manager.CreateFile(L"RuleAst"); + Fill(_ast->cppNss, L"vl", L"glr", L"parsergen"); + Fill(_ast->refNss, L"glr", L"parsergen"); + _ast->classPrefix = L"Glr"; + + auto _Syntax = _ast->CreateClass(L"Syntax"); + + auto _RefSyntax = _ast->CreateClass(L"RefSyntax"); + _RefSyntax->SetBaseClass(L"Syntax"); + _RefSyntax->CreateProp(L"name")->SetPropType(AstPropType::Token); + _RefSyntax->CreateProp(L"field")->SetPropType(AstPropType::Token); + + auto _LiteralSyntax = _ast->CreateClass(L"LiteralSyntax"); + _LiteralSyntax->SetBaseClass(L"Syntax"); + _LiteralSyntax->CreateProp(L"value")->SetPropType(AstPropType::Token); + + auto _UseSyntax = _ast->CreateClass(L"UseSyntax"); + _UseSyntax->SetBaseClass(L"Syntax"); + _UseSyntax->CreateProp(L"name")->SetPropType(AstPropType::Token); + + auto _LoopSyntax = _ast->CreateClass(L"LoopSyntax"); + _LoopSyntax->SetBaseClass(L"Syntax"); + _LoopSyntax->CreateProp(L"syntax")->SetPropType(AstPropType::Type, L"Syntax"); + _LoopSyntax->CreateProp(L"delimiter")->SetPropType(AstPropType::Type, L"Syntax"); + + auto _OptionalPriority = _ast->CreateEnum(L"OptionalPriority"); + _OptionalPriority->CreateItem(L"Equal"); + _OptionalPriority->CreateItem(L"PreferTake"); + _OptionalPriority->CreateItem(L"PreferSkip"); + + auto _OptionalSyntax = _ast->CreateClass(L"OptionalSyntax"); + _OptionalSyntax->SetBaseClass(L"Syntax"); + _OptionalSyntax->CreateProp(L"priority")->SetPropType(AstPropType::Type, L"OptionalPriority"); + _OptionalSyntax->CreateProp(L"syntax")->SetPropType(AstPropType::Type, L"Syntax"); + + auto _SequenceSyntax = _ast->CreateClass(L"SequenceSyntax"); + _SequenceSyntax->SetBaseClass(L"Syntax"); + _SequenceSyntax->CreateProp(L"first")->SetPropType(AstPropType::Type, L"Syntax"); + _SequenceSyntax->CreateProp(L"second")->SetPropType(AstPropType::Type, L"Syntax"); + + auto _AlternativeSyntax = _ast->CreateClass(L"AlternativeSyntax"); + _AlternativeSyntax->SetBaseClass(L"Syntax"); + _AlternativeSyntax->CreateProp(L"first")->SetPropType(AstPropType::Type, L"Syntax"); + _AlternativeSyntax->CreateProp(L"second")->SetPropType(AstPropType::Type, L"Syntax"); + + auto _Clause = _ast->CreateClass(L"Clause"); + + auto _Assignment = _ast->CreateClass(L"Assignment"); + _Assignment->CreateProp(L"field")->SetPropType(AstPropType::Token); + _Assignment->CreateProp(L"value")->SetPropType(AstPropType::Token); + + auto _CreateClause = _ast->CreateClass(L"CreateClause"); + _CreateClause->SetBaseClass(L"Clause"); + _CreateClause->CreateProp(L"type")->SetPropType(AstPropType::Token); + _CreateClause->CreateProp(L"syntax")->SetPropType(AstPropType::Type, L"Syntax"); + _CreateClause->CreateProp(L"assignments")->SetPropType(AstPropType::Array, L"Assignment"); + + auto _PartialClause = _ast->CreateClass(L"PartialClause"); + _PartialClause->SetBaseClass(L"Clause"); + _PartialClause->CreateProp(L"type")->SetPropType(AstPropType::Token); + _PartialClause->CreateProp(L"syntax")->SetPropType(AstPropType::Type, L"Syntax"); + _PartialClause->CreateProp(L"assignments")->SetPropType(AstPropType::Array, L"Assignment"); + + auto _ReuseClause = _ast->CreateClass(L"ReuseClause"); + _ReuseClause->SetBaseClass(L"Clause"); + _ReuseClause->CreateProp(L"syntax")->SetPropType(AstPropType::Type, L"Syntax"); + _ReuseClause->CreateProp(L"assignments")->SetPropType(AstPropType::Array, L"Assignment"); + + auto _Rule = _ast->CreateClass(L"Rule"); + _Rule->CreateProp(L"name")->SetPropType(AstPropType::Token); + _Rule->CreateProp(L"clauses")->SetPropType(AstPropType::Array, L"Clause"); + + auto _File = _ast->CreateClass(L"SyntaxFile"); + _File->CreateProp(L"rules")->SetPropType(AstPropType::Array, L"Rule"); + + return _ast; + } + } + } +} + +/*********************************************************************** +.\AST\ASTSYMBOL_CREATEPARSERGENTYPEAST.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +CreateParserGenTypeAst +***********************************************************************/ + + AstDefFile* CreateParserGenTypeAst(AstSymbolManager& manager) + { + auto _ast = manager.CreateFile(L"TypeAst"); + Fill(_ast->cppNss, L"vl", L"glr", L"parsergen"); + Fill(_ast->refNss, L"glr", L"parsergen"); + _ast->classPrefix = L"Glr"; + + auto _type = _ast->CreateClass(L"Type"); + _type->CreateProp(L"name")->SetPropType(AstPropType::Token); + + auto _enumItem = _ast->CreateClass(L"EnumItem"); + _enumItem->CreateProp(L"name")->SetPropType(AstPropType::Token); + + auto _enum = _ast->CreateClass(L"Enum"); + _enum->SetBaseClass(L"Type"); + _enum->CreateProp(L"items")->SetPropType(AstPropType::Array, L"EnumItem"); + + auto _propType = _ast->CreateEnum(L"PropType"); + _propType->CreateItem(L"Token"); + _propType->CreateItem(L"Type"); + _propType->CreateItem(L"Array"); + + auto _classProp = _ast->CreateClass(L"ClassProp"); + _classProp->CreateProp(L"name")->SetPropType(AstPropType::Token); + _classProp->CreateProp(L"propType")->SetPropType(AstPropType::Type, L"PropType"); + _classProp->CreateProp(L"propTypeName")->SetPropType(AstPropType::Token); + + auto _classAmbiguity = _ast->CreateEnum(L"ClassAmbiguity"); + _classAmbiguity->CreateItem(L"No"); + _classAmbiguity->CreateItem(L"Yes"); + + auto _class = _ast->CreateClass(L"Class"); + _class->SetBaseClass(L"Type"); + _class->CreateProp(L"baseClass")->SetPropType(AstPropType::Token); + _class->CreateProp(L"ambiguity")->SetPropType(AstPropType::Type, L"ClassAmbiguity"); + _class->CreateProp(L"props")->SetPropType(AstPropType::Array, L"ClassProp"); + + auto _file = _ast->CreateClass(L"AstFile"); + _file->CreateProp(L"types")->SetPropType(AstPropType::Array, L"Type"); + + return _ast; + } + } + } +} + +/*********************************************************************** +.\LEXER\LEXERCPPGEN.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + using namespace regex; + +/*********************************************************************** +WriteLexerHeaderFile +***********************************************************************/ + + void WriteLexerHeaderFile(LexerSymbolManager& manager, Ptr output, stream::StreamWriter& writer) + { + WriteFileComment(manager.Global().name, writer); + if (manager.Global().headerGuard != L"") + { + writer.WriteString(L"#ifndef "); + writer.WriteLine(manager.Global().headerGuard + L"_LEXER"); + writer.WriteString(L"#define "); + writer.WriteLine(manager.Global().headerGuard + L"_LEXER"); + } + else + { + writer.WriteLine(L"#pragma once"); + } + writer.WriteLine(L""); + for (auto include : manager.Global().includes) + { + if (include.Length() > 0 && include[0] == L'<') + { + writer.WriteLine(L"#include " + include); + } + else + { + writer.WriteLine(L"#include \"" + include + L"\""); + } + } + writer.WriteLine(L""); + + WString prefix = WriteNssBegin(manager.Global().cppNss, writer); + { + vint index = 0; + writer.WriteLine(prefix + L"enum class " + manager.Global().name + L"Tokens : vl::vint32_t"); + writer.WriteLine(prefix + L"{"); + for (auto tokenName : manager.TokenOrder()) + { + auto tokenSymbol = manager.Tokens()[tokenName]; + output->tokenIds.Add(tokenSymbol, (vint32_t)index); + writer.WriteLine(prefix + L"\t" + tokenSymbol->Name() + L" = " + itow(index) + L","); + index++; + } + writer.WriteLine(prefix + L"};"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"constexpr vl::vint " + manager.Global().name + L"TokenCount = " + itow(manager.Tokens().Count()) + L";"); + writer.WriteLine(prefix + L"extern bool " + manager.Global().name + L"TokenDeleter(vl::vint token);"); + writer.WriteLine(prefix + L"extern const wchar_t* " + manager.Global().name + L"TokenId(" + manager.Global().name + L"Tokens token);"); + writer.WriteLine(prefix + L"extern const wchar_t* " + manager.Global().name + L"TokenDisplayText(" + manager.Global().name + L"Tokens token);"); + writer.WriteLine(prefix + L"extern const wchar_t* " + manager.Global().name + L"TokenRegex(" + manager.Global().name + L"Tokens token);"); + WriteLoadDataFunctionHeader(prefix, manager.Global().name + L"LexerData", writer); + } + WriteNssEnd(manager.Global().cppNss, writer); + + if (manager.Global().headerGuard != L"") + { + writer.WriteString(L"#endif"); + } + } + +/*********************************************************************** +WriteLexerCppFile +***********************************************************************/ + + void WriteLexerCppFile(LexerSymbolManager& manager, Ptr output, stream::StreamWriter& writer) + { + WriteFileComment(manager.Global().name, writer); + writer.WriteLine(L"#include \"" + output->lexerH + L"\""); + writer.WriteLine(L""); + WString prefix = WriteNssBegin(manager.Global().cppNss, writer); + { + writer.WriteLine(prefix + L"bool " + manager.Global().name + L"TokenDeleter(vl::vint token)"); + writer.WriteLine(prefix + L"{"); + + List discarded; + for (auto tokenSymbol : manager.Tokens().Values()) + { + if (tokenSymbol->discarded) + { + discarded.Add(tokenSymbol->Name()); + } + } + + if (discarded.Count() > 0) + { + writer.WriteLine(prefix + L"\tswitch((" + manager.Global().name + L"Tokens)token)"); + writer.WriteLine(prefix + L"\t{"); + for (auto tokenName : discarded) + { + writer.WriteLine(prefix + L"\tcase " + manager.Global().name + L"Tokens::" + tokenName + L":"); + } + writer.WriteLine(prefix + L"\t\treturn true;"); + writer.WriteLine(prefix + L"\tdefault:"); + writer.WriteLine(prefix + L"\t\treturn false;"); + writer.WriteLine(prefix + L"\t}"); + } + else + { + writer.WriteLine(prefix + L"\treturn false;"); + } + writer.WriteLine(prefix + L"}"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.Global().name + L"TokenId(" + manager.Global().name + L"Tokens token)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tstatic const wchar_t* results[] = {"); + for (auto tokenName : manager.TokenOrder()) + { + writer.WriteLine(prefix + L"\t\tL\"" + tokenName + L"\","); + } + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::vint index = (vl::vint)token;"); + writer.WriteLine(prefix + L"\treturn 0 <= index && index < " + manager.Global().name + L"TokenCount ? results[index] : nullptr;"); + writer.WriteLine(prefix + L"}"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.Global().name + L"TokenDisplayText(" + manager.Global().name + L"Tokens token)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tstatic const wchar_t* results[] = {"); + for (auto tokenName : manager.TokenOrder()) + { + auto displayText = manager.Tokens()[tokenName]->displayText; + if (displayText == L"") + { + writer.WriteLine(prefix + L"\t\tnullptr,"); + } + else + { + writer.WriteString(prefix + L"\t\tL\""); + WriteCppStringBody(displayText, writer); + writer.WriteLine(L"\","); + } + } + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::vint index = (vl::vint)token;"); + writer.WriteLine(prefix + L"\treturn 0 <= index && index < " + manager.Global().name + L"TokenCount ? results[index] : nullptr;"); + writer.WriteLine(prefix + L"}"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.Global().name + L"TokenRegex(" + manager.Global().name + L"Tokens token)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tstatic const wchar_t* results[] = {"); + for (auto tokenName : manager.TokenOrder()) + { + writer.WriteString(prefix + L"\t\tL\""); + WriteCppStringBody(manager.Tokens()[tokenName]->regex, writer); + writer.WriteLine(L"\","); + } + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::vint index = (vl::vint)token;"); + writer.WriteLine(prefix + L"\treturn 0 <= index && index < " + manager.Global().name + L"TokenCount ? results[index] : nullptr;"); + writer.WriteLine(prefix + L"}"); + } + { + MemoryStream lexerData; + { + RegexLexer lexer( + From(manager.TokenOrder()) + .Select([&](const WString& name) { return manager.Tokens()[name]->regex; }) + ); + lexer.Serialize(lexerData); + } + lexerData.SeekFromBegin(0); + + writer.WriteLine(L""); + WriteLoadDataFunctionCpp(prefix, manager.Global().name + L"LexerData", lexerData, true, writer); + } + WriteNssEnd(manager.Global().cppNss, writer); + } + +/*********************************************************************** +WriteLexerFiles +***********************************************************************/ + + void WriteLexerFiles(LexerSymbolManager& manager, Ptr output, collections::Dictionary& files) + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteLexerHeaderFile(manager, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteLexerCppFile(manager, output, writer); + }); + + files.Add(output->lexerH, fileH); + files.Add(output->lexerCpp, fileCpp); + } + } + } +} + +/*********************************************************************** +.\LEXER\LEXERSYMBOL.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +TokenSymbol +***********************************************************************/ + + TokenSymbol::TokenSymbol(LexerSymbolManager* _ownerManager, const WString& _name) + : ownerManager(_ownerManager) + , name(_name) + { + } + +/*********************************************************************** +LexerSymbolManager +***********************************************************************/ + + LexerSymbolManager::LexerSymbolManager(ParserSymbolManager& _global) + : global(_global) + { + } + + TokenSymbol* LexerSymbolManager::CreateToken(const WString& _name, const WString& _regex, ParsingTextRange codeRange) + { + auto token = new TokenSymbol(this, _name); + token->regex = _regex; + if (!tokens.Add(_name, token)) + { + AddError( + ParserErrorType::DuplicatedToken, + codeRange, + _name + ); + } + try + { + auto expr = regex_internal::ParseRegexExpression(wtou32(_regex)); + if (!expr->expression->HasNoExtension()) + { + AddError( + ParserErrorType::TokenRegexNotPure, + codeRange, + _name + ); + } + + Array buffer(_regex.Length() + 1); + memset(&buffer[0], 0, sizeof(char32_t) * buffer.Count()); + vint writing = 0; + + List expanding; + expanding.Add(expr->expression.Obj()); + while (expanding.Count() > 0) + { + auto current = expanding[expanding.Count() - 1]; + if (auto charset = dynamic_cast(current)) + { + if (charset->ranges.Count() == 1 && !charset->reverse) + { + auto range = charset->ranges[0]; + if (range.begin == range.end) + { + expanding.RemoveAt(expanding.Count() - 1); + buffer[writing++] = range.begin; + continue; + } + } + } + else if (auto sequence = dynamic_cast(current)) + { + expanding.RemoveAt(expanding.Count() - 1); + expanding.Add(sequence->right.Obj()); + expanding.Add(sequence->left.Obj()); + continue; + } + goto FINISHED_CALCULATING_DISPLAY_TEXT; + } + + FINISHED_CALCULATING_DISPLAY_TEXT: + if (expanding.Count() == 0) + { + token->displayText = u32tow(U32String::Unmanaged(&buffer[0])); + if (tokensByDisplayText.Keys().Contains(token->displayText)) + { + AddError( + ParserErrorType::DuplicatedTokenByDisplayText, + codeRange, + _name + ); + } + else + { + tokensByDisplayText.Add(token->displayText, token); + } + } + } + catch (const regex_internal::RegexException& e) + { + AddError( + ParserErrorType::InvalidTokenRegex, + codeRange, + _name, + (e.Message() + L" : " + itow(e.position) + L" : " + _regex) + ); + } + return token; + } + + TokenSymbol* LexerSymbolManager::CreateDiscardedToken(const WString& _name, const WString& _regex, ParsingTextRange codeRange) + { + auto token = CreateToken(_name, _regex, codeRange); + token->discarded = true; + return token; + } + } + } +} + +/*********************************************************************** +.\LEXER\LEXERSYMBOL_CREATEPARSERGENLEXER.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +CreateParserGenAst +***********************************************************************/ + + void CreateParserGenLexer(LexerSymbolManager& manager) + { + manager.CreateToken(L"AMBIGUOUS", L"ambiguous"); + manager.CreateToken(L"CLASS", L"class"); + manager.CreateToken(L"ENUM", L"enum"); + manager.CreateToken(L"VAR", L"var"); + manager.CreateToken(L"TOKEN", L"token"); + manager.CreateToken(L"AS", L"as"); + manager.CreateToken(L"PARTIAL", L"partial"); + + manager.CreateToken(L"OPEN_ROUND", L"/("); + manager.CreateToken(L"CLOSE_ROUND", L"/)"); + manager.CreateToken(L"OPEN_SQUARE", L"/["); + manager.CreateToken(L"CLOSE_SQUARE", L"/]"); + manager.CreateToken(L"OPEN_CURLY", L"/{"); + manager.CreateToken(L"CLOSE_CURLY", L"/}"); + + manager.CreateToken(L"COMMA", L","); + manager.CreateToken(L"COLON", L":"); + manager.CreateToken(L"SEMICOLON", L";"); + + manager.CreateToken(L"INFER", L"::="); + manager.CreateToken(L"ALTERNATIVE", L"/|"); + manager.CreateToken(L"USE", L"!"); + manager.CreateToken(L"ASSIGN", L"="); + manager.CreateToken(L"POSITIVE", L"/+"); + manager.CreateToken(L"NEGATIVE", L"-"); + + manager.CreateToken(L"ID", L"[a-zA-Z_][a-zA-Z0-9_]*"); + manager.CreateToken(L"STRING", L"(\"[^\"]*\")+"); + + manager.CreateDiscardedToken(L"SPACE", L"/s+"); + manager.CreateDiscardedToken(L"COMMENT", L"////[^/r/n]*"); + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILEAST.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + +/*********************************************************************** +CompileAst +***********************************************************************/ + + class CreateAstSymbolVisitor :public Object, public virtual GlrType::IVisitor + { + protected: + AstDefFile* astDefFile; + public: + CreateAstSymbolVisitor(AstDefFile* _astDefFile) + : astDefFile(_astDefFile) + { + } + + void Visit(GlrEnum* node) override + { + astDefFile->CreateEnum(node->name.value, node->name.codeRange); + } + + void Visit(GlrClass* node) override + { + astDefFile->CreateClass(node->name.value, node->name.codeRange); + } + }; + + class FillAstSymbolVisitor :public Object, public virtual GlrType::IVisitor + { + protected: + AstDefFile* astDefFile; + public: + FillAstSymbolVisitor(AstDefFile* _astDefFile) + : astDefFile(_astDefFile) + { + } + + void Visit(GlrEnum* node) override + { + auto enumSymbol = dynamic_cast(astDefFile->Symbols()[node->name.value]); + for (auto item : node->items) + { + enumSymbol->CreateItem(item->name.value, item->name.codeRange); + } + } + + void Visit(GlrClass* node) override + { + auto classSymbol = dynamic_cast(astDefFile->Symbols()[node->name.value]); + if (node->baseClass) + { + classSymbol->SetBaseClass(node->baseClass.value, node->baseClass.codeRange); + } + if (node->ambiguity == GlrClassAmbiguity::Yes) + { + classSymbol->CreateAmbiguousDerivedClass(node->name.codeRange); + } + for (auto prop : node->props) + { + auto propSymbol = classSymbol->CreateProp(prop->name.value, prop->name.codeRange); + switch (prop->propType) + { + case GlrPropType::Token: + propSymbol->SetPropType(AstPropType::Token); + break; + case GlrPropType::Type: + propSymbol->SetPropType(AstPropType::Type, prop->propTypeName.value, prop->propTypeName.codeRange); + break; + case GlrPropType::Array: + propSymbol->SetPropType(AstPropType::Array, prop->propTypeName.value, prop->propTypeName.codeRange); + break; + } + } + } + }; + + void CompileAst(AstSymbolManager& astManager, AstDefFile* astDefFile, Ptr file) + { + { + CreateAstSymbolVisitor visitor(astDefFile); + for (auto type : file->types) + { + type->Accept(&visitor); + } + } + if (astManager.Global().Errors().Count() == 0) + { + FillAstSymbolVisitor visitor(astDefFile); + for (auto type : file->types) + { + type->Accept(&visitor); + } + } + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILELEXER.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace stream; + using namespace regex; + +/*********************************************************************** +CompileLexer +***********************************************************************/ + + void CompileLexer(LexerSymbolManager& lexerManager, const WString& input) + { + Regex regexToken(L"^(/s*|(discard/s)?/s*([a-zA-Z_]/w*):(/.+))$"); + vint _discard = regexToken.CaptureNames().IndexOf(L"discard"); + vint _name = regexToken.CaptureNames().IndexOf(L"name"); + vint _regex = regexToken.CaptureNames().IndexOf(L"regex"); + + StringReader reader(input); + vint lineIndex = 0; + while (!reader.IsEnd()) + { + auto line = reader.ReadLine(); + ParsingTextRange codeRange = { {lineIndex,0}, {lineIndex,0} }; + if (auto match = regexToken.MatchHead(line)) + { + if (match->Groups().Keys().Contains(_name)) + { + auto tokenName = match->Groups()[_name][0].Value(); + auto tokenRegex = match->Groups()[_regex][0].Value(); + if (match->Groups().Keys().Contains(_discard)) + { + lexerManager.CreateDiscardedToken(tokenName, tokenRegex, codeRange); + } + else + { + lexerManager.CreateToken(tokenName, tokenRegex, codeRange); + } + } + } + else + { + lexerManager.AddError( + ParserErrorType::InvalidTokenDefinition, + codeRange, + line + ); + } + lineIndex++; + } + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILESYNTAX.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace compile_syntax; + + extern void ResolveName(VisitorContext& context, List>& files); + extern void ValidatePartialRules(VisitorContext& context, List>& files); + extern void CalculateRuleAndClauseTypes(VisitorContext& context); + extern void ValidateTypes(VisitorContext& context, List>& files); + extern void ValidateStructure(VisitorContext& context, List>& files); + extern void CompileSyntax(VisitorContext& context, List>& files); + +/*********************************************************************** +CompileSyntax +***********************************************************************/ + + void CompileSyntax(AstSymbolManager& astManager, LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, Ptr output, collections::List>& files) + { + VisitorContext context(astManager, lexerManager, syntaxManager, output); + + for (auto file : files) + { + for (auto rule : file->rules) + { + if (context.lexerManager.Tokens().Keys().Contains(rule->name.value)) + { + context.syntaxManager.AddError( + ParserErrorType::RuleNameConflictedWithToken, + rule->codeRange, + rule->name.value + ); + } + else + { + auto ruleSymbol = context.syntaxManager.CreateRule(rule->name.value, rule->codeRange); + context.astRules.Add(ruleSymbol, rule.Obj()); + } + } + } + if (syntaxManager.Global().Errors().Count() > 0) return; + + ResolveName(context, files); + if (syntaxManager.Global().Errors().Count() > 0) return; + + ValidatePartialRules(context, files); + if (syntaxManager.Global().Errors().Count() > 0) return; + + CalculateRuleAndClauseTypes(context); + if (syntaxManager.Global().Errors().Count() > 0) return; + + ValidateTypes(context, files); + if (syntaxManager.Global().Errors().Count() > 0) return; + + ValidateStructure(context, files); + if (syntaxManager.Global().Errors().Count() > 0) return; + + CompileSyntax(context, files); + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILESYNTAX_CALCULATETYPES.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace compile_syntax; + +/*********************************************************************** +ValidatePartialRules +***********************************************************************/ + + void ValidatePartialRules(VisitorContext& context, List>& files) + { + for (auto file : files) + { + for (auto rule : file->rules) + { + List> partialClauses; + CopyFrom(partialClauses, From(rule->clauses).FindType()); + if (partialClauses.Count() == 0) continue; + + auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; + ruleSymbol->isPartial = partialClauses.Count() > 0; + + if (partialClauses.Count() != rule->clauses.Count()) + { + context.syntaxManager.AddError( + ParserErrorType::RuleMixedPartialClauseWithOtherClause, + rule->codeRange, + ruleSymbol->Name() + ); + } + + AstClassSymbol* partialType = nullptr; + for (auto clause : partialClauses) + { + vint index = context.clauseTypes.Keys().IndexOf(clause.Obj()); + if (index != -1) + { + auto type = context.clauseTypes.Values()[index]; + if (!partialType) + { + partialType = type; + } + else if (type && partialType != type) + { + context.syntaxManager.AddError( + ParserErrorType::RuleWithDifferentPartialTypes, + rule->codeRange, + ruleSymbol->Name() + ); + break; + } + } + } + } + } + } + +/*********************************************************************** +CalculateRuleAndClauseTypes +***********************************************************************/ + + void CalculateRuleAndClauseTypes(VisitorContext& context) + { + // find cyclic dependencies in "Rule ::= !Rule" + auto&& rules = context.syntaxManager.Rules().Values(); + PartialOrderingProcessor pop; + pop.InitWithGroup(rules, context.ruleReuseDependencies); + pop.Sort(); + + // remove cyclic dependended rules from ruleReuseDependencies + List> cyclicReuseDependencies; + for (auto&& component : pop.components) + { + if (component.nodeCount == 1) continue; + + for (vint i = 0; i < component.nodeCount - 1; i++) + { + for (vint j = i + 1; j < component.nodeCount; j++) + { + auto r1 = rules[component.firstNode[i]]; + auto r2 = rules[component.firstNode[j]]; + context.ruleReuseDependencies.Remove(r1, r2); + context.ruleReuseDependencies.Remove(r2, r1); + } + } + + List cyclicRules; + for (vint i = 0; i < component.nodeCount; i++) + { + cyclicRules.Add(rules[component.firstNode[i]]); + } + cyclicReuseDependencies.Add(std::move(cyclicRules)); + } + + // calculate types for rules from clauses with known types + for (auto rule : rules) + { + for (auto clause : context.astRules[rule]->clauses) + { + vint index = context.clauseTypes.Keys().IndexOf(clause.Obj()); + if (index != -1) + { + rule->ruleType = FindCommonBaseClass(rule->ruleType, context.clauseTypes.Values()[index]); + if (!rule->ruleType) + { + context.syntaxManager.AddError( + ParserErrorType::RuleCannotResolveToDeterministicType, + context.astRules[rule]->codeRange, + rule->Name() + ); + break; + } + } + } + } + if (context.global.Errors().Count() > 0) return; + + // calculate types for rules that contain reuse dependency + for (auto&& component : pop.components) + { + for (vint i = 0; i < component.nodeCount; i++) + { + auto rule = rules[component.firstNode[i]]; + vint index = context.ruleReuseDependencies.Keys().IndexOf(rule); + if (index != -1) + { + AstClassSymbol* type = nullptr; + for (auto dep : context.ruleReuseDependencies.GetByIndex(index)) + { + type = FindCommonBaseClass(type, dep->ruleType); + } + if (type) + { + rule->ruleType = FindCommonBaseClass(rule->ruleType, type); + if (!rule->ruleType) + { + context.syntaxManager.AddError( + ParserErrorType::RuleCannotResolveToDeterministicType, + context.astRules[rule]->codeRange, + rule->Name() + ); + break; + } + } + } + } + } + if (context.global.Errors().Count() > 0) return; + + // calculate types for rules that contain cyclic reuse dependency + for (auto&& cyclicRules : cyclicReuseDependencies) + { + AstClassSymbol* type = nullptr; + for (auto rule : cyclicRules) + { + type = FindCommonBaseClass(type, rule->ruleType); + } + + if (!type) + { + for (auto rule : cyclicRules) + { + context.syntaxManager.AddError( + ParserErrorType::CyclicDependedRuleTypeIncompatible, + context.astRules[rule]->codeRange, + rule->Name() + ); + } + } + else + { + for (auto rule : cyclicRules) + { + rule->ruleType = type; + } + } + } + + // prompt errors + for (auto rule : rules) + { + if (!rule->ruleType) + { + context.syntaxManager.AddError( + ParserErrorType::RuleCannotResolveToDeterministicType, + context.astRules[rule]->codeRange, + rule->Name() + ); + } + } + + // calculate types for reuse clauses + for (auto astRule : context.astRules.Values()) + { + for (auto clause : From(astRule->clauses).FindType()) + { + vint index = context.clauseReuseDependencies.Keys().IndexOf(clause.Obj()); + if (index == -1) + { + context.syntaxManager.AddError( + ParserErrorType::ReuseClauseContainsNoUseRule, + clause->codeRange, + astRule->name.value + ); + } + else + { + AstClassSymbol* type = nullptr; + for (auto dep : context.clauseReuseDependencies.GetByIndex(index)) + { + type = FindCommonBaseClass(type, dep->ruleType); + } + + if (type) + { + context.clauseTypes.Add(clause.Obj(), type); + } + else + { + context.syntaxManager.AddError( + ParserErrorType::ReuseClauseCannotResolveToDeterministicType, + clause->codeRange, + astRule->name.value + ); + } + } + } + } + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILESYNTAX_COMPILESYNTAX.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace compile_syntax; + +/*********************************************************************** +CompileSyntaxVisitor +***********************************************************************/ + + class CompileSyntaxVisitor + : public Object + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + protected: + struct StatePair + { + StateSymbol* begin; + StateSymbol* end; + }; + + using StatePosMap = Dictionary; + protected: + VisitorContext& context; + RuleSymbol* ruleSymbol; + AstClassSymbol* clauseType; + + WString clauseDisplayText; + StatePosMap startPoses; + StatePosMap endPoses; + StatePair result; + + StateSymbol* CreateState() + { + return ruleSymbol->Owner()->CreateState(ruleSymbol, ruleSymbol->CurrentClauseId()); + } + + EdgeSymbol* CreateEdge(StateSymbol* from, StateSymbol* to) + { + return ruleSymbol->Owner()->CreateEdge(from, to); + } + + StatePair Build(const Ptr& node) + { + node->Accept(this); + return result; + } + + StatePair Build(const Ptr& node) + { + node->Accept(this); + return result; + } + public: + CompileSyntaxVisitor( + VisitorContext& _context, + RuleSymbol* _ruleSymbol + ) + : context(_context) + , ruleSymbol(_ruleSymbol) + { + } + + void AssignClause(const Ptr& node) + { + ruleSymbol->NewClause(); + + clauseDisplayText = L""; + startPoses.Clear(); + endPoses.Clear(); + + auto pair = Build(node); + ruleSymbol->startStates.Add(pair.begin); + pair.end->endingState = true; + + vint l = clauseDisplayText.Length(); + for (auto [state, pos] : startPoses) + { + state->label = clauseDisplayText.Left(pos) + L"@ " + clauseDisplayText.Right(l - pos); + } + for (auto [state, pos] : endPoses) + { + state->label = clauseDisplayText.Left(pos) + L" @" + clauseDisplayText.Right(l - pos); + } + } + + protected: + void Visit(GlrRefSyntax* node) override + { + { + vint index = context.lexerManager.TokenOrder().IndexOf(node->name.value); + if (index != -1) + { + auto token = context.lexerManager.Tokens()[node->name.value]; + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + { + auto edge = CreateEdge(pair.begin, pair.end); + edge->input.type = EdgeInputType::Token; + edge->input.token = (vint32_t)index; + if (node->field) + { + auto propSymbol = FindPropSymbol(clauseType, node->field.value); + edge->insAfterInput.Add({ AstInsType::Token }); + edge->insAfterInput.Add({ AstInsType::Field,context.output->fieldIds[propSymbol] }); + } + } + + clauseDisplayText += token->displayText == L"" ? token->Name() : L"\"" + token->displayText + L"\""; + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + return; + } + } + { + vint index = context.syntaxManager.Rules().Keys().IndexOf(node->name.value); + if (index != -1) + { + auto rule = context.syntaxManager.Rules().Values()[index]; + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + { + auto edge = CreateEdge(pair.begin, pair.end); + edge->input.type = EdgeInputType::Rule; + edge->input.rule = rule; + if (node->field) + { + auto propSymbol = FindPropSymbol(clauseType, node->field.value); + edge->insAfterInput.Add({ AstInsType::Field,context.output->fieldIds[propSymbol] }); + } + else if (!rule->isPartial) + { + edge->insAfterInput.Add({ AstInsType::DiscardValue }); + } + } + + clauseDisplayText += rule->Name(); + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + return; + } + } + CHECK_FAIL(L"Should not reach here!"); + } + + void Visit(GlrLiteralSyntax* node) override + { + vint index = context.literalTokens[node]; + auto token = context.lexerManager.Tokens()[context.lexerManager.TokenOrder()[index]]; + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + { + auto edge = CreateEdge(pair.begin, pair.end); + edge->input.type = EdgeInputType::Token; + edge->input.token = context.literalTokens[node]; + } + + clauseDisplayText += token->displayText == L"" ? token->Name() : L"\"" + token->displayText + L"\""; + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + } + + void Visit(GlrUseSyntax* node) override + { + vint index = context.syntaxManager.Rules().Keys().IndexOf(node->name.value); + if (index == -1) + { + context.syntaxManager.AddError( + ParserErrorType::TokenOrRuleNotExistsInRule, + node->codeRange, + node->name.value + ); + return; + } + + auto rule = context.syntaxManager.Rules().Values()[index]; + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + { + auto edge = CreateEdge(pair.begin, pair.end); + edge->input.type = EdgeInputType::Rule; + edge->input.rule = rule; + edge->insAfterInput.Add({ AstInsType::ReopenObject }); + } + + clauseDisplayText += L"!" + rule->Name(); + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + } + + void Visit(GlrLoopSyntax* node) override + { + StatePair pair, bodyPair, delimiterPair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"{ "; + bodyPair = Build(node->syntax); + if (node->delimiter) + { + clauseDisplayText += L" ; "; + delimiterPair = Build(node->delimiter); + } + clauseDisplayText += L" }"; + + CreateEdge(pair.begin, bodyPair.begin); + CreateEdge(bodyPair.end, pair.end); + CreateEdge(pair.begin, pair.end); + if (node->delimiter) + { + CreateEdge(bodyPair.end, delimiterPair.begin); + CreateEdge(delimiterPair.end, bodyPair.begin); + } + else + { + CreateEdge(bodyPair.end, bodyPair.begin); + } + + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + } + + void Visit(GlrOptionalSyntax* node) override + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + switch (node->priority) + { + case GlrOptionalPriority::Equal: + clauseDisplayText += L"[ "; + break; + case GlrOptionalPriority::PreferTake: + clauseDisplayText += L"+[ "; + break; + case GlrOptionalPriority::PreferSkip: + clauseDisplayText += L"-[ "; + break; + } + auto bodyPair = Build(node->syntax); + clauseDisplayText += L" ]"; + + auto takeEdge = CreateEdge(pair.begin, bodyPair.begin); + CreateEdge(bodyPair.end, pair.end); + auto skipEdge = CreateEdge(pair.begin, pair.end); + + if (node->priority == GlrOptionalPriority::PreferTake) + { + takeEdge->important = true; + } + if (node->priority == GlrOptionalPriority::PreferSkip) + { + skipEdge->important = true; + } + + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + } + + void Visit(GlrSequenceSyntax* node) override + { + auto firstPair = Build(node->first); + clauseDisplayText += L" "; + auto secondPair = Build(node->second); + CreateEdge(firstPair.end, secondPair.begin); + result = { firstPair.begin,secondPair.end }; + } + + void Visit(GlrAlternativeSyntax* node) override + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"( "; + auto firstPair = Build(node->first); + clauseDisplayText += L" | "; + auto secondPair = Build(node->second); + clauseDisplayText += L" )"; + + CreateEdge(pair.begin, firstPair.begin); + CreateEdge(firstPair.end, pair.end); + CreateEdge(pair.begin, secondPair.begin); + CreateEdge(secondPair.end, pair.end); + + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + } + + StatePair Visit(StatePair pair, GlrAssignment* node) + { + auto withState = CreateState(); + auto edge = CreateEdge(pair.end, withState); + + auto propSymbol = FindPropSymbol(clauseType, node->field.value); + auto enumSymbol = dynamic_cast(propSymbol->propSymbol); + edge->insBeforeInput.Add({ AstInsType::EnumItem,(vint32_t)enumSymbol->ItemOrder().IndexOf(node->value.value) }); + edge->insBeforeInput.Add({ AstInsType::Field,context.output->fieldIds[propSymbol] }); + + endPoses.Add(withState, clauseDisplayText.Length()); + return { pair.begin,withState }; + } + + void Visit(GlrCreateClause* node) override + { + clauseType = context.clauseTypes[node]; + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"< "; + auto bodyPair = Build(node->syntax); + for (auto assignment : node->assignments) + { + bodyPair = Visit(bodyPair, assignment.Obj()); + } + clauseDisplayText += L" >"; + { + auto classSymbol = dynamic_cast(context.astManager.Symbols()[node->type.value]); + auto edge = CreateEdge(pair.begin, bodyPair.begin); + edge->insBeforeInput.Add({ AstInsType::BeginObject,context.output->classIds[classSymbol] }); + } + { + auto edge = CreateEdge(bodyPair.end, pair.end); + edge->insBeforeInput.Add({ AstInsType::EndObject }); + } + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + } + + void Visit(GlrPartialClause* node) override + { + clauseType = context.clauseTypes[node]; + auto bodyPair = Build(node->syntax); + for (auto assignment : node->assignments) + { + bodyPair = Visit(bodyPair, assignment.Obj()); + } + result = bodyPair; + } + + void Visit(GlrReuseClause* node) override + { + clauseType = context.clauseTypes[node]; + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"<< "; + auto bodyPair = Build(node->syntax); + for (auto assignment : node->assignments) + { + bodyPair = Visit(bodyPair, assignment.Obj()); + } + clauseDisplayText += L" >>"; + { + auto edge = CreateEdge(pair.begin, bodyPair.begin); + edge->insBeforeInput.Add({ AstInsType::DelayFieldAssignment }); + } + { + auto edge = CreateEdge(bodyPair.end, pair.end); + edge->insBeforeInput.Add({ AstInsType::EndObject }); + } + endPoses.Add(pair.end, clauseDisplayText.Length()); + result = pair; + } + }; + +/*********************************************************************** +CompileSyntax +***********************************************************************/ + + void CompileSyntax(VisitorContext& context, List>& files) + { + for (auto file : files) + { + for (auto rule : file->rules) + { + auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; + CompileSyntaxVisitor visitor(context, ruleSymbol); + for (auto clause : rule->clauses) + { + visitor.AssignClause(clause); + } + } + } + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILESYNTAX_RESOLVENAME.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace compile_syntax; + +/*********************************************************************** +ResolveNameVisitor +***********************************************************************/ + + class ResolveNameVisitor + : public Object + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + protected: + VisitorContext& context; + RuleSymbol* ruleSymbol; + GlrClause* clause = nullptr; + + AstClassSymbol* GetRuleClass(ParsingToken& typeName) + { + vint index = context.astManager.Symbols().Keys().IndexOf(typeName.value); + if (index == -1) + { + context.syntaxManager.AddError( + ParserErrorType::TypeNotExistsInRule, + typeName.codeRange, + ruleSymbol->Name(), + typeName.value + ); + return nullptr; + } + + auto classSymbol = dynamic_cast(context.astManager.Symbols().Values()[index]); + if (!classSymbol) + { + context.syntaxManager.AddError( + ParserErrorType::TypeNotClassInRule, + typeName.codeRange, + ruleSymbol->Name(), + typeName.value + ); + } + return classSymbol; + } + public: + ResolveNameVisitor( + VisitorContext& _context, + RuleSymbol* _ruleSymbol + ) + : context(_context) + , ruleSymbol(_ruleSymbol) + { + } + + void ResolveClause(Ptr clause) + { + clause->Accept(this); + } + + protected: + void Visit(GlrRefSyntax* node) override + { + vint tokenIndex = context.lexerManager.TokenOrder().IndexOf(node->name.value); + vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->name.value); + if (tokenIndex == -1 && ruleIndex == -1) + { + context.syntaxManager.AddError( + ParserErrorType::TokenOrRuleNotExistsInRule, + node->codeRange, + ruleSymbol->Name(), + node->name.value + ); + } + } + + void Visit(GlrLiteralSyntax* node) override + { + if (node->value.value.Length() > 2) + { + Array buffer(node->value.value.Length()); + wchar_t* writing = &buffer[0]; + + for (vint i = 1; i < node->value.value.Length() - 1; i++) + { + wchar_t c = node->value.value[i]; + *writing++ = c; + if (c == L'\"') + { + i++; + } + } + *writing = 0; + + auto literalValue = WString::Unmanaged(&buffer[0]); + for (auto&& [tokenName, tokenIndex] : indexed(context.lexerManager.TokenOrder())) + { + auto tokenSymbol = context.lexerManager.Tokens()[tokenName]; + if (tokenSymbol->displayText==literalValue) + { + context.literalTokens.Add(node, (vint32_t)tokenIndex); + return; + } + } + } + context.syntaxManager.AddError( + ParserErrorType::TokenOrRuleNotExistsInRule, + node->codeRange, + ruleSymbol->Name(), + node->value.value + ); + } + + void Visit(GlrUseSyntax* node) override + { + vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->name.value); + if (ruleIndex == -1) + { + context.syntaxManager.AddError( + ParserErrorType::TokenOrRuleNotExistsInRule, + node->codeRange, + ruleSymbol->Name(), + node->name.value + ); + } + else if (clause) + { + auto usedRuleSymbol = context.syntaxManager.Rules().Values()[ruleIndex]; + if (!context.ruleReuseDependencies.Contains(ruleSymbol, usedRuleSymbol)) + { + context.ruleReuseDependencies.Add(ruleSymbol, usedRuleSymbol); + } + if (!context.clauseReuseDependencies.Contains(clause, usedRuleSymbol)) + { + context.clauseReuseDependencies.Add(clause, usedRuleSymbol); + } + } + } + + void Visit(GlrLoopSyntax* node) override + { + node->syntax->Accept(this); + if (node->delimiter) + { + node->delimiter->Accept(this); + } + } + + void Visit(GlrOptionalSyntax* node) override + { + node->syntax->Accept(this); + } + + void Visit(GlrSequenceSyntax* node) override + { + node->first->Accept(this); + node->second->Accept(this); + } + + void Visit(GlrAlternativeSyntax* node) override + { + node->first->Accept(this); + node->second->Accept(this); + } + + void Visit(GlrCreateClause* node) override + { + if (auto classSymbol = GetRuleClass(node->type)) + { + context.ruleKnownTypes.Add(ruleSymbol, classSymbol); + context.clauseTypes.Add(node, classSymbol); + } + node->syntax->Accept(this); + } + + void Visit(GlrPartialClause* node) override + { + if (auto classSymbol = GetRuleClass(node->type)) + { + context.ruleKnownTypes.Add(ruleSymbol, classSymbol); + context.clauseTypes.Add(node, classSymbol); + } + node->syntax->Accept(this); + } + + void Visit(GlrReuseClause* node) override + { + clause = node; + node->syntax->Accept(this); + } + }; + +/*********************************************************************** +ResolveName +***********************************************************************/ + + void ResolveName(VisitorContext& context, List>& files) + { + for (auto file : files) + { + for (auto rule : file->rules) + { + auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; + ResolveNameVisitor visitor(context, ruleSymbol); + for (auto clause : rule->clauses) + { + visitor.ResolveClause(clause); + } + } + } + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILESYNTAX_VALIDATESTRUCTURE.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace compile_syntax; + +/*********************************************************************** +ValidateStructureCountingVisitor +***********************************************************************/ + + class ValidateStructureCountingVisitor + : public Object + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + protected: + VisitorContext& context; + RuleSymbol* ruleSymbol; + GlrClause* clause = nullptr; + + vint optionalCounter = 0; + vint loopCounter = 0; + bool lastSyntaxPiece = true; + bool prioritySyntaxOccurred = false; + + vint syntaxMinLength = 0; + vint syntaxMinUseRuleCount = 0; + vint syntaxMaxUseRuleCount = 0; + + public: + ValidateStructureCountingVisitor( + VisitorContext& _context, + RuleSymbol* _ruleSymbol + ) + : context(_context) + , ruleSymbol(_ruleSymbol) + { + } + + void ValidateClause(Ptr clause) + { + optionalCounter = 0; + loopCounter = 0; + lastSyntaxPiece = true; + prioritySyntaxOccurred = false; + clause->Accept(this); + } + + protected: + void Visit(GlrRefSyntax* node) override + { + syntaxMinLength = 1; + syntaxMinUseRuleCount = 0; + syntaxMaxUseRuleCount = 0; + + if (loopCounter > 0) + { + auto clauseType = context.clauseTypes[clause]; + + if (node->field) + { + auto prop = FindPropSymbol(clauseType, node->field.value); + if (prop->propType != AstPropType::Array) + { + context.syntaxManager.AddError( + ParserErrorType::NonArrayFieldAssignedInLoop, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + prop->Name() + ); + } + } + + vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->name.value); + if (ruleIndex != -1) + { + auto fieldRule = context.syntaxManager.Rules().Values()[ruleIndex]; + if (fieldRule->isPartial && fieldRule->assignedNonArrayField) + { + context.syntaxManager.AddError( + ParserErrorType::NonLoopablePartialRuleUsedInLoop, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + fieldRule->Name() + ); + } + } + } + } + + void Visit(GlrLiteralSyntax* node) override + { + syntaxMinLength = 1; + syntaxMinUseRuleCount = 0; + syntaxMaxUseRuleCount = 0; + } + + void Visit(GlrUseSyntax* node) override + { + syntaxMinLength = 1; + syntaxMinUseRuleCount = 1; + syntaxMaxUseRuleCount = 1; + + if (loopCounter > 0) + { + context.syntaxManager.AddError( + ParserErrorType::UseRuleUsedInLoopBody, + node->codeRange, + ruleSymbol->Name(), + node->name.value + ); + } + if (optionalCounter > 0) + { + context.syntaxManager.AddError( + ParserErrorType::UseRuleUsedInOptionalBody, + node->codeRange, + ruleSymbol->Name(), + node->name.value + ); + } + } + + void Visit(GlrLoopSyntax* node) override + { + vint bodyMinLength = 0, bodyMaxUseRuleCount = 0; + vint delimiterMinLength = 0, delimiterMaxUseRuleCount = 0; + + loopCounter++; + + node->syntax->Accept(this); + bodyMinLength = syntaxMinLength; + bodyMaxUseRuleCount = syntaxMaxUseRuleCount; + + if (node->delimiter) + { + node->delimiter->Accept(this); + delimiterMinLength = syntaxMinLength; + delimiterMaxUseRuleCount = syntaxMaxUseRuleCount; + } + + if (delimiterMinLength + bodyMinLength == 0) + { + context.syntaxManager.AddError( + ParserErrorType::LoopBodyCouldExpandToEmptySequence, + node->codeRange, + ruleSymbol->Name() + ); + } + syntaxMinLength = 0; + syntaxMinUseRuleCount = 0; + syntaxMaxUseRuleCount = bodyMaxUseRuleCount * 2 + delimiterMaxUseRuleCount * 2; + + loopCounter--; + } + + void Visit(GlrOptionalSyntax* node) override + { + if (node->priority != GlrOptionalPriority::Equal) + { + if (prioritySyntaxOccurred) + { + context.syntaxManager.AddError( + ParserErrorType::MultiplePrioritySyntaxInAClause, + node->codeRange, + ruleSymbol->Name() + ); + } + else + { + prioritySyntaxOccurred = true; + } + } + optionalCounter++; + + node->syntax->Accept(this); + + if (syntaxMinLength == 0) + { + context.syntaxManager.AddError( + ParserErrorType::OptionalBodyCouldExpandToEmptySequence, + node->codeRange, + ruleSymbol->Name() + ); + } + + if (node->priority == GlrOptionalPriority::PreferSkip && lastSyntaxPiece) + { + context.syntaxManager.AddError( + ParserErrorType::NegativeOptionalEndsAClause, + node->codeRange, + ruleSymbol->Name() + ); + } + syntaxMinLength = 0; + syntaxMinUseRuleCount = 0; + + optionalCounter--; + } + + void Visit(GlrSequenceSyntax* node) override + { + node->second->Accept(this); + vint secondMinLength = syntaxMinLength; + vint secondMinUseRuleCount = syntaxMinUseRuleCount; + vint secondMaxUseRuleCount = syntaxMaxUseRuleCount; + + bool last = lastSyntaxPiece; + lastSyntaxPiece = last && secondMinLength == 0; + node->first->Accept(this); + vint firstMinLength = syntaxMinLength; + vint firstMinUseRuleCount = syntaxMinUseRuleCount; + vint firstMaxUseRuleCount = syntaxMaxUseRuleCount; + lastSyntaxPiece = last; + + syntaxMinLength = firstMinLength + secondMinLength; + syntaxMinUseRuleCount = firstMinUseRuleCount + secondMinUseRuleCount; + syntaxMaxUseRuleCount = firstMaxUseRuleCount + secondMaxUseRuleCount; + } + + void Visit(GlrAlternativeSyntax* node) override + { + node->first->Accept(this); + vint firstMinLength = syntaxMinLength; + vint firstMinUseRuleCount = syntaxMinUseRuleCount; + vint firstMaxUseRuleCount = syntaxMaxUseRuleCount; + + node->second->Accept(this); + vint secondMinLength = syntaxMinLength; + vint secondMinUseRuleCount = syntaxMinUseRuleCount; + vint secondMaxUseRuleCount = syntaxMaxUseRuleCount; + + syntaxMinLength = firstMinLength < secondMinLength ? firstMinLength : secondMinLength; + syntaxMinUseRuleCount = firstMinUseRuleCount < secondMinUseRuleCount ? firstMinUseRuleCount : secondMinUseRuleCount; + syntaxMaxUseRuleCount = firstMaxUseRuleCount > secondMaxUseRuleCount ? firstMaxUseRuleCount : secondMaxUseRuleCount; + } + + void CheckAfterClause(GlrClause* node, bool reuseClause) + { + if (syntaxMinLength == 0) + { + context.syntaxManager.AddError( + ParserErrorType::ClauseCouldExpandToEmptySequence, + node->codeRange, + ruleSymbol->Name() + ); + } + if (reuseClause) + { + if (syntaxMinUseRuleCount == 0) + { + context.syntaxManager.AddError( + ParserErrorType::ClauseNotCreateObject, + node->codeRange, + ruleSymbol->Name() + ); + } + if (syntaxMaxUseRuleCount > 1) + { + context.syntaxManager.AddError( + ParserErrorType::ClauseTooManyUseRule, + node->codeRange, + ruleSymbol->Name() + ); + } + } + } + + void Visit(GlrCreateClause* node) override + { + clause = node; + node->syntax->Accept(this); + CheckAfterClause(node, false); + } + + void Visit(GlrPartialClause* node) override + { + clause = node; + node->syntax->Accept(this); + CheckAfterClause(node, false); + } + + void Visit(GlrReuseClause* node) override + { + clause = node; + node->syntax->Accept(this); + CheckAfterClause(node, true); + } + }; + +/*********************************************************************** +ValidateStructureRelationshipVisitor +***********************************************************************/ + + class ValidateStructureRelationshipVisitor + : public Object + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + struct Link + { + GlrRefSyntax* ref = nullptr; + Link* prev = nullptr; + Link* next = nullptr; + + Link(GlrRefSyntax* _ref) : ref(_ref) {} + }; + + struct LinkPair + { + Link* first = nullptr; + Link* last = nullptr; + + void EnsureComplete() + { + CHECK_ERROR(!first || !first->prev, L"Illegal Operation!"); + CHECK_ERROR(!last || !last->next, L"Illegal Operation!"); + } + + LinkPair Append(Link* link) + { + EnsureComplete(); + if (first) + { + link->prev = last; + last->next = link; + return { first,link }; + } + else + { + return { link,link }; + } + } + + LinkPair Connect(LinkPair pair) + { + EnsureComplete(); + pair.EnsureComplete(); + if (!first && !pair.first) + { + return {}; + } + else if (!first) + { + return pair; + } + else if (!pair.first) + { + return *this; + } + else + { + last->next = pair.first; + pair.first->prev = last; + return { first,pair.last }; + } + } + + void CutAfter(Link* link, LinkPair& l1, LinkPair& l2) + { + EnsureComplete(); + if (!first) + { + CHECK_ERROR(!link, L"Illegal Operation!"); + l1 = {}; + l2 = {}; + } + else if (!link) + { + l2 = *this; + l1 = {}; + } + else if (link == last) + { + l1 = *this; + l2 = {}; + } + else + { + auto a = first; + auto b = last; + l1 = { a,link }; + l2 = { link->next,b }; + l1.last->next = nullptr; + l2.first->prev = nullptr; + } + } + + operator bool() const + { + return last; + } + }; + protected: + VisitorContext& context; + RuleSymbol* ruleSymbol; + GlrClause* clause = nullptr; + + LinkPair existingFields; + LinkPair existingPartials; + public: + ValidateStructureRelationshipVisitor( + VisitorContext& _context, + RuleSymbol* _ruleSymbol + ) + : context(_context) + , ruleSymbol(_ruleSymbol) + { + } + + ~ValidateStructureRelationshipVisitor() + { + { + auto c = existingFields.first; + while (c) + { + auto n = c->next; + delete c; + c = n; + } + } + { + auto c = existingPartials.first; + while (c) + { + auto n = c->next; + delete c; + c = n; + } + } + } + + void ValidateClause(Ptr clause) + { + clause->Accept(this); + } + + protected: + void Visit(GlrRefSyntax* node) override + { + if (node->field) + { + existingFields = existingFields.Append(new Link(node)); + } + + vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->name.value); + if (ruleIndex != -1) + { + auto fieldRule = context.syntaxManager.Rules().Values()[ruleIndex]; + if (fieldRule->isPartial) + { + existingPartials= existingPartials.Append(new Link(node)); + } + } + } + + void Visit(GlrLiteralSyntax* node) override + { + } + + void Visit(GlrUseSyntax* node) override + { + } + + void Visit(GlrLoopSyntax* node) override + { + node->syntax->Accept(this); + if (node->delimiter) + { + node->delimiter->Accept(this); + } + } + + void Visit(GlrOptionalSyntax* node) override + { + node->syntax->Accept(this); + } + + void Visit(GlrSequenceSyntax* node) override + { + node->first->Accept(this); + node->second->Accept(this); + } + + void Visit(GlrAlternativeSyntax* node) override + { + auto currentFields = existingFields; + auto currentPartials = existingPartials; + + node->first->Accept(this); + + LinkPair firstFields, firstPartials; + existingFields.CutAfter(currentFields.last, existingFields, firstFields); + existingPartials.CutAfter(currentPartials.last, existingPartials, firstPartials); + + node->second->Accept(this); + + existingFields = existingFields.Connect(firstFields); + existingPartials = existingPartials.Connect(firstPartials); + } + + void CheckAfterClause(GlrClause* node) + { + Dictionary counters; + auto c = existingFields.first; + while (c) + { + auto fieldName = c->ref->field.value; + vint index = counters.Keys().IndexOf(fieldName); + if (index == -1) + { + counters.Add(fieldName, 1); + } + else + { + counters.Set(fieldName, counters.Values()[index] + 1); + } + c = c->next; + } + + auto clauseType = context.clauseTypes[clause]; + for (auto [key, value] : counters) + { + auto prop = FindPropSymbol(clauseType, key); + if (prop->propType != AstPropType::Array && value > 1) + { + context.syntaxManager.AddError( + ParserErrorType::FieldAssignedMoreThanOnce, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + prop->Name() + ); + } + } + } + + void Visit(GlrCreateClause* node) override + { + clause = node; + node->syntax->Accept(this); + CheckAfterClause(node); + } + + void Visit(GlrPartialClause* node) override + { + clause = node; + node->syntax->Accept(this); + CheckAfterClause(node); + } + + void Visit(GlrReuseClause* node) override + { + clause = node; + node->syntax->Accept(this); + CheckAfterClause(node); + } + }; + +/*********************************************************************** +ValidateStructure +***********************************************************************/ + + void ValidateStructure(VisitorContext& context, List>& files) + { + for (auto file : files) + { + for (auto rule : file->rules) + { + auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; + ValidateStructureCountingVisitor visitor1(context, ruleSymbol); + for (auto clause : rule->clauses) + { + ValidateStructureRelationshipVisitor visitor2(context, ruleSymbol); + visitor1.ValidateClause(clause); + visitor2.ValidateClause(clause); + } + } + } + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\COMPILESYNTAX_VALIDATETYPES.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace compile_syntax; + +/*********************************************************************** +ValidateTypesVisitor +***********************************************************************/ + + class ValidateTypesVisitor + : public Object + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + protected: + VisitorContext& context; + RuleSymbol* ruleSymbol; + GlrClause* clause = nullptr; + + AstClassPropSymbol* FindField(AstClassSymbol*& clauseType, ParsingToken& name) + { + clauseType = context.clauseTypes[clause]; + if (auto prop = FindPropSymbol(clauseType, name.value)) + { + if (prop->propType != AstPropType::Array) + { + ruleSymbol->assignedNonArrayField = true; + } + return prop; + } + else + { + context.syntaxManager.AddError( + ParserErrorType::FieldNotExistsInClause, + name.codeRange, + ruleSymbol->Name(), + clauseType->Name(), + name.value + ); + return nullptr; + } + } + + bool ConvertibleTo(AstClassSymbol* from, AstClassSymbol* to) + { + while (from) + { + if (from == to) return true; + from = from->baseClass; + } + return false; + } + + public: + ValidateTypesVisitor( + VisitorContext& _context, + RuleSymbol* _ruleSymbol + ) + : context(_context) + , ruleSymbol(_ruleSymbol) + { + } + + void ValidateClause(Ptr clause) + { + clause->Accept(this); + } + + protected: + void Visit(GlrRefSyntax* node) override + { + vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->name.value); + auto clauseType = context.clauseTypes[clause]; + auto fieldRule = ruleIndex == -1 ? nullptr : context.syntaxManager.Rules().Values()[ruleIndex]; + + if (fieldRule && fieldRule->isPartial) + { + if (!ConvertibleTo(clauseType, fieldRule->ruleType)) + { + context.syntaxManager.AddError( + ParserErrorType::ClauseTypeMismatchedToPartialRule, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + fieldRule->Name(), + fieldRule->ruleType->Name() + ); + } + } + + if (node->field) + { + AstClassSymbol* clauseType = nullptr; + if (auto prop = FindField(clauseType, node->field)) + { + if (fieldRule) + { + if (fieldRule->isPartial) + { + context.syntaxManager.AddError( + ParserErrorType::PartialRuleUsedOnField, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + fieldRule->Name(), + node->field.value + ); + } + + if (auto propClassSymbol = dynamic_cast(prop->propSymbol)) + { + if (ConvertibleTo(fieldRule->ruleType, propClassSymbol)) + { + goto PASS_FIELD_TYPE; + } + } + context.syntaxManager.AddError( + ParserErrorType::RuleTypeMismatchedToField, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + node->field.value, + fieldRule->ruleType->Name() + ); + PASS_FIELD_TYPE:; + } + else + { + if (prop->propType != AstPropType::Token) + { + context.syntaxManager.AddError( + ParserErrorType::RuleTypeMismatchedToField, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + node->field.value, + L"token" + ); + } + } + } + } + } + + void Visit(GlrLiteralSyntax* node) override + { + } + + void Visit(GlrUseSyntax* node) override + { + auto fieldRule = context.syntaxManager.Rules()[node->name.value]; + if (fieldRule->isPartial) + { + context.syntaxManager.AddError( + ParserErrorType::UseRuleWithPartialRule, + node->codeRange, + ruleSymbol->Name(), + node->name.value + ); + } + if (!dynamic_cast(clause)) + { + context.syntaxManager.AddError( + ParserErrorType::UseRuleInNonReuseClause, + node->codeRange, + ruleSymbol->Name(), + node->name.value + ); + } + } + + void Visit(GlrLoopSyntax* node) override + { + node->syntax->Accept(this); + if (node->delimiter) + { + node->delimiter->Accept(this); + } + } + + void Visit(GlrOptionalSyntax* node) override + { + node->syntax->Accept(this); + } + + void Visit(GlrSequenceSyntax* node) override + { + node->first->Accept(this); + node->second->Accept(this); + } + + void Visit(GlrAlternativeSyntax* node) override + { + node->first->Accept(this); + node->second->Accept(this); + } + + void Visit(GlrAssignment* node) + { + AstClassSymbol* clauseType = nullptr; + if (auto prop = FindField(clauseType, node->field)) + { + if (auto enumPropSymbol = dynamic_cast(prop->propSymbol)) + { + if (!enumPropSymbol->Items().Keys().Contains(node->value.value)) + { + context.syntaxManager.AddError( + ParserErrorType::EnumItemMismatchedToField, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + node->field.value, + node->value.value + ); + } + } + else + { + context.syntaxManager.AddError( + ParserErrorType::AssignmentToNonEnumField, + node->codeRange, + ruleSymbol->Name(), + clauseType->Name(), + node->field.value + ); + } + } + } + + void Visit(GlrCreateClause* node) override + { + clause = node; + node->syntax->Accept(this); + for (auto assignment : node->assignments) + { + Visit(assignment.Obj()); + } + } + + void Visit(GlrPartialClause* node) override + { + clause = node; + node->syntax->Accept(this); + for (auto assignment : node->assignments) + { + Visit(assignment.Obj()); + } + } + + void Visit(GlrReuseClause* node) override + { + clause = node; + node->syntax->Accept(this); + for (auto assignment : node->assignments) + { + Visit(assignment.Obj()); + } + } + }; + +/*********************************************************************** +ValidateTypes +***********************************************************************/ + + void ValidateTypes(VisitorContext& context, List>& files) + { + for (auto file : files) + { + for (auto rule : file->rules) + { + auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; + ValidateTypesVisitor visitor(context, ruleSymbol); + for (auto clause : rule->clauses) + { + visitor.ValidateClause(clause); + } + } + } + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\PARSERCPPGEN.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + +/*********************************************************************** +GenerateParserFileNames +***********************************************************************/ + + Ptr GenerateParserFileNames(ParserSymbolManager& manager) + { + auto parserOutput = MakePtr(); + parserOutput->assemblyH = manager.name + L"_Assembler.h"; + parserOutput->assemblyCpp = manager.name + L"_Assembler.cpp"; + parserOutput->lexerH = manager.name + L"_Lexer.h"; + parserOutput->lexerCpp = manager.name + L"_Lexer.cpp"; + return parserOutput; + } + +/*********************************************************************** +WriteCppStringBody +***********************************************************************/ + + void WriteCppStringBody(const WString& body, stream::StreamWriter& writer) + { + for (vint i = 0; i < body.Length(); i++) + { + auto c = body[i]; + switch (c) + { + case L'\t': + writer.WriteString(L"\\t"); + break; + case L'\r': + writer.WriteString(L"\\r"); + break; + case L'\n': + writer.WriteString(L"\\n"); + break; + case L'\\': + writer.WriteString(L"\\\\"); + break; + case L'\"': + writer.WriteString(L"\\\""); + break; + case L'\'': + writer.WriteString(L"\\\'"); + break; + default: + writer.WriteChar(c); + } + } + } + +/*********************************************************************** +Utility +***********************************************************************/ + + void WriteFileComment(const WString& name, stream::StreamWriter& writer) + { + writer.WriteLine(L"/***********************************************************************"); + writer.WriteLine(L"This file is generated by: Vczh Parser Generator"); + writer.WriteLine(L"From parser definition:" + name); + writer.WriteLine(L"Licensed under https://github.com/vczh-libraries/License"); + writer.WriteLine(L"***********************************************************************/"); + writer.WriteLine(L""); + } + + WString WriteNssBegin(collections::List& cppNss, stream::StreamWriter& writer) + { + WString prefix; + for (auto ns : cppNss) + { + writer.WriteLine(prefix + L"namespace " + ns); + writer.WriteLine(prefix + L"{"); + prefix += L"\t"; + } + return prefix; + } + + void WriteNssEnd(collections::List& cppNss, stream::StreamWriter& writer) + { + vint counter = cppNss.Count(); + for (auto ns : cppNss) + { + counter--; + for (vint i = 0; i < counter; i++) writer.WriteChar(L'\t'); + writer.WriteLine(L"}"); + } + } + + extern void WriteLoadDataFunctionHeader(const WString& prefix, const WString& functionName, stream::StreamWriter& writer) + { + writer.WriteLine(prefix + L"extern void " + functionName + L"(vl::stream::IStream& outputStream);"); + } + + extern void WriteLoadDataFunctionCpp(const WString& prefix, const WString& functionName, stream::MemoryStream& rawData, bool compressData, stream::StreamWriter& writer) + { + MemoryStream compressedData; + if (compressData) + { + CompressStream(rawData, compressedData); + } + else + { + CopyStream(rawData, compressedData); + } + compressedData.SeekFromBegin(0); + + vint lengthBeforeCompressing = (vint)rawData.Size(); + vint length = (vint)compressedData.Size(); + const vint block = 256; + vint remain = length % block; + vint solidRows = length / block; + vint rows = solidRows + (remain ? 1 : 0); + + writer.WriteLine(prefix + L"void " + functionName + L"(vl::stream::IStream& outputStream)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tstatic const vl::vint dataLength = " + itow(length) + L"; // " + itow(lengthBeforeCompressing) + L" bytes before compressing"); + writer.WriteLine(prefix + L"\tstatic const vl::vint dataBlock = " + itow(block) + L";"); + writer.WriteLine(prefix + L"\tstatic const vl::vint dataRemain = " + itow(remain) + L";"); + writer.WriteLine(prefix + L"\tstatic const vl::vint dataSolidRows = " + itow(solidRows) + L";"); + writer.WriteLine(prefix + L"\tstatic const vl::vint dataRows = " + itow(rows) + L";"); + writer.WriteLine(prefix + L"\tstatic const char* compressed[] = {"); + { + char buffer[block]; + const wchar_t* hex = L"0123456789ABCDEF"; + for (vint i = 0; i < rows; i++) + { + vint size = i == solidRows ? remain : block; + vint read = compressedData.Read(buffer, size); + CHECK_ERROR(size == read, L"vl::glr::parsergen::WriteLexerCppFile()#Failed to read compressed data."); + writer.WriteString(prefix + L"\t\t\""); + for (vint j = 0; j < size; j++) + { + vuint8_t byte = buffer[j]; + writer.WriteString(L"\\x"); + writer.WriteChar(hex[byte / 16]); + writer.WriteChar(hex[byte % 16]); + } + writer.WriteLine(L"\","); + } + } + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\tvl::glr::DecompressSerializedData(compressed, " + WString(compressData ? L"true" : L"false") + L", dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);"); + writer.WriteLine(prefix + L"}"); + } + } + } +} + +/*********************************************************************** +.\PARSERGEN\PARSERSYMBOL.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + +/*********************************************************************** +Utility +***********************************************************************/ + + void InitializeParserSymbolManager(ParserSymbolManager& manager) + { + manager.name = L"ParserGen"; + Fill(manager.includes, L"../AstBase.h", L"../SyntaxBase.h"); + Fill(manager.cppNss, L"vl", L"glr", L"parsergen"); + manager.headerGuard = L"VCZH_PARSER2_PARSERGEN"; + } + } + } +} + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { +/*********************************************************************** +Visitor Pattern Implementation +***********************************************************************/ + + void GlrRefSyntax::Accept(GlrSyntax::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrLiteralSyntax::Accept(GlrSyntax::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrUseSyntax::Accept(GlrSyntax::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrLoopSyntax::Accept(GlrSyntax::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrOptionalSyntax::Accept(GlrSyntax::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrSequenceSyntax::Accept(GlrSyntax::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrAlternativeSyntax::Accept(GlrSyntax::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrCreateClause::Accept(GlrClause::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrPartialClause::Accept(GlrClause::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrReuseClause::Accept(GlrClause::IVisitor* visitor) + { + visitor->Visit(this); + } + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrSyntax, glr::parsergen::GlrSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrSyntax::IVisitor, glr::parsergen::GlrSyntax::IVisitor) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrRefSyntax, glr::parsergen::GlrRefSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrLiteralSyntax, glr::parsergen::GlrLiteralSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrUseSyntax, glr::parsergen::GlrUseSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrLoopSyntax, glr::parsergen::GlrLoopSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrOptionalPriority, glr::parsergen::GlrOptionalPriority) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrOptionalSyntax, glr::parsergen::GlrOptionalSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrSequenceSyntax, glr::parsergen::GlrSequenceSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrAlternativeSyntax, glr::parsergen::GlrAlternativeSyntax) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrClause, glr::parsergen::GlrClause) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrClause::IVisitor, glr::parsergen::GlrClause::IVisitor) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrAssignment, glr::parsergen::GlrAssignment) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrCreateClause, glr::parsergen::GlrCreateClause) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrPartialClause, glr::parsergen::GlrPartialClause) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrReuseClause, glr::parsergen::GlrReuseClause) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrRule, glr::parsergen::GlrRule) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrSyntaxFile, glr::parsergen::GlrSyntaxFile) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrSyntax) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + END_CLASS_MEMBER(vl::glr::parsergen::GlrSyntax) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrRefSyntax) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + CLASS_MEMBER_FIELD(field) + END_CLASS_MEMBER(vl::glr::parsergen::GlrRefSyntax) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrLiteralSyntax) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(value) + END_CLASS_MEMBER(vl::glr::parsergen::GlrLiteralSyntax) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrUseSyntax) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + END_CLASS_MEMBER(vl::glr::parsergen::GlrUseSyntax) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrLoopSyntax) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(syntax) + CLASS_MEMBER_FIELD(delimiter) + END_CLASS_MEMBER(vl::glr::parsergen::GlrLoopSyntax) + + BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrOptionalPriority) + ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrOptionalPriority) + ENUM_NAMESPACE_ITEM(Equal) + ENUM_NAMESPACE_ITEM(PreferTake) + ENUM_NAMESPACE_ITEM(PreferSkip) + END_ENUM_ITEM(vl::glr::parsergen::GlrOptionalPriority) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrOptionalSyntax) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(priority) + CLASS_MEMBER_FIELD(syntax) + END_CLASS_MEMBER(vl::glr::parsergen::GlrOptionalSyntax) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrSequenceSyntax) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(first) + CLASS_MEMBER_FIELD(second) + END_CLASS_MEMBER(vl::glr::parsergen::GlrSequenceSyntax) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrAlternativeSyntax) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(first) + CLASS_MEMBER_FIELD(second) + END_CLASS_MEMBER(vl::glr::parsergen::GlrAlternativeSyntax) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrClause) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + END_CLASS_MEMBER(vl::glr::parsergen::GlrClause) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrAssignment) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(field) + CLASS_MEMBER_FIELD(value) + END_CLASS_MEMBER(vl::glr::parsergen::GlrAssignment) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrCreateClause) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrClause) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(type) + CLASS_MEMBER_FIELD(syntax) + CLASS_MEMBER_FIELD(assignments) + END_CLASS_MEMBER(vl::glr::parsergen::GlrCreateClause) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrPartialClause) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrClause) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(type) + CLASS_MEMBER_FIELD(syntax) + CLASS_MEMBER_FIELD(assignments) + END_CLASS_MEMBER(vl::glr::parsergen::GlrPartialClause) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrReuseClause) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrClause) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(syntax) + CLASS_MEMBER_FIELD(assignments) + END_CLASS_MEMBER(vl::glr::parsergen::GlrReuseClause) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrRule) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + CLASS_MEMBER_FIELD(clauses) + END_CLASS_MEMBER(vl::glr::parsergen::GlrRule) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrSyntaxFile) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(rules) + END_CLASS_MEMBER(vl::glr::parsergen::GlrSyntaxFile) + + BEGIN_INTERFACE_MEMBER(vl::glr::parsergen::GlrSyntax::IVisitor) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrRefSyntax* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrLiteralSyntax* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrUseSyntax* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrLoopSyntax* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrOptionalSyntax* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrSequenceSyntax* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrAlternativeSyntax* node)) + END_INTERFACE_MEMBER(vl::glr::parsergen::GlrSyntax) + + BEGIN_INTERFACE_MEMBER(vl::glr::parsergen::GlrClause::IVisitor) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrClause::IVisitor::*)(vl::glr::parsergen::GlrCreateClause* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrClause::IVisitor::*)(vl::glr::parsergen::GlrPartialClause* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrClause::IVisitor::*)(vl::glr::parsergen::GlrReuseClause* node)) + END_INTERFACE_MEMBER(vl::glr::parsergen::GlrClause) + +#endif + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + class ParserGenRuleAstTypeLoader : public vl::Object, public ITypeLoader + { + public: + void Load(ITypeManager* manager) + { + ADD_TYPE_INFO(vl::glr::parsergen::GlrSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrSyntax::IVisitor) + ADD_TYPE_INFO(vl::glr::parsergen::GlrRefSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrLiteralSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrUseSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrLoopSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrOptionalPriority) + ADD_TYPE_INFO(vl::glr::parsergen::GlrOptionalSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrSequenceSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrAlternativeSyntax) + ADD_TYPE_INFO(vl::glr::parsergen::GlrClause) + ADD_TYPE_INFO(vl::glr::parsergen::GlrClause::IVisitor) + ADD_TYPE_INFO(vl::glr::parsergen::GlrAssignment) + ADD_TYPE_INFO(vl::glr::parsergen::GlrCreateClause) + ADD_TYPE_INFO(vl::glr::parsergen::GlrPartialClause) + ADD_TYPE_INFO(vl::glr::parsergen::GlrReuseClause) + ADD_TYPE_INFO(vl::glr::parsergen::GlrRule) + ADD_TYPE_INFO(vl::glr::parsergen::GlrSyntaxFile) + } + + void Unload(ITypeManager* manager) + { + } + }; +#endif +#endif + + bool ParserGenRuleAstLoadTypes() + { +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + if (auto manager = GetGlobalTypeManager()) + { + Ptr loader = new ParserGenRuleAstTypeLoader; + return manager->AddTypeLoader(loader); + } +#endif + return false; + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_BUILDER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace builder + { + +/*********************************************************************** +MakeAlternativeSyntax +***********************************************************************/ + + MakeAlternativeSyntax& MakeAlternativeSyntax::first(const vl::Ptr& value) + { + node->first = value; + return *this; + } + + MakeAlternativeSyntax& MakeAlternativeSyntax::second(const vl::Ptr& value) + { + node->second = value; + return *this; + } + +/*********************************************************************** +MakeAssignment +***********************************************************************/ + + MakeAssignment& MakeAssignment::field(const vl::WString& value) + { + node->field.value = value; + return *this; + } + + MakeAssignment& MakeAssignment::value(const vl::WString& value) + { + node->value.value = value; + return *this; + } + +/*********************************************************************** +MakeCreateClause +***********************************************************************/ + + MakeCreateClause& MakeCreateClause::assignments(const vl::Ptr& value) + { + node->assignments.Add(value); + return *this; + } + + MakeCreateClause& MakeCreateClause::syntax(const vl::Ptr& value) + { + node->syntax = value; + return *this; + } + + MakeCreateClause& MakeCreateClause::type(const vl::WString& value) + { + node->type.value = value; + return *this; + } + +/*********************************************************************** +MakeLiteralSyntax +***********************************************************************/ + + MakeLiteralSyntax& MakeLiteralSyntax::value(const vl::WString& value) + { + node->value.value = value; + return *this; + } + +/*********************************************************************** +MakeLoopSyntax +***********************************************************************/ + + MakeLoopSyntax& MakeLoopSyntax::delimiter(const vl::Ptr& value) + { + node->delimiter = value; + return *this; + } + + MakeLoopSyntax& MakeLoopSyntax::syntax(const vl::Ptr& value) + { + node->syntax = value; + return *this; + } + +/*********************************************************************** +MakeOptionalSyntax +***********************************************************************/ + + MakeOptionalSyntax& MakeOptionalSyntax::priority(GlrOptionalPriority value) + { + node->priority = value; + return *this; + } + + MakeOptionalSyntax& MakeOptionalSyntax::syntax(const vl::Ptr& value) + { + node->syntax = value; + return *this; + } + +/*********************************************************************** +MakePartialClause +***********************************************************************/ + + MakePartialClause& MakePartialClause::assignments(const vl::Ptr& value) + { + node->assignments.Add(value); + return *this; + } + + MakePartialClause& MakePartialClause::syntax(const vl::Ptr& value) + { + node->syntax = value; + return *this; + } + + MakePartialClause& MakePartialClause::type(const vl::WString& value) + { + node->type.value = value; + return *this; + } + +/*********************************************************************** +MakeRefSyntax +***********************************************************************/ + + MakeRefSyntax& MakeRefSyntax::field(const vl::WString& value) + { + node->field.value = value; + return *this; + } + + MakeRefSyntax& MakeRefSyntax::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + +/*********************************************************************** +MakeReuseClause +***********************************************************************/ + + MakeReuseClause& MakeReuseClause::assignments(const vl::Ptr& value) + { + node->assignments.Add(value); + return *this; + } + + MakeReuseClause& MakeReuseClause::syntax(const vl::Ptr& value) + { + node->syntax = value; + return *this; + } + +/*********************************************************************** +MakeRule +***********************************************************************/ + + MakeRule& MakeRule::clauses(const vl::Ptr& value) + { + node->clauses.Add(value); + return *this; + } + + MakeRule& MakeRule::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + +/*********************************************************************** +MakeSequenceSyntax +***********************************************************************/ + + MakeSequenceSyntax& MakeSequenceSyntax::first(const vl::Ptr& value) + { + node->first = value; + return *this; + } + + MakeSequenceSyntax& MakeSequenceSyntax::second(const vl::Ptr& value) + { + node->second = value; + return *this; + } + +/*********************************************************************** +MakeSyntaxFile +***********************************************************************/ + + MakeSyntaxFile& MakeSyntaxFile::rules(const vl::Ptr& value) + { + node->rules.Add(value); + return *this; + } + +/*********************************************************************** +MakeUseSyntax +***********************************************************************/ + + MakeUseSyntax& MakeUseSyntax::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_COPY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace copy_visitor + { + void RuleAstVisitor::CopyFields(GlrAlternativeSyntax* from, GlrAlternativeSyntax* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->first = CopyNode(from->first.Obj()); + to->second = CopyNode(from->second.Obj()); + } + + void RuleAstVisitor::CopyFields(GlrAssignment* from, GlrAssignment* to) + { + to->field = from->field; + to->value = from->value; + } + + void RuleAstVisitor::CopyFields(GlrClause* from, GlrClause* to) + { + } + + void RuleAstVisitor::CopyFields(GlrCreateClause* from, GlrCreateClause* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->assignments) + { + to->assignments.Add(CopyNode(listItem.Obj())); + } + to->syntax = CopyNode(from->syntax.Obj()); + to->type = from->type; + } + + void RuleAstVisitor::CopyFields(GlrLiteralSyntax* from, GlrLiteralSyntax* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->value = from->value; + } + + void RuleAstVisitor::CopyFields(GlrLoopSyntax* from, GlrLoopSyntax* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->delimiter = CopyNode(from->delimiter.Obj()); + to->syntax = CopyNode(from->syntax.Obj()); + } + + void RuleAstVisitor::CopyFields(GlrOptionalSyntax* from, GlrOptionalSyntax* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->priority = from->priority; + to->syntax = CopyNode(from->syntax.Obj()); + } + + void RuleAstVisitor::CopyFields(GlrPartialClause* from, GlrPartialClause* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->assignments) + { + to->assignments.Add(CopyNode(listItem.Obj())); + } + to->syntax = CopyNode(from->syntax.Obj()); + to->type = from->type; + } + + void RuleAstVisitor::CopyFields(GlrRefSyntax* from, GlrRefSyntax* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->field = from->field; + to->name = from->name; + } + + void RuleAstVisitor::CopyFields(GlrReuseClause* from, GlrReuseClause* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->assignments) + { + to->assignments.Add(CopyNode(listItem.Obj())); + } + to->syntax = CopyNode(from->syntax.Obj()); + } + + void RuleAstVisitor::CopyFields(GlrRule* from, GlrRule* to) + { + for (auto&& listItem : from->clauses) + { + to->clauses.Add(CopyNode(listItem.Obj())); + } + to->name = from->name; + } + + void RuleAstVisitor::CopyFields(GlrSequenceSyntax* from, GlrSequenceSyntax* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->first = CopyNode(from->first.Obj()); + to->second = CopyNode(from->second.Obj()); + } + + void RuleAstVisitor::CopyFields(GlrSyntax* from, GlrSyntax* to) + { + } + + void RuleAstVisitor::CopyFields(GlrSyntaxFile* from, GlrSyntaxFile* to) + { + for (auto&& listItem : from->rules) + { + to->rules.Add(CopyNode(listItem.Obj())); + } + } + + void RuleAstVisitor::CopyFields(GlrUseSyntax* from, GlrUseSyntax* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->name = from->name; + } + + void RuleAstVisitor::Visit(GlrAssignment* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrRule* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrSyntaxFile* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrRefSyntax* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrLiteralSyntax* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrUseSyntax* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrLoopSyntax* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrOptionalSyntax* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrSequenceSyntax* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrAlternativeSyntax* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrCreateClause* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrPartialClause* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void RuleAstVisitor::Visit(GlrReuseClause* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrSyntax* node) + { + if (!node) return nullptr; + node->Accept(static_cast(this)); + return this->result.Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrClause* node) + { + if (!node) return nullptr; + node->Accept(static_cast(this)); + return this->result.Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrAssignment* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrRule* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrSyntaxFile* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrAlternativeSyntax* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrCreateClause* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrLiteralSyntax* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrLoopSyntax* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrOptionalSyntax* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrPartialClause* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrRefSyntax* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrReuseClause* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrSequenceSyntax* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr RuleAstVisitor::CopyNode(GlrUseSyntax* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_EMPTY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace empty_visitor + { + +/*********************************************************************** +SyntaxVisitor +***********************************************************************/ + + // Visitor Members ----------------------------------- + + void SyntaxVisitor::Visit(GlrRefSyntax* node) + { + } + + void SyntaxVisitor::Visit(GlrLiteralSyntax* node) + { + } + + void SyntaxVisitor::Visit(GlrUseSyntax* node) + { + } + + void SyntaxVisitor::Visit(GlrLoopSyntax* node) + { + } + + void SyntaxVisitor::Visit(GlrOptionalSyntax* node) + { + } + + void SyntaxVisitor::Visit(GlrSequenceSyntax* node) + { + } + + void SyntaxVisitor::Visit(GlrAlternativeSyntax* node) + { + } + +/*********************************************************************** +ClauseVisitor +***********************************************************************/ + + // Visitor Members ----------------------------------- + + void ClauseVisitor::Visit(GlrCreateClause* node) + { + } + + void ClauseVisitor::Visit(GlrPartialClause* node) + { + } + + void ClauseVisitor::Visit(GlrReuseClause* node) + { + } + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_JSON.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace json_visitor + { + void RuleAstVisitor::PrintFields(GlrAlternativeSyntax* node) + { + BeginField(L"first"); + Print(node->first.Obj()); + EndField(); + BeginField(L"second"); + Print(node->second.Obj()); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrAssignment* node) + { + BeginField(L"field"); + WriteToken(node->field); + EndField(); + BeginField(L"value"); + WriteToken(node->value); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrClause* node) + { + } + void RuleAstVisitor::PrintFields(GlrCreateClause* node) + { + BeginField(L"assignments"); + BeginArray(); + for (auto&& listItem : node->assignments) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + BeginField(L"syntax"); + Print(node->syntax.Obj()); + EndField(); + BeginField(L"type"); + WriteToken(node->type); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrLiteralSyntax* node) + { + BeginField(L"value"); + WriteToken(node->value); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrLoopSyntax* node) + { + BeginField(L"delimiter"); + Print(node->delimiter.Obj()); + EndField(); + BeginField(L"syntax"); + Print(node->syntax.Obj()); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrOptionalSyntax* node) + { + BeginField(L"priority"); + switch (node->priority) + { + case vl::glr::parsergen::GlrOptionalPriority::Equal: + WriteString(L"Equal"); + break; + case vl::glr::parsergen::GlrOptionalPriority::PreferSkip: + WriteString(L"PreferSkip"); + break; + case vl::glr::parsergen::GlrOptionalPriority::PreferTake: + WriteString(L"PreferTake"); + break; + default: + WriteNull(); + } + EndField(); + BeginField(L"syntax"); + Print(node->syntax.Obj()); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrPartialClause* node) + { + BeginField(L"assignments"); + BeginArray(); + for (auto&& listItem : node->assignments) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + BeginField(L"syntax"); + Print(node->syntax.Obj()); + EndField(); + BeginField(L"type"); + WriteToken(node->type); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrRefSyntax* node) + { + BeginField(L"field"); + WriteToken(node->field); + EndField(); + BeginField(L"name"); + WriteToken(node->name); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrReuseClause* node) + { + BeginField(L"assignments"); + BeginArray(); + for (auto&& listItem : node->assignments) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + BeginField(L"syntax"); + Print(node->syntax.Obj()); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrRule* node) + { + BeginField(L"clauses"); + BeginArray(); + for (auto&& listItem : node->clauses) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + BeginField(L"name"); + WriteToken(node->name); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrSequenceSyntax* node) + { + BeginField(L"first"); + Print(node->first.Obj()); + EndField(); + BeginField(L"second"); + Print(node->second.Obj()); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrSyntax* node) + { + } + void RuleAstVisitor::PrintFields(GlrSyntaxFile* node) + { + BeginField(L"rules"); + BeginArray(); + for (auto&& listItem : node->rules) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + } + void RuleAstVisitor::PrintFields(GlrUseSyntax* node) + { + BeginField(L"name"); + WriteToken(node->name); + EndField(); + } + + void RuleAstVisitor::Visit(GlrRefSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"RefSyntax", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrLiteralSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"LiteralSyntax", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrUseSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"UseSyntax", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrLoopSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"LoopSyntax", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrOptionalSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"OptionalSyntax", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrSequenceSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"SequenceSyntax", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrAlternativeSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"AlternativeSyntax", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrCreateClause* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"CreateClause", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrPartialClause* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"PartialClause", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Visit(GlrReuseClause* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"ReuseClause", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + RuleAstVisitor::RuleAstVisitor(vl::stream::StreamWriter& _writer) + : vl::glr::JsonVisitorBase(_writer) + { + } + + void RuleAstVisitor::Print(GlrSyntax* node) + { + if (!node) + { + WriteNull(); + return; + } + node->Accept(static_cast(this)); + } + + void RuleAstVisitor::Print(GlrClause* node) + { + if (!node) + { + WriteNull(); + return; + } + node->Accept(static_cast(this)); + } + + void RuleAstVisitor::Print(GlrAssignment* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Assignment", node); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Print(GlrRule* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Rule", node); + PrintFields(static_cast(node)); + EndObject(); + } + + void RuleAstVisitor::Print(GlrSyntaxFile* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"SyntaxFile", node); + PrintFields(static_cast(node)); + EndObject(); + } + + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_TRAVERSE.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace traverse_visitor + { + void RuleAstVisitor::Traverse(vl::glr::ParsingToken& token) {} + void RuleAstVisitor::Traverse(vl::glr::ParsingAstBase* node) {} + void RuleAstVisitor::Traverse(GlrAlternativeSyntax* node) {} + void RuleAstVisitor::Traverse(GlrAssignment* node) {} + void RuleAstVisitor::Traverse(GlrClause* node) {} + void RuleAstVisitor::Traverse(GlrCreateClause* node) {} + void RuleAstVisitor::Traverse(GlrLiteralSyntax* node) {} + void RuleAstVisitor::Traverse(GlrLoopSyntax* node) {} + void RuleAstVisitor::Traverse(GlrOptionalSyntax* node) {} + void RuleAstVisitor::Traverse(GlrPartialClause* node) {} + void RuleAstVisitor::Traverse(GlrRefSyntax* node) {} + void RuleAstVisitor::Traverse(GlrReuseClause* node) {} + void RuleAstVisitor::Traverse(GlrRule* node) {} + void RuleAstVisitor::Traverse(GlrSequenceSyntax* node) {} + void RuleAstVisitor::Traverse(GlrSyntax* node) {} + void RuleAstVisitor::Traverse(GlrSyntaxFile* node) {} + void RuleAstVisitor::Traverse(GlrUseSyntax* node) {} + + void RuleAstVisitor::Finishing(vl::glr::ParsingAstBase* node) {} + void RuleAstVisitor::Finishing(GlrAlternativeSyntax* node) {} + void RuleAstVisitor::Finishing(GlrAssignment* node) {} + void RuleAstVisitor::Finishing(GlrClause* node) {} + void RuleAstVisitor::Finishing(GlrCreateClause* node) {} + void RuleAstVisitor::Finishing(GlrLiteralSyntax* node) {} + void RuleAstVisitor::Finishing(GlrLoopSyntax* node) {} + void RuleAstVisitor::Finishing(GlrOptionalSyntax* node) {} + void RuleAstVisitor::Finishing(GlrPartialClause* node) {} + void RuleAstVisitor::Finishing(GlrRefSyntax* node) {} + void RuleAstVisitor::Finishing(GlrReuseClause* node) {} + void RuleAstVisitor::Finishing(GlrRule* node) {} + void RuleAstVisitor::Finishing(GlrSequenceSyntax* node) {} + void RuleAstVisitor::Finishing(GlrSyntax* node) {} + void RuleAstVisitor::Finishing(GlrSyntaxFile* node) {} + void RuleAstVisitor::Finishing(GlrUseSyntax* node) {} + + void RuleAstVisitor::Visit(GlrRefSyntax* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->field); + Traverse(node->name); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrLiteralSyntax* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->value); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrUseSyntax* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->name); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrLoopSyntax* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + InspectInto(node->delimiter.Obj()); + InspectInto(node->syntax.Obj()); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrOptionalSyntax* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + InspectInto(node->syntax.Obj()); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrSequenceSyntax* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + InspectInto(node->first.Obj()); + InspectInto(node->second.Obj()); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrAlternativeSyntax* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + InspectInto(node->first.Obj()); + InspectInto(node->second.Obj()); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrCreateClause* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->assignments) + { + InspectInto(listItem.Obj()); + } + InspectInto(node->syntax.Obj()); + Traverse(node->type); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrPartialClause* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->assignments) + { + InspectInto(listItem.Obj()); + } + InspectInto(node->syntax.Obj()); + Traverse(node->type); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::Visit(GlrReuseClause* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->assignments) + { + InspectInto(listItem.Obj()); + } + InspectInto(node->syntax.Obj()); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::InspectInto(GlrSyntax* node) + { + if (!node) return; + node->Accept(static_cast(this)); + } + + void RuleAstVisitor::InspectInto(GlrClause* node) + { + if (!node) return; + node->Accept(static_cast(this)); + } + + void RuleAstVisitor::InspectInto(GlrAssignment* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->field); + Traverse(node->value); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::InspectInto(GlrRule* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->clauses) + { + InspectInto(listItem.Obj()); + } + Traverse(node->name); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void RuleAstVisitor::InspectInto(GlrSyntaxFile* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->rules) + { + InspectInto(listItem.Obj()); + } + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEPARSER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + void ParserGenRuleParserData(vl::stream::IStream& outputStream) + { + static const vl::vint dataLength = 6495; // 70565 bytes before compressing + static const vl::vint dataBlock = 256; + static const vl::vint dataRemain = 95; + static const vl::vint dataSolidRows = 25; + static const vl::vint dataRows = 26; + static const char* compressed[] = { + "\xA5\x13\x01\x00\x57\x19\x00\x00\x1A\x00\x01\x82\x80\x09\x03\x82\x81\x82\x06\x89\x82\x85\x0A\x80\x81\x85\x0F\x0A\xA5\x0A\x88\x1A\x85\x16\x85\x21\x0A\xC9\x0A\x8C\x38\x01\x87\x7F\x8F\x20\x9F\x8A\x80\x01\x91\x93\x91\x92\x20\xA7\xA8\x9F\x7A\x90\x95\x97\x92\x2F\xA6\x8A\x8B\x9C\x93\x9B\x95\x98\x29\xB6\xAE\x83\x9A\x81\x02\x9C\x98\x3F\xB2\x9E\x97\x91\xA1\x9F\xA1\x9D\x47\xC0\x89\xA2\xA6\x84\x98\x9C\x91\x45\xD0\x8B\xA6\xAD\xA4\xA3\xA8\xA9\x55\xC8\x99\xAA\xAB\xAC\xA7\x80\xA7\x51\xB5\x97\xA2\xBD\xAC\xAB\xAE\xAB\x65\xD8\xA7\xBA\xAB\xB4\xAD\xB6\xAF\x02\xE0\xA3\xAF\xA4\xB7\xB6\xB3\xB8\x68\xF6\xAA\xB8\xBC\xB4\xBE\xB6\xBF\x70\x81\xB2\xA9\xB5\xB8\xC3\xBA\xC1\x79\x86\xFB\xA8\xCD\xBC\xC7\xBE\xC7\x81\xA4\x89\xD0\xC7\xC2\xC9\xC6\xCB\x8F\x98\xD1\xC3\xCA\xBD\xC0\xCB\xC5\x9A\x95\xDC\xCA\xCE\xC8\x02\x9F\x84\xA7\x84\xE3\x82\x0D\x99\xB3\x91\x01\xAD\xF3\xAE\xD3\xD2\xDD\xDA\xD4\x85\x04\x31\xF7\xC9\x8C\x80\xD6\x84\x03\xBA\x83\x87\x01\xE2\x85\x8E\xDE\xDB\x9D\xA3\x88\x86\x89\xD1\xE4\xDB\xDD\xD0\xCE\xC8\xE4\xD4\xBD\xEB\xE6\xE9\xD1\xD4\xD7\xFA", + "\xE3\xEF\xCD\xD3\xD1\xDE\xD6\xDD\xE1\xD0\xD0\xF0\xF3\xEF\x93\xE7\xE2\xF9\xE1\xF3\xED\xF7\xF1\xE6\xF1\xE9\xF2\xF7\xCC\xF9\xCC\x05\xC4\xEF\xEC\xEA\xFE\xF4\xFC\xF9\xF9\x00\xB5\x71\x81\x66\xF6\x5B\x63\x82\x81\x02\x89\x84\x83\x81\xA2\x4C\x85\x7A\x83\xA5\x4B\x09\x7E\x7F\x06\x4C\x03\x86\x79\x0D\x17\x80\x87\x7A\xD8\x5D\x8C\x76\x41\x0E\x1A\x87\x67\x03\x13\x90\x03\x85\x04\x13\x92\x02\x8B\x82\x0A\x88\x8C\x8B\x8B\x2E\xB1\x8D\x81\x8B\x33\xB0\x85\x8E\x8C\x0F\xB4\x89\x8E\x8D\x3B\xB8\x88\x7A\x8E\x3F\xBC\x81\x92\x8F\x1C\x9F\x8E\x86\x7E\x47\x94\x89\x91\x81\x37\x8D\x9D\x8E\x93\x43\x90\x95\x90\x92\x46\x95\x94\x97\x95\x4A\x96\x99\x94\x96\x4C\x8F\x90\x6B\x04\x2B\x84\x9D\x7C\x05\x61\x92\x9D\x7D\x97\x51\x9E\x99\x9B\x9A\x53\x9B\x9E\x98\x9A\x6D\xB0\x97\x9B\x86\x73\x80\x91\x9C\x9D\xFF\x76\x95\x9E\x90\x77\xBA\x99\x9C\x9F\x0A\x55\x05\x9A\x9A\x7D\x80\xAF\x9E\x98\x87\xA6\x99\xA0\xA1\x7B\x91\x66\x07\xA0\x6C\x8D\xAA\xA3\x7E\x72\x8B\xA1\xA6\xA5\x85\x88\xA4\xA4\x9E\x9B\xBE\x9D\xA6\xA1\x9F\x9A\xAB\x90\xA7\xA3\x9E\xA5\xA8\xA8\x49\x97\x00\xA5\xA6", + "\x93\xA7\xA2\xAA\x96\x95\xA1\xAD\xA8\xAC\xA4\x82\x48\x07\xAA\x92\x8C\xA8\xA5\xAE\x97\xB2\xAA\xAE\xAF\xBD\xAE\xA3\xAC\x97\xB5\x84\xB6\xA8\xAD\xC7\x86\xB8\xA8\xB2\xCB\x8A\xBF\xA9\x40\x19\x38\xA9\x42\x43\xCC\x7D\x7B\x06\xB4\xC0\xAC\xAF\xAF\x40\x1C\x18\xB3\x41\x07\x13\x9E\x03\x84\x44\xC7\x46\x40\x0A\xB7\xCC\x8F\xBF\x99\xB1\xEB\x89\xBD\xB9\xB3\xEF\xAA\xB1\x08\xBA\x58\xA2\x04\xBD\xBC\xC3\xB8\xBB\xB5\xBA\xF9\xB1\xA2\xB3\xBE\xCE\xBD\xB9\x7B\x08\xF7\xA4\x07\xBE\x44\xE5\xBF\xB1\xB0\xBF\x00\xC0\x06\x0B\xBD\x27\x13\x84\x45\xC2\x02\x69\x03\x86\x0A\xF7\xBE\xBC\xC3\xC2\x01\xCD\xCA\xC5\xC7\x1C\xFA\xB5\x6B\x0A\x19\xEC\xBF\xC6\xC8\xDA\xA1\xC7\xCA\x79\x2C\x25\xCE\xBB\xCA\x26\xF1\xCF\xCA\xCC\xF0\xB0\xC3\xCF\xCD\x35\xF4\xCA\xBA\x45\x14\xE0\xC9\xCB\xCF\xBC\x80\xDB\xAF\xD0\xFB\x6E\x0E\xC9\xCE\x38\xEA\xB6\xCC\xD2\x4C\xCA\xDA\xCE\xC0\x49\xD0\xDD\xD2\xD4\x4E\xD1\xDE\xC4\xBB\x2F\x07\xDA\xB8\x0C\x5A\xD4\xDE\xD7\xD5\x56\xEA\xCF\xD0\xD8\x53\xE4\xD5\xD5\xD9\x62\xEE\xB1\x0D\xD7\x66\xDF\xD9\xD8\xDA\x42\xD9\xB1\xD3\xDC\x44\xCA\xC1\xDE\xDD\xFD", + "\x72\x0C\xDB\xDB\x67\xFD\xDE\xDB\xDD\x1B\xC0\xEE\xCC\xDD\x72\xF5\xD1\xE1\x7F\x33\x3B\xD2\xE0\xCA\x84\xF8\xD6\xE3\xE0\x8F\xCC\xE1\xE7\xD2\x7E\xED\xD6\xE4\xDF\x7F\xCD\xE7\xE1\x42\x34\x0A\xEA\xE4\xE4\x85\xE1\xEE\xE2\xE8\x9B\xE4\xE0\xEB\xE8\xA8\xE5\xE3\x41\x0D\xF7\xB6\x07\xBF\x0D\x9E\xD3\xEC\xB8\x0E\xF7\xB9\x03\x86\x0E\x13\xBB\x03\x84\x0F\xB1\xE6\xE2\xE6\xEF\x94\xD5\x6D\x0F\xBD\x3E\x37\xBF\x0D\xEF\xA9\xE7\xE2\x40\x10\xF7\x81\x13\x86\x10\x13\x98\x4D\xCC\x00\x44\x08\xFA\xEB\xF5\xCA\xD9\xFF\xED\xF2\xDB\xD8\xFD\xF6\xF6\xC1\xD7\xEB\xE1\xF8\x98\xE2\xFF\xE6\x9B\x45\x37\xB6\x13\xBD\x47\x16\xF0\xF8\xBB\x48\x37\xBA\x47\xF4\x4A\x13\x8B\x13\x84\x4C\x2E\xF0\x01\x13\x13\x8E\x1A\xFC\xF9\xE3\x63\x6D\xF9\x03\x81\x81\xB0\x45\x80\x6E\xE7\x6F\x0B\x84\x50\x0F\x7E\x01\x87\x85\x72\x04\x87\x7C\x00\x92\x8E\x80\x0A\x86\x86\x82\x08\x92\x77\x65\x51\x07\x5E\x29\x37\x5B\x0A\x0D\x97\x83\x78\x54\x07\x5F\x2A\x13\x46\x0A\x13\x57\x0B\x84\x58\x01\x85\x0C\x80\x7D\x82\x1A\x8E\x84\xF7\x13\x81\x86\x08\x8F\x81\x73\x35\x98\x87\x0B\xEE\x59\x0B\x7B\x5A\x0F", + "\x5E\x5B\x0D\x86\x0D\xFD\x3C\x0B\x7B\x5D\x0B\x42\x5E\x13\x43\x17\x13\x40\x0C\xFD\x61\x0B\x42\x62\x02\x8A\x0E\xB3\x80\x87\x1D\xB2\x86\x7B\x34\x96\x8B\x10\xB9\x86\x7C\x2E\x91\x86\x8B\x37\x9D\x8A\xEF\x63\x02\x8A\x31\x94\x8F\x32\x64\x13\x41\x19\x65\x8F\x8A\x2D\x93\x88\x8B\x55\x87\x8F\x15\xEF\x72\x84\x37\xA6\x88\x8E\x75\x83\x22\x19\x77\x57\x0D\x7B\x68\x0C\x8D\x61\x85\x35\x1A\x77\x5A\x0D\x09\x6B\x0B\x42\x6C\x13\x41\x1B\x00\x98\x83\x2D\xB6\x8D\x8D\x72\x8E\x91\x24\xEF\x84\x8F\x39\x9F\x78\x00\x6E\x0C\x90\x18\x8D\x94\x93\x4B\x99\x8B\x92\x77\x95\x92\x24\xF8\x86\x93\x4F\xA4\x93\x94\xA2\x9D\x92\x29\xA9\x9D\x61\x37\x1A\x97\x91\x81\x91\x94\x27\xA1\x9E\x93\x38\xA7\x92\x95\xB6\x8C\x94\x24\xB7\x94\x97\x55\xB5\x91\x8F\xBC\x9B\x96\xF6\x70\x0F\x95\x81\x31\x0D\x98\xC1\x92\x97\x26\xCB\x90\x97\x59\x82\x9F\x97\xA5\x99\x94\x34\xA8\x93\x9A\x5C\x80\x9A\x97\x6D\x52\x0C\x32\xD8\x9E\x98\x65\x8D\x99\x21\x73\x0A\x20\x6C\x63\x36\x0E\x71\xBD\x39\x0F\xE6\x8C\x98\x28\xA5\x3C\x0F\x74\xBB\x3F\x0F\xEE\x83\x22\x20\x71\x92\x21\x42\x34\x99\x20\x88\x17", + "\x9D\x35\xBD\x92\x9A\x5F\xBE\x9D\x9F\x00\xB7\x9B\x3E\xCF\x9F\x9E\x81\x85\xA1\x9A\x06\xA1\xA0\x42\x8B\xAA\x5D\x45\x1B\x98\x00\x8C\x0F\xA3\x41\xD4\x9E\x97\x46\x12\xA2\xA1\x14\xB8\xA2\x35\x8C\xAB\xA3\x8C\x89\xA7\x32\x8E\x17\xA3\x47\x96\x9F\x10\x91\x9C\xA4\x9F\x23\xBE\xA3\x49\x84\xAA\xA2\x5A\x90\x17\xA1\x91\x06\xA6\x4A\xB3\xAD\xA3\x9A\xA8\xA3\xA5\xDE\x8B\x9D\x4E\xC9\x9D\x9B\x9E\xA3\x3A\x12\x13\x53\x12\x4C\xB6\xAC\xA5\x94\x84\xAB\xA7\x58\x54\x13\x50\xB7\xA4\xA6\xA6\x87\xAE\xA7\xDF\x91\xAA\x4E\xD0\xA3\xAA\x75\xBC\xA6\xAA\x01\x35\x13\x43\x96\x1B\xA9\xA2\xB8\xA7\x7C\x97\x1D\xA8\x52\x83\xA3\xAD\x89\x8F\xA8\xAB\x64\xA7\x7C\x26\x62\xA4\xAA\xEF\x59\x14\xAD\x68\xA6\xAE\x53\xF3\xAE\xAB\xA6\xB5\xA9\x5F\x9A\x0F\xA3\x26\x70\xA2\xAB\xAB\xBD\xAC\x9B\x71\xAD\xA7\x5D\xF4\xA5\xAC\xC1\x85\xB6\x5D\x9C\x13\x41\x27\x7C\xA5\xAB\xBF\xA9\xA9\xB0\x02\xBE\x10\x63\xFE\xAD\xB1\xCA\x94\xB7\xB2\x80\xAE\xB3\xC9\x1F\x13\xB3\xCC\x96\xB6\xB3\x98\xAF\xB3\x7E\x20\x1D\xB2\xD1\x9F\xB7\x92\xA1\x05\xB6\x5C\x83\xBC\xB5\xC3\x9F\xA8\xB2\xAF\xA6\x22\x28\x2A", + "\xB6\xB1\xFE\x23\x14\xB6\x46\xA4\xB1\x5B\xA0\xBC\xB6\xD3\xA1\xB6\x3C\xA4\x0F\xA1\x29\x38\xB1\xB7\xD3\xAB\xB6\xB5\x76\xA8\xBB\x59\x9A\xB5\xB6\xD8\xAA\x5E\x14\x13\x47\x14\x71\xC9\xBB\xB6\xDF\xBD\xB7\xB8\xD5\xB8\xBA\x73\xCB\xB9\x48\x54\x13\xBC\xBB\xBF\xAD\xB8\x73\xB9\xBD\xB5\xEC\xA2\xBE\xB8\xE7\xA1\xBC\x79\x8B\x79\x15\x09\x6A\x17\xBB\xBA\xBB\xB9\x7C\x8E\xBB\x14\x7D\xA6\x3E\x15\xF6\xA9\x3D\x2C\x79\xBB\xBD\xF3\x74\x14\xBF\x99\x37\x16\x3E\xBA\x1A\x9F\x5E\x3A\x98\x18\x00\xD4\xBA\x7C\xE5\xBB\xC0\xE5\xA0\x33\x18\x13\x44\x18\x7C\x8C\xCB\x3F\x62\x13\xC6\xC1\x14\xC8\xBD\x7F\x8D\xC6\xBD\x0D\xE3\xBD\xB8\xEA\xA0\xC7\x75\xE9\xB1\x20\x63\x17\xC5\xC3\x22\xD6\xBA\x8A\xDA\xBF\xC2\x05\xFE\x77\x18\x27\xDC\xC2\x8C\xAD\xC0\xBD\xDE\x88\x1F\xA1\xC9\x11\xC4\x8D\xF3\xBA\xC3\x14\xEC\xC3\x20\xCA\x0F\xA0\x21\x2C\x36\x21\xDC\x23\x2C\x26\x46\xC4\x30\x92\xE1\x2B\xC9\x23\xEB\x21\xC9\x9D\x2D\xCA\x92\xCF\xCC\xC9\x95\x04\xCE\x20\x12\x43\x2C\x94\xA4\x32\xCB\x28\xD4\xCE\xC9\x28\x37\xCB\x40\x78\x3A\xCB\x2A\xE8\x23\xCB\xDE\x3D\xC8\x97\xD6\xCA\x20\x32", + "\x65\xC8\xCC\x25\x28\xCF\x79\x6A\xC9\xCC\x36\xC9\x21\xCB\x84\x32\xCC\x4D\x74\xC3\xCF\x2F\xD3\xC9\xCC\x0A\x38\xCD\x67\x7A\xCB\xCF\x33\xE6\xC9\xCE\x87\xC1\x26\x98\x82\x29\x42\x4B\x74\x26\x38\x06\x31\x5B\x9B\xFF\xC8\xD0\x38\xE1\x24\xD0\x85\xCA\xD2\x42\x4B\x3A\x61\x47\xCA\x26\x44\x93\xDE\xC8\xA0\xF7\xC1\x2D\x45\xC1\x24\xCC\x84\x26\xD4\x00\x6E\xC9\xD5\x40\xE5\xD6\xD5\x63\x2A\xD5\xA3\xC0\x5E\xD3\x84\x12\xD5\xD5\x09\x3C\xD3\xC6\x35\xD6\x20\x50\xF4\xD3\x25\x90\xC3\x22\xBD\x63\x20\x38\x4B\xE0\x25\x39\x02\x28\xDA\x77\x41\xD2\x20\x30\x44\xD9\xD1\xC7\xCA\x22\xAA\xBC\xD3\x20\x67\xC4\x35\xD8\x94\xD7\xD0\xB4\x9F\x28\xD3\x4C\xDC\xDB\xDB\xFF\x1D\xDA\xB7\xE2\xD9\xD2\x72\xC5\xD6\xDC\x7B\xCA\xD6\xA0\xA4\x38\xDC\x3E\xDE\xDA\xDB\xC6\xDF\x22\xAA\xA8\xD3\xD0\x70\xED\xDE\xCF\xA2\xC5\x26\xAA\xAC\xD5\xDF\x78\xE1\xDE\xDE\xE0\xCA\xDD\x58\x77\xD6\xD0\x7F\xC4\xE2\xDF\xB0\xD9\xCC\xC0\x86\xE1\xE0\x85\x33\xD5\xD3\xC0\xCA\x23\xAD\xFD\xD9\xDA\x90\x07\xE0\xDE\x15\xF2\xDF\xA6\xBC\x54\xDA\x81\x3E\xD4\xE2\xF9\xD8\xE1\xC8\x96\xEB\xE1\x8C\xFF\xDC\xE1", + "\x28\xE6\xE6\xC0\xA1\xDB\xCD\x82\xE6\xE7\xE2\x20\x33\xDF\xC0\xA5\xE3\xE5\x6F\xFE\xDB\xDF\x33\xE9\xE5\xCD\xA7\xEA\xE5\x84\xE0\xE5\xE5\x95\xCF\xE5\xC3\xA4\xDC\xE5\x3A\xEE\xE3\xE7\x30\xFA\xE1\x42\x0F\xEB\xD7\x88\xF6\xD1\xE7\x42\xFA\xE4\xD0\x9A\xD9\xD6\x8E\xCE\xED\xD7\x61\x38\xDB\xCE\xDA\xE3\xEA\x28\x5D\xE1\x20\xB7\x4F\xDA\xBF\xCA\xDC\x27\xAF\xC0\x06\xDA\x9D\x3C\xEA\xD1\xA5\x2A\xED\x3E\xE8\x25\xED\xEF\xC4\xE6\xD4\xEB\xE2\xE5\xAE\xF6\xE1\xEA\x78\xE8\xEB\xD0\xD8\xC0\xEA\xBD\xF3\xEE\xED\x08\xE9\x20\xBD\xEC\xD4\xE6\xBB\xFC\xE3\xE7\x38\xE5\xE8\xE0\xF5\xE4\xEE\xB9\xFD\xE4\xE8\x0A\xFF\xED\xDC\xF7\xE8\xF0\x9F\xC4\xF2\xF2\x93\xE9\xEB\x3F\x32\xD6\xEA\x94\x0C\xD8\x5A\x7D\xE6\xF2\xE6\x9A\xFA\xD4\x5D\xE0\x66\xEC\x1F\xF7\xF1\xDE\xA2\xFB\xEF\x81\x2B\xDE\x3B\xA4\xEA\x23\xE0\xB0\xFD\xF4\x81\x3C\xDA\xF5\x95\xF0\xF3\xCF\x8D\xFA\xE8\xBE\xCA\xF3\xF2\x9B\xEE\xE1\xE7\xA5\x2F\xF2\x00\x13\xE0\xF7\x86\xE5\xF7\xF0\xA1\x25\xF9\xD4\xF4\xF7\xE6\x96\xFE\x3A\xCC\xB1\xDD\xCD\x57\xFA\xF4\x34\x2B\xF8\xD6\x41\x4C\xE7\xF5\xAB\xC3\x27\xF8\xD2\xFB\xE2", + "\xA3\xDE\xFE\xE3\xAC\xE0\xD8\xEE\x93\xE3\x9C\xD6\xE3\x25\xF8\x71\x62\xEE\xE4\xE8\xF1\xEE\xFA\x83\x2E\xF9\xF3\x2D\xF9\xF4\xBC\xE7\xF0\xEB\x98\xF1\xEF\xD8\xD7\xFF\xF9\xAB\x79\x7F\xD3\x71\x79\x01\x8B\x78\x31\x75\x7D\xBF\x79\x79\xB5\x71\x10\xAF\x77\x1E\xA3\x7B\x80\x00\x0D\x80\xEE\x6A\x80\xD0\x7B\x74\xCB\x70\x12\xC5\x70\x7E\x0E\x85\x78\x02\x82\x7E\xBF\x6E\x79\x9F\x68\x7F\x06\x84\x79\xFB\x7F\x78\xBE\x74\x80\xB9\x76\x10\xB3\x7B\x81\x15\x86\x10\xB7\x70\x80\x29\x8E\x7A\x22\x80\x7C\xD9\x7B\x7B\x23\x81\x7C\x16\x83\x7E\x20\x8F\x74\x09\x81\x77\xCA\x7A\x83\xC4\x71\x82\xEF\x7B\x75\xE0\x63\x7F\x3C\x1B\x6C\x47\x87\x6D\xE7\x75\x84\x49\x8D\x19\xC5\x74\x17\x0F\x8C\x7F\xEF\x61\x85\x05\x80\x7C\xFE\x77\x82\x36\x86\x85\x1C\x87\x83\x03\x89\x85\x14\x85\x85\x93\x79\x78\x28\x85\x82\x7E\x76\x82\x32\x8D\x83\x53\x8B\x85\x34\x81\x7D\x2C\x80\x86\xFD\x70\x81\xDC\x72\x32\x66\x7A\x81\x13\x8F\x86\x52\x8E\x6D\x3F\x8F\x81\x41\x89\x10\xF5\x74\x13\xF1\x7F\x6E\xAA\x64\x76\x68\x26\x76\xD3\x60\x21\x66\x76\x84\xDE\x1F\x87\x78\x8A\x10\x16\x28\x86\xE3\x6A", + "\x86\x5F\x81\x83\x02\x1A\x88\x8E\x75\x86\x96\x84\x86\xC9\x7A\x10\x21\x2E\x88\xE5\x60\x89\x76\x86\x86\x02\x1D\x88\x63\x89\x7F\x54\x82\x89\x0C\x86\x7D\x06\x14\x89\x24\x84\x8A\x9E\x80\x88\x6C\x84\x13\xAA\x6B\x89\xA3\x87\x83\xA5\x89\x89\xFF\x77\x1E\xAA\x62\x8A\x5E\x8F\x89\x97\x8D\x81\x82\x78\x8A\x03\x1A\x8A\xFA\x7C\x8A\x77\x89\x69\x5D\x88\x7D\x9A\x83\x83\x91\x88\x89\xBE\x8A\x82\xC0\x81\x8A\xCA\x8C\x8B\xCC\x8C\x85\x08\x8A\x7D\xC1\x81\x8D\x69\x85\x8C\x85\x62\x86\x9D\x11\x8B\xD8\x8F\x88\xDA\x89\x6E\xD5\x8D\x8D\x8C\x8F\x8D\x9D\x81\x8E\xB0\x8F\x8A\x76\x69\x8A\xE6\x87\x6E\xAD\x8B\x88\xB7\x89\x8E\x09\x12\x8B\xBB\x89\x8D\x6E\x8E\x8A\xF1\x8B\x8E\x03\x1A\x8B\xC8\x74\x8C\xF7\x80\x8F\x58\x88\x8C\x09\x12\x8C\xB5\x8E\x8F\xA6\x81\x81\xCF\x81\x10\xF4\x8D\x8F\xB4\x8F\x8E\xC6\x8A\x8E\xA3\x65\x21\xED\x8B\x67\x05\x94\x8D\x39\x8A\x87\xCC\x72\x71\x09\x90\x00\x04\x9E\x90\xEE\x8D\x82\x03\x11\x87\x83\x84\x7E\xA0\x74\x7D\xF3\x83\x91\x75\x86\x8F\x07\x92\x92\x86\x84\x92\xC6\x7B\x91\xFC\x80\x83\xD3\x8A\x85\x20\x97\x10\x17\x8F\x11\xCD\x7B\x91", + "\x1D\x98\x8E\xF8\x66\x8B\x06\x16\x7A\x72\x8E\x92\x7D\x8A\x8F\x02\x1B\x90\x32\x96\x90\x33\x91\x86\x1E\x80\x71\x3B\x8B\x7E\x18\x98\x81\x0A\x1A\x2A\x43\x8E\x93\x03\x12\x88\x2D\x9D\x94\x03\x15\x88\x11\x95\x95\x37\x9F\x0F\xC5\x7A\x95\x6C\x70\x6E\x74\x16\x76\x2C\x9F\x76\x10\x86\x95\x40\x24\x88\x1B\x98\x96\x42\x2A\x96\x53\x99\x7F\xC2\x82\x8F\xD5\x20\x84\x19\x99\x10\x60\x94\x75\x73\x9F\x94\x38\x92\x6D\xE6\x75\x93\x01\x14\x22\x74\x90\x95\x09\x10\x2E\x26\x92\x91\x9C\x8F\x91\xFF\x87\x8E\xA0\x81\x10\x3B\x99\x98\x88\x9D\x8B\x16\x90\x22\x28\x9D\x93\x48\x95\x99\x91\x9B\x8F\x93\x97\x74\x49\x9E\x83\x10\x91\x78\xEC\x87\x98\x14\x9E\x91\xE2\x89\x8F\x5B\x95\x94\x99\x91\x74\x90\x9B\x86\xA4\x9E\x99\x98\x90\x9A\x29\x90\x8E\x8B\x90\x00\x2B\x82\x97\xD7\x8E\x9A\x94\x9D\x90\x7E\x92\x9B\x1B\x96\x94\x6D\x89\x9A\xCB\x8D\x8C\x63\x60\x93\xA7\x9C\x78\xB8\x91\x9B\x2F\x88\x8B\xBF\x13\x9C\x95\x8B\x99\xF8\x8E\x82\xBB\x9A\x9C\xAB\x85\x9C\x07\x97\x9C\xB4\x90\x8D\xB6\x9A\x99\x96\x9A\x9A\x01\x91\x7E\x03\x90\x9D\xC3\x82\x9D\x54\x92\x10\x12\x84\x94\x0A", + "\x9E\x9D\x15\x9A\x9D\x67\x86\x8D\xD6\x93\x8B\x34\x9E\x98\xA3\x9B\x9D\xC8\x9D\x9D\xD7\x98\x9A\xCC\x90\x90\xE9\x94\x8E\x27\x93\x9F\xC4\x9D\x9E\x07\x93\x9E\xA5\x91\x10\x31\x9D\x9B\xF5\x9A\x98\x2B\x9D\x95\x19\x8A\x93\xE6\x92\x9A\xD5\x91\x10\x65\x9D\x96\x2E\x94\x87\xE4\x90\x00\xBC\x9F\x9A\x04\xA3\xA0\xDB\x82\x7C\x81\x9B\x97\x3C\x8A\x9E\x00\xA9\xA0\x3C\x9F\x9F\x04\x16\xA0\x42\x8C\xA1\x1C\x9E\xA1\xEE\x9B\xA0\x21\xA9\xA1\x5E\x93\xA2\xF8\x92\x99\xFA\x9B\x9C\xD9\x9A\x94\x55\x7A\xA2\x39\x9F\x96\x97\x92\x10\x2A\x25\x98\x03\x10\x98\x7A\x9B\xA2\x83\x9D\x97\xB1\x9C\xA3\x4C\x9B\x87\x06\x14\x98\x4A\x89\x9B\x42\xAD\x74\x58\x92\x10\x46\xAE\x84\xE3\x84\x1A\xBD\x16\x72\x51\xAB\x73\x53\xA6\x78\xC5\x79\xA3\x84\x15\x7C\x28\x23\x16\x55\xA9\x7F\xC5\x74\x2E\x59\xA0\x29\xC5\x7F\x28\xEC\x75\x8E\x65\xA9\x10\xD7\x27\xA6\x06\x12\x28\x6A\xA3\x10\x6C\xA1\xA6\xAB\x95\x97\xF0\x96\x76\xD4\x2E\xA4\xD3\x21\x16\xC5\x7D\x2D\x6D\xA2\x10\xE7\x2B\xA7\x01\x1D\xA7\x70\xA6\x2E\x61\x1B\x0B\x64\x73\x21\xAA\x68\x88\x3C\x14\x76\x87\xA8\x1B\x4D\x89\x6C\x7C\x99", + "\x10\x88\xA3\x12\x8A\xAA\x4F\x92\xAF\xA8\x06\x11\xA9\x86\xA4\xA9\x99\xA0\xA9\x8D\xA1\x10\x93\xAC\xA9\x09\x12\x67\x5D\xA5\xA2\x09\x13\x1C\xD3\x3B\xA8\xA5\xAB\xA9\x97\xAC\xA8\xA9\xA7\xAA\xFA\x46\xAA\x79\x99\x95\xAF\xAA\xAA\x03\x18\xA8\xB0\xAC\x95\x76\x93\xAB\xAE\xA0\xAA\x06\x17\xAB\x8E\xA9\xAB\xBC\xA3\x10\xC5\x7F\xA9\xAB\xA9\x10\xC3\xA6\xA9\xB5\xAC\xAA\x06\x17\xAC\xC0\xA5\xAC\xCB\xA4\xAB\x02\x18\xA8\xCC\xA6\x10\xA8\xAF\xAC\xBB\xAE\xAC\xC2\xA0\xAD\x01\x12\xAD\xDA\xA0\x00\x88\xA0\x94\xC4\xA9\xAC\x33\xA1\xAB\x02\x15\xAD\x03\x12\x67\xE0\xA8\xAC\xD1\xAB\x94\xBF\xA4\xAD\xFA\x49\xAE\xCD\xA2\xAE\x3F\x9D\xAD\xDF\xA4\xAF\xEC\xAE\xA9\xEA\xAB\xAD\xFA\x48\xA8\x72\x68\xA8\xFE\xAB\xAF\xFA\x4B\x82\x2B\x82\x67\x02\xB2\x7B\x06\xBF\x8B\x08\xBE\xAE\xC1\xA5\xAE\xFA\x42\x67\xE6\xAC\xB0\x0B\xB1\x10\x0F\xB2\xB1\xFA\x43\xB1\x00\x06\xB1\x0D\x88\xA8\x19\xBA\xAC\xF7\x9B\xAE\xB7\x8A\xB1\xFA\x4B\xB1\x1F\xBC\x86\x88\xA1\xAE\x1E\xB4\xAE\x14\xB1\xB1\x00\x02\x67\x26\xBA\xAF\xD7\xA2\xAF\xB8\xAA\xB0\xD8\xAD\xAE\xB2\xAA\xB2\x2D\xBE\xAD\xF6\xA9\x10", + "\x01\xA7\xB3\x88\xA1\x87\x3C\xB9\x8C\x2F\xB7\xB2\xAD\x98\xB2\x17\xBD\xB0\x18\xA4\xB4\x16\xB2\x67\xBC\x9F\xB3\xA1\xA6\xA6\x48\xBA\x4F\x3E\xB9\xAF\x38\xB9\x9F\x4F\xBA\xB2\x3B\xB2\xB5\x3D\xB9\xB3\x2E\xA5\xB5\x33\xBD\xA1\x41\xBE\xB2\xDB\x7A\xB5\x03\x1B\xB4\x58\xBE\xB4\x31\xB5\xB3\x5D\xB0\x00\x51\xB1\xAF\x42\xB6\x9A\x5F\xB3\xB5\x86\x9C\xB5\x30\xBC\x68\x62\xBE\xB6\x72\xBD\xB6\x5E\xB7\xB7\x60\xB1\x92\x75\xB5\x9E\x6F\xB8\xA8\x49\xA1\x10\xF5\x7B\xA5\x06\x18\xA5\xD5\x6F\xA4\x01\x1F\xA6\x43\xB7\xB6\x10\xB9\xB6\x8A\xB4\xB7\x7F\xB1\x28\x40\xBA\xB7\x70\xBE\xA6\x66\xB4\xB3\x8D\xB3\xB7\x01\x12\x67\x8F\xBC\xA0\x7D\xBB\xB2\x92\xB4\xB5\x8C\xB9\xB2\x69\xBC\xB9\x97\xB8\xAF\x6C\xBB\xB7\x02\x1D\xB9\x6A\xBF\xB9\xAC\xB4\xB6\xA9\xB5\xB9\xAB\xB7\xBA\xA6\x15\xB6\x09\x1C\xBA\x6B\xB2\xB3\x9A\xB0\x00\xAF\xBE\xBA\xB4\xBC\xB4\x6B\xA7\xB4\xA3\xB5\xB4\x2A\xBD\xBB\x91\xB7\xBB\xBF\xB6\xBB\xC1\xB7\x91\xC3\xB6\xB1\xC6\xB4\xB9\x88\xAC\xBA\x57\xB1\xBB\xD1\xB2\xBC\x98\xB4\xBA\xBB\xBF\xBC\xCD\xBA\x4F\xD2\xBE\xBB\xCC\xB7\xBD\xC4\xBE\xB8\x93\xBB\xBD\x2A", + "\xB4\xA6\x06\x12\x95\x06\x11\x76\x91\x6C\xB1\x02\x12\x67\x23\x1E\x06\xA6\x64\x76\x88\xA1\x31\x9D\xAF\x06\xF1\xB2\xB5\x06\x3D\xA9\x70\x07\xBF\xD3\x3E\x7E\x8D\xA1\x07\xFC\xBD\xA8\xAC\xBD\x26\x23\x1B\x82\x04\xC4\xBB\x6D\x2A\xB4\x9D\xA0\x00\x72\x01\xC0\xE7\xAC\xA2\x49\x83\x07\x0E\xCD\xBE\x0A\x1A\xBE\x4D\x84\x07\x13\xC8\xBA\x45\xAB\xC0\x75\x09\xC1\xE1\xB2\x6C\x0B\xC6\x07\x1E\xC2\x67\xBC\x3D\xA9\x77\x03\xC2\x0A\x13\x3C\x9D\xA8\x07\x28\xC9\x10\xC5\x3D\xA9\x79\x0E\xC1\xA3\xAD\x39\x9D\xAA\x07\x32\xCA\x10\x34\xCD\xA8\x7B\x07\xC3\x09\x1A\x3B\x9D\xAC\x07\x3C\xC6\x10\x3E\xCD\xA8\x7D\x01\xC4\x03\x10\x3D\x9D\xAE\x07\x46\xC2\x10\x48\xCD\xA8\x7F\x0E\xC1\x6D\x7D\x3E\x9D\xA0\x08\x1E\xCE\xAB\x01\x17\x3F\x9D\xA1\x08\x55\xCA\x10\xF9\x3D\xA9\x82\x0B\xC5\x09\x1D\xC5\x8D\xA3\x08\x1E\xCB\x0C\x0B\xCA\x6A\x63\x5A\x6A\x1A\x8B\xC0\xA0\xB3\x1E\x23\x1E\xB0\x52\xBF\xC6\xEC\xB8\x25\xA2\xA2\xB5\x71\x83\x12\xC5\x78\x6E\xCA\x13\xC7\x1F\xC2\x10\x56\xCC\x13\x01\xAA\xC7\xD6\xBB\xB9\x52\xB0\x94\x23\x15\x7F\x82\xC9\x10\x84\xBF\xC0\xB1\xBD\x80\x23\x17", + "\x9C\x89\xCB\xBC\x45\x62\xB5\x86\xB9\x84\x16\xC4\xC1\x09\x1A\xA7\xBA\xB2\x10\x1A\x80\xC7\x09\x16\xBE\x4D\x8E\xBF\x8C\xC6\x10\xC3\x6B\xC9\x01\x1D\xA4\x98\xC9\xB6\x85\xA5\x5D\xFD\xAB\xC0\xBE\x43\xAA\x6B\xCA\x10\xF9\xB4\xB4\x27\x33\xAA\x68\xC1\x11\xF7\x23\x2F\xD3\x33\xAA\x77\xCA\x10\x0F\x33\x3D\xB5\xCA\x10\x7F\xC3\x12\xF4\xB4\xCB\xEC\x23\xAA\x86\xC3\x11\xFA\x33\xAA\x8E\xCA\x10\x16\x30\xCC\xC7\xCA\x10\x95\xC7\x84\x18\x33\x3D\x24\x31\xBB\xE6\x13\xAA\xA0\xC9\x84\x3C\x34\xB4\x46\x38\xCD\xE9\x1F\xC7\x4F\x8D\x1F\x5C\x30\xCE\x97\x15\x7C\x6D\x73\x12\x7A\x30\xCD\xEE\x20\x94\xB7\xC1\x39\xA5\xC3\xBC\x2B\x89\xCE\x0A\x19\x38\x2A\xB7\x32\x0D\x8F\xCE\xBE\x34\x30\xD3\x31\xA0\xF4\xC9\x10\xAE\x37\xCF\xEC\x21\x87\xB1\xC9\x10\xB6\x3D\xB4\xE3\x13\xCB\xA3\xCC\xB7\xB1\xB3\x12\x2A\xC3\xC9\xE3\x13\x31\x06\x1C\xCB\x83\xCC\x13\xCE\x38\xD0\xFB\x1D\xCD\x0B\xD0\xB9\xBD\xAB\xC0\xE9\x38\xD1\x49\x2B\x36\x20\xDC\xD1\x03\x19\xCC\x09\x13\x3F\x10\xDB\x1F\xAC\x33\xD2\x9E\xB7\x8B\x23\x1C\x3F\x2C\xDE\x26\x07\xD9\xD2\x0C\xD5\xB8\x0B\xCC\x41\x31\xD6\x42", + "\xB1\xBF\xD0\x1B\xDD\xD2\x06\x1B\xCD\x47\x8A\x42\x31\xD1\x44\xB1\xB7\xD1\x34\xD6\xB7\x03\x1B\xC8\x49\x8E\x4B\xBC\x91\xB8\x65\x72\x4D\x4E\xD5\xD0\x06\x17\x44\x31\xD6\x1E\x1F\xD7\xD4\x7F\x91\xC7\x0A\x1F\x44\x55\xD9\x1E\x28\xD3\x10\xA3\xAE\xD4\xBD\xC9\x10\x6B\x4D\xD5\x97\x1E\x3F\x31\xDE\xD4\xC3\xCA\x10\x83\x46\xD6\x99\x1E\x41\x69\xD7\xAF\x3C\x1B\x48\x6E\xD1\x19\x28\x41\xD7\x2E\xDA\x10\xC7\x45\xD7\x95\x1F\x43\x78\xD6\xD3\x9D\xA5\x07\x7C\xC8\x4E\xB1\xB9\x44\x7F\xD3\x10\x40\xDC\x13\x7B\x0C\xC7\xF0\x41\xBB\x51\x41\xD3\x83\xBE\xCA\xD2\x4A\xD4\x8C\x9B\xC0\x81\x0A\x3F\xD3\xC4\xAA\x8D\xA3\x4F\xEC\xC0\x2F\x99\xD8\x76\x4B\xD2\x4D\xA0\xD1\x10\xC7\x9D\x26\x83\x02\xB5\xE6\x17\x9C\xFF\xC6\x10\xF6\x4D\xD9\xEA\x2C\xBA\xAB\xD3\x10\x86\x09\x60\xF9\x29\xD8\xB1\xD2\x10\x89\x0A\x3F\xE8\xB5\x9B\x8D\xAA\x08\xFA\x37\xC9\x01\x1B\xDB\xA1\xD2\x50\x1A\x82\xD5\x03\x1E\x50\x7C\xD0\x1A\x7B\x41\xD3\x1A\x8A\xCF\x03\x15\x52\xC9\xD5\x1A\x85\x4C\x1B\x1A\x9F\xBD\x47\x82\x54\xD1\xD3\x12\xAE\x4C\xDC\xC2\xCB\xC0\x61\x59\xDD\x0A\x11\x4E\xDC\xD3\xAE\x4D", + "\x8B\x57\xE0\xD9\x10\x77\x0C\xC7\x1A\x8D\xCC\x09\x1C\x59\xE7\xD6\x10\x8B\xD3\xDE\x80\xDD\xA8\xB7\x51\xD3\xD2\x51\xBB\x8D\xD8\xD5\x2F\x9F\xC9\x0B\xCD\x5E\x31\xDD\x0A\x52\xB7\xDA\x31\xD5\xA7\x9C\xCB\xC0\xAF\x08\xDA\xE9\x17\x08\x13\x24\xE0\xD8\xB9\x84\xFB\x56\xCE\x99\x19\x4F\xB1\xBC\xE0\xAD\xBD\xA9\xB3\x08\xE0\x97\x1E\xDB\xD3\x34\xE1\x6B\xD9\x10\xB5\x08\xE1\x99\x18\xDC\x44\xB4\xE1\x26\xD6\x10\x02\x60\xE1\x91\x11\x51\x1B\xEC\x86\x23\x19\x0B\x20\xE1\x19\x16\x5B\xE2\x09\x19\xD9\x23\x1B\x0B\x52\xB6\x60\xB1\xB1\x52\x32\xEF\xD3\x0B\xCF\x0B\x52\xB1\x0C\x52\xB0\xDD\x44\xBA\xC9\xDF\x7B\xC0\x10\x6E\xDA\x95\x1F\x52\xD3\x34\xE4\x99\xB9\x84\x12\x68\xE4\xA0\x11\x53\xB1\xBC\xE4\x3E\xDD\x84\x16\x60\xE5\xA5\x18\xDD\x43\xED\xDD\x9D\xA6\x62\x58\xE3\x12\x4A\x5B\xE4\x72\xD3\x12\x30\x6F\xE5\x0A\x1A\x55\x62\xE9\xD7\x09\x17\x63\x66\xE9\x10\x5C\x59\xE6\xF3\xDD\x84\x39\x63\x3D\x41\x61\xBB\xDF\xDB\xE5\xFC\xDD\xA9\xCC\x03\x21\xCD\x02\xB5\x6B\x53\x3D\xA8\xC1\x10\x69\xAD\xA8\xCF\x0A\x3F\x81\xE0\x00\x54\xEC\x13\xD0\x02\xB5\xD2\x07\x2F\xA2\xC2", + "\x10\x83\xED\x84\xD3\x0A\x3F\x8F\xE1\x10\x89\xE3\x12\xD4\x02\xB5\xD6\x07\x2F\x60\xA5\xE4\x9D\xA7\x0D\xB4\xD0\x1A\x6F\x51\xBB\x9D\xED\xE4\x47\x8A\x0D\xA1\xE5\x1A\xE6\xD9\xB6\xA5\xE5\xE5\x49\x8D\x0D\xA9\xE3\x12\x92\x54\xEA\x5C\xED\xA8\xE0\x01\xEB\x0A\x14\x5A\xB4\xE4\xDE\x49\x83\x0E\xB8\xE9\x10\xB3\x5B\xEB\xF0\x93\x12\xE6\x0F\xEB\x06\x11\x5C\xC2\xE3\x10\x34\xEA\x10\xE9\x0A\x4F\xEC\x02\xB5\xD0\x59\xEC\x02\x19\xD8\x23\x1E\x0E\xFA\x41\x0F\x52\xBE\x5D\xB1\xBA\xCB\xEB\xBD\xA9\xF3\x0F\xE2\x95\x1F\x5E\xDB\xEA\xD5\x09\x15\x0F\xE0\xE0\x1A\xAC\x0A\x4F\xDC\xE5\xD3\x4D\x87\x0F\xE7\xE5\x1A\x07\xE3\xEE\xAD\xAD\xA8\xF9\x0F\xEE\x23\x1F\xE0\xA6\xC0\x00\xEB\xE6\x93\x9D\xAB\x0F\xF6\xEA\x10\x17\xE2\xEF\xC3\xEA\x10\xFD\x0F\xEF\x1E\xE2\xB5\xFB\xE1\x10\xCB\xEE\x11\x52\xB1\x00\xCA\x6A\x6A\x27\xE9\xEF\x09\xF0\x00\xD4\xE2\x4E\x0F\xFA\x10\x05\x07\xF1\x09\x1E\xE2\xB1\xB1\xCF\x7C\xAB\xC0\x07\x0A\x6C\x6C\x9A\x2E\x1E\xF1\x10\xFC\xCD\xA8\x08\x0A\xF1\x2A\x82\xF2\xFD\x17\xF2\x03\x13\xF1\x63\x5A\xD0\x1F\xFD\xA9\x0B\x0C\xF2\x91\x32\xF3\x26\xFB\xC0", + "\x0C\x0A\xF2\x63\xB6\xF3\xFB\x18\x30\xDD\xED\xA8\x0F\x0A\x6C\x91\xC3\x10\x36\xEA\xB2\x40\xF8\xB6\x4D\x83\x01\x44\xFD\x1F\xBE\x0C\xC7\x49\xF4\xD2\x49\x87\x01\x4D\xF3\x1E\xC2\x0A\x4F\x51\xF1\x10\x1D\xE6\x10\x1B\x05\xF5\x15\x68\xF5\x63\xEA\x10\x1F\x0E\xF5\x49\x2C\xE6\x69\xB9\xF5\x08\x9D\xA9\x23\x04\xF6\x5A\x26\xC6\x48\xF2\xCD\x0B\xC7\x02\x6C\xF1\x10\x2B\x0C\xF3\x02\x1E\x0C\x60\xF9\xE7\x8D\xAD\x02\x73\xF0\x00\x31\x06\xF7\x01\x11\x0D\xFA\x45\xCC\x03\x1F\xCB\x8D\xA3\x03\x3E\xFC\x3D\x12\xD3\x10\x2D\x3D\xA9\x34\x09\xF8\x02\x15\x03\x80\xFE\x26\xD5\xC6\x10\xD7\xCD\xA8\xE6\x17\x03\x93\xF6\x1E\x97\xF3\x10\xCF\xCD\xA8\x39\x00\xF9\xDA\x3D\xF8\x06\x15\xF9\x4D\x8E\x4B\x1A\xD5\xE0\x9D\xAA\x03\xCA\x63\xAA\xE6\x19\xE9\x31\xD9\xFA\x25\x9D\xA8\x3F\x0D\xFA\xFD\x18\x0D\x7C\xC2\xFB\xFB\xDD\xA8\x44\x06\xFB\xE3\x1C\x0D\xB9\xF4\xEE\x06\x19\x04\xBE\xFB\x1F\xB7\xE4\xDD\x09\x1A\xFB\xCE\xD2\x10\x4E\x05\xFC\x49\x25\x0E\x18\xF5\x11\xC2\xF3\x10\x53\x0E\xFC\x5A\x2A\x0E\xD1\xF9\xFC\x15\xD3\x12\x58\x06\xFD\x58\x2F\x0E\xC1\xF6\xDD\x3C\x1D\x05\xDE", + "\xFE\x26\xDF\xE1\xFB\xDB\xFA\x10\x62\x05\xFE\xE6\x1E\xEE\xE8\xF3\xEF\x4D\x87\x06\xEC\xF9\x1E\xFE\xEF\xFE\x1D\xDD\xA9\x6C\x03\xFF\xF5\x11\xFE\xF7\xFF\xBF\xFA\xF9\x19\x03\x05\xEF\x7A\x7D\x12\x73\x10\x76\x03\xFF\x71\x0C\x21\x7E\xFE\x65\x69\x05\x6B\x07\x07\x81\x65\x15\x79\x0A\x84\xDF\x4D\x54\x40\x0E\x00\xA0\x0F\xD0\x71\x80\xA7\x45\x53\x45\x05\x0A\x85\x1A\x4C\x78\x06\x89\x7B\xBD\x6C\x03\xA3\x08\xAA\x7F\x01\xEC\x6E\x41\x0F\x04\x22\x82\x21\x1D\x7B\x0F\x8B\xF0\x06\x08\x25\x05\x7F\x99\x03\xF2\x63\x7A\x16\x8B\xC0\x1B\x05\xF9\x60\x05\x93\x7B\xED\x74\x81\x4E\x52\x0A\x65\x7F\x29\x13\x7C\x72\x7F\x03\x95\x79\x84\x09\x0A\x65\x7E\x2B\x13\x7C\x75\x7A\x08\x8B\x60\x58\x05\xFE\x35\x07\xE4\x6F\x01\x02\x82\x21\x03\x82\x13\x75\xFE\x3C\x07\xE4\x68\x7C\x31\x69\x6B\x09\x09\x72\x68\xF9\x69\x0E\x2F\x1B\x7C\xE9\x0C\x0B\x83\x09\x6F\x6D\xA8\x40\x06\xE8\x77\x24\x62\x82\x20\x22\x69\x2E\x82\x50\x6B\x83\x40\x16\x67\x6C\x86\x92\x2E\x82\x81\x04\xFA\x4D\x41\x30\x07\x83\xC2\x03\xF2\x5A\x7D\xE9\x1B\xCE\x06\x09\x1D\x8E\x72\x67\x85\x18\x13\x7C\x1C\x07", + "\x06\xF0\x83\x18\x8B\x60\xC7\x07\x0C\xA7\x19\x1C\x6F\x06\x92\x6E\x40\x2C\x84\x02\x0D\x0F\xA7\x7C\x69\x2B\xD2\x06\x0A\x16\x91\x83\xD4\x21\xA0\x46\x08\xD8\x1D\xA9\x66\x0C\x32\x00\x83\x97\x0C\x13\x86\x08\x32\x8D\x84\x4A\x06\x22\x8C\x17\xA2\x83\x20\x34\x1D\x4E\x82\x4D\x2B\x86\x41\x18\x1D\xAC\x82\xA0\x2E\x84\xC6\x7B\xC0\x4B\x07\x19\x8C\x06\x93\x79\xF4\x53\x1F\x99\x64\x0B\x9D\x56\x33\x07\x83\xCF\x03\xF2\x6C\x7D\xE9\x10\x0B\xA3\x87\x02\x71\x06\xA7\x86\x5D\x03\x63\x81\x05\x0C\x93\x86\x40\x2B\x86\x02\x0C\x17\x83\x6E\x4B\x25\xC2\x06\x09\x25\x8E\x86\x96\x24\xA7\x42\x08\x4D\x88\x0D\xD4\x27\x0B\x66\x86\x9D\x52\x1A\x09\x86\x78\x1F\x0D\x83\x0B\xF1\x11\x85\x96\x27\x1C\x86\x08\xA3\x6D\x0D\x9D\x26\x3A\x9D\x85\x8D\x53\x1A\x27\x82\x6A\x03\xF9\x3B\x03\x19\x8C\x1E\x09\x0F\x0F\x87\x42\x6B\x07\x06\xD7\x07\xE4\x7C\x01\x67\x84\x1D\x82\x08\x52\x89\x84\x59\x07\x38\x8A\x17\x4D\x63\x20\x02\x89\x23\x4E\x4B\x09\x8B\xF2\x0E\x84\x96\x22\x7A\x06\x09\xAB\x6D\x84\x5A\x07\x19\x9B\x06\xA0\x81\x33\x14\x88\x81\x01\x3F\x68\x84\x35\x3B\x88\x01\x0B\x7D", + "\x1E\x89\x4E\x22\x12\xC1\x79\x13\x5D\x06\x29\x81\x21\x3D\x01\xF2\x75\x12\x9E\x75\xA3\x42\x07\x29\x8E\x20\x02\x02\x96\x85\xDD\x0D\x57\x39\x11\x89\x03\x0F\x08\x34\x89\x86\x6A\x10\x6C\x04\x4E\x82\x08\x4C\x02\xD9\x2D\x3B\x96\x86\xEA\x3C\x09\x3C\x1F\x89\x01\x0A\x0A\x02\x8A\x85\x04\x14\x8D\x73\x11\x56\x07\x48\x88\x00\x1D\x7E\xF9\x46\x10\x4D\x89\x85\x6D\x54\xFB\x01\x2A\x9E\x03\x9D\x81\xB6\x67\x60\xF2\x7B\x0F\x63\x04\x2B\xAC\x77\x24\x45\x00\x26\x36\xEB\x69\x0F\x68\x02\x2C\xBE\x63\x05\x6A\x00\x66\x89\x7F\x0D\x03\x6A\x8A\xEB\x4B\x61\x07\x0E\x16\xE3\x0E\x1C\x11\x8B\x00\x03\xEB\x43\x08\x0A\x05\x17\xFB\x0F\x1D\x18\x8B\x04\x84\x93\x7D\x8B\x24\x1C\x07\x00\x8F\x02\x7E\x00\x83\x8A\x4B\x01\x04\xC3\x8A\xF6\x09\x8C\x96\x06\x04\x78\x8E\x04\x83\x08\x14\x0E\x18\xEE\x13\x22\x11\x8C\x0B\x65\x05\x15\x8C\xF3\x00\x09\x18\x8D\xA7\x52\x01\x9B\x89\x3D\x15\x04\xBC\x8D\x02\x83\x0B\x0D\x15\x8C\x3C\x06\xD4\x2A\x34\x4D\x04\x1A\x8B\x62\x0F\x15\x8C\x43\x02\x35\x8A\x09\x4F\x0D\x1A\x9D\x55\x11\x15\x8C\x4A\x02\x36\x89\x08\x52\x08\x17\xD3\x83\x40\x0C", + "\x02\x95\x89\x0A\x3A\x8C\x83\x05\x04\xDF\x8B\x40\x16\x8A\xBE\x8A\x20\x13\x03\xCA\x88\x05\x43\x8F\x40\x07\x82\xC6\x8A\x20\x08\x8F\x05\x6A\x05\x15\x8F\x17\x0E\x8E\x02\x0B\x16\x25\x7E\x29\x66\x10\x1D\x88\x26\x9D\x24\xDC\x8F\x38\x90\x88\x6A\x2E\x1D\x83\x09\xF5\x1D\x54\x61\x06\x83\x67\x19\xAF\x62\x10\x20\x88\x4F\x02\x03\xD8\x89\x20\x24\x03\xF8\x80\x00\x38\x07\x19\x98\x62\x06\x0D\x7E\x1D\x54\x33\x0A\x1E\xEC\x14\x7E\x83\x08\xEE\x8B\x24\x27\x02\x0F\x68\x06\x74\x8D\x2E\x07\x83\x62\x63\x20\x3A\x8F\x46\x5A\x06\x7D\x8E\xBB\x09\x90\xED\x8B\x81\x6B\x02\x0F\x6C\x06\x74\x8E\x2E\x07\x83\x30\x6F\x3B\xA0\x0D\x39\x3C\xC6\x1D\x92\x87\x83\x79\x29\x08\x44\x91\x37\x86\x67\xB3\x35\x5D\x4C\x66\x91\xFA\x68\x45\xA0\x6B\x4A\x51\x1D\xE0\x5D\xA4\x52\x5F\x2C\x91\x6D\x6A\x90\xBC\x5A\xC1\x3B\x5F\x8C\x89\x42\xAB\x63\x42\x09\x55\xE4\x43\x21\x05\x54\xD9\x23\x66\x3F\x91\x46\x82\x0F\xD5\x0E\x1A\x77\x48\x5E\x43\x5E\x7D\x65\x46\x8A\x7B\x26\x48\xA8\x4E\x09\x93\x94\x09\x25\x5F\x35\x3A\x91\x28\x9A\xA9\x7C\x62\x53\x0D\x37\xEE\x5B\x24\x27\x8A\x97\x0B\x25", + "\xA8\x0B\xA8\x5C\x09\x5F\x92\x4B\xAC\x62\x61\x4A\xD9\x51\x31\xDB\x25\x54\x67\x93\x24\x29\x92\x1E\x94\xB4\x65\x90\xF8\x4E\x93\x4A\x93\x12\x7A\x91\xDB\x62\x27\x8B\x60\x9D\x95\x6C\x76\x93\x4C\xBA\x93\xE9\x10\x27\xC7\x41\xDB\x28\x63\x7F\x92\x4D\xB1\x63\x40\x9C\x26\xCB\x93\x5A\x93\x0B\x7F\x63\xCF\x3A\x8B\x21\x90\xF2\x6C\x63\xA2\x85\x0E\xAE\x0D\xF8\x3B\x33\x71\x6A\x10\x14\x95\x42\x00", + }; + vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); + } + + const wchar_t* RuleParserRuleName(vl::vint index) + { + static const wchar_t* results[] = { + L"OptionalBody", + L"Syntax0", + L"Syntax1", + L"Syntax2", + L"Syntax", + L"Assignment", + L"Clause", + L"Rule", + L"File", + }; + return results[index]; + } + + const wchar_t* RuleParserStateLabel(vl::vint index) + { + static const wchar_t* results[] = { + L"[0][OptionalBody] BEGIN ", + L"[1][OptionalBody] END [ENDING]", + L"[2][OptionalBody]\"[\" @ Syntax \"]\"", + L"[3][OptionalBody]\"[\" Syntax \"]\" @", + L"[4][OptionalBody]\"[\" Syntax @ \"]\"", + L"[5][Syntax0] BEGIN ", + L"[6][Syntax0] END [ENDING]", + L"[7][Syntax0]< \"!\" @ ID >", + L"[8][Syntax0]< \"!\" ID @ >", + L"[9][Syntax0]< \"+\" @ OptionalBody >", + L"[10][Syntax0]< \"+\" OptionalBody @ >", + L"[11][Syntax0]< \"-\" @ OptionalBody >", + L"[12][Syntax0]< \"-\" OptionalBody @ >", + L"[13][Syntax0]< \"{\" @ Syntax [ \";\" Syntax ] \"}\" >", + L"[14][Syntax0]< \"{\" Syntax @ [ \";\" Syntax ] \"}\" >", + L"[15][Syntax0]< \"{\" Syntax [ \";\" @ Syntax ] \"}\" >", + L"[16][Syntax0]< \"{\" Syntax [ \";\" Syntax @ ] \"}\" >", + L"[17][Syntax0]< \"{\" Syntax [ \";\" Syntax ] \"}\" @ >", + L"[18][Syntax0]< ID @ [ \":\" ID ] >", + L"[19][Syntax0]< ID [ \":\" @ ID ] >", + L"[20][Syntax0]< ID [ \":\" ID @ ] >", + L"[21][Syntax0]< OptionalBody @ >", + L"[22][Syntax0]< STRING @ >", + L"[23][Syntax0]<< \"(\" !Syntax \")\" @ >>", + L"[24][Syntax0]<< \"(\" !Syntax @ \")\" >>", + L"[25][Syntax0]<< \"(\" @ !Syntax \")\" >>", + L"[26][Syntax1] BEGIN ", + L"[27][Syntax1] END [ENDING]", + L"[28][Syntax1]< Syntax1 @ Syntax0 >", + L"[29][Syntax1]< Syntax1 Syntax0 @ >", + L"[30][Syntax1]<< !Syntax0 @ >>", + L"[31][Syntax2] BEGIN ", + L"[32][Syntax2] END [ENDING]", + L"[33][Syntax2]< Syntax2 \"|\" @ Syntax1 >", + L"[34][Syntax2]< Syntax2 \"|\" Syntax1 @ >", + L"[35][Syntax2]< Syntax2 @ \"|\" Syntax1 >", + L"[36][Syntax2]<< !Syntax1 @ >>", + L"[37][Syntax] BEGIN ", + L"[38][Syntax] END [ENDING]", + L"[39][Syntax]<< !Syntax2 @ >>", + L"[40][Assignment] BEGIN ", + L"[41][Assignment] END [ENDING]", + L"[42][Assignment]< ID \"=\" @ ID >", + L"[43][Assignment]< ID \"=\" ID @ >", + L"[44][Assignment]< ID @ \"=\" ID >", + L"[45][Clause] BEGIN ", + L"[46][Clause] END [ENDING]", + L"[47][Clause]< Syntax \"as\" \"partial\" @ ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[48][Clause]< Syntax \"as\" \"partial\" ID @ [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[49][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" @ { Assignment ; \",\" } \"}\" ] >", + L"[50][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" @ } \"}\" ] >", + L"[51][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" @ ] >", + L"[52][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment @ ; \",\" } \"}\" ] >", + L"[53][Clause]< Syntax \"as\" @ \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[54][Clause]< Syntax \"as\" @ ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[55][Clause]< Syntax \"as\" ID @ [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[56][Clause]< Syntax \"as\" ID [ \"{\" @ { Assignment ; \",\" } \"}\" ] >", + L"[57][Clause]< Syntax \"as\" ID [ \"{\" { Assignment ; \",\" @ } \"}\" ] >", + L"[58][Clause]< Syntax \"as\" ID [ \"{\" { Assignment ; \",\" } \"}\" @ ] >", + L"[59][Clause]< Syntax \"as\" ID [ \"{\" { Assignment @ ; \",\" } \"}\" ] >", + L"[60][Clause]< Syntax @ \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[61][Clause]< Syntax @ \"as\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[62][Clause]< Syntax @ [ \"{\" { Assignment ; \",\" } \"}\" ] >", + L"[63][Clause]< Syntax [ \"{\" @ { Assignment ; \",\" } \"}\" ] >", + L"[64][Clause]< Syntax [ \"{\" { Assignment ; \",\" @ } \"}\" ] >", + L"[65][Clause]< Syntax [ \"{\" { Assignment ; \",\" } \"}\" @ ] >", + L"[66][Clause]< Syntax [ \"{\" { Assignment @ ; \",\" } \"}\" ] >", + L"[67][Rule] BEGIN ", + L"[68][Rule] END [ENDING]", + L"[69][Rule]< ID @ { \"::=\" Clause } \";\" >", + L"[70][Rule]< ID { \"::=\" @ Clause } \";\" >", + L"[71][Rule]< ID { \"::=\" Clause @ } \";\" >", + L"[72][Rule]< ID { \"::=\" Clause } \";\" @ >", + L"[73][File] BEGIN ", + L"[74][File] END [ENDING]", + L"[75][File]< Rule @ { Rule } >", + L"[76][File]< Rule { Rule @ } >", + }; + return results[index]; + } + + RuleParser::RuleParser() + : vl::glr::ParserBase(&ParserGenTokenDeleter, &ParserGenLexerData, &ParserGenRuleParserData) + { + }; + + vl::vint32_t RuleParser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const + { + return -1; + }; + + vl::Ptr RuleParser::ParseFile(const vl::WString& input, vl::vint codeIndex) const + { + return Parse(input, this, codeIndex); + }; + + vl::Ptr RuleParser::ParseFile(vl::collections::List& tokens, vl::vint codeIndex) const + { + return Parse(tokens, this, codeIndex); + }; + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { +/*********************************************************************** +Visitor Pattern Implementation +***********************************************************************/ + + void GlrEnum::Accept(GlrType::IVisitor* visitor) + { + visitor->Visit(this); + } + + void GlrClass::Accept(GlrType::IVisitor* visitor) + { + visitor->Visit(this); + } + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrType, glr::parsergen::GlrType) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrType::IVisitor, glr::parsergen::GlrType::IVisitor) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrEnumItem, glr::parsergen::GlrEnumItem) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrEnum, glr::parsergen::GlrEnum) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrPropType, glr::parsergen::GlrPropType) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrClassProp, glr::parsergen::GlrClassProp) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrClassAmbiguity, glr::parsergen::GlrClassAmbiguity) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrClass, glr::parsergen::GlrClass) + IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrAstFile, glr::parsergen::GlrAstFile) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrType) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_FIELD(name) + END_CLASS_MEMBER(vl::glr::parsergen::GlrType) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrEnumItem) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + END_CLASS_MEMBER(vl::glr::parsergen::GlrEnumItem) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrEnum) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrType) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(items) + END_CLASS_MEMBER(vl::glr::parsergen::GlrEnum) + + BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrPropType) + ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrPropType) + ENUM_NAMESPACE_ITEM(Token) + ENUM_NAMESPACE_ITEM(Type) + ENUM_NAMESPACE_ITEM(Array) + END_ENUM_ITEM(vl::glr::parsergen::GlrPropType) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrClassProp) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(name) + CLASS_MEMBER_FIELD(propType) + CLASS_MEMBER_FIELD(propTypeName) + END_CLASS_MEMBER(vl::glr::parsergen::GlrClassProp) + + BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrClassAmbiguity) + ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrClassAmbiguity) + ENUM_NAMESPACE_ITEM(No) + ENUM_NAMESPACE_ITEM(Yes) + END_ENUM_ITEM(vl::glr::parsergen::GlrClassAmbiguity) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrClass) + CLASS_MEMBER_BASE(vl::glr::parsergen::GlrType) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(baseClass) + CLASS_MEMBER_FIELD(ambiguity) + CLASS_MEMBER_FIELD(props) + END_CLASS_MEMBER(vl::glr::parsergen::GlrClass) + + BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrAstFile) + CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) + + CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) + + CLASS_MEMBER_FIELD(types) + END_CLASS_MEMBER(vl::glr::parsergen::GlrAstFile) + + BEGIN_INTERFACE_MEMBER(vl::glr::parsergen::GlrType::IVisitor) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrType::IVisitor::*)(vl::glr::parsergen::GlrEnum* node)) + CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrType::IVisitor::*)(vl::glr::parsergen::GlrClass* node)) + END_INTERFACE_MEMBER(vl::glr::parsergen::GlrType) + +#endif + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + class ParserGenTypeAstTypeLoader : public vl::Object, public ITypeLoader + { + public: + void Load(ITypeManager* manager) + { + ADD_TYPE_INFO(vl::glr::parsergen::GlrType) + ADD_TYPE_INFO(vl::glr::parsergen::GlrType::IVisitor) + ADD_TYPE_INFO(vl::glr::parsergen::GlrEnumItem) + ADD_TYPE_INFO(vl::glr::parsergen::GlrEnum) + ADD_TYPE_INFO(vl::glr::parsergen::GlrPropType) + ADD_TYPE_INFO(vl::glr::parsergen::GlrClassProp) + ADD_TYPE_INFO(vl::glr::parsergen::GlrClassAmbiguity) + ADD_TYPE_INFO(vl::glr::parsergen::GlrClass) + ADD_TYPE_INFO(vl::glr::parsergen::GlrAstFile) + } + + void Unload(ITypeManager* manager) + { + } + }; +#endif +#endif + + bool ParserGenTypeAstLoadTypes() + { +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + if (auto manager = GetGlobalTypeManager()) + { + Ptr loader = new ParserGenTypeAstTypeLoader; + return manager->AddTypeLoader(loader); + } +#endif + return false; + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_BUILDER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace builder + { + +/*********************************************************************** +MakeAstFile +***********************************************************************/ + + MakeAstFile& MakeAstFile::types(const vl::Ptr& value) + { + node->types.Add(value); + return *this; + } + +/*********************************************************************** +MakeClass +***********************************************************************/ + + MakeClass& MakeClass::ambiguity(GlrClassAmbiguity value) + { + node->ambiguity = value; + return *this; + } + + MakeClass& MakeClass::baseClass(const vl::WString& value) + { + node->baseClass.value = value; + return *this; + } + + MakeClass& MakeClass::props(const vl::Ptr& value) + { + node->props.Add(value); + return *this; + } + + MakeClass& MakeClass::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + +/*********************************************************************** +MakeClassProp +***********************************************************************/ + + MakeClassProp& MakeClassProp::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + + MakeClassProp& MakeClassProp::propType(GlrPropType value) + { + node->propType = value; + return *this; + } + + MakeClassProp& MakeClassProp::propTypeName(const vl::WString& value) + { + node->propTypeName.value = value; + return *this; + } + +/*********************************************************************** +MakeEnum +***********************************************************************/ + + MakeEnum& MakeEnum::items(const vl::Ptr& value) + { + node->items.Add(value); + return *this; + } + + MakeEnum& MakeEnum::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + +/*********************************************************************** +MakeEnumItem +***********************************************************************/ + + MakeEnumItem& MakeEnumItem::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + +/*********************************************************************** +MakeType +***********************************************************************/ + + MakeType& MakeType::name(const vl::WString& value) + { + node->name.value = value; + return *this; + } + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_COPY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace copy_visitor + { + void TypeAstVisitor::CopyFields(GlrAstFile* from, GlrAstFile* to) + { + for (auto&& listItem : from->types) + { + to->types.Add(CopyNode(listItem.Obj())); + } + } + + void TypeAstVisitor::CopyFields(GlrClass* from, GlrClass* to) + { + CopyFields(static_cast(from), static_cast(to)); + to->ambiguity = from->ambiguity; + to->baseClass = from->baseClass; + for (auto&& listItem : from->props) + { + to->props.Add(CopyNode(listItem.Obj())); + } + } + + void TypeAstVisitor::CopyFields(GlrClassProp* from, GlrClassProp* to) + { + to->name = from->name; + to->propType = from->propType; + to->propTypeName = from->propTypeName; + } + + void TypeAstVisitor::CopyFields(GlrEnum* from, GlrEnum* to) + { + CopyFields(static_cast(from), static_cast(to)); + for (auto&& listItem : from->items) + { + to->items.Add(CopyNode(listItem.Obj())); + } + } + + void TypeAstVisitor::CopyFields(GlrEnumItem* from, GlrEnumItem* to) + { + to->name = from->name; + } + + void TypeAstVisitor::CopyFields(GlrType* from, GlrType* to) + { + to->name = from->name; + } + + void TypeAstVisitor::Visit(GlrEnumItem* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void TypeAstVisitor::Visit(GlrClassProp* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void TypeAstVisitor::Visit(GlrAstFile* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void TypeAstVisitor::Visit(GlrEnum* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + void TypeAstVisitor::Visit(GlrClass* node) + { + auto newNode = vl::MakePtr(); + CopyFields(node, newNode.Obj()); + this->result = newNode; + } + + vl::Ptr TypeAstVisitor::CopyNode(GlrType* node) + { + if (!node) return nullptr; + node->Accept(static_cast(this)); + return this->result.Cast(); + } + + vl::Ptr TypeAstVisitor::CopyNode(GlrEnumItem* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr TypeAstVisitor::CopyNode(GlrClassProp* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr TypeAstVisitor::CopyNode(GlrAstFile* node) + { + if (!node) return nullptr; + Visit(node); + return this->result.Cast(); + } + + vl::Ptr TypeAstVisitor::CopyNode(GlrClass* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + vl::Ptr TypeAstVisitor::CopyNode(GlrEnum* node) + { + if (!node) return nullptr; + return CopyNode(static_cast(node)).Cast(); + } + + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_EMPTY.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace empty_visitor + { + +/*********************************************************************** +TypeVisitor +***********************************************************************/ + + // Visitor Members ----------------------------------- + + void TypeVisitor::Visit(GlrEnum* node) + { + } + + void TypeVisitor::Visit(GlrClass* node) + { + } + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_JSON.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace json_visitor + { + void TypeAstVisitor::PrintFields(GlrAstFile* node) + { + BeginField(L"types"); + BeginArray(); + for (auto&& listItem : node->types) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + } + void TypeAstVisitor::PrintFields(GlrClass* node) + { + BeginField(L"ambiguity"); + switch (node->ambiguity) + { + case vl::glr::parsergen::GlrClassAmbiguity::No: + WriteString(L"No"); + break; + case vl::glr::parsergen::GlrClassAmbiguity::Yes: + WriteString(L"Yes"); + break; + default: + WriteNull(); + } + EndField(); + BeginField(L"baseClass"); + WriteToken(node->baseClass); + EndField(); + BeginField(L"props"); + BeginArray(); + for (auto&& listItem : node->props) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + } + void TypeAstVisitor::PrintFields(GlrClassProp* node) + { + BeginField(L"name"); + WriteToken(node->name); + EndField(); + BeginField(L"propType"); + switch (node->propType) + { + case vl::glr::parsergen::GlrPropType::Array: + WriteString(L"Array"); + break; + case vl::glr::parsergen::GlrPropType::Token: + WriteString(L"Token"); + break; + case vl::glr::parsergen::GlrPropType::Type: + WriteString(L"Type"); + break; + default: + WriteNull(); + } + EndField(); + BeginField(L"propTypeName"); + WriteToken(node->propTypeName); + EndField(); + } + void TypeAstVisitor::PrintFields(GlrEnum* node) + { + BeginField(L"items"); + BeginArray(); + for (auto&& listItem : node->items) + { + BeginArrayItem(); + Print(listItem.Obj()); + EndArrayItem(); + } + EndArray(); + EndField(); + } + void TypeAstVisitor::PrintFields(GlrEnumItem* node) + { + BeginField(L"name"); + WriteToken(node->name); + EndField(); + } + void TypeAstVisitor::PrintFields(GlrType* node) + { + BeginField(L"name"); + WriteToken(node->name); + EndField(); + } + + void TypeAstVisitor::Visit(GlrEnum* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Enum", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + void TypeAstVisitor::Visit(GlrClass* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"Class", node); + PrintFields(static_cast(node)); + PrintFields(static_cast(node)); + EndObject(); + } + + TypeAstVisitor::TypeAstVisitor(vl::stream::StreamWriter& _writer) + : vl::glr::JsonVisitorBase(_writer) + { + } + + void TypeAstVisitor::Print(GlrType* node) + { + if (!node) + { + WriteNull(); + return; + } + node->Accept(static_cast(this)); + } + + void TypeAstVisitor::Print(GlrEnumItem* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"EnumItem", node); + PrintFields(static_cast(node)); + EndObject(); + } + + void TypeAstVisitor::Print(GlrClassProp* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"ClassProp", node); + PrintFields(static_cast(node)); + EndObject(); + } + + void TypeAstVisitor::Print(GlrAstFile* node) + { + if (!node) + { + WriteNull(); + return; + } + BeginObject(); + WriteType(L"AstFile", node); + PrintFields(static_cast(node)); + EndObject(); + } + + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_TRAVERSE.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace traverse_visitor + { + void TypeAstVisitor::Traverse(vl::glr::ParsingToken& token) {} + void TypeAstVisitor::Traverse(vl::glr::ParsingAstBase* node) {} + void TypeAstVisitor::Traverse(GlrAstFile* node) {} + void TypeAstVisitor::Traverse(GlrClass* node) {} + void TypeAstVisitor::Traverse(GlrClassProp* node) {} + void TypeAstVisitor::Traverse(GlrEnum* node) {} + void TypeAstVisitor::Traverse(GlrEnumItem* node) {} + void TypeAstVisitor::Traverse(GlrType* node) {} + + void TypeAstVisitor::Finishing(vl::glr::ParsingAstBase* node) {} + void TypeAstVisitor::Finishing(GlrAstFile* node) {} + void TypeAstVisitor::Finishing(GlrClass* node) {} + void TypeAstVisitor::Finishing(GlrClassProp* node) {} + void TypeAstVisitor::Finishing(GlrEnum* node) {} + void TypeAstVisitor::Finishing(GlrEnumItem* node) {} + void TypeAstVisitor::Finishing(GlrType* node) {} + + void TypeAstVisitor::Visit(GlrEnum* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->items) + { + InspectInto(listItem.Obj()); + } + Traverse(node->name); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void TypeAstVisitor::Visit(GlrClass* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->baseClass); + for (auto&& listItem : node->props) + { + InspectInto(listItem.Obj()); + } + Traverse(node->name); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void TypeAstVisitor::InspectInto(GlrType* node) + { + if (!node) return; + node->Accept(static_cast(this)); + } + + void TypeAstVisitor::InspectInto(GlrEnumItem* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->name); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void TypeAstVisitor::InspectInto(GlrClassProp* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + Traverse(node->name); + Traverse(node->propTypeName); + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + void TypeAstVisitor::InspectInto(GlrAstFile* node) + { + if (!node) return; + Traverse(static_cast(node)); + Traverse(static_cast(node)); + for (auto&& listItem : node->types) + { + InspectInto(listItem.Obj()); + } + Finishing(static_cast(node)); + Finishing(static_cast(node)); + } + + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEPARSER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + void ParserGenTypeParserData(vl::stream::IStream& outputStream) + { + static const vl::vint dataLength = 2267; // 29656 bytes before compressing + static const vl::vint dataBlock = 256; + static const vl::vint dataRemain = 219; + static const vl::vint dataSolidRows = 8; + static const vl::vint dataRows = 9; + static const char* compressed[] = { + "\xD8\x73\x00\x00\xD3\x08\x00\x00\x1A\x00\x01\x82\x80\x08\x03\x82\x81\x82\x06\x89\x82\x84\x0A\x83\x06\x84\x09\x0A\x99\x0A\x81\x1A\x80\x16\x84\x16\x0A\xC0\x05\x09\x8F\x7D\x8E\x8F\x8E\x0A\x80\x1F\x9F\x81\x93\x92\x8F\x92\x26\xFF\x68\x86\x9B\x93\x91\x96\x92\x0A\xA9\xAA\x91\x99\x97\x97\x92\x9A\x2C\xB8\xAE\x9A\x90\x9C\x8D\x9A\x9E\x37\xBE\xB9\x82\xAB\x9C\xA1\x9E\x83\x32\xB6\xA0\x80\xAB\xA6\xA1\xA0\xA4\x3F\xCE\x8D\xA1\x96\x81\x00\xA7\x99\x52\xD8\x90\xA3\xAB\xAD\xA1\xAF\xA3\x03\xC9\x97\xAA\xAA\xA9\xB1\xA9\xAF\x4F\xE6\x9C\xAA\xBE\xAC\xB4\xB0\x81\x62\xD9\xA4\xB3\xB3\xB5\xBA\xB8\xBB\x68\xD3\xAE\xA9\xB0\xBF\xB3\xBC\xBD\x7D\xEB\x81\xCD\xB3\xC7\xB5\x81\xB8\x79\xE5\x85\xDC\xB1\x86\xA9\x84\xC7\x89\xF4\xB7\xB3\xC1\xC8\xBF\xBE\xC5\x87\xFE\x8B\xC0\xC9\xCA\xC1\xCE\xC2\x9F\x86\xE2\x9A\xC1\xD4\xC7\xD0\xCF\xA7\xA0\xE9\xC2\xD8\xC7\xCA\xC9\xCA\x94\xAE\xD6\xDB\xC8\xCB\xD6\xD3\xD6\xB4\xAF\xF2\xD1\xD9\xDB\xD9\xD2\xCE\xB6\xC0\xF8\xDF\xD5\xDB\xE1\xE1\xE2\xA4\xC7\xFA\xC2\x82\x02\x84\xC9\xDD\xB0\xD1\xD0\xF3\xED\xDC\xDC\xE3\xE5\xD7\xBE\xCA\xFA", + "\xE6\xE5\xED\xE5\x01\xCE\xDC\xC9\xFE\xE8\xD4\xF2\xD4\xF3\xAC\xE3\xEA\xE5\xFB\xF7\xF1\xF7\xF4\xEC\xF1\xEE\xF2\xF0\xFB\xFA\xFB\xFA\xF8\xB7\xEF\xFA\xF4\xFC\xFF\xFA\xFF\xF9\x42\x7B\x7E\x80\xFD\x44\x8F\x7E\x81\x01\x88\x75\x82\x82\x07\x8C\x89\x80\x76\xDB\x56\x71\x86\x74\xD5\x54\x89\x76\x84\xE8\x40\x8A\x84\x82\x1B\x8E\x8D\x84\x84\x19\x9C\x82\x8A\x87\x23\xA0\x83\x80\x89\xB5\x4C\x4F\x62\x78\x0B\xA6\x8D\x88\x8B\x0D\xAE\x81\x8C\x8C\x0F\xB4\x86\x6B\x46\x2B\x98\x87\x8A\x8C\x35\xBA\x8F\x89\x42\x06\x21\x7E\x8F\x8C\x43\xBD\x86\x87\x84\xD4\x57\x87\x91\x88\x28\xBC\x8F\x86\x42\x07\x02\x9B\x93\x8E\x36\xA5\x85\x95\x93\x0A\x48\x45\x57\x95\x10\x89\x02\x95\x92\x48\x95\x80\x98\x93\x4E\x96\x95\x93\x93\x67\xA6\x93\x97\x8F\x6B\x84\x9D\x9A\x91\x63\x94\x99\x98\x96\x73\xA5\x94\x9F\x9B\x68\xB8\x90\x72\x02\x5F\xA2\x9E\x9E\x92\x71\xAC\x91\xA2\x9B\x83\xB0\x9F\x9D\x98\x80\x87\xA4\x98\x97\x0D\x7D\x99\xA3\xA3\x88\x91\xAB\xA1\x9D\x8C\x94\xA6\xA6\x9E\x77\x83\x4C\x02\x42\xCD\x57\xA5\xA1\x9E\x9F\xAA\x91\xA9\xA6\x8A\xB2\x98\xA6\x9D\xA8\x95\xA7\xAA\xAA", + "\xA3\xA9\xA2\x86\x03\x8E\x92\xA6\xA9\xAB\xAC\xA5\xA2\xA2\xAD\x84\xB8\xA6\xA0\xA4\x93\xAB\xAE\xA6\xAE\xA0\x87\xAF\x01\xAC\xBD\xB4\xAF\xAC\xAF\xB3\x80\xB2\xAA\xB2\xA4\x88\xB7\xAE\xB3\xB9\x90\xBB\xAE\xAC\xCF\x94\xB1\xB6\xB5\xD3\x85\xBC\xB2\xAB\x06\x50\x04\xB1\xB2\xD2\x81\xB1\xBB\xB2\xE3\x8D\xB8\xB6\xB8\x91\x91\x0F\xB5\xB5\xDA\xA5\xBC\xB6\xB1\xBE\xB1\xB0\xBF\xBC\xDB\xB5\xAE\xBA\xBD\xE7\xA4\xB9\xBE\xB9\xED\xBB\xBF\xBA\x40\x10\x79\x82\xBD\xBD\xC7\xBE\xB8\xBD\xBF\x08\xE0\xB6\xC1\xC1\xC6\x53\x0B\xBB\xB5\x09\xEC\xBA\xC1\xC4\x10\xD3\xC6\xC6\xC4\x18\xD5\xC9\xC5\xB6\x17\xDA\xCE\xC4\xC7\x1B\xE8\xB4\xC4\xC8\x1F\xE2\xCD\xC4\xC9\x28\xE6\xC1\xCA\xBE\x23\xEA\xC5\xC8\xCB\x27\xEE\xC9\xCA\xBE\x14\x0F\xC3\xCC\xBF\x31\xF0\xC8\x69\x05\x36\xF2\xCE\xCE\xCE\x2F\xF8\xCB\xCA\xD0\x41\xE1\x46\x04\xA7\x07\xC9\x78\x05\xCF\x40\xF7\xCF\xBF\xBD\x0C\xF9\xC4\xD2\xD3\x49\xC3\xDF\xD3\xC2\x03\xD0\xD9\xD4\xD6\xF4\x9A\xDD\xD4\xD7\x87\x92\x42\xC3\xD7\x2D\xCD\xDF\xCF\xD4\x67\xD7\xD5\xD8\xDA\x66\xED\xDC\xD9\x6D\x00\x63\xD4\xC3\xD6\x6B\xEA\xD2\xD6\xDD\x56", + "\xD5\xD5\xD2\xDE\x54\xD1\xD9\xDE\xDF\xAA\x5B\x0C\xD3\xDB\x78\xFB\xD0\xE1\xDF\x74\xF7\xDC\xDD\xDA\x8B\xEE\xD5\xE0\xE2\x64\xCA\xE7\xE0\xE3\x12\x9C\x03\xE0\x84\x1D\x17\xED\xE0\xE1\x9B\xCF\xE4\xE5\xE2\x7F\xE0\xE6\xE2\xE8\x90\xF3\xD1\xE5\xB5\x1E\x1A\xE3\xE6\xE3\x9D\xED\xEB\xEA\xB9\x1F\x2A\xE4\xEB\xE7\xA7\xE3\xE5\xED\xE9\x5E\xC7\xA0\x0A\xEC\xB7\xF4\xE6\xEA\x40\x14\x72\xD9\xEF\xF0\x60\xC4\xF5\xDE\xEB\xB3\xFA\xB2\x08\xEF\xBF\xC6\xF2\xE6\x41\x23\x0C\xFE\xF1\xE8\xBD\xEC\xE5\xC0\x09\xD2\xC5\xFA\xF7\xF1\xAF\xDE\xE6\xF5\xF2\x9C\xDD\xF8\xF3\xD7\x25\x31\xA6\x09\xF6\xDC\xE0\xFE\xF5\xF8\xEA\xE3\xFD\xF3\xF6\xCF\xD5\xFC\xFA\xFC\xEB\xF5\xFE\xFB\xF4\xB6\xEF\xF9\xF8\xFD\xF7\xF0\xF4\xF6\xFE\xF1\x60\x83\xFF\x78\x72\x35\x13\x28\x7A\x61\x16\x22\x7A\xFF\x79\x74\x80\xDF\x4D\x87\x7B\xFC\x62\x7E\x04\xED\x73\x83\x81\x29\x07\x80\x03\x8B\x80\xEE\x1A\x8E\x80\x0E\x90\x82\x80\x0C\x9E\x83\xFC\x20\x8B\x83\xFD\x64\x85\x83\x26\x8F\x81\x6D\x2A\x08\x83\x6B\x6B\x05\x85\x25\x81\x82\x0A\xF6\x75\x83\x13\x9F\x83\x86\xFD\x7D\x5C\x46\x0A\x8D\x05\x58\x6E\x00", + "\x86\x28\x92\x86\x08\xB4\x84\x83\x22\x91\x86\x88\x36\x83\x84\x0E\xB5\x8B\x88\x24\x8D\x8F\x88\x50\x82\x23\x0B\x40\x87\x87\x21\xB9\x82\x88\x29\x96\x88\x13\xDA\x8B\x6A\x18\x14\x8A\x89\x5C\x91\x8B\x13\xC9\x84\x88\x31\xA1\x8C\x8C\xDA\x31\x05\xAC\x32\x01\x57\x19\x1F\x8D\x8C\x68\x9B\x89\x16\xF3\x88\x8B\x3A\x99\x84\x8E\x77\x96\x8D\x08\xF8\x8B\x8E\x3D\xB1\x80\x35\x34\x19\x79\x0D\x31\x56\x07\x58\x77\x07\x8D\x57\x99\x8E\x22\xFD\x8B\x91\x3F\xA1\x80\x07\xD9\x79\x05\xAC\x3A\x01\x57\x1D\x08\x92\x8E\x7E\x81\x89\x23\x9A\x9C\x91\x10\x9A\x08\x69\x09\x3A\x4B\xA8\x32\x22\x94\x81\x03\x59\x2B\x41\x59\x2A\x4C\x1D\x56\x21\x28\x73\x4C\x94\x13\x37\x28\x2B\x83\x25\x95\x72\x70\x91\x21\xA7\x89\x33\x2C\x87\x27\x4B\x5B\x86\x21\x97\x97\x29\x95\x62\x4C\x4E\x97\x81\x3C\x4F\x95\x29\x35\x94\x00\x47\x99\x31\xE7\x14\x2C\x38\xCA\x9E\x49\x56\x4E\x91\x21\x5D\x90\x9A\x21\xD2\x8D\x9B\xE0\x51\x92\x96\x85\x2A\x40\x53\xC5\x9C\x94\x32\xA6\x2A\x98\x66\xA3\x91\x99\x0A\x26\x9C\x6D\x42\x97\x32\x62\xA8\x99\x21\xC1\x60\x9F\x3B\x86\x2C\x9C\xDA\x16\x98\x00\xDF\x97", + "\x33\x3D\xF9\x96\x9E\x85\x20\x39\x2B\xF7\x9F\x9E\x3C\xE4\x91\x97\x69\x9B\x9A\x21\x38\x49\x31\x3D\xC4\x3E\x9C\x82\xB0\x9F\x2A\xD4\x94\x29\x38\x81\x29\xA1\x60\x97\x2A\x26\xFC\x8C\xA1\x4A\x01\xA7\x2B\x8C\x87\x3B\x95\xFE\x9D\xA3\x45\x9B\xA0\x4B\xAB\x0B\xA7\xA3\x29\x27\xA6\x4C\x20\xA9\x21\x7B\x98\xA3\xA4\x26\x3C\xA0\x40\xA0\x99\x30\x8F\xAB\xA4\xA4\x09\x22\xA2\x3E\xB4\xA7\x32\x9B\xB7\xA3\x24\xF7\x8E\x96\x42\xB0\xA3\x24\x9F\xBF\xA6\x23\x32\xB5\xA4\x51\x9F\x29\xA9\x9E\x8B\xA8\xA9\x25\xA8\x97\x53\x9D\x26\xA9\xA3\xBF\x1D\xA9\xB4\x35\xAB\x51\xD8\xA4\x38\xAD\xBF\xA1\xA8\x57\x2A\x98\xAC\x59\x22\xAD\xB0\x91\xA9\x31\xCA\x82\xAB\x65\x15\xA4\x36\x99\x2C\xAA\xA3\x0E\xA6\x22\x57\x9D\x2A\x99\xB9\xBF\x1D\xAE\x57\x29\x77\x33\x83\x21\xA3\x7B\xBE\xA9\xA4\x09\x3E\xA3\x5B\x80\x07\xA4\xB5\x82\x26\xB0\x01\x3C\x99\x42\x08\xB0\x01\x6C\x83\x24\xB1\x8E\xA2\x9E\x41\x6A\x91\x20\xC6\x94\xB0\x00\x96\xB9\x49\xA3\x0B\xBB\xB3\x56\x9D\xB4\x96\x0A\x3B\x53\x5E\x92\xB3\xB5\x28\x31\x51\x24\xCA\x81\x26\x14\x31\x57\x9F\x0B\x23\xB7\x50\x3A\xA2\x21\xEC\x2F", + "\xB0\x01\x29\x31\x51\xB6\x01\x33\xB7\x6B\xD4\x01\x56\x8F\x98\x7C\xB6\xC6\x3E\xA2\x01\xC0\xB9\x39\xC1\xAF\x84\xB6\x55\x11\x55\x44\xAC\x84\xB6\x2B\x31\x57\xA4\x3F\x94\xB7\x15\x4F\xBA\x21\x29\xB4\xB0\x0B\xD4\xA9\x22\x75\xAF\xB9\x0B\x58\x7C\x04\xB6\x00\x18\xB4\x78\x8D\x3C\xB4\xED\x37\x99\xA2\x21\x22\xBD\x44\xFD\x52\xBD\x7B\xB0\x89\x20\x1E\xA7\xA5\x48\x1E\xAB\xBC\x85\x67\xA7\xB2\x10\x43\xB2\x4B\xC9\x30\xB2\xF0\x99\x8C\xB1\xE2\xA1\x24\x63\x91\xAA\x98\xF7\xB1\x52\xB1\xAF\xB9\x8A\x32\x81\xC9\x9D\x58\x4E\x25\xA5\xCA\xB8\x98\x42\xE0\xBD\x01\x4B\x93\xB7\xAC\xA3\xB9\x8B\x83\x86\x25\xC2\xE2\x99\x83\xC3\x03\x3E\x5A\x87\xAA\x33\xAC\x83\x3B\xB8\x35\x20\xC2\x22\xBA\x23\xC2\x34\x11\xE6\xC2\x3B\x1D\xC6\x22\x68\xAF\xB1\x61\x17\xC5\x65\xC4\x9A\x40\xBD\xCD\x10\xC5\x60\x60\x82\x20\xC7\x7B\xB9\x8A\x8B\xB9\xC4\xB7\xA3\x7C\xC3\x6B\x2B\xDF\x96\x7F\xC2\x85\xC7\x81\x3B\xC7\xB5\x4B\x6A\x81\xBF\x4F\xC3\x21\x28\xC9\xC1\x39\x62\x76\xC7\x91\x3C\x69\x21\x18\xD9\xC2\x61\xE7\xAA\x20\x97\xDD\x5B\xC8\xD4\x02\x77\xC8\x03\x2A\xBE\x98\x8A\x29\xC9\x2F", + "\xE8\x31\x73\x68\xCB\x21\xAC\x46\xC6\x20\x87\x74\xB2\xB7\x7C\xB8\x5E\x6B\x89\x24\xCE\x37\xE1\x86\xCA\x03\x23\xCE\x9F\x9B\x89\xCB\x81\x27\xCF\xCA\xA8\x3B\x75\x9C\x90\x57\xD1\x81\x3A\xA8\xD1\x21\x8D\xD2\x40\x16\x7C\xC5\x0E\x94\xD6\x20\x70\xD0\xD2\x68\x4B\x7B\xD1\x48\x59\xD6\xD1\x65\xC1\x87\xA3\xCE\xC0\xBD\xDF\x9B\x4A\x42\x83\xB1\xA3\xA8\x82\x2A\xD0\x4D\xDD\x80\xCF\x02\x34\xCB\x5E\xE5\x72\xCB\xE4\x27\xA1\xA2\xB0\xC1\x21\xAB\x83\xDD\x83\x5D\xC2\x21\x6E\xAE\xD5\x89\x3C\x83\x24\xD7\xD7\xA7\x7D\xD6\xD5\x43\xDA\x40\x47\xDF\xB5\xE1\xA7\xD3\x6B\xD1\x69\x22\xA4\xCF\x96\x39\x04\x9A\xCF\xB1\xB1\x46\xD7\x40\x1C\xDF\xB4\xE6\x86\x22\xBC\xFD\x45\xDB\x40\x51\xD1\xD8\x30\x8C\xDE\xD0\xA1\xC2\x35\x0F\x9D\xDA\x99\x88\x8E\xDB\xDB\xE0\xBB\xB9\x9A\xF8\x56\xDA\x62\xE0\xBC\x8D\x9D\xC6\x39\x64\xE4\xB9\x21\x7A\xCB\xD8\xBC\x81\x99\xDD\x72\x17\xB1\xA2\x7F\xC1\x22\xBE\x0A\x25\x92\xC0\xA8\xC1\x56\x6F\xD6\x80\xBC\x90\x88\xDA\x0B\x8A\x27\x82\xDA\x92\x92\xE2\xD3\x5B\x86\x41\x62\xDB\xAE\x4A\xB9\xA2\x3B\x33\xC3\x23\x3D\x9A\xE3\x21\x73\xFB\xAD\x07", + "\x80\xA7\x48\x90\xD5\x97\x22\x85\x08\xE1\x21\x40\x09\xE4\x98\x43\xCC\x38\x85\x11\xBE\x20\xEB\xCF\xB7\x10\x16\xC3\x21\x9B\xF6\xDC\xB6\x44\x1C\xA7\xA1\x4D\xC5\xE7\x84\x3E\xE7\xDF\xB4\xA6\x0A\xD0\x90\x52\xD6\x96\xC6\xEE\xE5\xE0\xA8\x0B\xD2\x91\x5D\xCF\xA2\xC6\x22\xDE\x02\x39\xE7\x68\xCA\x0C\xE6\x29\x8A\x24\xE3\xCF\x8B\x0B\xD4\xC6\x30\xD0\xAB\xC3\x20\xEB\x01\x26\xE7\x33\xCD\x03\xED\xE4\x00\xDA\xE4\xD5\xB0\xE8\x6D\xCF\x0D\xEC\xD4\x17\xD0\xEE\x09\x3E\x89\xA5\xC0\x3F\xA3\xF1\xBE\xE8\x00\xF5\xAC\x25\xE0\xA6\x28\xBD\x90\x05\xF7\xB4\x86\xE3\xBF\xE1\x8B\xEE\x25\x13\xF1\xA3\xBC\x7F\xB3\xEA\x7B\xE1\xC2\xF3\xF4\xA3\x28\xDC\x32\x2C\xC2\xCC\xA3\xBA\xF3\x8F\xE0\xBD\xF3\x72\xA3\x2E\x5D\xFF\x1E\xA2\xAA\x25\xF3\xBE\xE3\xA7\xF6\x37\xA9\xF3\xBD\xC1\x89\x2E\xF5\x6E\xA7\xB5\xAA\xA1\x23\xF7\x09\xE0\xBB\xB0\x54\x2A\xA5\x4D\x3A\xF9\xA5\xF1\xAF\xE4\xB3\x72\x2C\xB3\x4A\x8C\xB4\x2A\xE2\xE1\x20", + }; + vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); + } + + const wchar_t* TypeParserRuleName(vl::vint index) + { + static const wchar_t* results[] = { + L"EnumItem", + L"Enum", + L"ClassPropType", + L"classProp", + L"ClassBody", + L"Class", + L"Type", + L"File", + }; + return results[index]; + } + + const wchar_t* TypeParserStateLabel(vl::vint index) + { + static const wchar_t* results[] = { + L"[0][EnumItem] BEGIN ", + L"[1][EnumItem] END [ENDING]", + L"[2][EnumItem]< ID \",\" @ >", + L"[3][EnumItem]< ID @ \",\" >", + L"[4][Enum] BEGIN ", + L"[5][Enum] END [ENDING]", + L"[6][Enum]< \"enum\" @ ID \"{\" { EnumItem } \"}\" >", + L"[7][Enum]< \"enum\" ID \"{\" @ { EnumItem } \"}\" >", + L"[8][Enum]< \"enum\" ID \"{\" { EnumItem @ } \"}\" >", + L"[9][Enum]< \"enum\" ID \"{\" { EnumItem } \"}\" @ >", + L"[10][Enum]< \"enum\" ID @ \"{\" { EnumItem } \"}\" >", + L"[11][ClassPropType] BEGIN ", + L"[12][ClassPropType] END [ENDING]", + L"[13][ClassPropType]\"token\" @", + L"[14][ClassPropType]ID \"[\" \"]\" @", + L"[15][ClassPropType]ID \"[\" @ \"]\"", + L"[16][ClassPropType]ID @", + L"[17][ClassPropType]ID @ \"[\" \"]\"", + L"[18][classProp] BEGIN ", + L"[19][classProp] END [ENDING]", + L"[20][classProp]< \"var\" @ ID \":\" ClassPropType \";\" >", + L"[21][classProp]< \"var\" ID \":\" @ ClassPropType \";\" >", + L"[22][classProp]< \"var\" ID \":\" ClassPropType \";\" @ >", + L"[23][classProp]< \"var\" ID \":\" ClassPropType @ \";\" >", + L"[24][classProp]< \"var\" ID @ \":\" ClassPropType \";\" >", + L"[25][ClassBody] BEGIN ", + L"[26][ClassBody] END [ENDING]", + L"[27][ClassBody]ID @ [ \":\" ID ] \"{\" { classProp } \"}\"", + L"[28][ClassBody]ID [ \":\" @ ID ] \"{\" { classProp } \"}\"", + L"[29][ClassBody]ID [ \":\" ID @ ] \"{\" { classProp } \"}\"", + L"[30][ClassBody]ID [ \":\" ID ] \"{\" @ { classProp } \"}\"", + L"[31][ClassBody]ID [ \":\" ID ] \"{\" { classProp @ } \"}\"", + L"[32][ClassBody]ID [ \":\" ID ] \"{\" { classProp } \"}\" @", + L"[33][Class] BEGIN ", + L"[34][Class] END [ENDING]", + L"[35][Class]< \"ambiguous\" \"class\" @ ClassBody >", + L"[36][Class]< \"ambiguous\" \"class\" ClassBody @ >", + L"[37][Class]< \"ambiguous\" @ \"class\" ClassBody >", + L"[38][Class]< \"class\" @ ClassBody >", + L"[39][Class]< \"class\" ClassBody @ >", + L"[40][Type] BEGIN ", + L"[41][Type] END [ENDING]", + L"[42][Type]<< ( !Enum @ | !Class ) >>", + L"[43][Type]<< ( !Enum | !Class @ ) >>", + L"[44][File] BEGIN ", + L"[45][File] END [ENDING]", + L"[46][File]< Type @ { Type } >", + L"[47][File]< Type { Type @ } >", + }; + return results[index]; + } + + TypeParser::TypeParser() + : vl::glr::ParserBase(&ParserGenTokenDeleter, &ParserGenLexerData, &ParserGenTypeParserData) + { + }; + + vl::vint32_t TypeParser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const + { + return -1; + }; + + vl::Ptr TypeParser::ParseFile(const vl::WString& input, vl::vint codeIndex) const + { + return Parse(input, this, codeIndex); + }; + + vl::Ptr TypeParser::ParseFile(vl::collections::List& tokens, vl::vint codeIndex) const + { + return Parse(tokens, this, codeIndex); + }; + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGEN_ASSEMBLER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + +/*********************************************************************** +ParserGenAstInsReceiver : public vl::glr::AstInsReceiverBase +***********************************************************************/ + + vl::Ptr ParserGenAstInsReceiver::CreateAstNode(vl::vint32_t type) + { + auto cppTypeName = ParserGenCppTypeName((ParserGenClasses)type); + switch((ParserGenClasses)type) + { + case ParserGenClasses::AlternativeSyntax: + return new vl::glr::parsergen::GlrAlternativeSyntax(); + case ParserGenClasses::Assignment: + return new vl::glr::parsergen::GlrAssignment(); + case ParserGenClasses::AstFile: + return new vl::glr::parsergen::GlrAstFile(); + case ParserGenClasses::Class: + return new vl::glr::parsergen::GlrClass(); + case ParserGenClasses::ClassProp: + return new vl::glr::parsergen::GlrClassProp(); + case ParserGenClasses::CreateClause: + return new vl::glr::parsergen::GlrCreateClause(); + case ParserGenClasses::Enum: + return new vl::glr::parsergen::GlrEnum(); + case ParserGenClasses::EnumItem: + return new vl::glr::parsergen::GlrEnumItem(); + case ParserGenClasses::LiteralSyntax: + return new vl::glr::parsergen::GlrLiteralSyntax(); + case ParserGenClasses::LoopSyntax: + return new vl::glr::parsergen::GlrLoopSyntax(); + case ParserGenClasses::OptionalSyntax: + return new vl::glr::parsergen::GlrOptionalSyntax(); + case ParserGenClasses::PartialClause: + return new vl::glr::parsergen::GlrPartialClause(); + case ParserGenClasses::RefSyntax: + return new vl::glr::parsergen::GlrRefSyntax(); + case ParserGenClasses::ReuseClause: + return new vl::glr::parsergen::GlrReuseClause(); + case ParserGenClasses::Rule: + return new vl::glr::parsergen::GlrRule(); + case ParserGenClasses::SequenceSyntax: + return new vl::glr::parsergen::GlrSequenceSyntax(); + case ParserGenClasses::SyntaxFile: + return new vl::glr::parsergen::GlrSyntaxFile(); + case ParserGenClasses::UseSyntax: + return new vl::glr::parsergen::GlrUseSyntax(); + default: + return vl::glr::AssemblyThrowCannotCreateAbstractType(type, cppTypeName); + } + } + + void ParserGenAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value) + { + auto cppFieldName = ParserGenCppFieldName((ParserGenFields)field); + switch((ParserGenFields)field) + { + case ParserGenFields::AlternativeSyntax_first: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrAlternativeSyntax::first, object, field, value, cppFieldName); + case ParserGenFields::AlternativeSyntax_second: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrAlternativeSyntax::second, object, field, value, cppFieldName); + case ParserGenFields::AstFile_types: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrAstFile::types, object, field, value, cppFieldName); + case ParserGenFields::Class_props: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrClass::props, object, field, value, cppFieldName); + case ParserGenFields::CreateClause_assignments: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrCreateClause::assignments, object, field, value, cppFieldName); + case ParserGenFields::CreateClause_syntax: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrCreateClause::syntax, object, field, value, cppFieldName); + case ParserGenFields::Enum_items: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrEnum::items, object, field, value, cppFieldName); + case ParserGenFields::LoopSyntax_delimiter: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrLoopSyntax::delimiter, object, field, value, cppFieldName); + case ParserGenFields::LoopSyntax_syntax: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrLoopSyntax::syntax, object, field, value, cppFieldName); + case ParserGenFields::OptionalSyntax_syntax: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrOptionalSyntax::syntax, object, field, value, cppFieldName); + case ParserGenFields::PartialClause_assignments: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrPartialClause::assignments, object, field, value, cppFieldName); + case ParserGenFields::PartialClause_syntax: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrPartialClause::syntax, object, field, value, cppFieldName); + case ParserGenFields::ReuseClause_assignments: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrReuseClause::assignments, object, field, value, cppFieldName); + case ParserGenFields::ReuseClause_syntax: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrReuseClause::syntax, object, field, value, cppFieldName); + case ParserGenFields::Rule_clauses: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrRule::clauses, object, field, value, cppFieldName); + case ParserGenFields::SequenceSyntax_first: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrSequenceSyntax::first, object, field, value, cppFieldName); + case ParserGenFields::SequenceSyntax_second: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrSequenceSyntax::second, object, field, value, cppFieldName); + case ParserGenFields::SyntaxFile_rules: + return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrSyntaxFile::rules, object, field, value, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName); + } + } + + void ParserGenAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) + { + auto cppFieldName = ParserGenCppFieldName((ParserGenFields)field); + switch((ParserGenFields)field) + { + case ParserGenFields::Assignment_field: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrAssignment::field, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::Assignment_value: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrAssignment::value, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::Class_baseClass: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrClass::baseClass, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::ClassProp_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrClassProp::name, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::ClassProp_propTypeName: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrClassProp::propTypeName, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::CreateClause_type: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrCreateClause::type, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::EnumItem_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrEnumItem::name, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::LiteralSyntax_value: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrLiteralSyntax::value, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::PartialClause_type: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrPartialClause::type, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::RefSyntax_field: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRefSyntax::field, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::RefSyntax_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRefSyntax::name, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::Rule_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRule::name, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::Type_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrType::name, object, field, token, tokenIndex, cppFieldName); + case ParserGenFields::UseSyntax_name: + return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrUseSyntax::name, object, field, token, tokenIndex, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName); + } + } + + void ParserGenAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem) + { + auto cppFieldName = ParserGenCppFieldName((ParserGenFields)field); + switch((ParserGenFields)field) + { + case ParserGenFields::Class_ambiguity: + return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrClass::ambiguity, object, field, enumItem, cppFieldName); + case ParserGenFields::ClassProp_propType: + return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrClassProp::propType, object, field, enumItem, cppFieldName); + case ParserGenFields::OptionalSyntax_priority: + return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrOptionalSyntax::priority, object, field, enumItem, cppFieldName); + default: + return vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName); + } + } + + const wchar_t* ParserGenTypeName(ParserGenClasses type) + { + const wchar_t* results[] = { + L"AlternativeSyntax", + L"Assignment", + L"AstFile", + L"Class", + L"ClassProp", + L"Clause", + L"CreateClause", + L"Enum", + L"EnumItem", + L"LiteralSyntax", + L"LoopSyntax", + L"OptionalSyntax", + L"PartialClause", + L"RefSyntax", + L"ReuseClause", + L"Rule", + L"SequenceSyntax", + L"Syntax", + L"SyntaxFile", + L"Type", + L"UseSyntax", + }; + vl::vint index = (vl::vint)type; + return 0 <= index && index < 21 ? results[index] : nullptr; + } + + const wchar_t* ParserGenCppTypeName(ParserGenClasses type) + { + const wchar_t* results[] = { + L"vl::glr::parsergen::GlrAlternativeSyntax", + L"vl::glr::parsergen::GlrAssignment", + L"vl::glr::parsergen::GlrAstFile", + L"vl::glr::parsergen::GlrClass", + L"vl::glr::parsergen::GlrClassProp", + L"vl::glr::parsergen::GlrClause", + L"vl::glr::parsergen::GlrCreateClause", + L"vl::glr::parsergen::GlrEnum", + L"vl::glr::parsergen::GlrEnumItem", + L"vl::glr::parsergen::GlrLiteralSyntax", + L"vl::glr::parsergen::GlrLoopSyntax", + L"vl::glr::parsergen::GlrOptionalSyntax", + L"vl::glr::parsergen::GlrPartialClause", + L"vl::glr::parsergen::GlrRefSyntax", + L"vl::glr::parsergen::GlrReuseClause", + L"vl::glr::parsergen::GlrRule", + L"vl::glr::parsergen::GlrSequenceSyntax", + L"vl::glr::parsergen::GlrSyntax", + L"vl::glr::parsergen::GlrSyntaxFile", + L"vl::glr::parsergen::GlrType", + L"vl::glr::parsergen::GlrUseSyntax", + }; + vl::vint index = (vl::vint)type; + return 0 <= index && index < 21 ? results[index] : nullptr; + } + + const wchar_t* ParserGenFieldName(ParserGenFields field) + { + const wchar_t* results[] = { + L"AlternativeSyntax::first", + L"AlternativeSyntax::second", + L"Assignment::field", + L"Assignment::value", + L"AstFile::types", + L"Class::ambiguity", + L"Class::baseClass", + L"Class::props", + L"ClassProp::name", + L"ClassProp::propType", + L"ClassProp::propTypeName", + L"CreateClause::assignments", + L"CreateClause::syntax", + L"CreateClause::type", + L"Enum::items", + L"EnumItem::name", + L"LiteralSyntax::value", + L"LoopSyntax::delimiter", + L"LoopSyntax::syntax", + L"OptionalSyntax::priority", + L"OptionalSyntax::syntax", + L"PartialClause::assignments", + L"PartialClause::syntax", + L"PartialClause::type", + L"RefSyntax::field", + L"RefSyntax::name", + L"ReuseClause::assignments", + L"ReuseClause::syntax", + L"Rule::clauses", + L"Rule::name", + L"SequenceSyntax::first", + L"SequenceSyntax::second", + L"SyntaxFile::rules", + L"Type::name", + L"UseSyntax::name", + }; + vl::vint index = (vl::vint)field; + return 0 <= index && index < 35 ? results[index] : nullptr; + } + + const wchar_t* ParserGenCppFieldName(ParserGenFields field) + { + const wchar_t* results[] = { + L"vl::glr::parsergen::GlrAlternativeSyntax::first", + L"vl::glr::parsergen::GlrAlternativeSyntax::second", + L"vl::glr::parsergen::GlrAssignment::field", + L"vl::glr::parsergen::GlrAssignment::value", + L"vl::glr::parsergen::GlrAstFile::types", + L"vl::glr::parsergen::GlrClass::ambiguity", + L"vl::glr::parsergen::GlrClass::baseClass", + L"vl::glr::parsergen::GlrClass::props", + L"vl::glr::parsergen::GlrClassProp::name", + L"vl::glr::parsergen::GlrClassProp::propType", + L"vl::glr::parsergen::GlrClassProp::propTypeName", + L"vl::glr::parsergen::GlrCreateClause::assignments", + L"vl::glr::parsergen::GlrCreateClause::syntax", + L"vl::glr::parsergen::GlrCreateClause::type", + L"vl::glr::parsergen::GlrEnum::items", + L"vl::glr::parsergen::GlrEnumItem::name", + L"vl::glr::parsergen::GlrLiteralSyntax::value", + L"vl::glr::parsergen::GlrLoopSyntax::delimiter", + L"vl::glr::parsergen::GlrLoopSyntax::syntax", + L"vl::glr::parsergen::GlrOptionalSyntax::priority", + L"vl::glr::parsergen::GlrOptionalSyntax::syntax", + L"vl::glr::parsergen::GlrPartialClause::assignments", + L"vl::glr::parsergen::GlrPartialClause::syntax", + L"vl::glr::parsergen::GlrPartialClause::type", + L"vl::glr::parsergen::GlrRefSyntax::field", + L"vl::glr::parsergen::GlrRefSyntax::name", + L"vl::glr::parsergen::GlrReuseClause::assignments", + L"vl::glr::parsergen::GlrReuseClause::syntax", + L"vl::glr::parsergen::GlrRule::clauses", + L"vl::glr::parsergen::GlrRule::name", + L"vl::glr::parsergen::GlrSequenceSyntax::first", + L"vl::glr::parsergen::GlrSequenceSyntax::second", + L"vl::glr::parsergen::GlrSyntaxFile::rules", + L"vl::glr::parsergen::GlrType::name", + L"vl::glr::parsergen::GlrUseSyntax::name", + }; + vl::vint index = (vl::vint)field; + return 0 <= index && index < 35 ? results[index] : nullptr; + } + + vl::Ptr ParserGenAstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates) + { + auto cppTypeName = ParserGenCppTypeName((ParserGenClasses)type); + return vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName); + } + } + } +} + + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGEN_LEXER.CPP +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + bool ParserGenTokenDeleter(vl::vint token) + { + switch((ParserGenTokens)token) + { + case ParserGenTokens::COMMENT: + case ParserGenTokens::SPACE: + return true; + default: + return false; + } + } + + const wchar_t* ParserGenTokenId(ParserGenTokens token) + { + static const wchar_t* results[] = { + L"AMBIGUOUS", + L"CLASS", + L"ENUM", + L"VAR", + L"TOKEN", + L"AS", + L"PARTIAL", + L"OPEN_ROUND", + L"CLOSE_ROUND", + L"OPEN_SQUARE", + L"CLOSE_SQUARE", + L"OPEN_CURLY", + L"CLOSE_CURLY", + L"COMMA", + L"COLON", + L"SEMICOLON", + L"INFER", + L"ALTERNATIVE", + L"USE", + L"ASSIGN", + L"POSITIVE", + L"NEGATIVE", + L"ID", + L"STRING", + L"SPACE", + L"COMMENT", + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < ParserGenTokenCount ? results[index] : nullptr; + } + + const wchar_t* ParserGenTokenDisplayText(ParserGenTokens token) + { + static const wchar_t* results[] = { + L"ambiguous", + L"class", + L"enum", + L"var", + L"token", + L"as", + L"partial", + L"(", + L")", + L"[", + L"]", + L"{", + L"}", + L",", + L":", + L";", + L"::=", + L"|", + L"!", + L"=", + L"+", + L"-", + nullptr, + nullptr, + nullptr, + nullptr, + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < ParserGenTokenCount ? results[index] : nullptr; + } + + const wchar_t* ParserGenTokenRegex(ParserGenTokens token) + { + static const wchar_t* results[] = { + L"ambiguous", + L"class", + L"enum", + L"var", + L"token", + L"as", + L"partial", + L"/(", + L"/)", + L"/[", + L"/]", + L"/{", + L"/}", + L",", + L":", + L";", + L"::=", + L"/|", + L"!", + L"=", + L"/+", + L"-", + L"[a-zA-Z_][a-zA-Z0-9_]*", + L"(\"[^\"]*\")+", + L"/s+", + L"////[^/r/n]*", + }; + vl::vint index = (vl::vint)token; + return 0 <= index && index < ParserGenTokenCount ? results[index] : nullptr; + } + + void ParserGenLexerData(vl::stream::IStream& outputStream) + { + static const vl::vint dataLength = 1368; // 15852 bytes before compressing + static const vl::vint dataBlock = 256; + static const vl::vint dataRemain = 88; + static const vl::vint dataSolidRows = 5; + static const vl::vint dataRows = 6; + static const char* compressed[] = { + "\xEC\x3D\x00\x00\x50\x05\x00\x00\x40\x00\x01\xBB\x01\x84\x81\x82\x1C\x82\x01\x04\x88\x04\x89\x04\x84\x82\x05\x0F\x84\x8B\x04\x8C\x04\x81\x06\x8B\x04\x8E\x04\x9F\x04\x80\x11\x8E\x82\x21\x20\x84\x82\x13\x94\x83\x10\x82\x27\x04\xA8\x0A\x94\x81\x15\x96\x82\x2A\x30\x84\x8B\x13\x9C\x80\x16\x9B\x04\xAD\x39\x84\x8E\x14\x9C\x83\x17\x3F\x84\xB0\x04\x89\x1C\x83\x82\x83\x04\x83\x82\x84\x8C\x1C\xA4\x83\x1E\x4F\x84\xBE\x04\x80\x81\x81\x20\x82\x5A\x04\x9B\x3A\xA4\x84\x2D\xAE\x82\x5D\x60\x84\x9E\x23\xB4\x83\x2E\xB3\x04\xE0\x29\xA4\x81\x34\xB4\x82\x31\x6F\x84\xA3\x32\xB4\x84\x31\xBA\x82\x65\x78\x84\x86\x3B\xBC\x83\x32\xBF\x04\xE8\x01\xC4\x89\x34\xC0\x82\x35\x87\x84\xAB\x2A\xC4\x84\x35\xC6\x82\x6D\x10\xC4\x8E\x33\xCC\x83\x36\xCB\x04\xF0\x19\xC4\x81\x3C\xCC\x82\x39\x9F\x84\xB3\x22\xD4\x84\x39\xD2\x82\x75\x28\xC4\x96\x3B\xD4\x83\x3A\x82\x7A\x04\xBB\x32\xD4\x84\x3D\xDA\x82\x7D\x38\xC4\x9E\x34\x87\x7F\x7E\x08\x00\x3E\xFE\xD7\x04\x84\xE1\x80\xE1\xFF\x46\xC1\xE2\xEA\xE1\x08\x82\x0B\xBD\xC2\xC7\x0A\x81\xEE\xDF\x08\x8C\x01\x94\x15\xFF", + "\x78\x0B\xEE\x8D\x80\x0F\x5B\xD2\x1B\xE5\x0E\x87\xE2\xE1\x10\xE7\xFE\xC5\xFA\xF7\x7D\x85\x80\xEC\x80\x02\x04\x81\xFB\x00\xFB\xFB\xF0\xF8\xC0\x11\xFC\xFA\xFD\xFF\x80\x06\x3E\x7A\x7D\x01\xFA\x44\x0A\x7F\x44\x01\x40\x71\x41\x45\xED\x48\x7E\x83\x83\x10\x91\x82\x87\x84\x14\x95\x88\x73\x06\xDB\x56\x82\x70\x86\x0D\x94\x8C\x87\x72\xBE\x5F\x82\x88\x41\x23\x81\x45\x88\x00\x27\xA9\x84\x41\x06\x24\xAD\x86\x8A\x8B\x28\x84\x4A\x04\x8C\x2A\x9D\x8A\x87\x8D\x38\xB9\x8A\x8F\x83\x1F\xBB\x8F\x3D\x8F\x37\x80\x91\x88\x8D\x44\xAF\x86\x91\x8C\x47\xA7\x8C\x05\x91\x48\x8D\x95\x8E\x93\x4C\xBE\x82\x97\x94\x54\xBC\x89\x85\x90\x57\x93\x82\x93\x8F\x4C\x8F\x9E\x95\x97\x04\x5D\x00\x99\x92\x63\x8D\x95\x97\x99\x68\xB9\x8B\x94\x8E\x6B\x9E\x8B\x76\x07\x65\x9F\x94\x9B\x9C\x50\xB4\x92\x9D\x9D\x66\xA9\x9A\x9F\x9E\x10\xAD\x9A\x86\x9F\x12\x9B\x97\x9F\xA0\x71\xB0\x8C\x46\x9D\x85\x87\x9C\x9F\xA2\x8B\x80\xA5\x86\xA3\x7D\x9B\x7E\x44\xA2\x94\xB8\x94\xA1\xA5\x97\xB9\x9C\xA3\xA6\x9C\x9D\xAE\xA7\xA7\xA0\xA1\xA2\xAB\xA8\xA4\xA5\xA6\xAB\xA9\xA8\xA9\xAA\xAB\xAA", + "\xAC\xAD\xAE\xAB\xAB\xB0\xB1\xA2\xAF\xAC\xB4\xB5\xA6\xAF\xAD\xB8\xB9\xAA\xAF\xAE\xBC\x8B\xA1\x4A\x8D\xBD\x81\xB2\xB3\xB0\xC4\x85\xB6\xB3\xB1\xC8\x89\xBA\xB3\xB2\xCC\x8D\xBE\xB3\xB3\xD0\x91\xB2\xB7\xB4\xD4\xBE\x80\xA6\x96\x59\x81\xAB\x75\xA6\xDC\x89\xA6\xA6\xB7\xD7\x92\x84\x49\x40\xE3\x80\x05\xBB\xB9\x25\x64\xB9\xB8\x00\x27\x6A\xBE\xBA\xB9\xEB\xA8\xBF\xBA\xBC\xF0\xB3\xB1\xBF\xBD\xF6\xB9\xB5\xBF\xBE\xF4\xBD\xB8\xBC\xBF\xFF\xBE\xBA\xBE\xC0\x00\xC3\xC1\xC1\xB6\x24\x04\x49\xC1\x7B\x0B\xE0\x8F\x3D\xC3\xD5\x91\xC2\xC6\x84\x25\x19\xB3\xC7\xC5\xA7\xA1\xB1\x86\xC6\x1B\x9B\xB4\x42\x09\xE0\xA1\xC8\xA6\xC8\x78\x97\xCC\xC6\x95\xC0\x9B\xCE\xC7\xC8\x2C\xDF\xBD\xC9\xB7\x8A\x93\xC7\xCA\x83\x33\xC2\xA4\xC8\xCC\x2E\xF9\xC9\xA6\xC9\x16\xEE\x99\xC9\xA4\xED\x69\x4F\xCB\xCD\x44\xC3\xDF\xCF\xB3\x33\xD7\x8D\xCC\xCA\x0E\xF8\xCE\xD1\xD1\x4D\xAB\x44\x9C\xCF\x47\xDA\xB5\xD6\xD2\xED\x4F\xD6\xD2\xCE\x30\xAE\x4B\xD4\xD5\x0E\xEC\x9B\xD0\xCD\x2B\xDC\xDB\xD5\x4C\x5B\xDA\xD1\xD8\xB5\x49\xDD\xC7\xD6\xDB\x4D\xD0\xDA\xDB\x93\x34\x5F\xD8\xC6\x86\x37", + "\x6F\xD7\xDE\xA7\x04\xFD\xDB\xB9\xBB\x05\xC1\xEE\xDE\xC1\x84\xC2\xE7\xC1\xE1\x83\xC6\xE8\xE3\xE1\x8A\xCD\xE9\xE0\xBD\x9E\xBA\x4A\xDF\xDE\x77\xCD\xC0\xC6\x70\x97\xFE\x69\xE4\xE5\x9C\xD5\x8D\x4D\x40\x9F\xCE\xC1\xE8\x72\xA1\xE5\xEE\x4C\xE8\xA7\xC0\x06\xE8\xEA\xAC\xEA\xE9\xEB\xEA\xAE\xED\xE0\xEF\xEC\xAF\xF5\xE2\xEE\xED\xB1\xF9\xE4\xEF\xED\xBC\xFA\xE8\xEF\xEE\xBE\xFD\xE0\xF3\xE8\xC8\xAD\xD3\x93\xE4\x36\xE9\xD0\x8C\x50\xCA\xCD\xF5\xCA\xCC\x63\xEA\xC8\xF1\xD9\x73\xF2\xDC\x93\x50\x2D\xE0\xD6\xB5\xF4\x70\xD8\xD6\xDB\xF7\x4F\xB1\x06\xF5\xA5\xDA\xFB\x85\xCC\xF5\xE3\xE0\xF9\xFB\x89\xE5\xFA\x87\xF9\xD6\x65\xB2\x0B\xFB\xFC\x53\xD0\xF3\xE6\xF7\x62\xF0\xFE\xF1\xF5\x2D\xF3\x05\x99\xE7\x00\x95\x54\x0D\x04\x23\x81\x80\x05\x80\x00\x07\x89\x80\x01\x8B\x81\x21\x1A\x0C\x80\x81\x0F\x8A\x82\x01\x91\x84\x83\x09\x96\x80\x82\x17\x92\x80\x06\x9B\x8A\x83\x0E\x95\x84\x83\x1F\x9E\x81\x06\xA1\x84\x85\x11\xA6\x80\x84\x27\x87\x80\xE9\x29\x7B\x85\xF6\x03\x7F\x77\x30\x82\x79\x0C\xC1\x74\x87\x17\xB2\x87\x86\x35\x93\x86\x0D\xB9\x88\x87\x1D\x80\x79", + "\x59\xC6\x7C\x4B\xF4\x7A\x7A\x7D\x80\x36\x04\x7E\x45\x99\x65\xFB\x6A\x4C\x7B\xE3\x71\x6B\x7F\x48\x87\x47\x0D\x5E\x5B\x89\xFC\x6B\x68\x5B\x44\x9C\x7D\x12\xDA\x81\x89\x62\x41\x8F\x7D\x4F\x9B\x88\xD4\x38\x01\x8B\x26\x8A\x5F\x8B\x66\x89\x7A\x18\xC7\x45\x28\x28\xAE\x8F\x8A\x16\x42\x84\x0A\xF3\x87\x80\x07\xA9\x85\x84\x74\x98\x8E\x1C\xFB\x8A\x8F\x3E\xB7\x8F\x8F\x79\x80\x90\x1F\x82\x9F\x83\xC8\x66\x89\x80\x88\x91\x54\x1A\xC3\x81\x8C\x2E\xA5\x8F\x48\x47\x2F\x7A\xC4\x0B\x90\x8E\xE9\x4D\x97\x91\x6B\x99\x91\x15\xD8\x4C\x90\xEF\x4E\x97\x8D\x38\x7B\x93\x9F\x69\x8B\x3A\xA5\x19\x97\x93\xA7\x87\x91\xF1\x2A\x9E\x88\x2B\x9E\x90\x93\x4F\x4D\x28\x28\xAC\x96\x58\x4A\xAE\x90\x6E\xA8\x9F\x40\x54\x33\x94\x7C\xFB\x55\x96\x67\xBF\x8C\x6B\x2B\xBC\x99\x95\x4A\x53\x2D\x7E\x93\x94\x94\x18\xC3\x95\x99\x66\xAA\x6A\x94\x16\x4B\x98\x2E\xB0\x90\x6B\x1F\x14\x8E\x97\xDB\x7D\x93\x34\xC4\x99\x97\xFF\x7B\x46\x1F\xFF\x1F\x16\x3F\x79\x1F\x1B\x77\x3F\x1D\x2A\x05\x20\x00\x74\x01\x2B\x9C\x75\x8F\x3F\x9D\xEC\x84\x23\x74\x01\x2B\x21\x80\x0D\x21\x20\xE9\x20", + "\x00\x82\x00\x0C\x40\x00\x17\x21\x20\xDF\x20\x01\x78\x01\x2E\x39\x80\x23\x39\x20\xD7\x39\x3A\x7E\x6D\x93\x47\x80\x1D\x39\x20\x0D\xAE\x9D\x40\x04\x41\x9F\x8A\x92\xA7\xA2\xED\x8C\xA2\x8C\x45\x34\x21\x87\x80\x04\x45\x16\xB9\xA0\x41\x76\x31\xA4\x82\x0A\x40\x00\x11\xA0\xA4\x46\x84\x23\x3F\x92\x90\xA4\xA3\x16\xAF\x3C\x00\x06\x4E\xA5\x95\x80\x40\x9E\xE9\x80", + }; + vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); + } + } + } +} + + +/*********************************************************************** +.\SYNTAX\SYNTAXCPPGEN.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace stream; + using namespace regex; + +/*********************************************************************** +GenerateSyntaxFileNames +***********************************************************************/ + + Ptr GenerateSyntaxFileNames(SyntaxSymbolManager& manager, Ptr output) + { + auto syntaxOutput = MakePtr(); + syntaxOutput->syntaxH = manager.Global().name + manager.name + L".h"; + syntaxOutput->syntaxCpp = manager.Global().name + manager.name + L".cpp"; + output->syntaxOutputs.Add(&manager, syntaxOutput); + return syntaxOutput; + } + +/*********************************************************************** +WriteSyntaxHeaderFile +***********************************************************************/ + + void WriteSyntaxHeaderFile(SyntaxSymbolManager& manager, automaton::Executable& executable, automaton::Metadata& metadata, Ptr output, stream::StreamWriter& writer) + { + WriteFileComment(manager.Global().name, writer); + if (manager.Global().headerGuard != L"") + { + writer.WriteString(L"#ifndef "); + writer.WriteLine(manager.Global().headerGuard + L"_" + wupper(manager.name) + L"_SYNTAX"); + writer.WriteString(L"#define "); + writer.WriteLine(manager.Global().headerGuard + L"_" + wupper(manager.name) + L"_SYNTAX"); + } + else + { + writer.WriteLine(L"#pragma once"); + } + writer.WriteLine(L""); + writer.WriteLine(L"#include \"" + output->assemblyH + L"\""); + writer.WriteLine(L"#include \"" + output->lexerH +L"\""); + writer.WriteLine(L""); + + WString prefix = WriteNssBegin(manager.Global().cppNss, writer); + { + writer.WriteLine(prefix + L"enum class " + manager.name + L"States"); + writer.WriteLine(prefix + L"{"); + for (auto&& [ruleName, index] : indexed(metadata.ruleNames)) + { + writer.WriteLine(prefix + L"\t" + ruleName + L" = " + itow(executable.ruleStartStates[index]) + L","); + } + writer.WriteLine(prefix + L"};"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"template<" + manager.name + L"States> struct " + manager.name + L"StateTypes;"); + for(auto ruleName : manager.RuleOrder()) + { + auto ruleSymbol = manager.Rules()[ruleName]; + if (manager.parsableRules.Contains(ruleSymbol)) + { + auto astType = manager.ruleTypes[ruleSymbol]; + writer.WriteLine(prefix + L"template<> struct " + manager.name + L"StateTypes<" + manager.name + L"States::" + ruleName + L"> { using Type = " + astType + L"; };"); + } + } + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.name + L"RuleName(vl::vint index);"); + writer.WriteLine(prefix + L"const wchar_t* " + manager.name + L"StateLabel(vl::vint index);"); + WriteLoadDataFunctionHeader(prefix, manager.Global().name + manager.name + L"Data", writer); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"class " + manager.name); + writer.WriteString(prefix+L"\t: public vl::glr::ParserBase<"); + writer.WriteString(manager.Global().name + L"Tokens, "); + writer.WriteString(manager.name + L"States, "); + writer.WriteString(manager.Global().name + L"AstInsReceiver, "); + writer.WriteLine(manager.name + L"StateTypes>"); + writer.WriteLine(prefix + L"\t, protected vl::glr::automaton::TraceManager::ITypeCallback"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"protected:"); + writer.WriteLine(prefix + L"\tvl::vint32_t FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const override;"); + writer.WriteLine(prefix + L"public:"); + writer.WriteLine(prefix + L"\t" + manager.name + L"();"); + writer.WriteLine(L""); + for (auto ruleName : manager.RuleOrder()) + { + auto ruleSymbol = manager.Rules()[ruleName]; + if (manager.parsableRules.Contains(ruleSymbol)) + { + auto astType = manager.ruleTypes[ruleSymbol]; + writer.WriteLine(prefix + L"\tvl::Ptr<" + astType + L"> Parse" + ruleName + L"(const vl::WString& input, vl::vint codeIndex = -1) const;"); + writer.WriteLine(prefix + L"\tvl::Ptr<" + astType + L"> Parse" + ruleName + L"(vl::collections::List& tokens, vl::vint codeIndex = -1) const;"); + } + } + writer.WriteLine(prefix + L"};"); + } + WriteNssEnd(manager.Global().cppNss, writer); + + if (manager.Global().headerGuard != L"") + { + writer.WriteString(L"#endif"); + } + } + +/*********************************************************************** +WriteSyntaxCppFile +***********************************************************************/ + + void WriteSyntaxCppFile(SyntaxSymbolManager& manager, automaton::Executable& executable, automaton::Metadata& metadata, Ptr output, stream::StreamWriter& writer) + { + WriteFileComment(manager.Global().name, writer); + writer.WriteLine(L"#include \"" + output->syntaxOutputs[&manager]->syntaxH + L"\""); + writer.WriteLine(L""); + WString prefix = WriteNssBegin(manager.Global().cppNss, writer); + { + MemoryStream syntaxData; + executable.Serialize(syntaxData); + syntaxData.SeekFromBegin(0); + WriteLoadDataFunctionCpp(prefix, manager.Global().name + manager.name + L"Data", syntaxData, true, writer); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.name + L"RuleName(vl::vint index)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tstatic const wchar_t* results[] = {"); + for (auto&& ruleName : metadata.ruleNames) + { + writer.WriteString(prefix + L"\t\tL\""); + WriteCppStringBody(ruleName, writer); + writer.WriteLine(L"\","); + } + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\treturn results[index];"); + writer.WriteLine(prefix + L"}"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"const wchar_t* " + manager.name + L"StateLabel(vl::vint index)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\tstatic const wchar_t* results[] = {"); + for (auto&& stateLabel : metadata.stateLabels) + { + writer.WriteString(prefix + L"\t\tL\""); + WriteCppStringBody(stateLabel, writer); + writer.WriteLine(L"\","); + } + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\treturn results[index];"); + writer.WriteLine(prefix + L"}"); + } + { + writer.WriteLine(L""); + writer.WriteLine(prefix + manager.name + L"::"+ manager.name + L"()"); + writer.WriteString(prefix + L"\t: vl::glr::ParserBase<"); + writer.WriteString(manager.Global().name + L"Tokens, "); + writer.WriteString(manager.name + L"States, "); + writer.WriteString(manager.Global().name + L"AstInsReceiver, "); + writer.WriteString(manager.name + L"StateTypes>("); + writer.WriteString(L"&" + manager.Global().name + L"TokenDeleter, "); + writer.WriteString(L"&" + manager.Global().name + L"LexerData, "); + writer.WriteLine(L"&" + manager.Global().name + manager.name + L"Data)"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"};"); + } + + { + writer.WriteLine(L""); + writer.WriteLine(prefix + L"vl::vint32_t " + manager.name + L"::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const"); + writer.WriteLine(prefix + L"{"); + if ( + output->classIds.Count() == 0 || + From(output->classIds.Keys()) + .Where([](auto c) { return c->ambiguousDerivedClass != nullptr; }) + .IsEmpty() + ) + { + writer.WriteLine(prefix + L"\treturn -1;"); + } + else + { + Array idToClasses(output->classIds.Count()); + for (auto [k, v] : output->classIds) + { + idToClasses[v] = k; + } + + writer.WriteLine(prefix + L"\tstatic vl::vint32_t results[" + itow(idToClasses.Count()) + L"][" + itow(idToClasses.Count()) + L"] = {"); + for (auto [c1, i1] : indexed(idToClasses)) + { + writer.WriteString(prefix + L"\t\t{"); + for (auto [c2, i2] : indexed(idToClasses)) + { + if (auto baseClass = FindCommonBaseClass(c1, c2)) + { + writer.WriteString(itow(output->classIds[baseClass]) + L", "); + } + else + { + writer.WriteString(L"-1, "); + } + } + writer.WriteLine(L"},"); + } + writer.WriteLine(prefix + L"\t};"); + writer.WriteLine(prefix + L"\treturn vl::glr::AssemblerFindCommonBaseClass(class1, class2, results);"); + } + writer.WriteLine(prefix + L"};"); + } + + for (auto ruleName : manager.RuleOrder()) + { + auto ruleSymbol = manager.Rules()[ruleName]; + if (manager.parsableRules.Contains(ruleSymbol)) + { + auto astType = manager.ruleTypes[ruleSymbol]; + writer.WriteLine(L""); + writer.WriteLine(prefix + L"vl::Ptr<" + astType + L"> " + manager.name + L"::Parse" + ruleName + L"(const vl::WString& input, vl::vint codeIndex) const"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\t return Parse<" + manager.name + L"States::" + ruleName + L">(input, this, codeIndex);"); + writer.WriteLine(prefix + L"};"); + writer.WriteLine(L""); + writer.WriteLine(prefix + L"vl::Ptr<" + astType + L"> " + manager.name + L"::Parse" + ruleName + L"(vl::collections::List& tokens, vl::vint codeIndex) const"); + writer.WriteLine(prefix + L"{"); + writer.WriteLine(prefix + L"\t return Parse<" + manager.name + L"States::" + ruleName + L">(tokens, this, codeIndex);"); + writer.WriteLine(prefix + L"};"); + } + } + WriteNssEnd(manager.Global().cppNss, writer); + } + +/*********************************************************************** +WriteLexerFiles +***********************************************************************/ + + void WriteSyntaxFiles(SyntaxSymbolManager& manager, automaton::Executable& executable, automaton::Metadata& metadata, Ptr output, collections::Dictionary& files) + { + WString fileH = GenerateToStream([&](StreamWriter& writer) + { + WriteSyntaxHeaderFile(manager, executable, metadata, output, writer); + }); + + WString fileCpp = GenerateToStream([&](StreamWriter& writer) + { + WriteSyntaxCppFile(manager, executable, metadata, output, writer); + }); + + files.Add(output->syntaxOutputs[&manager]->syntaxH, fileH); + files.Add(output->syntaxOutputs[&manager]->syntaxCpp, fileCpp); + } + } + } +} + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +StateSymbol +***********************************************************************/ + + StateSymbol::StateSymbol(RuleSymbol* _rule, vint32_t _clauseId) + : ownerManager(_rule->Owner()) + , rule(_rule) + , clauseId(_clauseId) + { + } + + void StateSymbol::GetOutEdgesInStableOrder(collections::List& orderedStates, EdgeList& orderedEdges) + { + CopyFrom(orderedEdges, From(outEdges) + .OrderBy([&](EdgeSymbol* e1, EdgeSymbol* e2) + { + vint result = 0; + if (e1->input.type != e2->input.type) + { + result = (vint)e1->input.type - (vint)e2->input.type; + } + else + { + switch (e1->input.type) + { + case EdgeInputType::Token: + result = e1->input.token - e2->input.token; + break; + case EdgeInputType::Rule: + result = ownerManager->RuleOrder().IndexOf(e1->input.rule->Name()) - ownerManager->RuleOrder().IndexOf(e2->input.rule->Name()); + break; + default:; + } + } + + if (result != 0) return result; + return orderedStates.IndexOf(e1->To()) - orderedStates.IndexOf(e2->To()); + })); + } + +/*********************************************************************** +EdgeSymbol +***********************************************************************/ + + EdgeSymbol::EdgeSymbol(StateSymbol* _from, StateSymbol* _to) + : ownerManager(_from->Owner()) + , fromState(_from) + , toState(_to) + { + fromState->outEdges.Add(this); + toState->inEdges.Add(this); + } + +/*********************************************************************** +RuleSymbol +***********************************************************************/ + + RuleSymbol::RuleSymbol(SyntaxSymbolManager* _ownerManager, const WString& _name) + : ownerManager(_ownerManager) + , name(_name) + { + } + +/*********************************************************************** +SyntaxSymbolManager +***********************************************************************/ + + SyntaxSymbolManager::SyntaxSymbolManager(ParserSymbolManager& _global) + : global(_global) + { + } + + RuleSymbol* SyntaxSymbolManager::CreateRule(const WString& name, ParsingTextRange codeRange) + { + CHECK_ERROR(states.Count() + edges.Count() == 0, L"vl::gre::parsergen::SyntaxSymbolManager::CreateRule(const WString&)#Cannot create new rules after building the automaton."); + auto rule = new RuleSymbol(this, name); + if (!rules.Add(name, rule)) + { + AddError( + ParserErrorType::DuplicatedRule, + codeRange, + name + ); + } + return rule; + } + + StateSymbol* SyntaxSymbolManager::CreateState(RuleSymbol* rule, vint32_t clauseId) + { + CHECK_ERROR(phase == SyntaxPhase::EpsilonNFA, L"vl::gre::parsergen::SyntaxSymbolManager::CreateState(RuleSymbol*)#Cannot change the automaton after calling BuildCompactSyntax()."); + auto symbol = new StateSymbol(rule, clauseId); + states.Add(symbol); + return symbol; + } + + EdgeSymbol* SyntaxSymbolManager::CreateEdge(StateSymbol* from, StateSymbol* to) + { + CHECK_ERROR(phase == SyntaxPhase::EpsilonNFA, L"vl::gre::parsergen::SyntaxSymbolManager::CreateEdge(StateSymbol*, StateSymbol*)#Cannot change the automaton after calling BuildCompactSyntax()."); + auto symbol = new EdgeSymbol(from, to); + edges.Add(symbol); + return symbol; + } + + void SyntaxSymbolManager::BuildCompactNFA() + { + CHECK_ERROR(global.Errors().Count() == 0, L"vl::gre::parsergen::SyntaxSymbolManager::BuildCompactSyntax()#BuildCompactNFA() cannot be called before errors are resolved."); + CHECK_ERROR(phase == SyntaxPhase::EpsilonNFA, L"vl::gre::parsergen::SyntaxSymbolManager::BuildCompactSyntax()#BuildCompactNFA() can only be called on epsilon NFA."); + BuildCompactNFAInternal(); + phase = SyntaxPhase::CompactNFA; + } + + void SyntaxSymbolManager::BuildCrossReferencedNFA() + { + CHECK_ERROR(global.Errors().Count() == 0, L"vl::gre::parsergen::SyntaxSymbolManager::BuildCompactSyntax()#BuildCrossReferencedNFA() cannot be called before errors are resolved."); + CHECK_ERROR(phase == SyntaxPhase::CompactNFA, L"vl::gre::parsergen::SyntaxSymbolManager::BuildCompactSyntax()#BuildCrossReferencedNFA() can only be called on compact NFA."); + BuildCrossReferencedNFAInternal(); + phase = SyntaxPhase::CrossReferencedNFA; + } + + void SyntaxSymbolManager::GetStatesInStableOrder(collections::List& order) + { + Group groupedStates; + { + List visited; + for (auto ruleName : rules.order) + { + auto ruleSymbol = rules.map[ruleName]; + for (auto startState : ruleSymbol->startStates) + { + if (!visited.Contains(startState)) + { + vint startIndex = visited.Add(startState); + for (vint i = startIndex; i < visited.Count(); i++) + { + auto state = visited[i]; + groupedStates.Add(state->Rule(), state); + for (auto edge : state->OutEdges()) + { + auto target = edge->To(); + if (!visited.Contains(target)) + { + visited.Add(target); + } + } + } + } + } + } + } + { + vint counter = 0; + for (auto ruleName : rules.order) + { + auto ruleSymbol = rules.map[ruleName]; + auto orderedStates = From(groupedStates[ruleSymbol]) + .OrderBy([](StateSymbol* s1, StateSymbol* s2) + { + return WString::Compare(s1->label, s2->label); + }); + for (auto state : orderedStates) + { + order.Add(state); + } + } + } + } + + WString SyntaxSymbolManager::GetStateGlobalLabel(StateSymbol* state, vint index) + { + return L"[" + itow(index) + L"][" + state->Rule()->Name() + L"]" + state->label + (state->endingState ? L"[ENDING]" : L""); + } + } + } +} + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL_AUTOMATON.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +SyntaxSymbolManager::BuildAutomaton +***********************************************************************/ + + void SyntaxSymbolManager::BuildAutomaton(vint tokenCount, automaton::Executable& executable, automaton::Metadata& metadata) + { + CHECK_ERROR(global.Errors().Count() == 0, L"vl::gre::parsergen::SyntaxSymbolManager::BuildAutomaton(Executable&, Metadata&)#BuildAutomaton() cannot be called before errors are resolved."); + CHECK_ERROR(phase == SyntaxPhase::CrossReferencedNFA, L"vl::gre::parsergen::SyntaxSymbolManager::BuildAutomaton(Executable&, Metadata&)#BuildAutomaton() can only be called on cross referenced NFA."); + + // metadata.ruleNames + List rulesInOrder; + CopyFrom(rulesInOrder, From(rules.order).Select([this](auto&& name) { return rules.map[name]; })); + metadata.ruleNames.Resize(rulesInOrder.Count()); + for (auto [rule, index] : indexed(rulesInOrder)) + { + metadata.ruleNames[index] = rule->Name(); + } + + // metadata.stateLabels + List statesInOrder; + GetStatesInStableOrder(statesInOrder); + metadata.stateLabels.Resize(statesInOrder.Count()); + for (auto [state, index] : indexed(statesInOrder)) + { + metadata.stateLabels[index] = GetStateGlobalLabel(state, index); + } + + executable.tokenCount = (vint32_t)tokenCount; + executable.ruleCount = (vint32_t)rulesInOrder.Count(); + + // executable.ruleStartStates + executable.ruleStartStates.Resize(rulesInOrder.Count()); + for (auto [rule, index] : indexed(rulesInOrder)) + { + executable.ruleStartStates[index] = (vint32_t)statesInOrder.IndexOf(rule->startStates[0]); + } + + // executable.states + executable.states.Resize(statesInOrder.Count()); + for (auto [state, index] : indexed(statesInOrder)) + { + auto&& stateDesc = executable.states[index]; + stateDesc.rule = (vint32_t)rulesInOrder.IndexOf(state->Rule()); + stateDesc.clause = state->ClauseId(); + stateDesc.endingState = state->endingState; + } + + List edgesInOrder; + List returnEdgesInOrder; + List returnIndicesInOrder; + List instructionsInOrder; + + // executable.transitions + vint inputCount = automaton::Executable::TokenBegin + tokenCount; + executable.transitions.Resize(statesInOrder.Count() * inputCount); + for (auto [state, stateIndex] : indexed(statesInOrder)) + { + for (vint input = 0; input < inputCount; input++) + { + auto&& transition = executable.transitions[stateIndex * inputCount + input]; + auto orderedEdges = From(state->OutEdges()) + .Where([&](EdgeSymbol* edge) + { + switch (input) + { + case automaton::Executable::EndingInput: + return edge->input.type == EdgeInputType::Ending; + case automaton::Executable::LeftrecInput: + return edge->input.type == EdgeInputType::LeftRec; + default: + return edge->input.type == EdgeInputType::Token && edge->input.token == input - automaton::Executable::TokenBegin; + } + }) + .OrderBy([&](EdgeSymbol* e1, EdgeSymbol* e2) + { + return statesInOrder.IndexOf(e1->To()) - statesInOrder.IndexOf(e2->To()); + }); + transition.start = (vint32_t)edgesInOrder.Count(); + CopyFrom(edgesInOrder, orderedEdges, true); + transition.count = (vint32_t)edgesInOrder.Count() - transition.start; + if (transition.count == 0) + { + transition.start = -1; + continue; + } + } + } + + // executable.edges + executable.edges.Resize(edgesInOrder.Count()); + for (auto [edge, edgeIndex] : indexed(edgesInOrder)) + { + auto&& edgeDesc = executable.edges[edgeIndex]; + edgeDesc.fromState = (vint32_t)statesInOrder.IndexOf(edge->From()); + edgeDesc.toState = (vint32_t)statesInOrder.IndexOf(edge->To()); + switch (edge->importancy) + { + case EdgeImportancy::HighPriority: + edgeDesc.priority = automaton::EdgePriority::HighPriority; + break; + case EdgeImportancy::LowPriority: + edgeDesc.priority = automaton::EdgePriority::LowPriority; + break; + } + + edgeDesc.insBeforeInput.start = (vint32_t)instructionsInOrder.Count(); + CopyFrom(instructionsInOrder, edge->insBeforeInput, true); + edgeDesc.insBeforeInput.count = (vint32_t)instructionsInOrder.Count() - edgeDesc.insBeforeInput.start; + + edgeDesc.insAfterInput.start = (vint32_t)instructionsInOrder.Count(); + CopyFrom(instructionsInOrder, edge->insAfterInput, true); + edgeDesc.insAfterInput.count = (vint32_t)instructionsInOrder.Count() - edgeDesc.insAfterInput.start; + + edgeDesc.returnIndices.start = (vint32_t)returnIndicesInOrder.Count(); + for (auto returnEdge : edge->returnEdges) + { + vint index = returnEdgesInOrder.IndexOf(returnEdge); + if (index == -1) + { + index = returnEdgesInOrder.Add(returnEdge); + } + returnIndicesInOrder.Add((vint32_t)index); + } + edgeDesc.returnIndices.count = (vint32_t)returnIndicesInOrder.Count() - edgeDesc.returnIndices.start; + + if (edgeDesc.insBeforeInput.count == 0) edgeDesc.insBeforeInput.start = -1; + if (edgeDesc.insAfterInput.count == 0) edgeDesc.insAfterInput.start = -1; + if (edgeDesc.returnIndices.count == 0) edgeDesc.returnIndices.start = -1; + } + + // executable.returns + executable.returns.Resize(returnEdgesInOrder.Count()); + for (auto [edge, edgeIndex] : indexed(returnEdgesInOrder)) + { + auto&& returnDesc = executable.returns[edgeIndex]; + returnDesc.consumedRule = (vint32_t)rulesInOrder.IndexOf(edge->input.rule); + returnDesc.returnState = (vint32_t)statesInOrder.IndexOf(edge->To()); + switch (edge->importancy) + { + case EdgeImportancy::HighPriority: + returnDesc.priority = automaton::EdgePriority::HighPriority; + break; + case EdgeImportancy::LowPriority: + returnDesc.priority = automaton::EdgePriority::LowPriority; + break; + } + + returnDesc.insAfterInput.start = (vint32_t)instructionsInOrder.Count(); + CopyFrom(instructionsInOrder, edge->insAfterInput, true); + returnDesc.insAfterInput.count = (vint32_t)instructionsInOrder.Count() - returnDesc.insAfterInput.start; + if (returnDesc.insAfterInput.count == 0) returnDesc.insAfterInput.start = -1; + } + + // executable.returnIndices + CopyFrom(executable.returnIndices, returnIndicesInOrder); + + // executable.instructions + CopyFrom(executable.instructions, instructionsInOrder); + } + } + } +} + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL_CREATEPARSERGENRULESYNTAX.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace syntax_writer; + + extern syntax_writer::Token tok(ParserGenTokens id); + extern syntax_writer::Token tok(ParserGenTokens id, ParserGenFields field); + +/*********************************************************************** +CreateParserGenRuleSyntax +***********************************************************************/ + + void CreateParserGenRuleSyntax(SyntaxSymbolManager& manager) + { + manager.name = L"RuleParser"; + + auto _optionalBody = manager.CreateRule(L"OptionalBody"); + auto _syntax0 = manager.CreateRule(L"Syntax0"); + auto _syntax1 = manager.CreateRule(L"Syntax1"); + auto _syntax2 = manager.CreateRule(L"Syntax2"); + auto _syntax = manager.CreateRule(L"Syntax"); + auto _assignment = manager.CreateRule(L"Assignment"); + auto _clause = manager.CreateRule(L"Clause"); + auto _rule = manager.CreateRule(L"Rule"); + auto _file = manager.CreateRule(L"File"); + + manager.parsableRules.Add(_file); + manager.ruleTypes.Add(_file, L"vl::glr::parsergen::GlrSyntaxFile"); + + using T = ParserGenTokens; + using C = ParserGenClasses; + using F = ParserGenFields; + + // "[" Syntax:syntax "]" as partial OptionalSyntax + Clause{ _optionalBody } = partial(tok(T::OPEN_SQUARE) + rule(_syntax, F::OptionalSyntax_syntax) + tok(T::CLOSE_SQUARE)); + + // ID:name [":" ID:field] as RefSyntax + Clause{ _syntax0 } = create(tok(T::ID, F::RefSyntax_name) + opt(tok(T::COLON) + tok(T::ID, F::RefSyntax_field)), C::RefSyntax); + + // STRING:value as LiteralSyntax + Clause{ _syntax0 } = create(tok(T::STRING, F::LiteralSyntax_value), C::LiteralSyntax); + + // "!" ID:name as UseSyntax + Clause{ _syntax0 } = create(tok(T::USE) + tok(T::ID, F::UseSyntax_name), C::UseSyntax); + + // "{" Syntax:syntax [";" syntax:delimiter] "}" as LoopSyntax + Clause{ _syntax0 } = create(tok(T::OPEN_CURLY) + rule(_syntax, F::LoopSyntax_syntax) + opt(tok(T::SEMICOLON) + rule(_syntax, F::LoopSyntax_delimiter)) + tok(T::CLOSE_CURLY), C::LoopSyntax); + + // "+" OptionalBody as OptionalSyntax {priority = PreferTake} + Clause{ _syntax0 } = create(tok(T::POSITIVE) + prule(_optionalBody), C::OptionalSyntax).with(F::OptionalSyntax_priority, GlrOptionalPriority::PreferTake); + + // "-" OptionalBody as OptionalSyntax {priority = PreferSkip} + Clause{ _syntax0 } = create(tok(T::NEGATIVE) + prule(_optionalBody), C::OptionalSyntax).with(F::OptionalSyntax_priority, GlrOptionalPriority::PreferSkip); + + // OptionalBody as OptionalSyntax {priority = Equal} + Clause{ _syntax0 } = create(prule(_optionalBody), C::OptionalSyntax).with(F::OptionalSyntax_priority, GlrOptionalPriority::Equal); + + // "(" !Syntax ")" + Clause{ _syntax0 } = tok(T::OPEN_ROUND) + use(_syntax) + tok(T::CLOSE_ROUND); + + // !Syntax0 + Clause{ _syntax1 } = use(_syntax0); + + // Syntax1:first Syntax0:second as SequenceSyntax + Clause{ _syntax1 } = create(rule(_syntax1, F::SequenceSyntax_first) + rule(_syntax0, F::SequenceSyntax_second), C::SequenceSyntax); + + // !Syntax1 + Clause{ _syntax2 } = use(_syntax1); + + // Syntax2:first "|" Syntax1:second as AlternativeSyntax + Clause{ _syntax2 } = create(rule(_syntax2, F::AlternativeSyntax_first) + tok(T::ALTERNATIVE) + rule(_syntax1, F::AlternativeSyntax_second), C::AlternativeSyntax); + + // !Syntax2 + Clause{ _syntax } = use(_syntax2); + + // ID:field "=" STRING:value as partial Assignment + Clause{ _assignment } = create(tok(T::ID, F::Assignment_field) + tok(T::ASSIGN) + tok(T::ID, F::Assignment_value), C::Assignment); + + // Syntax:syntax "as" ID:type ["{" {Assignment:assignments ; ","} "}"] as CreateClause + Clause{ _clause } = create(rule(_syntax, F::CreateClause_syntax) + tok(T::AS) + tok(T::ID, F::CreateClause_type) + opt(tok(T::OPEN_CURLY) + loop(rule(_assignment, F::CreateClause_assignments), tok(T::COMMA)) + tok(T::CLOSE_CURLY)), C::CreateClause); + + // Syntax:syntax "as" "partial" ID:type ["{" {Assignment:assignments ; ","} "}"] as PartialClause + Clause{ _clause } = create(rule(_syntax, F::PartialClause_syntax) + tok(T::AS) + tok(T::PARTIAL) + tok(T::ID, F::PartialClause_type) + opt(tok(T::OPEN_CURLY) + loop(rule(_assignment, F::PartialClause_assignments), tok(T::COMMA)) + tok(T::CLOSE_CURLY)), C::PartialClause); + + // Syntax:syntax ["{" {Assignment:assignments ; ","} "}"] as ReuseClause + Clause{ _clause } = create(rule(_syntax, F::ReuseClause_syntax) + opt(tok(T::OPEN_CURLY) + loop(rule(_assignment, F::ReuseClause_assignments), tok(T::COMMA)) + tok(T::CLOSE_CURLY)), C::ReuseClause); + + // ID:name {"::=" Clause:clauses} ";" as Rule + Clause{ _rule } = create(tok(T::ID, F::Rule_name) + loop(tok(T::INFER) + rule(_clause, F::Rule_clauses)) + tok(T::SEMICOLON), C::Rule); + + // Rule:rules {Rule:rules} as SyntaxFile + Clause{ _file } = create(rule(_rule, F::SyntaxFile_rules) + loop(rule(_rule, F::SyntaxFile_rules)), C::SyntaxFile); + } + } + } +} + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL_CREATEPARSERGENTYPESYNTAX.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + using namespace syntax_writer; + + extern syntax_writer::Token tok(ParserGenTokens id); + extern syntax_writer::Token tok(ParserGenTokens id, ParserGenFields field); + +/*********************************************************************** +CreateParserGenTypeSyntax +***********************************************************************/ + + void CreateParserGenTypeSyntax(SyntaxSymbolManager& manager) + { + manager.name = L"TypeParser"; + + auto _enumItem = manager.CreateRule(L"EnumItem"); + auto _enum = manager.CreateRule(L"Enum"); + auto _classPropType = manager.CreateRule(L"ClassPropType"); + auto _classProp = manager.CreateRule(L"classProp"); + auto _classBody = manager.CreateRule(L"ClassBody"); + auto _class = manager.CreateRule(L"Class"); + auto _type = manager.CreateRule(L"Type"); + auto _file = manager.CreateRule(L"File"); + + manager.parsableRules.Add(_file); + manager.ruleTypes.Add(_file, L"vl::glr::parsergen::GlrAstFile"); + + using T = ParserGenTokens; + using C = ParserGenClasses; + using F = ParserGenFields; + + // ID:name "," as EnumItem + Clause{ _enumItem } = create(tok(T::ID, F::EnumItem_name) + tok(T::COMMA), C::EnumItem); + + // "enum" ID:name "{" {EnumItem} "}" as Enum + Clause{ _enum } = create(tok(T::ENUM) + tok(T::ID, F::Type_name) + tok(T::OPEN_CURLY) + loop(rule(_enumItem, F::Enum_items)) + tok(T::CLOSE_CURLY), C::Enum); + + // "token" as partial ClassProp {propType = "Token"} + Clause{ _classPropType } = partial(tok(T::TOKEN)).with(F::ClassProp_propType, GlrPropType::Token); + + // ID:propTypeName as partial ClassProp {propType = "Type"} + Clause{ _classPropType } = partial(tok(T::ID, F::ClassProp_propTypeName)).with(F::ClassProp_propType, GlrPropType::Type); + + // ID:propTypeName "[" "]" as partial ClassProp {propType = "Array"} + Clause{ _classPropType } = partial(tok(T::ID, F::ClassProp_propTypeName) + tok(T::OPEN_SQUARE) + tok(T::CLOSE_SQUARE)).with(F::ClassProp_propType, GlrPropType::Array); + + // "var" ID:name ":" ClassPropType ";" as ClassProp + Clause{ _classProp } = create(tok(T::VAR) + tok(T::ID, F::ClassProp_name) + tok(T::COLON) + prule(_classPropType) + tok(T::SEMICOLON), C::ClassProp); + + // ID:name [":" ID:baseClass] "{" {ClassProp} "}" as partial Class + Clause{ _classBody } = partial(tok(T::ID, F::Type_name) + opt(tok(T::COLON) + tok(T::ID, F::Class_baseClass)) + tok(T::OPEN_CURLY) + loop(rule(_classProp, F::Class_props)) + tok(T::CLOSE_CURLY)); + + // "class" ClassBody {ambiguity = No} + Clause{ _class } = create(tok(T::CLASS) + prule(_classBody), C::Class).with(F::Class_ambiguity, GlrClassAmbiguity::No); + + // "ambiguous" "class" ClassBody {ambiguity = Yes} + Clause{ _class } = create(tok(T::AMBIGUOUS) + tok(T::CLASS) + prule(_classBody), C::Class).with(F::Class_ambiguity, GlrClassAmbiguity::Yes); + + // !Class | !Enum + Clause{ _type } = use(_enum) | use(_class); + + // type:types {type:types} as AstFile + Clause{ _file } = create(rule(_type, F::AstFile_types) + loop(rule(_type, F::AstFile_types)), C::AstFile); + } + } + } +} + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL_CREATEPARSERGENUTILITY.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + syntax_writer::Token tok(ParserGenTokens id) + { + auto d = ParserGenTokenDisplayText(id); + auto n = ParserGenTokenId(id); + return syntax_writer::tok( + id, + (d ? L"\"" + WString::Unmanaged(d) + L"\"" : WString::Unmanaged(n)) + ); + } + + syntax_writer::Token tok(ParserGenTokens id, ParserGenFields field) + { + auto d = ParserGenTokenDisplayText(id); + auto n = ParserGenTokenId(id); + return syntax_writer::tok( + id, + (d ? L"\"" + WString::Unmanaged(d) + L"\"" : WString::Unmanaged(n)), + field + ); + } + } + } +} + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL_NFACOMPACT.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +StateSymbolSet +***********************************************************************/ + + struct StateSymbolSet + { + private: + static const SortedList EmptyStates; + + Ptr> states; + + public: + StateSymbolSet() = default; + StateSymbolSet(const StateSymbolSet&) = delete; + StateSymbolSet& operator=(const StateSymbolSet&) = delete; + + StateSymbolSet(StateSymbolSet&& set) + { + states = set.states; + set.states = nullptr; + } + + StateSymbolSet& operator=(StateSymbolSet&& set) + { + states = set.states; + set.states = nullptr; + return *this; + } + + StateSymbolSet Copy() const + { + StateSymbolSet set; + set.states = states; + return set; + } + + bool Add(StateSymbol* state) + { + if (states) + { + if (states->Contains(state)) return false; + states->Add(state); + return true; + } + else + { + states = new SortedList(); + states->Add(state); + return true; + } + } + + const SortedList& States() const + { + return states ? *states.Obj() : EmptyStates; + } + + vint Compare(const StateSymbolSet& set) const + { + if (!states && !set.states) return 0; + if (!states) return -1; + if (!set.states) return 1; + return CompareEnumerable(*states.Obj(), *set.states.Obj()); + } + + bool operator==(const StateSymbolSet& set) const { return Compare(set) == 0; } + bool operator!=(const StateSymbolSet& set) const { return Compare(set) != 0; } + bool operator< (const StateSymbolSet& set) const { return Compare(set) < 0; } + bool operator<=(const StateSymbolSet& set) const { return Compare(set) <= 0; } + bool operator> (const StateSymbolSet& set) const { return Compare(set) > 0; } + bool operator>=(const StateSymbolSet& set) const { return Compare(set) >= 0; } + }; + const SortedList StateSymbolSet::EmptyStates; + +/*********************************************************************** +CompactSyntaxBuilder +***********************************************************************/ + + class CompactSyntaxBuilder + { + using StateList = collections::List>; + using EdgeList = collections::List>; + protected: + RuleSymbol* rule; + StateList& newStates; + EdgeList& newEdges; + Dictionary oldToNew; + Dictionary newToOld; + + void BuildEpsilonEliminatedEdgesInternal( + StateSymbol* walkingOldState, + StateSymbol* newState, + StateSymbol* endState, + List& visited, + List& accumulatedEdges) + { + /* + * walkingOldState : a state in the epsilon-NFA + * newState : a state in the compact-NFA + * it represents the mirrored walkingOldState in the first call when accumulatedEdges is empty + * in future recursive calls, walkingOldState keeps changing, but newState stays the same + * endState : the ending state of the rule + * visited : stores any new discovered epsilon-NFA states + * duplicated states will not be added to this list + * accumulatedEdges : epsilon edges from the first walkingOldState to the current walkingOldState + */ + + for (auto edge : walkingOldState->OutEdges()) + { + accumulatedEdges.Add(edge); + switch (edge->input.type) + { + case EdgeInputType::Token: + case EdgeInputType::Rule: + { + auto targetNewState = CreateCompactState(edge->To()); + if (!visited.Contains(targetNewState)) + { + visited.Add(targetNewState); + } + auto newEdge = new EdgeSymbol(newState, targetNewState); + newEdges.Add(newEdge); + newEdge->input = edge->input; + newEdge->important |= edge->important; + for (auto accumulatedEdge : accumulatedEdges) + { + CopyFrom(newEdge->insBeforeInput, accumulatedEdge->insBeforeInput, true); + CopyFrom(newEdge->insAfterInput, accumulatedEdge->insAfterInput, true); + newEdge->important |= accumulatedEdge->important; + } + } + break; + case EdgeInputType::Epsilon: + BuildEpsilonEliminatedEdgesInternal(edge->To(), newState, endState, visited, accumulatedEdges); + break; + } + accumulatedEdges.RemoveAt(accumulatedEdges.Count() - 1); + } + + if (walkingOldState->endingState) + { + auto newEdge = new EdgeSymbol(newState, endState); + newEdge->input.type = EdgeInputType::Ending; + for (auto accumulatedEdge : accumulatedEdges) + { + CopyFrom(newEdge->insBeforeInput, accumulatedEdge->insBeforeInput, true); + CopyFrom(newEdge->insAfterInput, accumulatedEdge->insAfterInput, true); + newEdge->important |= accumulatedEdge->important; + } + + for (auto endingEdge : newState->OutEdges()) + { + if (endingEdge != newEdge && endingEdge->input.type == EdgeInputType::Ending) + { + if ( + CompareEnumerable(endingEdge->insBeforeInput, newEdge->insBeforeInput) == 0 && + CompareEnumerable(endingEdge->insAfterInput, newEdge->insAfterInput) == 0) + { + CHECK_ERROR(newEdge->important == endingEdge->important, L"It is not possible to have two equal ending edges with different priority."); + newState->outEdges.Remove(newEdge); + endState->inEdges.Remove(newEdge); + delete newEdge; + goto DISCARD_ENDING_EDGE; + } + } + } + newEdges.Add(newEdge); + DISCARD_ENDING_EDGE:; + } + } + + public: + CompactSyntaxBuilder(RuleSymbol* _rule, StateList& _newStates, EdgeList& _newEdges) + : rule(_rule) + , newStates(_newStates) + , newEdges(_newEdges) + { + } + + StateSymbol* CreateCompactState(StateSymbol* state) + { + vint index = oldToNew.Keys().IndexOf(state); + if (index != -1) + { + return oldToNew.Values()[index]; + } + else + { + auto newState = new StateSymbol(rule, state->ClauseId()); + newState->label = state->label; + newStates.Add(newState); + oldToNew.Add(state, newState); + newToOld.Add(newState, state); + return newState; + } + } + + void BuildEpsilonEliminatedEdges( + StateSymbol* newState, + StateSymbol* endState, + List& visited) + { + List accumulatedEdges; + BuildEpsilonEliminatedEdgesInternal(newToOld[newState], newState, endState, visited, accumulatedEdges); + } + }; + +/*********************************************************************** +SyntaxSymbolManager::CreateLeftRecEdge +***********************************************************************/ + + void SyntaxSymbolManager::BuildLeftRecEdge(EdgeSymbol* newEdge, EdgeSymbol* endingEdge, EdgeSymbol* lrecPrefixEdge) + { + newEdge->important |= endingEdge->important; + newEdge->important |= lrecPrefixEdge->important; + + newEdge->input.type = EdgeInputType::LeftRec; + CopyFrom(newEdge->insBeforeInput, endingEdge->insBeforeInput, true); + CopyFrom(newEdge->insAfterInput, endingEdge->insAfterInput, true); + CopyFrom(newEdge->insBeforeInput, lrecPrefixEdge->insBeforeInput, true); + CopyFrom(newEdge->insAfterInput, lrecPrefixEdge->insAfterInput, true); + + for (vint i = 0; i < newEdge->insBeforeInput.Count(); i++) + { + auto& ins = newEdge->insBeforeInput[i]; + if (ins.type == AstInsType::BeginObject) + { + ins.type = AstInsType::BeginObjectLeftRecursive; + } + } + for (vint i = 0; i < newEdge->insAfterInput.Count(); i++) + { + auto& ins = newEdge->insAfterInput[i]; + if (ins.type == AstInsType::BeginObject) + { + ins.type = AstInsType::BeginObjectLeftRecursive; + } + } + } + +/*********************************************************************** +SyntaxSymbolManager::EliminateLeftRecursion +***********************************************************************/ + + void SyntaxSymbolManager::EliminateLeftRecursion(RuleSymbol* rule, StateSymbol* startState, StateSymbol* endState, StateList& newStates, EdgeList& newEdges) + { + /* + * Move the single rule prefix from the rule begin state + * if it is left recursive + * + * [BEFORE] (r is the current rule) + * +-> ... -> A --------(ending)-+ + * | | + * S -+-(r)----> ... -> B -(ending)-+-> E + * | --- | + * +-(r)----> ... -> C -(ending)-+ + * + * [AFTER] (the epsilon edge doesn't exist, it is for demo only) + * +----(epsilon)----------+ + * | | + * | +-(leftrec)-> ... -> B -(ending)---+ + * v | v + * S-> ... -> A -+-----------------------(ending)-> E + * ^ | ^ + * | +-(leftrec)-> ... -> C -(ending)---+ + * | | + * +----(epsilon)----------+ + */ + + List lrecEdges; + for (auto edge : startState->OutEdges()) + { + if (edge->input.type != EdgeInputType::Rule) continue; + if (edge->input.rule != rule) continue; + lrecEdges.Add(edge); + } + + for (auto lrecEdge : lrecEdges) + { + for (auto endingEdge : endState->InEdges()) + { + auto state = endingEdge->From(); + auto newEdge = new EdgeSymbol(state, lrecEdge->To()); + newEdges.Add(newEdge); + BuildLeftRecEdge(newEdge, endingEdge, lrecEdge); + } + } + + for (auto lrecEdge : lrecEdges) + { + lrecEdge->From()->outEdges.Remove(lrecEdge); + lrecEdge->To()->inEdges.Remove(lrecEdge); + newEdges.Remove(lrecEdge); + } + } + +/*********************************************************************** +SyntaxSymbolManager::EliminateEpsilonEdges +***********************************************************************/ + + void SyntaxSymbolManager::EliminateSingleRulePrefix(RuleSymbol* rule, StateSymbol* startState, StateSymbol* endState, StateList& newStates, EdgeList& newEdges) + { + /* + * Move the single rule prefix from the rule begin state + * if there is any single rule clause consist of the same rule + * + * [BEFORE] + * +-(x)-> A --------(ending)-+ + * | | + * S -+-(x)-> ... -> B -(ending)-+-> E + * | | + * +-(x)-> ... -> C -(ending)-+ + * + * [AFTER] + * +-(leftrec)-> ... -> B -(ending)---+ + * | v + * S-(x)-> A -+-----------------------(ending)-> E + * | ^ + * +-(leftrec)-> ... -> C -(ending)---+ + */ + + Group prefixEdges; + List continuationEdges; + + for (auto edge : startState->OutEdges()) + { + if (edge->input.type != EdgeInputType::Rule) continue; + if (edge->input.rule == rule) continue; + auto state = edge->To(); + if (state->InEdges().Count() > 1) continue; + + if (state->OutEdges().Count() == 1 && state->OutEdges()[0]->input.type == EdgeInputType::Ending) + { + prefixEdges.Add(edge->input.rule, edge); + } + else + { + continuationEdges.Add(edge); + } + } + + for (auto continuationEdge : continuationEdges) + { + vint prefixIndex = prefixEdges.Keys().IndexOf(continuationEdge->input.rule); + if (prefixIndex == -1) continue; + for (auto prefixEdge : prefixEdges.GetByIndex(prefixIndex)) + { + auto state = prefixEdge->To(); + auto endingEdge = state->OutEdges()[0]; + auto newEdge = new EdgeSymbol(state, continuationEdge->To()); + newEdges.Add(newEdge); + BuildLeftRecEdge(newEdge, endingEdge, continuationEdge); + } + } + + for (auto continuationEdge : continuationEdges) + { + vint prefixIndex = prefixEdges.Keys().IndexOf(continuationEdge->input.rule); + if (prefixIndex == -1) continue; + continuationEdge->From()->outEdges.Remove(continuationEdge); + continuationEdge->To()->inEdges.Remove(continuationEdge); + newEdges.Remove(continuationEdge); + } + } + +/*********************************************************************** +SyntaxSymbolManager::EliminateEpsilonEdges +***********************************************************************/ + + StateSymbol* SyntaxSymbolManager::EliminateEpsilonEdges(RuleSymbol* rule, StateList& newStates, EdgeList& newEdges) + { + /* + * For any transition that goes through some epsilon edge and ends with a non-epsilon edge + * we copy all instructions from epsilon edges and the non-epsilon edge in order + * and create a new edge directly pointing to the toState of the non-epsilon edge + * + * [BEFORE] + * +-(x)-> B + * | + * A -(e1)-+-(e2)-> C -+-(y)-> E + * | | + * +-(e3)-> D -+ + * + * [AFTER] + * +-(e1,x)-> B + * | + * A -+-(e1,e2,y)-> E + * | ^ + * +-(e1,e3,y)---+ + */ + + // epsilon-NFAs are per clause + // now we need to create a start state and an ending state + // to connect all epsilon-NFAs of its clauses together + auto psuedoState = CreateState(rule, -1); + for (auto startState : rule->startStates) + { + CreateEdge(psuedoState, startState); + } + + CompactSyntaxBuilder builder(rule, newStates, newEdges); + auto compactStartState = builder.CreateCompactState(psuedoState); + compactStartState->label = L" BEGIN "; + + auto compactEndState = new StateSymbol(rule, -1); + compactEndState->label = L" END "; + compactEndState->endingState = true; + newStates.Add(compactEndState); + + List visited; + visited.Add(compactStartState); + + // all epsilon-NFAs of its clauses become one connected epsilon-NFA of this rule + // we can build the compact-NFA out of this epsilon-NFA starting from the start state + for (vint i = 0; i < visited.Count(); i++) + { + auto current = visited[i]; + builder.BuildEpsilonEliminatedEdges(current, compactEndState, visited); + } + + // optimize + EliminateLeftRecursion(rule, compactStartState, compactEndState, newStates, newEdges); + EliminateSingleRulePrefix(rule, compactStartState, compactEndState, newStates, newEdges); + + return compactStartState; + } + +/*********************************************************************** +SyntaxSymbolManager::BuildCompactNFAInternal +***********************************************************************/ + + void SyntaxSymbolManager::BuildCompactNFAInternal() + { + StateList newStates; + EdgeList newEdges; + for (auto ruleSymbol : rules.map.Values()) + { + auto startState = EliminateEpsilonEdges(ruleSymbol, newStates, newEdges); + ruleSymbol->startStates.Clear(); + ruleSymbol->startStates.Add(startState); + } + CopyFrom(states, newStates); + CopyFrom(edges, newEdges); + + // only when a state has any important out edge + // its out edges are marked accordingly + for (auto state : states) + { + bool competition = false; + for (auto edge : state->OutEdges()) + { + if (edge->important) + { + competition = true; + break; + } + } + + if (competition) + { + for (auto edge : state->OutEdges()) + { + edge->importancy = edge->important ? EdgeImportancy::HighPriority : EdgeImportancy::LowPriority; + } + } + } + } + } + } +} + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL_NFACROSSREFERENCED.CPP +***********************************************************************/ + +namespace vl +{ + namespace glr + { + namespace parsergen + { + using namespace collections; + +/*********************************************************************** +SyntaxSymbolManager::FixCrossReferencedRuleEdge +***********************************************************************/ + + void SyntaxSymbolManager::FixCrossReferencedRuleEdge(StateSymbol* startState, collections::Group& orderedEdges, collections::List& accumulatedEdges) + { + auto lastEdge = accumulatedEdges[accumulatedEdges.Count() - 1]; + auto lastRule = lastEdge->input.rule; + auto ruleBegin = lastRule->startStates[0]; + vint index = orderedEdges.Keys().IndexOf(ruleBegin); + if (index == -1) return; + + for (auto edge : orderedEdges.GetByIndex(index)) + { + switch (edge->input.type) + { + case EdgeInputType::Token: + if (edge->returnEdges.Count() == 0) + { + auto newEdge = new EdgeSymbol(startState, edge->To()); + edges.Add(newEdge); + + newEdge->input = edge->input; + newEdge->importancy = edge->importancy; + for (auto acc : accumulatedEdges) + { + CopyFrom(newEdge->insBeforeInput, acc->insBeforeInput, true); + newEdge->returnEdges.Add(acc); + } + CopyFrom(newEdge->insBeforeInput, edge->insBeforeInput, true); + CopyFrom(newEdge->insAfterInput, edge->insAfterInput, true); + } + break; + case EdgeInputType::Rule: + if (accumulatedEdges.Contains(edge)) + { + AddError( + ParserErrorType::RuleIsIndirectlyLeftRecursive, + {}, + edge->input.rule->Name() + ); + } + else + { + accumulatedEdges.Add(edge); + FixCrossReferencedRuleEdge(startState, orderedEdges, accumulatedEdges); + accumulatedEdges.RemoveAt(accumulatedEdges.Count() - 1); + } + break; + } + } + } + +/*********************************************************************** +SyntaxSymbolManager::BuildCrossReferencedNFAInternal +***********************************************************************/ + + void SyntaxSymbolManager::BuildCrossReferencedNFAInternal() + { + List states; + GetStatesInStableOrder(states); + + Group orderedEdges; + for (auto state : states) + { + List edges; + state->GetOutEdgesInStableOrder(states, edges); + for (auto edge : edges) + { + orderedEdges.Add(state, edge); + } + } + + for (auto state : states) + { + vint index = orderedEdges.Keys().IndexOf(state); + if (index != -1) + { + for (auto edge : orderedEdges.GetByIndex(index)) + { + if (edge->input.type == EdgeInputType::Rule) + { + List accumulatedEdges; + accumulatedEdges.Add(edge); + FixCrossReferencedRuleEdge(edge->From(), orderedEdges, accumulatedEdges); + } + } + } + } + } + } + } +} diff --git a/Import/VlppGlrParserCompiler.h b/Import/VlppGlrParserCompiler.h new file mode 100644 index 00000000..48677e22 --- /dev/null +++ b/Import/VlppGlrParserCompiler.h @@ -0,0 +1,2908 @@ +/*********************************************************************** +THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY +DEVELOPER: Zihan Chen(vczh) +***********************************************************************/ +#include "VlppOS.h" +#include "Vlpp.h" +#include "VlppGlrParser.h" +#include "VlppReflection.h" +#include "VlppRegex.h" + +/*********************************************************************** +.\PARSERGEN\PARSERSYMBOL.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_PARSERSYMBOl +#define VCZH_PARSER2_PARSERGEN_PARSERSYMBOl + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + template + struct MappedOwning + { + collections::List> items; + collections::List order; + collections::Dictionary map; + + bool Add(const WString& name, T* item) + { + items.Add(item); + if (map.Keys().Contains(name)) return false; + order.Add(name); + map.Add(name, item); + return true; + } + }; + + template + void Fill(collections::List& ss, TArgs&& ...args) + { + WString items[] = { args... }; + for (auto& item : items) + { + ss.Add(item); + } + } + +/*********************************************************************** +ParserSymbolManager +***********************************************************************/ + + enum class ParserErrorType + { + // AstSymbolManager ------------------------------------------------------------------- + DuplicatedFile, // (fileName) + FileDependencyNotExists, // (fileName, dependency) + FileCyclicDependency, // (fileName, dependency) + DuplicatedSymbol, // (fileName, symbolName) + DuplicatedSymbolGlobally, // (fileName, symbolName, anotherFileName) + DuplicatedClassProp, // (fileName, className, propName) + DuplicatedEnumItem, // (fileName, enumName, propName) + BaseClassNotExists, // (fileName, className, typeName) + BaseClassNotClass, // (fileName, className, typeName) + BaseClassCyclicDependency, // (fileName, className) + FieldTypeNotExists, // (fileName, className, propName) + FieldTypeNotClass, // (fileName, className, propName) + + // LexerSymbolManager ----------------------------------------------------------------- + InvalidTokenDefinition, // (code) + DuplicatedToken, // (tokenName) + DuplicatedTokenByDisplayText, // (tokenName) + InvalidTokenRegex, // (tokenName, errorMessage) + TokenRegexNotPure, // (tokenName) + + // SyntaxSymbolManager ---------------------------------------------------------------- + DuplicatedRule, // (ruleName) + RuleIsIndirectlyLeftRecursive, // (ruleName) : Indirect left recursion must be resolved before. + + // SyntaxAst (ResolveName) ------------------------------------------------------------ + RuleNameConflictedWithToken, // (ruleName) + TypeNotExistsInRule, // (ruleName, name) + TypeNotClassInRule, // (ruleName, name) + TokenOrRuleNotExistsInRule, // (ruleName, name) + + // SyntaxAst (CalculateTypes) --------------------------------------------------------- + RuleMixedPartialClauseWithOtherClause, // (ruleName) + RuleWithDifferentPartialTypes, // (ruleName) + RuleCannotResolveToDeterministicType, // (ruleName) : Unable to resolve to one type from clauses (token, type) or (create, partial). + CyclicDependedRuleTypeIncompatible, // (ruleName) : Types of rules are not compatible to each other when they build cyclic dependency by reuse clauses. + ReuseClauseCannotResolveToDeterministicType,// (ruleName) : A reuse clause contains multiple use rule but their types are not compatible to each other. + ReuseClauseContainsNoUseRule, // (ruleName) : A reuse clause contains no use rule therefore the type cannot be determined. + + // SyntaxAst (ValidateTypes) ---------------------------------------------------------- + FieldNotExistsInClause, // (ruleName, clauseType, fieldName) : The field does not exist in the type of the clause. + RuleTypeMismatchedToField, // (ruleName, clauseType, fieldName, fieldRuleType) : The rule type is not compatible to the assigning field. + AssignmentToNonEnumField, // (ruleName, clauseType, fieldName) : Assignment can only assign fields in enum types. + EnumItemMismatchedToField, // (ruleName, clauseType, fieldName, enumItem) : Try to assign an unexisting or mismatched enum item to a field in an enum type. + UseRuleWithPartialRule, // (ruleName, useRuleName) : A use rule should not be used with a partial rule. + UseRuleInNonReuseClause, // (ruleName, useRuleName) : A use rule should only appear in reuse clause. + PartialRuleUsedOnField, // (ruleName, clauseType, partialRuleName, fieldName) : A partial rule does not create object, it cannot be assigned to a field. + ClauseTypeMismatchedToPartialRule, // (ruleName, clauseType, partialRuleName, partialRuleType) : A clause uses a partial rule of an incompatible type. + + // SyntaxAst (ValidateStructure, counting) -------------------------------------------- + ClauseNotCreateObject, // (ruleName) : A reuse clause does not contain use rule in some potential sequences. + UseRuleUsedInOptionalBody, // (ruleName, useRuleName) + UseRuleUsedInLoopBody, // (ruleName, useRuleName) + ClauseTooManyUseRule, // (ruleName) : Multiple use rules in a potential sequence in a clause. + NonArrayFieldAssignedInLoop, // (ruleName, clauseType, fieldName) + NonLoopablePartialRuleUsedInLoop, // (ruleName, clauseType, partialRuleName) + ClauseCouldExpandToEmptySequence, // (ruleName) + LoopBodyCouldExpandToEmptySequence, // (ruleName) + OptionalBodyCouldExpandToEmptySequence, // (ruleName) + NegativeOptionalEndsAClause, // (ruleName) : Negative optional syntax cannot ends a clause. + MultiplePrioritySyntaxInAClause, // (ruleName) : Too many syntax with priority in the a clause. + + // SyntaxAst (ValidateStructure, relationship) ---------------------------------------- + FieldAssignedMoreThanOnce, // (ruleName, clauseType, fieldName) + }; + + enum class ParserDefFileType + { + Ast, + Lexer, + Syntax, + }; + + struct ParserErrorLocation + { + ParserDefFileType type; + WString name; + ParsingTextRange codeRange; + }; + + struct ParserError + { + ParserErrorType type; + ParserErrorLocation location; + WString arg1; + WString arg2; + WString arg3; + WString arg4; + }; + + class ParserSymbolManager : public Object + { + using ErrorList = collections::List; + using StringItems = collections::List; + protected: + + ErrorList errors; + public: + WString name; + StringItems includes; + StringItems cppNss; + WString headerGuard; + + const auto& Errors() { return errors; } + + template + void AddError(ParserErrorType type, ParserErrorLocation location, TArgs&& ...args) + { + ParserError error; + error.type = type; + error.location = location; + + WString sargs[] = { WString(args)... }; + WString* dargs[] = { &error.arg1,&error.arg2,&error.arg3,&error.arg4 }; + constexpr vint sl = sizeof(sargs) / sizeof(*sargs); + constexpr vint dl = sizeof(dargs) / sizeof(*dargs); + constexpr vint ml = sl < dl ? sl : dl; + for (vint i = 0; i < ml; i++) + { + *dargs[i] = sargs[i]; + } + + errors.Add(std::move(error)); + } + }; + +/*********************************************************************** +Utility +***********************************************************************/ + + extern void InitializeParserSymbolManager(ParserSymbolManager& manager); + } + } +} + +#endif + +/*********************************************************************** +.\AST\ASTSYMBOL.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_AST_ASTSYMBOL +#define VCZH_PARSER2_AST_ASTSYMBOL + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + class AstEnumSymbol; + class AstClassSymbol; + class AstDefFile; + class AstSymbolManager; + +/*********************************************************************** +AstSymbol +***********************************************************************/ + + class AstSymbol : public Object + { + protected: + AstDefFile* ownerFile = nullptr; + WString name; + + AstSymbol(AstDefFile* _file, const WString& _name); + public: + AstDefFile* Owner() { return ownerFile; } + const WString& Name() { return name; } + }; + +/*********************************************************************** +AstEnumSymbol +***********************************************************************/ + + class AstEnumItemSymbol : public AstSymbol + { + friend class AstEnumSymbol; + protected: + AstEnumSymbol* parent = nullptr; + + AstEnumItemSymbol(AstEnumSymbol* _parent, const WString& name); + public: + vint value = 0; + + AstEnumSymbol* Parent() { return parent; } + }; + + class AstEnumSymbol : public AstSymbol + { + friend class AstDefFile; + protected: + MappedOwning items; + + AstEnumSymbol(AstDefFile* _file, const WString& _name); + public: + AstEnumItemSymbol* CreateItem(const WString& itemName, ParsingTextRange codeRange = {}); + const auto& Items() { return items.map; } + const auto& ItemOrder() { return items.order; } + }; + +/*********************************************************************** +AstClassSymbol +***********************************************************************/ + + enum class AstPropType + { + Token, + Type, + Array, + }; + + class AstClassPropSymbol : public AstSymbol + { + friend class AstClassSymbol; + protected: + AstClassSymbol* parent = nullptr; + + AstClassPropSymbol(AstClassSymbol* _parent, const WString& name); + public: + AstPropType propType = AstPropType::Token; + AstSymbol* propSymbol = nullptr; + + AstClassSymbol* Parent() { return parent; } + bool SetPropType(AstPropType _type, const WString& typeName = WString::Empty, ParsingTextRange codeRange = {}); + }; + + class AstClassSymbol : public AstSymbol + { + friend class AstDefFile; + protected: + MappedOwning props; + + AstClassSymbol(AstDefFile* _file, const WString& _name); + public: + AstClassSymbol* baseClass = nullptr; + AstClassSymbol* ambiguousDerivedClass = nullptr; + collections::List derivedClasses; + + bool SetBaseClass(const WString& typeName, ParsingTextRange codeRange = {}); + AstClassSymbol* CreateAmbiguousDerivedClass(ParsingTextRange codeRange); + AstClassPropSymbol* CreateProp(const WString& propName, ParsingTextRange codeRange = {}); + const auto& Props() { return props.map; } + const auto& PropOrder() { return props.order; } + }; + + extern AstClassSymbol* FindCommonBaseClass(AstClassSymbol* c1, AstClassSymbol* c2); + extern AstClassPropSymbol* FindPropSymbol(AstClassSymbol*& type, const WString& name); + +/*********************************************************************** +AstDefFile +***********************************************************************/ + + class AstDefFile : public Object + { + friend class AstSymbolManager; + + using DependenciesList = collections::List; + using StringItems = collections::List; + protected: + ParserSymbolManager* global = nullptr; + AstSymbolManager* ownerManager = nullptr; + WString name; + MappedOwning symbols; + + template + T* CreateSymbol(const WString& symbolName, ParsingTextRange codeRange); + + AstDefFile(ParserSymbolManager* _global, AstSymbolManager* _ownerManager, const WString& _name); + public: + DependenciesList dependencies; + StringItems cppNss; + StringItems refNss; + WString classPrefix; + + AstSymbolManager* Owner() { return ownerManager; } + const WString& Name() { return name; } + bool AddDependency(const WString& dependency, ParsingTextRange codeRange = {}); + AstEnumSymbol* CreateEnum(const WString& symbolName, ParsingTextRange codeRange = {}); + AstClassSymbol* CreateClass(const WString& symbolName, ParsingTextRange codeRange = {}); + const auto& Symbols() { return symbols.map; } + const auto& SymbolOrder() { return symbols.order; } + + template + void AddError(ParserErrorType type, ParsingTextRange codeRange, TArgs&&... args) + { + global->AddError(type, { ParserDefFileType::Ast,name,codeRange }, std::forward(args)...); + } + }; + +/*********************************************************************** +AstSymbolManager +***********************************************************************/ + + class AstSymbolManager : public Object + { + using SymbolMap = collections::Dictionary; + + friend class AstDefFile; + protected: + MappedOwning files; + SymbolMap symbolMap; + ParserSymbolManager& global; + + public: + AstSymbolManager(ParserSymbolManager& _global); + + AstDefFile* CreateFile(const WString& name); + + ParserSymbolManager& Global() { return global; } + const auto& Files() { return files.map; } + const auto& FileOrder() { return files.order; } + const auto& Symbols() { return symbolMap; } + }; + + extern AstDefFile* CreateParserGenTypeAst(AstSymbolManager& manager); + extern AstDefFile* CreateParserGenRuleAst(AstSymbolManager& manager); + } + } +} + +#endif + +/*********************************************************************** +.\LEXER\LEXERSYMBOL.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_LEXER_LEXERSYMBOL +#define VCZH_PARSER2_LEXER_LEXERSYMBOL + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + class LexerSymbolManager; + +/*********************************************************************** +LexerSymbolManager +***********************************************************************/ + + class TokenSymbol : public Object + { + friend class LexerSymbolManager; + protected: + LexerSymbolManager* ownerManager; + WString name; + + TokenSymbol(LexerSymbolManager* _ownerManager, const WString& _name); + public: + WString regex; + WString displayText; + bool discarded = false; + + LexerSymbolManager* Owner() { return ownerManager; } + const WString& Name() { return name; } + }; + + class LexerSymbolManager : public Object + { + using TokenMap = collections::Dictionary; + protected: + MappedOwning tokens; + TokenMap tokensByDisplayText; + ParserSymbolManager& global; + + public: + LexerSymbolManager(ParserSymbolManager& _global); + + TokenSymbol* CreateToken(const WString& _name, const WString& _regex, ParsingTextRange codeRange = {}); + TokenSymbol* CreateDiscardedToken(const WString& _name, const WString& _regex, ParsingTextRange codeRange = {}); + + ParserSymbolManager& Global() { return global; } + const auto& Tokens() { return tokens.map; } + const auto& TokensByDisplayText() { return tokensByDisplayText; } + const auto& TokenOrder() { return tokens.order; } + + template + void AddError(ParserErrorType type, ParsingTextRange codeRange, TArgs&&... args) + { + global.AddError(type, { ParserDefFileType::Lexer,WString::Empty,codeRange }, std::forward(args)...); + } + }; + + extern void CreateParserGenLexer(LexerSymbolManager& manager); + } + } +} + +#endif + +/*********************************************************************** +.\PARSERGEN\PARSERCPPGEN.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_PARSERCPPGEN +#define VCZH_PARSER2_PARSERGEN_PARSERCPPGEN + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + class AstDefFile; + class AstClassPropSymbol; + class AstClassSymbol; + class TokenSymbol; + class SyntaxSymbolManager; + +/*********************************************************************** +Output +***********************************************************************/ + + struct CppAstGenOutput + { + WString astH; + WString astCpp; + WString builderH; + WString builderCpp; + WString emptyH; + WString emptyCpp; + WString copyH; + WString copyCpp; + WString traverseH; + WString traverseCpp; + WString jsonH; + WString jsonCpp; + }; + + struct CppSyntaxGenOutput + { + WString syntaxH; + WString syntaxCpp; + }; + + struct CppParserGenOutput + { + WString assemblyH; + WString assemblyCpp; + WString lexerH; + WString lexerCpp; + collections::Dictionary> astOutputs; + collections::Dictionary> syntaxOutputs; + + collections::Dictionary classIds; + collections::Dictionary fieldIds; + collections::Dictionary tokenIds; + }; + +/*********************************************************************** +Utility +***********************************************************************/ + + extern Ptr GenerateParserFileNames(ParserSymbolManager& manager); + + extern void WriteCppStringBody(const WString& body, stream::StreamWriter& writer); + extern void WriteFileComment(const WString& name, stream::StreamWriter& writer); + extern WString WriteNssBegin(collections::List& cppNss, stream::StreamWriter& writer); + extern void WriteNssEnd(collections::List& cppNss, stream::StreamWriter& writer); + extern void WriteLoadDataFunctionHeader(const WString& prefix, const WString& functionName, stream::StreamWriter& writer); + extern void WriteLoadDataFunctionCpp(const WString& prefix, const WString& functionName, stream::MemoryStream& rawData, bool compressData, stream::StreamWriter& writer); + } + } +} + +#endif + +/*********************************************************************** +.\AST\ASTCPPGEN.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_AST_ASTCPPGEN +#define VCZH_PARSER2_AST_ASTCPPGEN + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + extern void GenerateAstFileNames(AstSymbolManager& manager, Ptr parserOutput); + + extern void WriteAstHeaderFile (AstDefFile* file, stream::StreamWriter& writer); + extern void WriteAstCppFile (AstDefFile* file, const WString& astHeaderName, stream::StreamWriter& writer); + + extern void WriteAstUtilityHeaderFile (AstDefFile* file, Ptr output, const WString& extraNss, stream::StreamWriter& writer, Func callback); + extern void WriteAstUtilityCppFile (AstDefFile* file, const WString& utilityHeaderFile, const WString& extraNss, stream::StreamWriter& writer, Func callback); + extern void WriteParserUtilityHeaderFile (AstSymbolManager& manager, Ptr output, const WString& guardPostfix, stream::StreamWriter& writer, Func callback); + extern void WriteParserUtilityCppFile (AstSymbolManager& manager, const WString& utilityHeaderFile, stream::StreamWriter& writer, Func callback); + + extern void WriteAstBuilderHeaderFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteAstBuilderCppFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteEmptyVisitorHeaderFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteEmptyVisitorCppFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteCopyVisitorHeaderFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteCopyVisitorCppFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteTraverseVisitorHeaderFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteTraverseVisitorCppFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteJsonVisitorHeaderFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + extern void WriteJsonVisitorCppFile (AstDefFile* file, Ptr output, stream::StreamWriter& writer); + + extern void WriteAstAssemblerHeaderFile (AstSymbolManager& manager, Ptr output, stream::StreamWriter& writer); + extern void WriteAstAssemblerCppFile (AstSymbolManager& manager, Ptr output, stream::StreamWriter& writer); + + extern void WriteAstFiles (AstDefFile* file, Ptr output, collections::Dictionary& files); + extern void WriteAstFiles (AstSymbolManager& manager, Ptr output, collections::Dictionary& files); + } + } +} + +#endif + +/*********************************************************************** +.\LEXER\LEXERCPPGEN.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_LEXER_LEXERCPPGEN +#define VCZH_PARSER2_LEXER_LEXERCPPGEN + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + extern void WriteLexerHeaderFile (LexerSymbolManager& manager, Ptr output, stream::StreamWriter& writer); + extern void WriteLexerCppFile (LexerSymbolManager& manager, Ptr output, stream::StreamWriter& writer); + extern void WriteLexerFiles (LexerSymbolManager& manager, Ptr output, collections::Dictionary& files); + } + } +} + +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_RULEAST_AST +#define VCZH_PARSER2_PARSERGEN_RULEAST_AST + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + class GlrAlternativeSyntax; + class GlrAssignment; + class GlrClause; + class GlrCreateClause; + class GlrLiteralSyntax; + class GlrLoopSyntax; + class GlrOptionalSyntax; + class GlrPartialClause; + class GlrRefSyntax; + class GlrReuseClause; + class GlrRule; + class GlrSequenceSyntax; + class GlrSyntax; + class GlrSyntaxFile; + class GlrUseSyntax; + + enum class GlrOptionalPriority + { + UNDEFINED_ENUM_ITEM_VALUE = -1, + Equal = 0, + PreferTake = 1, + PreferSkip = 2, + }; + + class GlrSyntax abstract : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + class IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description + { + public: + virtual void Visit(GlrRefSyntax* node) = 0; + virtual void Visit(GlrLiteralSyntax* node) = 0; + virtual void Visit(GlrUseSyntax* node) = 0; + virtual void Visit(GlrLoopSyntax* node) = 0; + virtual void Visit(GlrOptionalSyntax* node) = 0; + virtual void Visit(GlrSequenceSyntax* node) = 0; + virtual void Visit(GlrAlternativeSyntax* node) = 0; + }; + + virtual void Accept(GlrSyntax::IVisitor* visitor) = 0; + + }; + + class GlrRefSyntax : public GlrSyntax, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + vl::glr::ParsingToken field; + + void Accept(GlrSyntax::IVisitor* visitor) override; + }; + + class GlrLiteralSyntax : public GlrSyntax, vl::reflection::Description + { + public: + vl::glr::ParsingToken value; + + void Accept(GlrSyntax::IVisitor* visitor) override; + }; + + class GlrUseSyntax : public GlrSyntax, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + + void Accept(GlrSyntax::IVisitor* visitor) override; + }; + + class GlrLoopSyntax : public GlrSyntax, vl::reflection::Description + { + public: + vl::Ptr syntax; + vl::Ptr delimiter; + + void Accept(GlrSyntax::IVisitor* visitor) override; + }; + + class GlrOptionalSyntax : public GlrSyntax, vl::reflection::Description + { + public: + GlrOptionalPriority priority = GlrOptionalPriority::UNDEFINED_ENUM_ITEM_VALUE; + vl::Ptr syntax; + + void Accept(GlrSyntax::IVisitor* visitor) override; + }; + + class GlrSequenceSyntax : public GlrSyntax, vl::reflection::Description + { + public: + vl::Ptr first; + vl::Ptr second; + + void Accept(GlrSyntax::IVisitor* visitor) override; + }; + + class GlrAlternativeSyntax : public GlrSyntax, vl::reflection::Description + { + public: + vl::Ptr first; + vl::Ptr second; + + void Accept(GlrSyntax::IVisitor* visitor) override; + }; + + class GlrClause abstract : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + class IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description + { + public: + virtual void Visit(GlrCreateClause* node) = 0; + virtual void Visit(GlrPartialClause* node) = 0; + virtual void Visit(GlrReuseClause* node) = 0; + }; + + virtual void Accept(GlrClause::IVisitor* visitor) = 0; + + }; + + class GlrAssignment : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::glr::ParsingToken field; + vl::glr::ParsingToken value; + }; + + class GlrCreateClause : public GlrClause, vl::reflection::Description + { + public: + vl::glr::ParsingToken type; + vl::Ptr syntax; + vl::collections::List> assignments; + + void Accept(GlrClause::IVisitor* visitor) override; + }; + + class GlrPartialClause : public GlrClause, vl::reflection::Description + { + public: + vl::glr::ParsingToken type; + vl::Ptr syntax; + vl::collections::List> assignments; + + void Accept(GlrClause::IVisitor* visitor) override; + }; + + class GlrReuseClause : public GlrClause, vl::reflection::Description + { + public: + vl::Ptr syntax; + vl::collections::List> assignments; + + void Accept(GlrClause::IVisitor* visitor) override; + }; + + class GlrRule : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + vl::collections::List> clauses; + }; + + class GlrSyntaxFile : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::collections::List> rules; + }; + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + DECL_TYPE_INFO(vl::glr::parsergen::GlrSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrSyntax::IVisitor) + DECL_TYPE_INFO(vl::glr::parsergen::GlrRefSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrLiteralSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrUseSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrLoopSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrOptionalPriority) + DECL_TYPE_INFO(vl::glr::parsergen::GlrOptionalSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrSequenceSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrAlternativeSyntax) + DECL_TYPE_INFO(vl::glr::parsergen::GlrClause) + DECL_TYPE_INFO(vl::glr::parsergen::GlrClause::IVisitor) + DECL_TYPE_INFO(vl::glr::parsergen::GlrAssignment) + DECL_TYPE_INFO(vl::glr::parsergen::GlrCreateClause) + DECL_TYPE_INFO(vl::glr::parsergen::GlrPartialClause) + DECL_TYPE_INFO(vl::glr::parsergen::GlrReuseClause) + DECL_TYPE_INFO(vl::glr::parsergen::GlrRule) + DECL_TYPE_INFO(vl::glr::parsergen::GlrSyntaxFile) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::glr::parsergen::GlrSyntax::IVisitor) + void Visit(vl::glr::parsergen::GlrRefSyntax* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrLiteralSyntax* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrUseSyntax* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrLoopSyntax* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrOptionalSyntax* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrSequenceSyntax* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrAlternativeSyntax* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + END_INTERFACE_PROXY(vl::glr::parsergen::GlrSyntax::IVisitor) + + BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::glr::parsergen::GlrClause::IVisitor) + void Visit(vl::glr::parsergen::GlrCreateClause* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrPartialClause* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrReuseClause* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + END_INTERFACE_PROXY(vl::glr::parsergen::GlrClause::IVisitor) + +#endif +#endif + /// Load all reflectable AST types, only available when VCZH_DEBUG_NO_REFLECTION is off. + /// Returns true if this operation succeeded. + extern bool ParserGenRuleAstLoadTypes(); + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_BUILDER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_RULEAST_AST_BUILDER +#define VCZH_PARSER2_PARSERGEN_RULEAST_AST_BUILDER + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace builder + { + class MakeAlternativeSyntax : public vl::glr::ParsingAstBuilder + { + public: + MakeAlternativeSyntax& first(const vl::Ptr& value); + MakeAlternativeSyntax& second(const vl::Ptr& value); + }; + + class MakeAssignment : public vl::glr::ParsingAstBuilder + { + public: + MakeAssignment& field(const vl::WString& value); + MakeAssignment& value(const vl::WString& value); + }; + + class MakeCreateClause : public vl::glr::ParsingAstBuilder + { + public: + MakeCreateClause& assignments(const vl::Ptr& value); + MakeCreateClause& syntax(const vl::Ptr& value); + MakeCreateClause& type(const vl::WString& value); + }; + + class MakeLiteralSyntax : public vl::glr::ParsingAstBuilder + { + public: + MakeLiteralSyntax& value(const vl::WString& value); + }; + + class MakeLoopSyntax : public vl::glr::ParsingAstBuilder + { + public: + MakeLoopSyntax& delimiter(const vl::Ptr& value); + MakeLoopSyntax& syntax(const vl::Ptr& value); + }; + + class MakeOptionalSyntax : public vl::glr::ParsingAstBuilder + { + public: + MakeOptionalSyntax& priority(GlrOptionalPriority value); + MakeOptionalSyntax& syntax(const vl::Ptr& value); + }; + + class MakePartialClause : public vl::glr::ParsingAstBuilder + { + public: + MakePartialClause& assignments(const vl::Ptr& value); + MakePartialClause& syntax(const vl::Ptr& value); + MakePartialClause& type(const vl::WString& value); + }; + + class MakeRefSyntax : public vl::glr::ParsingAstBuilder + { + public: + MakeRefSyntax& field(const vl::WString& value); + MakeRefSyntax& name(const vl::WString& value); + }; + + class MakeReuseClause : public vl::glr::ParsingAstBuilder + { + public: + MakeReuseClause& assignments(const vl::Ptr& value); + MakeReuseClause& syntax(const vl::Ptr& value); + }; + + class MakeRule : public vl::glr::ParsingAstBuilder + { + public: + MakeRule& clauses(const vl::Ptr& value); + MakeRule& name(const vl::WString& value); + }; + + class MakeSequenceSyntax : public vl::glr::ParsingAstBuilder + { + public: + MakeSequenceSyntax& first(const vl::Ptr& value); + MakeSequenceSyntax& second(const vl::Ptr& value); + }; + + class MakeSyntaxFile : public vl::glr::ParsingAstBuilder + { + public: + MakeSyntaxFile& rules(const vl::Ptr& value); + }; + + class MakeUseSyntax : public vl::glr::ParsingAstBuilder + { + public: + MakeUseSyntax& name(const vl::WString& value); + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_COPY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_RULEAST_AST_COPY_VISITOR +#define VCZH_PARSER2_PARSERGEN_RULEAST_AST_COPY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace copy_visitor + { + /// A copy visitor, overriding all abstract methods with AST copying code. + class RuleAstVisitor + : public virtual vl::glr::CopyVisitorBase + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + protected: + void CopyFields(GlrAlternativeSyntax* from, GlrAlternativeSyntax* to); + void CopyFields(GlrAssignment* from, GlrAssignment* to); + void CopyFields(GlrClause* from, GlrClause* to); + void CopyFields(GlrCreateClause* from, GlrCreateClause* to); + void CopyFields(GlrLiteralSyntax* from, GlrLiteralSyntax* to); + void CopyFields(GlrLoopSyntax* from, GlrLoopSyntax* to); + void CopyFields(GlrOptionalSyntax* from, GlrOptionalSyntax* to); + void CopyFields(GlrPartialClause* from, GlrPartialClause* to); + void CopyFields(GlrRefSyntax* from, GlrRefSyntax* to); + void CopyFields(GlrReuseClause* from, GlrReuseClause* to); + void CopyFields(GlrRule* from, GlrRule* to); + void CopyFields(GlrSequenceSyntax* from, GlrSequenceSyntax* to); + void CopyFields(GlrSyntax* from, GlrSyntax* to); + void CopyFields(GlrSyntaxFile* from, GlrSyntaxFile* to); + void CopyFields(GlrUseSyntax* from, GlrUseSyntax* to); + + protected: + virtual void Visit(GlrAssignment* node); + virtual void Visit(GlrRule* node); + virtual void Visit(GlrSyntaxFile* node); + + void Visit(GlrRefSyntax* node) override; + void Visit(GlrLiteralSyntax* node) override; + void Visit(GlrUseSyntax* node) override; + void Visit(GlrLoopSyntax* node) override; + void Visit(GlrOptionalSyntax* node) override; + void Visit(GlrSequenceSyntax* node) override; + void Visit(GlrAlternativeSyntax* node) override; + + void Visit(GlrCreateClause* node) override; + void Visit(GlrPartialClause* node) override; + void Visit(GlrReuseClause* node) override; + + public: + virtual vl::Ptr CopyNode(GlrSyntax* node); + virtual vl::Ptr CopyNode(GlrClause* node); + virtual vl::Ptr CopyNode(GlrAssignment* node); + virtual vl::Ptr CopyNode(GlrRule* node); + virtual vl::Ptr CopyNode(GlrSyntaxFile* node); + + vl::Ptr CopyNode(GlrAlternativeSyntax* node); + vl::Ptr CopyNode(GlrCreateClause* node); + vl::Ptr CopyNode(GlrLiteralSyntax* node); + vl::Ptr CopyNode(GlrLoopSyntax* node); + vl::Ptr CopyNode(GlrOptionalSyntax* node); + vl::Ptr CopyNode(GlrPartialClause* node); + vl::Ptr CopyNode(GlrRefSyntax* node); + vl::Ptr CopyNode(GlrReuseClause* node); + vl::Ptr CopyNode(GlrSequenceSyntax* node); + vl::Ptr CopyNode(GlrUseSyntax* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_EMPTY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_RULEAST_AST_EMPTY_VISITOR +#define VCZH_PARSER2_PARSERGEN_RULEAST_AST_EMPTY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace empty_visitor + { + /// An empty visitor, overriding all abstract methods with empty implementations. + class SyntaxVisitor : public vl::Object, public GlrSyntax::IVisitor + { + protected: + // Dispatch (virtual) -------------------------------- + + public: + // Visitor Members ----------------------------------- + void Visit(GlrRefSyntax* node) override; + void Visit(GlrLiteralSyntax* node) override; + void Visit(GlrUseSyntax* node) override; + void Visit(GlrLoopSyntax* node) override; + void Visit(GlrOptionalSyntax* node) override; + void Visit(GlrSequenceSyntax* node) override; + void Visit(GlrAlternativeSyntax* node) override; + }; + + /// An empty visitor, overriding all abstract methods with empty implementations. + class ClauseVisitor : public vl::Object, public GlrClause::IVisitor + { + protected: + // Dispatch (virtual) -------------------------------- + + public: + // Visitor Members ----------------------------------- + void Visit(GlrCreateClause* node) override; + void Visit(GlrPartialClause* node) override; + void Visit(GlrReuseClause* node) override; + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_JSON.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_RULEAST_AST_JSON_VISITOR +#define VCZH_PARSER2_PARSERGEN_RULEAST_AST_JSON_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace json_visitor + { + /// A JSON visitor, overriding all abstract methods with AST to JSON serialization code. + class RuleAstVisitor + : public vl::glr::JsonVisitorBase + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + protected: + virtual void PrintFields(GlrAlternativeSyntax* node); + virtual void PrintFields(GlrAssignment* node); + virtual void PrintFields(GlrClause* node); + virtual void PrintFields(GlrCreateClause* node); + virtual void PrintFields(GlrLiteralSyntax* node); + virtual void PrintFields(GlrLoopSyntax* node); + virtual void PrintFields(GlrOptionalSyntax* node); + virtual void PrintFields(GlrPartialClause* node); + virtual void PrintFields(GlrRefSyntax* node); + virtual void PrintFields(GlrReuseClause* node); + virtual void PrintFields(GlrRule* node); + virtual void PrintFields(GlrSequenceSyntax* node); + virtual void PrintFields(GlrSyntax* node); + virtual void PrintFields(GlrSyntaxFile* node); + virtual void PrintFields(GlrUseSyntax* node); + + protected: + void Visit(GlrRefSyntax* node) override; + void Visit(GlrLiteralSyntax* node) override; + void Visit(GlrUseSyntax* node) override; + void Visit(GlrLoopSyntax* node) override; + void Visit(GlrOptionalSyntax* node) override; + void Visit(GlrSequenceSyntax* node) override; + void Visit(GlrAlternativeSyntax* node) override; + + void Visit(GlrCreateClause* node) override; + void Visit(GlrPartialClause* node) override; + void Visit(GlrReuseClause* node) override; + + public: + RuleAstVisitor(vl::stream::StreamWriter& _writer); + + void Print(GlrSyntax* node); + void Print(GlrClause* node); + void Print(GlrAssignment* node); + void Print(GlrRule* node); + void Print(GlrSyntaxFile* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEAST_TRAVERSE.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:RuleAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_RULEAST_AST_TRAVERSE_VISITOR +#define VCZH_PARSER2_PARSERGEN_RULEAST_AST_TRAVERSE_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace traverse_visitor + { + /// A traverse visitor, overriding all abstract methods with AST visiting code. + class RuleAstVisitor + : public vl::Object + , protected virtual GlrSyntax::IVisitor + , protected virtual GlrClause::IVisitor + { + protected: + virtual void Traverse(vl::glr::ParsingToken& token); + virtual void Traverse(vl::glr::ParsingAstBase* node); + virtual void Traverse(GlrAlternativeSyntax* node); + virtual void Traverse(GlrAssignment* node); + virtual void Traverse(GlrClause* node); + virtual void Traverse(GlrCreateClause* node); + virtual void Traverse(GlrLiteralSyntax* node); + virtual void Traverse(GlrLoopSyntax* node); + virtual void Traverse(GlrOptionalSyntax* node); + virtual void Traverse(GlrPartialClause* node); + virtual void Traverse(GlrRefSyntax* node); + virtual void Traverse(GlrReuseClause* node); + virtual void Traverse(GlrRule* node); + virtual void Traverse(GlrSequenceSyntax* node); + virtual void Traverse(GlrSyntax* node); + virtual void Traverse(GlrSyntaxFile* node); + virtual void Traverse(GlrUseSyntax* node); + + protected: + virtual void Finishing(vl::glr::ParsingAstBase* node); + virtual void Finishing(GlrAlternativeSyntax* node); + virtual void Finishing(GlrAssignment* node); + virtual void Finishing(GlrClause* node); + virtual void Finishing(GlrCreateClause* node); + virtual void Finishing(GlrLiteralSyntax* node); + virtual void Finishing(GlrLoopSyntax* node); + virtual void Finishing(GlrOptionalSyntax* node); + virtual void Finishing(GlrPartialClause* node); + virtual void Finishing(GlrRefSyntax* node); + virtual void Finishing(GlrReuseClause* node); + virtual void Finishing(GlrRule* node); + virtual void Finishing(GlrSequenceSyntax* node); + virtual void Finishing(GlrSyntax* node); + virtual void Finishing(GlrSyntaxFile* node); + virtual void Finishing(GlrUseSyntax* node); + + protected: + void Visit(GlrRefSyntax* node) override; + void Visit(GlrLiteralSyntax* node) override; + void Visit(GlrUseSyntax* node) override; + void Visit(GlrLoopSyntax* node) override; + void Visit(GlrOptionalSyntax* node) override; + void Visit(GlrSequenceSyntax* node) override; + void Visit(GlrAlternativeSyntax* node) override; + + void Visit(GlrCreateClause* node) override; + void Visit(GlrPartialClause* node) override; + void Visit(GlrReuseClause* node) override; + + public: + void InspectInto(GlrSyntax* node); + void InspectInto(GlrClause* node); + void InspectInto(GlrAssignment* node); + void InspectInto(GlrRule* node); + void InspectInto(GlrSyntaxFile* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_TYPEAST_AST +#define VCZH_PARSER2_PARSERGEN_TYPEAST_AST + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + class GlrAstFile; + class GlrClass; + class GlrClassProp; + class GlrEnum; + class GlrEnumItem; + class GlrType; + + enum class GlrPropType + { + UNDEFINED_ENUM_ITEM_VALUE = -1, + Token = 0, + Type = 1, + Array = 2, + }; + + enum class GlrClassAmbiguity + { + UNDEFINED_ENUM_ITEM_VALUE = -1, + No = 0, + Yes = 1, + }; + + class GlrType abstract : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + class IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description + { + public: + virtual void Visit(GlrEnum* node) = 0; + virtual void Visit(GlrClass* node) = 0; + }; + + virtual void Accept(GlrType::IVisitor* visitor) = 0; + + vl::glr::ParsingToken name; + }; + + class GlrEnumItem : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + }; + + class GlrEnum : public GlrType, vl::reflection::Description + { + public: + vl::collections::List> items; + + void Accept(GlrType::IVisitor* visitor) override; + }; + + class GlrClassProp : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::glr::ParsingToken name; + GlrPropType propType = GlrPropType::UNDEFINED_ENUM_ITEM_VALUE; + vl::glr::ParsingToken propTypeName; + }; + + class GlrClass : public GlrType, vl::reflection::Description + { + public: + vl::glr::ParsingToken baseClass; + GlrClassAmbiguity ambiguity = GlrClassAmbiguity::UNDEFINED_ENUM_ITEM_VALUE; + vl::collections::List> props; + + void Accept(GlrType::IVisitor* visitor) override; + }; + + class GlrAstFile : public vl::glr::ParsingAstBase, vl::reflection::Description + { + public: + vl::collections::List> types; + }; + } + } +} +namespace vl +{ + namespace reflection + { + namespace description + { +#ifndef VCZH_DEBUG_NO_REFLECTION + DECL_TYPE_INFO(vl::glr::parsergen::GlrType) + DECL_TYPE_INFO(vl::glr::parsergen::GlrType::IVisitor) + DECL_TYPE_INFO(vl::glr::parsergen::GlrEnumItem) + DECL_TYPE_INFO(vl::glr::parsergen::GlrEnum) + DECL_TYPE_INFO(vl::glr::parsergen::GlrPropType) + DECL_TYPE_INFO(vl::glr::parsergen::GlrClassProp) + DECL_TYPE_INFO(vl::glr::parsergen::GlrClassAmbiguity) + DECL_TYPE_INFO(vl::glr::parsergen::GlrClass) + DECL_TYPE_INFO(vl::glr::parsergen::GlrAstFile) + +#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA + + BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::glr::parsergen::GlrType::IVisitor) + void Visit(vl::glr::parsergen::GlrEnum* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + void Visit(vl::glr::parsergen::GlrClass* node) override + { + INVOKE_INTERFACE_PROXY(Visit, node); + } + + END_INTERFACE_PROXY(vl::glr::parsergen::GlrType::IVisitor) + +#endif +#endif + /// Load all reflectable AST types, only available when VCZH_DEBUG_NO_REFLECTION is off. + /// Returns true if this operation succeeded. + extern bool ParserGenTypeAstLoadTypes(); + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_BUILDER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_TYPEAST_AST_BUILDER +#define VCZH_PARSER2_PARSERGEN_TYPEAST_AST_BUILDER + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace builder + { + class MakeAstFile : public vl::glr::ParsingAstBuilder + { + public: + MakeAstFile& types(const vl::Ptr& value); + }; + + class MakeClass : public vl::glr::ParsingAstBuilder + { + public: + MakeClass& ambiguity(GlrClassAmbiguity value); + MakeClass& baseClass(const vl::WString& value); + MakeClass& props(const vl::Ptr& value); + MakeClass& name(const vl::WString& value); + }; + + class MakeClassProp : public vl::glr::ParsingAstBuilder + { + public: + MakeClassProp& name(const vl::WString& value); + MakeClassProp& propType(GlrPropType value); + MakeClassProp& propTypeName(const vl::WString& value); + }; + + class MakeEnum : public vl::glr::ParsingAstBuilder + { + public: + MakeEnum& items(const vl::Ptr& value); + MakeEnum& name(const vl::WString& value); + }; + + class MakeEnumItem : public vl::glr::ParsingAstBuilder + { + public: + MakeEnumItem& name(const vl::WString& value); + }; + + class MakeType : public vl::glr::ParsingAstBuilder + { + public: + MakeType& name(const vl::WString& value); + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_COPY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_TYPEAST_AST_COPY_VISITOR +#define VCZH_PARSER2_PARSERGEN_TYPEAST_AST_COPY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace copy_visitor + { + /// A copy visitor, overriding all abstract methods with AST copying code. + class TypeAstVisitor + : public virtual vl::glr::CopyVisitorBase + , protected virtual GlrType::IVisitor + { + protected: + void CopyFields(GlrAstFile* from, GlrAstFile* to); + void CopyFields(GlrClass* from, GlrClass* to); + void CopyFields(GlrClassProp* from, GlrClassProp* to); + void CopyFields(GlrEnum* from, GlrEnum* to); + void CopyFields(GlrEnumItem* from, GlrEnumItem* to); + void CopyFields(GlrType* from, GlrType* to); + + protected: + virtual void Visit(GlrEnumItem* node); + virtual void Visit(GlrClassProp* node); + virtual void Visit(GlrAstFile* node); + + void Visit(GlrEnum* node) override; + void Visit(GlrClass* node) override; + + public: + virtual vl::Ptr CopyNode(GlrType* node); + virtual vl::Ptr CopyNode(GlrEnumItem* node); + virtual vl::Ptr CopyNode(GlrClassProp* node); + virtual vl::Ptr CopyNode(GlrAstFile* node); + + vl::Ptr CopyNode(GlrClass* node); + vl::Ptr CopyNode(GlrEnum* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_EMPTY.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_TYPEAST_AST_EMPTY_VISITOR +#define VCZH_PARSER2_PARSERGEN_TYPEAST_AST_EMPTY_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace empty_visitor + { + /// An empty visitor, overriding all abstract methods with empty implementations. + class TypeVisitor : public vl::Object, public GlrType::IVisitor + { + protected: + // Dispatch (virtual) -------------------------------- + + public: + // Visitor Members ----------------------------------- + void Visit(GlrEnum* node) override; + void Visit(GlrClass* node) override; + }; + + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_JSON.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_TYPEAST_AST_JSON_VISITOR +#define VCZH_PARSER2_PARSERGEN_TYPEAST_AST_JSON_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace json_visitor + { + /// A JSON visitor, overriding all abstract methods with AST to JSON serialization code. + class TypeAstVisitor + : public vl::glr::JsonVisitorBase + , protected virtual GlrType::IVisitor + { + protected: + virtual void PrintFields(GlrAstFile* node); + virtual void PrintFields(GlrClass* node); + virtual void PrintFields(GlrClassProp* node); + virtual void PrintFields(GlrEnum* node); + virtual void PrintFields(GlrEnumItem* node); + virtual void PrintFields(GlrType* node); + + protected: + void Visit(GlrEnum* node) override; + void Visit(GlrClass* node) override; + + public: + TypeAstVisitor(vl::stream::StreamWriter& _writer); + + void Print(GlrType* node); + void Print(GlrEnumItem* node); + void Print(GlrClassProp* node); + void Print(GlrAstFile* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEAST_TRAVERSE.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:TypeAst +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_TYPEAST_AST_TRAVERSE_VISITOR +#define VCZH_PARSER2_PARSERGEN_TYPEAST_AST_TRAVERSE_VISITOR + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace traverse_visitor + { + /// A traverse visitor, overriding all abstract methods with AST visiting code. + class TypeAstVisitor + : public vl::Object + , protected virtual GlrType::IVisitor + { + protected: + virtual void Traverse(vl::glr::ParsingToken& token); + virtual void Traverse(vl::glr::ParsingAstBase* node); + virtual void Traverse(GlrAstFile* node); + virtual void Traverse(GlrClass* node); + virtual void Traverse(GlrClassProp* node); + virtual void Traverse(GlrEnum* node); + virtual void Traverse(GlrEnumItem* node); + virtual void Traverse(GlrType* node); + + protected: + virtual void Finishing(vl::glr::ParsingAstBase* node); + virtual void Finishing(GlrAstFile* node); + virtual void Finishing(GlrClass* node); + virtual void Finishing(GlrClassProp* node); + virtual void Finishing(GlrEnum* node); + virtual void Finishing(GlrEnumItem* node); + virtual void Finishing(GlrType* node); + + protected: + void Visit(GlrEnum* node) override; + void Visit(GlrClass* node) override; + + public: + void InspectInto(GlrType* node); + void InspectInto(GlrEnumItem* node); + void InspectInto(GlrClassProp* node); + void InspectInto(GlrAstFile* node); + }; + } + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGEN_ASSEMBLER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_AST_ASSEMBLER +#define VCZH_PARSER2_PARSERGEN_AST_ASSEMBLER + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + enum class ParserGenClasses : vl::vint32_t + { + AlternativeSyntax = 0, + Assignment = 1, + AstFile = 2, + Class = 3, + ClassProp = 4, + Clause = 5, + CreateClause = 6, + Enum = 7, + EnumItem = 8, + LiteralSyntax = 9, + LoopSyntax = 10, + OptionalSyntax = 11, + PartialClause = 12, + RefSyntax = 13, + ReuseClause = 14, + Rule = 15, + SequenceSyntax = 16, + Syntax = 17, + SyntaxFile = 18, + Type = 19, + UseSyntax = 20, + }; + + enum class ParserGenFields : vl::vint32_t + { + AlternativeSyntax_first = 0, + AlternativeSyntax_second = 1, + Assignment_field = 2, + Assignment_value = 3, + AstFile_types = 4, + Class_ambiguity = 5, + Class_baseClass = 6, + Class_props = 7, + ClassProp_name = 8, + ClassProp_propType = 9, + ClassProp_propTypeName = 10, + CreateClause_assignments = 11, + CreateClause_syntax = 12, + CreateClause_type = 13, + Enum_items = 14, + EnumItem_name = 15, + LiteralSyntax_value = 16, + LoopSyntax_delimiter = 17, + LoopSyntax_syntax = 18, + OptionalSyntax_priority = 19, + OptionalSyntax_syntax = 20, + PartialClause_assignments = 21, + PartialClause_syntax = 22, + PartialClause_type = 23, + RefSyntax_field = 24, + RefSyntax_name = 25, + ReuseClause_assignments = 26, + ReuseClause_syntax = 27, + Rule_clauses = 28, + Rule_name = 29, + SequenceSyntax_first = 30, + SequenceSyntax_second = 31, + SyntaxFile_rules = 32, + Type_name = 33, + UseSyntax_name = 34, + }; + + extern const wchar_t* ParserGenTypeName(ParserGenClasses type); + extern const wchar_t* ParserGenCppTypeName(ParserGenClasses type); + extern const wchar_t* ParserGenFieldName(ParserGenFields field); + extern const wchar_t* ParserGenCppFieldName(ParserGenFields field); + + class ParserGenAstInsReceiver : public vl::glr::AstInsReceiverBase + { + protected: + vl::Ptr CreateAstNode(vl::vint32_t type) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr value) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) override; + void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem) override; + vl::Ptr ResolveAmbiguity(vl::vint32_t type, vl::collections::Array>& candidates) override; + }; + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGEN_LEXER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_LEXER +#define VCZH_PARSER2_PARSERGEN_LEXER + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + enum class ParserGenTokens : vl::vint32_t + { + AMBIGUOUS = 0, + CLASS = 1, + ENUM = 2, + VAR = 3, + TOKEN = 4, + AS = 5, + PARTIAL = 6, + OPEN_ROUND = 7, + CLOSE_ROUND = 8, + OPEN_SQUARE = 9, + CLOSE_SQUARE = 10, + OPEN_CURLY = 11, + CLOSE_CURLY = 12, + COMMA = 13, + COLON = 14, + SEMICOLON = 15, + INFER = 16, + ALTERNATIVE = 17, + USE = 18, + ASSIGN = 19, + POSITIVE = 20, + NEGATIVE = 21, + ID = 22, + STRING = 23, + SPACE = 24, + COMMENT = 25, + }; + + constexpr vl::vint ParserGenTokenCount = 26; + extern bool ParserGenTokenDeleter(vl::vint token); + extern const wchar_t* ParserGenTokenId(ParserGenTokens token); + extern const wchar_t* ParserGenTokenDisplayText(ParserGenTokens token); + extern const wchar_t* ParserGenTokenRegex(ParserGenTokens token); + extern void ParserGenLexerData(vl::stream::IStream& outputStream); + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENRULEPARSER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_RULEPARSER_SYNTAX +#define VCZH_PARSER2_PARSERGEN_RULEPARSER_SYNTAX + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + enum class RuleParserStates + { + OptionalBody = 0, + Syntax0 = 5, + Syntax1 = 26, + Syntax2 = 31, + Syntax = 37, + Assignment = 40, + Clause = 45, + Rule = 67, + File = 73, + }; + + template struct RuleParserStateTypes; + template<> struct RuleParserStateTypes { using Type = vl::glr::parsergen::GlrSyntaxFile; }; + + const wchar_t* RuleParserRuleName(vl::vint index); + const wchar_t* RuleParserStateLabel(vl::vint index); + extern void ParserGenRuleParserData(vl::stream::IStream& outputStream); + + class RuleParser + : public vl::glr::ParserBase + , protected vl::glr::automaton::TraceManager::ITypeCallback + { + protected: + vl::vint32_t FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const override; + public: + RuleParser(); + + vl::Ptr ParseFile(const vl::WString& input, vl::vint codeIndex = -1) const; + vl::Ptr ParseFile(vl::collections::List& tokens, vl::vint codeIndex = -1) const; + }; + } + } +} +#endif + +/*********************************************************************** +.\PARSERGEN_GENERATED\PARSERGENTYPEPARSER.H +***********************************************************************/ +/*********************************************************************** +This file is generated by: Vczh Parser Generator +From parser definition:ParserGen +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_TYPEPARSER_SYNTAX +#define VCZH_PARSER2_PARSERGEN_TYPEPARSER_SYNTAX + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + enum class TypeParserStates + { + EnumItem = 0, + Enum = 4, + ClassPropType = 11, + classProp = 18, + ClassBody = 25, + Class = 33, + Type = 40, + File = 44, + }; + + template struct TypeParserStateTypes; + template<> struct TypeParserStateTypes { using Type = vl::glr::parsergen::GlrAstFile; }; + + const wchar_t* TypeParserRuleName(vl::vint index); + const wchar_t* TypeParserStateLabel(vl::vint index); + extern void ParserGenTypeParserData(vl::stream::IStream& outputStream); + + class TypeParser + : public vl::glr::ParserBase + , protected vl::glr::automaton::TraceManager::ITypeCallback + { + protected: + vl::vint32_t FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const override; + public: + TypeParser(); + + vl::Ptr ParseFile(const vl::WString& input, vl::vint codeIndex = -1) const; + vl::Ptr ParseFile(vl::collections::List& tokens, vl::vint codeIndex = -1) const; + }; + } + } +} +#endif + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOL.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_SYNTAX_SYNTAXSYMBOL +#define VCZH_PARSER2_SYNTAX_SYNTAXSYMBOL + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + class AstClassSymbol; + class StateSymbol; + class EdgeSymbol; + class RuleSymbol; + class SyntaxSymbolManager; + class CompactSyntaxBuilder; + +/*********************************************************************** +StateSymbol +***********************************************************************/ + + class StateSymbol : public Object + { + friend class EdgeSymbol; + friend class SyntaxSymbolManager; + friend class CompactSyntaxBuilder; + + using EdgeList = collections::List; + protected: + SyntaxSymbolManager* ownerManager; + RuleSymbol* rule; + vint32_t clauseId; + EdgeList inEdges; + EdgeList outEdges; + + StateSymbol(RuleSymbol* _rule, vint32_t _clauseId); + public: + WString label; + bool endingState = false; + + SyntaxSymbolManager* Owner() { return ownerManager; } + RuleSymbol* Rule() { return rule; } + vint32_t ClauseId() { return clauseId; } + const EdgeList& InEdges() { return inEdges; } + const EdgeList& OutEdges() { return outEdges; } + + void GetOutEdgesInStableOrder(collections::List& orderedStates, EdgeList& orderedEdges); + }; + +/*********************************************************************** +EdgeSymbol +***********************************************************************/ + + enum class EdgeInputType + { + Epsilon, // No input is needed to execute this edge. + Ending, // An epsilon edge that reduces the current rule. + LeftRec, // An epsilon edge that reduces the current rule, which is the first input of one of its left recursive clause. + Token, // An token is read to execute this edge. + Rule, // A rule is reduced to execute this edge. + }; + + struct EdgeInput + { + EdgeInputType type = EdgeInputType::Epsilon; + vint32_t token = -1; + RuleSymbol* rule = nullptr; + }; + + enum class EdgeImportancy + { + NoCompetition, + HighPriority, + LowPriority, + }; + + class EdgeSymbol : public Object + { + friend class SyntaxSymbolManager; + friend class CompactSyntaxBuilder; + + using InsList = collections::List; + using EdgeList = collections::List; + protected: + SyntaxSymbolManager* ownerManager; + StateSymbol* fromState; + StateSymbol* toState; + + EdgeSymbol(StateSymbol* _from, StateSymbol* _to); + public: + EdgeInput input; // Input of this edge. + bool important = false; // true and false are the only two priorites of edges. + EdgeImportancy importancy = EdgeImportancy::NoCompetition; // important -> HighPriority, !important with important sibling -> LowPriority. + // (filled by BuildCompactNFA) + // If any important edge forms a cross referenced NFA edge, it becomes important too. + InsList insBeforeInput; // Instructions to execute before pushing the value from a token or a reduced rule. + InsList insAfterInput; // Instructions to execute after pushing the value from a token or a reduced rule. + EdgeList returnEdges; // Edges of rule reduction. + // InsBeforeInput will be copied to a cross-referenced edge. + // When a reduction is done, only insAfterInput need to execute. + + SyntaxSymbolManager* Owner() { return ownerManager; } + StateSymbol* From() { return fromState; } + StateSymbol* To() { return toState; } + }; + +/*********************************************************************** +RuleSymbol +***********************************************************************/ + + class RuleSymbol : public Object + { + friend class SyntaxSymbolManager; + + using StateList = collections::List; + protected: + SyntaxSymbolManager* ownerManager; + WString name; + vint32_t currentClauseId = -1; + + RuleSymbol(SyntaxSymbolManager* _ownerManager, const WString& _name); + public: + StateList startStates; + bool isPartial = false; + bool assignedNonArrayField = false; + AstClassSymbol* ruleType = nullptr; + + SyntaxSymbolManager* Owner() { return ownerManager; } + const WString& Name() { return name; } + void NewClause() { currentClauseId++; } + vint32_t CurrentClauseId() { return currentClauseId; } + }; + +/*********************************************************************** +SyntaxSymbolManager +***********************************************************************/ + + enum class SyntaxPhase + { + EpsilonNFA, // An automaton that has edges of Epsilon, Token, Rule. + CompactNFA, // Epsilon edges are eliminated by compressing multiple edges into one. + // Epsilon edges to the ending state will be compressed to an Ending edge. + // The first edge of Rule in left-recursive clauses becomes a LeftRec edge, with its fromState changed to the ending state. + // fromState and toState of non-LeftRec edges belong to the same clause. + CrossReferencedNFA, // Edges of Rule are compressed to an edge that pointing towards states in other clauses. + // Multiple edges of rule are stored in returnEdges in the order of execution. + // insBeforeInput of an edge contains insBeforeInput from its returnEdges. + // returnEdges of an edge will be pushed to a stack when it is executed. + // Executing an Ending edge pops a returnEdges and execute its insAfterInput only. + // automaton::Executable is exactly the same to CrossReferencedNFA, stored a more cache friendly way. + }; + + class SyntaxSymbolManager : public Object + { + using StateList = collections::List>; + using EdgeList = collections::List>; + using RuleTypeMap = collections::Dictionary; + using RuleList = collections::List; + protected: + MappedOwning rules; + StateList states; + EdgeList edges; + ParserSymbolManager& global; + SyntaxPhase phase = SyntaxPhase::EpsilonNFA; + + void BuildLeftRecEdge(EdgeSymbol* newEdge, EdgeSymbol* endingEdge, EdgeSymbol* lrecPrefixEdge); + void EliminateLeftRecursion(RuleSymbol* rule, StateSymbol* startState, StateSymbol* endState, StateList& newStates, EdgeList& newEdges); + void EliminateSingleRulePrefix(RuleSymbol* rule, StateSymbol* startState, StateSymbol* endState, StateList& newStates, EdgeList& newEdges); + StateSymbol* EliminateEpsilonEdges(RuleSymbol* rule, StateList& newStates, EdgeList& newEdges); + void BuildCompactNFAInternal(); + + void FixCrossReferencedRuleEdge(StateSymbol* startState, collections::Group& orderedEdges, collections::List& accumulatedEdges); + void BuildCrossReferencedNFAInternal(); + public: + SyntaxSymbolManager(ParserSymbolManager& _global); + + WString name; + RuleTypeMap ruleTypes; + RuleList parsableRules; + + RuleSymbol* CreateRule(const WString& name, ParsingTextRange codeRange = {}); + StateSymbol* CreateState(RuleSymbol* rule, vint32_t clauseId); + EdgeSymbol* CreateEdge(StateSymbol* from, StateSymbol* to); + + void BuildCompactNFA(); + void BuildCrossReferencedNFA(); + void BuildAutomaton(vint tokenCount, automaton::Executable& executable, automaton::Metadata& metadata); + void GetStatesInStableOrder(collections::List& order); + WString GetStateGlobalLabel(StateSymbol* state, vint index); + + ParserSymbolManager& Global() { return global; } + const auto& Rules() { return rules.map; } + const auto& RuleOrder() { return rules.order; } + SyntaxPhase Phase() { return phase; } + + template + void AddError(ParserErrorType type, ParsingTextRange codeRange, TArgs&&... args) + { + global.AddError(type, { ParserDefFileType::Syntax,name,codeRange }, std::forward(args)...); + } + }; + + extern void CreateParserGenTypeSyntax(SyntaxSymbolManager& manager); + extern void CreateParserGenRuleSyntax(SyntaxSymbolManager& manager); + } + } +} + +#endif + +/*********************************************************************** +.\PARSERGEN\COMPILER.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_PARSERGEN_COMPILER +#define VCZH_PARSER2_PARSERGEN_COMPILER + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace compile_syntax + { + using GlrRuleMap = collections::Dictionary; + using LiteralTokenMap = collections::Dictionary; + using RuleReuseDependencies = collections::Group; + using RuleKnownTypes = collections::Group; + using ClauseReuseDependencies = collections::Group; + using ClauseTypeMap = collections::Dictionary; + + struct VisitorContext + { + ParserSymbolManager& global; + AstSymbolManager& astManager; + LexerSymbolManager& lexerManager; + SyntaxSymbolManager& syntaxManager; + Ptr output; + + GlrRuleMap astRules; + LiteralTokenMap literalTokens; + RuleReuseDependencies ruleReuseDependencies; + RuleKnownTypes ruleKnownTypes; + ClauseReuseDependencies clauseReuseDependencies; + ClauseTypeMap clauseTypes; + + VisitorContext( + AstSymbolManager& _astManager, + LexerSymbolManager& _lexerManager, + SyntaxSymbolManager& _syntaxManager, + Ptr _output + ) + : global(_syntaxManager.Global()) + , astManager(_astManager) + , lexerManager(_lexerManager) + , syntaxManager(_syntaxManager) + , output(_output) + { + } + }; + } + +/*********************************************************************** +Compiler +***********************************************************************/ + + extern void CompileAst(AstSymbolManager& astManager, AstDefFile* astDefFile, Ptr file); + extern void CompileLexer(LexerSymbolManager& lexerManager, const WString& input); + extern void CompileSyntax(AstSymbolManager& astManager, LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, Ptr output, collections::List>& files); + } + } +} + +#endif + +/*********************************************************************** +.\SYNTAX\SYNTAXCPPGEN.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_SYNTAX_SYNTAXCPPGEN +#define VCZH_PARSER2_SYNTAX_SYNTAXCPPGEN + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + extern Ptr GenerateSyntaxFileNames (SyntaxSymbolManager& manager, Ptr output); + extern void WriteSyntaxHeaderFile (SyntaxSymbolManager& manager, automaton::Executable& executable, automaton::Metadata& metadata, Ptr output, stream::StreamWriter& writer); + extern void WriteSyntaxCppFile (SyntaxSymbolManager& manager, automaton::Executable& executable, automaton::Metadata& metadata, Ptr output, stream::StreamWriter& writer); + extern void WriteSyntaxFiles (SyntaxSymbolManager& manager, automaton::Executable& executable, automaton::Metadata& metadata, Ptr output, collections::Dictionary& files); + } + } +} + +#endif + +/*********************************************************************** +.\SYNTAX\SYNTAXSYMBOLWRITER.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_PARSER2_SYNTAX_SYNTAXWRITER +#define VCZH_PARSER2_SYNTAX_SYNTAXWRITER + + +namespace vl +{ + namespace glr + { + namespace parsergen + { + namespace syntax_writer + { + +/*********************************************************************** +Clause +***********************************************************************/ + + struct Token + { + vint32_t id; + vint32_t field; + WString display; + }; + + struct Rule + { + static const vint Partial = -2; + static const vint Discard = -1; + + RuleSymbol* rule; + vint32_t field; + }; + + struct Use + { + RuleSymbol* rule; + }; + + template + struct Loop + { + T body; + }; + + template + struct LoopSep + { + T body; + U delimiter; + }; + + template + struct Opt + { + T body; + }; + + template + struct Seq + { + T first; + U second; + }; + + template + struct Alt + { + T first; + U second; + }; + + template + struct With + { + T body; + vint32_t field; + vint32_t enumItem; + }; + + template + struct Create + { + T body; + vint32_t type; + + template + Create> with(F field, E enumItem) + { + return { { body,(vint32_t)field,(vint32_t)enumItem }, type }; + } + }; + + template + struct Partial + { + T body; + + template + Partial> with(F field, E enumItem) + { + return { { body,(vint32_t)field,(vint32_t)enumItem } }; + } + }; + + template + struct Reuse + { + T body; + + template + Reuse> with(F field, E enumItem) + { + return { { body,(vint32_t)field,(vint32_t)enumItem } }; + } + }; + +/*********************************************************************** +Verification +***********************************************************************/ + + template + struct IsClause_ { static constexpr bool Value = false; }; + + template<> + struct IsClause_ { static constexpr bool Value = true; }; + + template<> + struct IsClause_ { static constexpr bool Value = true; }; + + template<> + struct IsClause_ { static constexpr bool Value = true; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value && IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value && IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value && IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value; }; + + template + struct IsClause_> { static constexpr bool Value = IsClause_::Value; }; + + template + constexpr bool IsClause = IsClause_::Value; + +/*********************************************************************** +Operators +***********************************************************************/ + + template + inline Token tok(T id, const WString& display) + { + return { (vint32_t)id,-1,display }; + } + + template + inline Token tok(T id, const WString& display, F field = -1) + { + return { (vint32_t)id,(vint32_t)field,display }; + } + + inline Rule drule(RuleSymbol* r) + { + return { r,Rule::Discard }; + } + + inline Rule prule(RuleSymbol* r) + { + return { r,Rule::Partial }; + } + + template + inline Rule rule(RuleSymbol* r, F field) + { + return { r,(vint32_t)field }; + } + + inline Use use(RuleSymbol* r) + { + return { r }; + } + + template + inline std::enable_if_t, Loop> loop(const C& clause) + { + return { clause }; + } + + template + inline std::enable_if_t && IsClause, LoopSep> loop(const C1& c1, const C2& c2) + { + return { c1,c2 }; + } + + template + inline std::enable_if_t, Opt> opt(const C& clause) + { + return { clause }; + } + + template + inline std::enable_if_t && IsClause, Seq> operator+(const C1& c1, const C2& c2) + { + return { c1,c2 }; + } + + template + inline std::enable_if_t&& IsClause, Alt> operator|(const C1& c1, const C2& c2) + { + return { c1,c2 }; + } + + template + inline std::enable_if_t, Create> create(const C& clause, T type) + { + return { clause,(vint32_t)type }; + } + + template + inline std::enable_if_t, Partial> partial(const C& clause) + { + return { clause }; + } + + template + inline std::enable_if_t, Reuse> reuse(const C& clause) + { + return { clause }; + } + +/*********************************************************************** +Builder +***********************************************************************/ + + struct Clause + { + using StatePosMap = collections::Dictionary; + private: + struct StatePair + { + StateSymbol* begin; + StateSymbol* end; + }; + + RuleSymbol* ruleSymbol; + WString clauseDisplayText; + StatePosMap startPoses; + StatePosMap endPoses; + + StateSymbol* CreateState() + { + return ruleSymbol->Owner()->CreateState(ruleSymbol, ruleSymbol->CurrentClauseId()); + } + + EdgeSymbol* CreateEdge(StateSymbol* from, StateSymbol* to) + { + return ruleSymbol->Owner()->CreateEdge(from, to); + } + + StatePair Build(const Token& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + { + auto edge = CreateEdge(pair.begin, pair.end); + edge->input.type = EdgeInputType::Token; + edge->input.token = clause.id; + if (clause.field != -1) + { + edge->insAfterInput.Add({ AstInsType::Token }); + edge->insAfterInput.Add({ AstInsType::Field,clause.field }); + } + } + + clauseDisplayText += clause.display; + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + StatePair Build(const Rule& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + { + auto edge = CreateEdge(pair.begin, pair.end); + edge->input.type = EdgeInputType::Rule; + edge->input.rule = clause.rule; + switch (clause.field) + { + case Rule::Partial: + break; + case Rule::Discard: + edge->insAfterInput.Add({ AstInsType::DiscardValue }); + break; + default: + edge->insAfterInput.Add({ AstInsType::Field,clause.field }); + } + } + + clauseDisplayText += clause.rule->Name(); + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + StatePair Build(const Use& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + { + auto edge = CreateEdge(pair.begin, pair.end); + edge->input.type = EdgeInputType::Rule; + edge->input.rule = clause.rule; + edge->insAfterInput.Add({ AstInsType::ReopenObject }); + } + + clauseDisplayText += L"!" + clause.rule->Name(); + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + template + StatePair Build(const Loop& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"{ "; + auto bodyPair = Build(clause.body); + clauseDisplayText += L" }"; + + CreateEdge(pair.begin, bodyPair.begin); + CreateEdge(bodyPair.end, pair.end); + CreateEdge(pair.begin, pair.end); + CreateEdge(bodyPair.end, bodyPair.begin); + + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + template + StatePair Build(const LoopSep& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"{ "; + auto bodyPair = Build(clause.body); + clauseDisplayText += L" ; "; + auto delimiterPair = Build(clause.delimiter); + clauseDisplayText += L" }"; + + CreateEdge(pair.begin, bodyPair.begin); + CreateEdge(bodyPair.end, pair.end); + CreateEdge(pair.begin, pair.end); + CreateEdge(bodyPair.end, delimiterPair.begin); + CreateEdge(delimiterPair.end, bodyPair.begin); + + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + template + StatePair Build(const Opt& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"[ "; + auto bodyPair = Build(clause.body); + clauseDisplayText += L" ]"; + + CreateEdge(pair.begin, bodyPair.begin); + CreateEdge(bodyPair.end, pair.end); + CreateEdge(pair.begin, pair.end); + + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + template + StatePair Build(const Seq& clause) + { + auto firstPair = Build(clause.first); + clauseDisplayText += L" "; + auto secondPair = Build(clause.second); + CreateEdge(firstPair.end, secondPair.begin); + return { firstPair.begin,secondPair.end }; + } + + template + StatePair Build(const Alt& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"( "; + auto firstPair = Build(clause.first); + clauseDisplayText += L" | "; + auto secondPair = Build(clause.second); + clauseDisplayText += L" )"; + + CreateEdge(pair.begin, firstPair.begin); + CreateEdge(firstPair.end, pair.end); + CreateEdge(pair.begin, secondPair.begin); + CreateEdge(secondPair.end, pair.end); + + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + template + StatePair Build(const With& clause) + { + auto pair = Build(clause.body); + auto withState = CreateState(); + auto edge = CreateEdge(pair.end, withState); + edge->insBeforeInput.Add({ AstInsType::EnumItem,clause.enumItem }); + edge->insBeforeInput.Add({ AstInsType::Field,clause.field }); + + endPoses.Add(withState, clauseDisplayText.Length()); + return { pair.begin,withState }; + } + + template + StatePair Build(const Create& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"< "; + auto bodyPair = Build(clause.body); + clauseDisplayText += L" >"; + { + auto edge = CreateEdge(pair.begin, bodyPair.begin); + edge->insBeforeInput.Add({ AstInsType::BeginObject,clause.type }); + } + { + auto edge = CreateEdge(bodyPair.end, pair.end); + edge->insBeforeInput.Add({ AstInsType::EndObject }); + } + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + template + StatePair Build(const Partial& clause) + { + return Build(clause.body); + } + + template + StatePair Build(const Reuse& clause) + { + StatePair pair; + pair.begin = CreateState(); + pair.end = CreateState(); + startPoses.Add(pair.begin, clauseDisplayText.Length()); + + clauseDisplayText += L"<< "; + auto bodyPair = Build(clause.body); + clauseDisplayText += L" >>"; + { + auto edge = CreateEdge(pair.begin, bodyPair.begin); + edge->insBeforeInput.Add({ AstInsType::DelayFieldAssignment }); + } + { + auto edge = CreateEdge(bodyPair.end, pair.end); + edge->insBeforeInput.Add({ AstInsType::EndObject }); + } + endPoses.Add(pair.end, clauseDisplayText.Length()); + return pair; + } + + template + void Assign(const C& clause) + { + ruleSymbol->NewClause(); + + clauseDisplayText = L""; + startPoses.Clear(); + endPoses.Clear(); + + auto pair = Build(clause); + ruleSymbol->startStates.Add(pair.begin); + pair.end->endingState = true; + + vint l = clauseDisplayText.Length(); + for (auto [state, pos] : startPoses) + { + state->label = clauseDisplayText.Left(pos) + L"@ " + clauseDisplayText.Right(l - pos); + } + for (auto [state, pos] : endPoses) + { + state->label = clauseDisplayText.Left(pos) + L" @" + clauseDisplayText.Right(l - pos); + } + } + public: + Clause(RuleSymbol* _ruleSymbol) : ruleSymbol(_ruleSymbol) {} + + template + Clause& operator=(const Create& clause) + { + Assign(clause); + return *this; + } + + template + Clause& operator=(const Partial& clause) + { + Assign(clause); + return *this; + } + + template + Clause& operator=(const Reuse& clause) + { + Assign(clause); + return *this; + } + + template + Clause& operator=(const C& clause) + { + return operator=(reuse(clause)); + } + }; + } + } + } +} + +#endif diff --git a/Tutorial/Console_Workflow/Lib/Lib.vcxproj b/Tutorial/Console_Workflow/Lib/Lib.vcxproj index a6e9e4d0..55b8729e 100644 --- a/Tutorial/Console_Workflow/Lib/Lib.vcxproj +++ b/Tutorial/Console_Workflow/Lib/Lib.vcxproj @@ -172,6 +172,12 @@ true + + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) /bigobj %(AdditionalOptions) @@ -185,12 +191,6 @@ true - - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) /bigobj %(AdditionalOptions) @@ -224,8 +224,8 @@ + - diff --git a/Tutorial/Console_Workflow/Lib/Lib.vcxproj.filters b/Tutorial/Console_Workflow/Lib/Lib.vcxproj.filters index b5e184ac..d189739b 100644 --- a/Tutorial/Console_Workflow/Lib/Lib.vcxproj.filters +++ b/Tutorial/Console_Workflow/Lib/Lib.vcxproj.filters @@ -21,9 +21,6 @@ Source Files - - Source Files - Source Files @@ -51,6 +48,9 @@ Source Files + + Source Files + @@ -59,9 +59,6 @@ Source Files - - Source Files - Source Files @@ -77,5 +74,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj b/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj index b9333b74..88b85b02 100644 --- a/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj +++ b/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj @@ -168,6 +168,12 @@ true + + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) /bigobj %(AdditionalOptions) @@ -181,12 +187,6 @@ true - - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) - /bigobj %(AdditionalOptions) /bigobj %(AdditionalOptions) @@ -216,8 +216,8 @@ + - diff --git a/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj.filters b/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj.filters index 8b1fc72f..c117643a 100644 --- a/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj.filters +++ b/Tutorial/Console_Workflow/W05_DynamicRun/W05_DynamicRun.vcxproj.filters @@ -24,9 +24,6 @@ Import - - Import - Import @@ -57,6 +54,9 @@ Import + + Import + @@ -65,9 +65,6 @@ Import - - Import - Import @@ -83,5 +80,8 @@ Source Files + + Import + \ No newline at end of file diff --git a/Tutorial/Lib/GacUI/GacUI.vcxproj b/Tutorial/Lib/GacUI/GacUI.vcxproj index 6f9906a5..4f6b64ad 100644 --- a/Tutorial/Lib/GacUI/GacUI.vcxproj +++ b/Tutorial/Lib/GacUI/GacUI.vcxproj @@ -106,6 +106,10 @@ true + + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) /bigobj %(AdditionalOptions) @@ -147,6 +151,7 @@ + diff --git a/Tutorial/Lib/GacUI/GacUI.vcxproj.filters b/Tutorial/Lib/GacUI/GacUI.vcxproj.filters index 44c7a910..4356b908 100644 --- a/Tutorial/Lib/GacUI/GacUI.vcxproj.filters +++ b/Tutorial/Lib/GacUI/GacUI.vcxproj.filters @@ -75,6 +75,9 @@ Import + + Import + @@ -113,5 +116,8 @@ Import + + Import + \ No newline at end of file diff --git a/Tutorial/Lib/GacUILite/GacUILite.vcxproj b/Tutorial/Lib/GacUILite/GacUILite.vcxproj index 957f8d49..98fe27e7 100644 --- a/Tutorial/Lib/GacUILite/GacUILite.vcxproj +++ b/Tutorial/Lib/GacUILite/GacUILite.vcxproj @@ -98,6 +98,10 @@ true + + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) /bigobj %(AdditionalOptions) @@ -133,6 +137,7 @@ + diff --git a/Tutorial/Lib/GacUILite/GacUILite.vcxproj.filters b/Tutorial/Lib/GacUILite/GacUILite.vcxproj.filters index 68e3420a..fce1da77 100644 --- a/Tutorial/Lib/GacUILite/GacUILite.vcxproj.filters +++ b/Tutorial/Lib/GacUILite/GacUILite.vcxproj.filters @@ -66,6 +66,9 @@ Import + + Import + @@ -95,5 +98,8 @@ Import + + Import + \ No newline at end of file