/*********************************************************************** 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 = Ptr(new CppAstGenOutput); 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, bool weakAssignment) 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 vl::Ptr(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, bool weakAssignment)"); 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, weakAssignment, 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"{"); if (output->fieldIds.Count() > 0) { 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;"); } else { writer.WriteLine(prefix + L"\treturn 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"{"); if (output->fieldIds.Count() > 0) { 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;"); } else { writer.WriteLine(prefix + L"\treturn 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\tauto loader = Ptr(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::Ptr(new "); 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::Ptr(new "); 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.WriteLine(prefix + L"\tthis->result->codeRange = node->codeRange;"); 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.WriteLine(prefix + L"\tthis->result->codeRange = node->codeRange;"); 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.map.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"; /////////////////////////////////////////////////////////////////////////////////// // Condition /////////////////////////////////////////////////////////////////////////////////// auto _Condition = _ast->CreateClass(L"Condition"); auto _RefCondition = _ast->CreateClass(L"RefCondition"); _RefCondition->SetBaseClass(L"Condition"); _RefCondition->CreateProp(L"name")->SetPropType(AstPropType::Token); auto _NotCondition = _ast->CreateClass(L"NotCondition"); _NotCondition->SetBaseClass(L"Condition"); _NotCondition->CreateProp(L"condition")->SetPropType(AstPropType::Type, L"Condition"); auto _AndCondition = _ast->CreateClass(L"AndCondition"); _AndCondition->SetBaseClass(L"Condition"); _AndCondition->CreateProp(L"first")->SetPropType(AstPropType::Type, L"Condition"); _AndCondition->CreateProp(L"second")->SetPropType(AstPropType::Type, L"Condition"); auto _OrCondition = _ast->CreateClass(L"OrCondition"); _OrCondition->SetBaseClass(L"Condition"); _OrCondition->CreateProp(L"first")->SetPropType(AstPropType::Type, L"Condition"); _OrCondition->CreateProp(L"second")->SetPropType(AstPropType::Type, L"Condition"); /////////////////////////////////////////////////////////////////////////////////// // Switch /////////////////////////////////////////////////////////////////////////////////// auto _SwitchValue = _ast->CreateEnum(L"SwitchValue"); _SwitchValue->CreateItem(L"False"); _SwitchValue->CreateItem(L"True"); auto _Switch = _ast->CreateClass(L"SwitchItem"); _Switch->CreateProp(L"name")->SetPropType(AstPropType::Token); _Switch->CreateProp(L"value")->SetPropType(AstPropType::Type, L"SwitchValue"); /////////////////////////////////////////////////////////////////////////////////// // Syntax /////////////////////////////////////////////////////////////////////////////////// auto _Syntax = _ast->CreateClass(L"Syntax"); auto _RefType = _ast->CreateEnum(L"RefType"); _RefType->CreateItem(L"Id"); _RefType->CreateItem(L"Literal"); _RefType->CreateItem(L"ConditionalLiteral"); auto _RefSyntax = _ast->CreateClass(L"RefSyntax"); _RefSyntax->SetBaseClass(L"Syntax"); _RefSyntax->CreateProp(L"refType")->SetPropType(AstPropType::Type, L"RefType"); _RefSyntax->CreateProp(L"literal")->SetPropType(AstPropType::Token); _RefSyntax->CreateProp(L"field")->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"); /////////////////////////////////////////////////////////////////////////////////// // Conditional Clause /////////////////////////////////////////////////////////////////////////////////// auto _PushConditionSyntax = _ast->CreateClass(L"PushConditionSyntax"); _PushConditionSyntax->SetBaseClass(L"Syntax"); _PushConditionSyntax->CreateProp(L"switches")->SetPropType(AstPropType::Array, L"SwitchItem"); _PushConditionSyntax->CreateProp(L"syntax")->SetPropType(AstPropType::Type, L"Syntax"); auto _TestConditionBranch = _ast->CreateClass(L"TestConditionBranch"); _TestConditionBranch->CreateProp(L"condition")->SetPropType(AstPropType::Type, L"Condition"); _TestConditionBranch->CreateProp(L"syntax")->SetPropType(AstPropType::Type, L"Syntax"); auto _TestConditionSyntax = _ast->CreateClass(L"TestConditionSyntax"); _TestConditionSyntax->SetBaseClass(L"Syntax"); _TestConditionSyntax->CreateProp(L"branches")->SetPropType(AstPropType::Array, L"TestConditionBranch"); /////////////////////////////////////////////////////////////////////////////////// // Clause /////////////////////////////////////////////////////////////////////////////////// auto _Clause = _ast->CreateClass(L"Clause"); auto _AssignmentType = _ast->CreateEnum(L"AssignmentType"); _AssignmentType->CreateItem(L"Strong"); _AssignmentType->CreateItem(L"Weak"); auto _Assignment = _ast->CreateClass(L"Assignment"); _Assignment->CreateProp(L"type")->SetPropType(AstPropType::Type, L"AssignmentType"); _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"); /////////////////////////////////////////////////////////////////////////////////// // Left Recursion Clauses /////////////////////////////////////////////////////////////////////////////////// auto _Lrp = _ast->CreateClass(L"LeftRecursionPlaceholder"); _Lrp->CreateProp(L"flag")->SetPropType(AstPropType::Token); auto _LrpClause = _ast->CreateClass(L"LeftRecursionPlaceholderClause"); _LrpClause->SetBaseClass(L"Clause"); _LrpClause->CreateProp(L"flags")->SetPropType(AstPropType::Array, L"LeftRecursionPlaceholder"); auto LriConfig = _ast->CreateEnum(L"LeftRecursionConfiguration"); LriConfig->CreateItem(L"Single"); LriConfig->CreateItem(L"Multiple"); auto LriContinuationType = _ast->CreateEnum(L"LeftRecursionInjectContinuationType"); LriContinuationType->CreateItem(L"Optional"); LriContinuationType->CreateItem(L"Required"); auto _LriContinuation = _ast->CreateClass(L"LeftRecursionInjectContinuation"); auto _LriClause = _ast->CreateClass(L"LeftRecursionInjectClause"); _LriContinuation->CreateProp(L"flags")->SetPropType(AstPropType::Array, L"LeftRecursionPlaceholder"); _LriContinuation->CreateProp(L"configuration")->SetPropType(AstPropType::Type, L"LeftRecursionConfiguration"); _LriContinuation->CreateProp(L"type")->SetPropType(AstPropType::Type, L"LeftRecursionInjectContinuationType"); _LriContinuation->CreateProp(L"injectionTargets")->SetPropType(AstPropType::Array, L"LeftRecursionInjectClause"); _LriClause->SetBaseClass(L"Clause"); _LriClause->CreateProp(L"rule")->SetPropType(AstPropType::Type, L"RefSyntax"); _LriClause->CreateProp(L"continuation")->SetPropType(AstPropType::Type, L"LeftRecursionInjectContinuation"); auto _PmClause = _ast->CreateClass(L"PrefixMergeClause"); _PmClause->SetBaseClass(L"Clause"); _PmClause->CreateProp(L"rule")->SetPropType(AstPropType::Type, L"RefSyntax"); /////////////////////////////////////////////////////////////////////////////////// // Rule /////////////////////////////////////////////////////////////////////////////////// auto _Rule = _ast->CreateClass(L"Rule"); _Rule->CreateProp(L"name")->SetPropType(AstPropType::Token); _Rule->CreateProp(L"type")->SetPropType(AstPropType::Token); _Rule->CreateProp(L"clauses")->SetPropType(AstPropType::Array, L"Clause"); /////////////////////////////////////////////////////////////////////////////////// // File /////////////////////////////////////////////////////////////////////////////////// auto _File = _ast->CreateClass(L"SyntaxFile"); _File->CreateProp(L"switches")->SetPropType(AstPropType::Array, L"SwitchItem"); _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(&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"SWITCH", L"switch"); 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"OPEN_PUSH", L"!/("); manager.CreateToken(L"OPEN_TEST", L"/?/("); manager.CreateToken(L"AND", L"&&"); manager.CreateToken(L"OR", 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"WEAK_ASSIGN", L"/?="); manager.CreateToken(L"POSITIVE", L"/+"); manager.CreateToken(L"NEGATIVE", L"-"); manager.CreateToken(L"LS_PH", L"left_recursion_placeholder"); manager.CreateToken(L"LS_I", L"left_recursion_inject"); manager.CreateToken(L"LS_IM", L"left_recursion_inject_multiple"); manager.CreateToken(L"LS_PM", L"prefix_merge"); manager.CreateToken(L"ID", L"[a-zA-Z_][a-zA-Z0-9_]*"); manager.CreateToken(L"STRING", L"(\"[^\"]*\")+"); manager.CreateToken(L"CONDITIONAL_LITERAL", 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; default:; } } } }; 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 collections; using namespace stream; using namespace regex; /*********************************************************************** UnescapeLiteral ***********************************************************************/ WString UnescapeLiteral(const WString& literal, wchar_t quot) { Array buffer(literal.Length()); wchar_t* writing = &buffer[0]; for (vint i = 1; i < literal.Length() - 1; i++) { wchar_t c = literal[i]; *writing++ = c; if (c == quot) { i++; } } *writing = 0; return &buffer[0]; } /*********************************************************************** CompileLexer ***********************************************************************/ void CompileLexer(LexerSymbolManager& lexerManager, const WString& input) { Regex regexToken(L"^(/s*|(discard/s)?/s*(/$?[a-zA-Z_]/w*)/s*:(/.+))$"); Regex regexFragment(L"/{(/$[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"); vint _fragment = regexFragment.CaptureNames().IndexOf(L"fragment"); Dictionary fragments; 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(); auto tokenDiscard = match->Groups().Keys().Contains(_discard); if (tokenName[0] == L'$') { if (tokenDiscard) { lexerManager.AddError( ParserErrorType::InvalidTokenDefinition, codeRange, line ); } else if (fragments.Keys().Contains(tokenName)) { lexerManager.AddError( ParserErrorType::DuplicatedTokenFragment, codeRange, tokenName ); } else { fragments.Add(tokenName, tokenRegex); } } else { WString resolvedRegex; List> matches; regexFragment.Cut(tokenRegex, false, matches); for (auto&& fragment : matches) { if (fragment->Success()) { auto fragmentName = fragment->Groups()[_fragment][0].Value(); vint index = fragments.Keys().IndexOf(fragmentName); if (index == -1) { lexerManager.AddError( ParserErrorType::TokenFragmentNotExists, codeRange, fragmentName ); } else { resolvedRegex += fragments.Values()[index]; } } else { resolvedRegex += fragment->Result().Value(); } } if (tokenDiscard) { lexerManager.CreateDiscardedToken(tokenName, resolvedRegex, codeRange); } else { lexerManager.CreateToken(tokenName, resolvedRegex, codeRange); } } } } else if (line.Length() < 2 || line.Left(2) != L"//") { 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, VisitorSwitchContext& sContext, Ptr syntaxFile); extern void ValidateSwitchesAndConditions(VisitorContext& context, VisitorSwitchContext& sContext, Ptr syntaxFile); extern void ValidatePartialRules(VisitorContext& context, Ptr syntaxFile); extern void CalculateRuleAndClauseTypes(VisitorContext& context); extern void CalculateFirstSet(VisitorContext& context, Ptr syntaxFile); extern void ValidateTypes(VisitorContext& context, Ptr syntaxFile); extern void ValidateStructure(VisitorContext& context, Ptr syntaxFile); extern void ValidatePrefixMerge(VisitorContext& context, Ptr syntaxFile); extern Ptr RewriteSyntax_Switch(VisitorContext& context, VisitorSwitchContext& sContext, SyntaxSymbolManager& syntaxManager, Ptr syntaxFile); extern Ptr RewriteSyntax_PrefixMerge(VisitorContext& context, SyntaxSymbolManager& syntaxManager, Ptr syntaxFile); extern void CompileSyntax(VisitorContext& context, Ptr output, Ptr syntaxFile); /*********************************************************************** CompileSyntax ***********************************************************************/ bool NeedRewritten_Switch(Ptr syntaxFile) { return syntaxFile->switches.Count() > 0; } bool NeedRewritten_PrefixMerge(Ptr syntaxFile) { return !From(syntaxFile->rules) .SelectMany([](auto rule) { return From(rule->clauses); }) .FindType() .IsEmpty(); } void CreateSyntaxSymbols(LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, Ptr syntaxFile) { for (auto rule : syntaxFile->rules) { if (lexerManager.Tokens().Keys().Contains(rule->name.value)) { syntaxManager.AddError( ParserErrorType::RuleNameConflictedWithToken, rule->codeRange, rule->name.value ); } else { auto ruleSymbol = syntaxManager.CreateRule(rule->name.value, rule->codeRange); } for (auto clause : rule->clauses) { if (auto lrpClause = clause.Cast()) { for (auto flag : lrpClause->flags) { if (!syntaxManager.lrpFlags.Contains(flag->flag.value)) { syntaxManager.lrpFlags.Add(flag->flag.value); } } } } } } bool VerifySyntax_UntilSwitch(VisitorContext& context, VisitorSwitchContext& sContext, Ptr syntaxFile) { ResolveName(context, sContext, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) return false; ValidateSwitchesAndConditions(context, sContext, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) return false; ValidatePartialRules(context, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) return false; CalculateRuleAndClauseTypes(context); if (context.syntaxManager.Global().Errors().Count() > 0) return false; return true; } bool VerifySyntax_UntilPrefixMerge(VisitorContext& context, Ptr syntaxFile) { CalculateFirstSet(context, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) return false; ValidateTypes(context, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) return false; ValidateStructure(context, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) return false; ValidatePrefixMerge(context, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) return false; return true; } Ptr CompileSyntax(AstSymbolManager& astManager, LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, Ptr output, collections::List>& files) { // merge files to single syntax file auto syntaxFile = Ptr(new GlrSyntaxFile); for (auto file : files) { CopyFrom(syntaxFile->switches, file->switches, true); CopyFrom(syntaxFile->rules, file->rules, true); } auto rawSyntaxFile = syntaxFile; CreateSyntaxSymbols(lexerManager, syntaxManager, syntaxFile); if (syntaxManager.Global().Errors().Count() > 0) goto FINISHED_COMPILING; if (NeedRewritten_Switch(syntaxFile)) { VisitorContext context(astManager, lexerManager, syntaxManager); VisitorSwitchContext sContext; if (!VerifySyntax_UntilSwitch(context, sContext, syntaxFile)) goto FINISHED_COMPILING; syntaxFile = RewriteSyntax_Switch(context, sContext, syntaxManager, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) goto FINISHED_COMPILING; } if (NeedRewritten_PrefixMerge(syntaxFile)) { VisitorContext context(astManager, lexerManager, syntaxManager); VisitorSwitchContext sContext; if (!VerifySyntax_UntilSwitch(context, sContext, syntaxFile)) goto FINISHED_COMPILING; if (!VerifySyntax_UntilPrefixMerge(context, syntaxFile)) goto FINISHED_COMPILING; syntaxFile = RewriteSyntax_PrefixMerge(context, syntaxManager, syntaxFile); if (context.syntaxManager.Global().Errors().Count() > 0) goto FINISHED_COMPILING; } { VisitorContext context(astManager, lexerManager, syntaxManager); VisitorSwitchContext sContext; if (!VerifySyntax_UntilSwitch(context, sContext, syntaxFile)) goto FINISHED_COMPILING; if (!VerifySyntax_UntilPrefixMerge(context, syntaxFile)) goto FINISHED_COMPILING; CompileSyntax(context, output, syntaxFile); } FINISHED_COMPILING: return rawSyntaxFile == syntaxFile ? nullptr : syntaxFile; } } } } /*********************************************************************** .\PARSERGEN\COMPILESYNTAX_CALCULATEFIRSTSET.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace compile_syntax; /*********************************************************************** DirectFirstSetVisitor ***********************************************************************/ class DirectFirstSetVisitor : public Object , protected virtual GlrSyntax::IVisitor , protected virtual GlrClause::IVisitor { private: bool couldBeEmpty = false; protected: VisitorContext& context; RuleSymbol* ruleSymbol; GlrClause* currentClause = nullptr; RuleSymbol* TryGetRuleSymbol(const WString& name) { vint index = context.syntaxManager.Rules().Keys().IndexOf(name); if (index == -1) return nullptr; return context.syntaxManager.Rules().Values()[index]; } void AddStartLiteral(const ParsingToken& literal) { context.ruleBeginsWithLiteral.Add(ruleSymbol, literal); context.clauseBeginsWithLiteral.Add(currentClause, literal); } void AddStartTokenOrRule(const ParsingToken& literal) { if (auto startRule = TryGetRuleSymbol(literal.value)) { context.directStartRules.Add(ruleSymbol, { startRule,currentClause }); context.clauseToStartRules.Add(currentClause, startRule); if (ruleSymbol == startRule && !context.leftRecursiveClauses.Contains(ruleSymbol, currentClause)) { context.leftRecursiveClauses.Add(ruleSymbol, currentClause); } } else { AddStartLiteral(literal); } } public: DirectFirstSetVisitor( VisitorContext& _context, RuleSymbol* _ruleSymbol ) : context(_context) , ruleSymbol(_ruleSymbol) { } void VisitClause(Ptr clause) { currentClause = clause.Obj(); clause->Accept(this); } protected: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { if (node->refType == GlrRefType::Id) { AddStartTokenOrRule(node->literal); } else { AddStartLiteral(node->literal); } couldBeEmpty = false; } void Visit(GlrUseSyntax* node) override { AddStartTokenOrRule(node->name); couldBeEmpty = false; } void Visit(GlrLoopSyntax* node) override { node->syntax->Accept(this); couldBeEmpty = true; } void Visit(GlrOptionalSyntax* node) override { node->syntax->Accept(this); couldBeEmpty = true; } void Visit(GlrSequenceSyntax* node) override { node->first->Accept(this); if (couldBeEmpty) node->second->Accept(this); } void Visit(GlrAlternativeSyntax* node) override { node->first->Accept(this); bool firstCouldBeEmpty = couldBeEmpty; node->second->Accept(this); bool secondCouldBeEmpty = couldBeEmpty; couldBeEmpty = firstCouldBeEmpty || secondCouldBeEmpty; } void Visit(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"GlrPushConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"GlrTestConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrCreateClause* node) override { node->syntax->Accept(this); } void Visit(GlrPartialClause* node) override { node->syntax->Accept(this); } void Visit(GlrReuseClause* node) override { node->syntax->Accept(this); if (node->assignments.Count() == 0) { auto nodeSyntax = node->syntax.Obj(); auto pushSyntax = dynamic_cast(nodeSyntax); if (pushSyntax) nodeSyntax = pushSyntax->syntax.Obj(); if (auto useSyntax = dynamic_cast(nodeSyntax)) { if (auto startRule = TryGetRuleSymbol(useSyntax->name.value)) { context.directSimpleUseRules.Add(ruleSymbol, { startRule,currentClause }); context.simpleUseClauseToReferencedRules.Add(currentClause, startRule); } } } } void Visit(GlrLeftRecursionPlaceholderClause* node) override { } void Visit(GlrLeftRecursionInjectClause* node) override { node->rule->Accept(this); } void Visit(GlrPrefixMergeClause* node) override { node->rule->Accept(this); } }; /*********************************************************************** CalculateFirstSet ***********************************************************************/ void CalculateFirstSet_DirectStartRules(VisitorContext& context, Ptr syntaxFile) { for (auto rule : syntaxFile->rules) { auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; DirectFirstSetVisitor visitor(context, ruleSymbol); for (auto clause : rule->clauses) { visitor.VisitClause(clause); } } } void CalculateFirstSet_RuleClosure(const RulePathDependencies& direct, RulePathDependencies& indirect, PathToLastRuleMap& pathToLastRules) { for (auto [rule, index] : indexed(direct.Keys())) { auto&& startRules = direct.GetByIndex(index); for (auto [startRule, clause] : startRules) { indirect.Add(rule, { startRule,clause }); pathToLastRules.Add({ rule,startRule }, { rule,clause }); } } while (true) { vint offset = 0; for (auto [rule, index] : indexed(indirect.Keys())) { auto&& startRules1 = indirect.GetByIndex(index); for (auto [startRule1, clause1] : startRules1) { if (rule == startRule1) continue; vint index2 = direct.Keys().IndexOf(startRule1); if (index2 != -1) { auto&& startRules2 = direct.GetByIndex(index2); for (auto [startRule2, clause2] : startRules2) { if (rule == startRule2 || startRule1 == startRule2) continue; if (!pathToLastRules.Contains({ rule,startRule2 }, { startRule1,clause2 })) { offset++; if (!indirect.Contains(rule, { startRule2,clause2 })) { indirect.Add(rule, { startRule2,clause2 }); } pathToLastRules.Add({ rule,startRule2 }, { startRule1,clause2 }); } } } } } if (offset == 0) { break; } } } void CalculateFirstSet_IndirectStartRules(VisitorContext& context) { CalculateFirstSet_RuleClosure( context.directStartRules, context.indirectStartRules, context.indirectStartPathToLastRules ); } void CalculateFirstSet_IndirectSimpleUseRules(VisitorContext& context) { CalculateFirstSet_RuleClosure( context.directSimpleUseRules, context.indirectSimpleUseRules, context.indirectSimpleUsePathToLastRules ); } template void CalculateFirstSet_MoveFromDirectClauses( SortedList& clauses, Group& indirectClauses, Group& directClauses, RuleSymbol* rule, RuleSymbol* startRule ) { vint index = directClauses.Keys().IndexOf(startRule); if (index != -1) { for (auto clause : directClauses.GetByIndex(index)) { if (!clauses.Contains(clause)) { clauses.Add(clause); indirectClauses.Add(rule, clause); } } } } void CalculateFirstSet_IndirectLrpPmClauses(VisitorContext& context) { for (auto [rule, index] : indexed(context.indirectStartRules.Keys())) { SortedList lriClauses; SortedList lrpClauses; SortedList pmClauses; CalculateFirstSet_MoveFromDirectClauses(lriClauses, context.indirectLriClauses, context.directLriClauses, rule, rule); CalculateFirstSet_MoveFromDirectClauses(lrpClauses, context.indirectLrpClauses, context.directLrpClauses, rule, rule); CalculateFirstSet_MoveFromDirectClauses(pmClauses, context.indirectPmClauses, context.directPmClauses, rule, rule); auto&& startRules = context.indirectStartRules.GetByIndex(index); for (auto startRule : startRules) { CalculateFirstSet_MoveFromDirectClauses(lriClauses, context.indirectLriClauses, context.directLriClauses, rule, startRule.ruleSymbol); CalculateFirstSet_MoveFromDirectClauses(lrpClauses, context.indirectLrpClauses, context.directLrpClauses, rule, startRule.ruleSymbol); CalculateFirstSet_MoveFromDirectClauses(pmClauses, context.indirectPmClauses, context.directPmClauses, rule, startRule.ruleSymbol); } } } void CalculateFirstSet(VisitorContext& context, Ptr syntaxFile) { CalculateFirstSet_DirectStartRules(context, syntaxFile); CalculateFirstSet_IndirectStartRules(context); CalculateFirstSet_IndirectSimpleUseRules(context); CalculateFirstSet_IndirectLrpPmClauses(context); } } } } /*********************************************************************** .\PARSERGEN\COMPILESYNTAX_CALCULATETYPES.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace compile_syntax; /*********************************************************************** ValidatePartialRules ***********************************************************************/ void ValidatePartialRules(VisitorContext& context, Ptr syntaxFile) { for (auto rule : syntaxFile->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(), partialType->Name(), type->Name() ); break; } } } } } /*********************************************************************** CalculateRuleAndClauseTypes ***********************************************************************/ WString GetRuleTypes(const IEnumerable& rules) { return From(rules) .Select([](auto r) { return r->ruleType; }) .Where([](auto rt) { return rt != nullptr; }) .Select([](auto rt) { return rt->Name(); }) .Aggregate(WString::Empty, [](auto a, auto b) {return a == WString::Empty ? b : a + L", " + b; }) ; } 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 // TODO: in order to remove the while(ruleTypeChanged) below // we need to determine the type following the order from PartialOrderingProcessor // instead of doing a tricky way to solve non-cyclic reusing before cyclic reusing // and having to while(ruleTypeChanged) because non-cyclic reusing could depends on the result from cyclic reusing 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)); } // do not update explicitly specified rule type SortedList explicitlyTypedRules; for (auto rule : rules) { if (rule->ruleType) { explicitlyTypedRules.Add(rule); } } // define updateRuleType function, check clause type added to rule auto updateRuleType = [&context, &explicitlyTypedRules](RuleSymbol* rule, AstClassSymbol* newClauseType, bool promptIfNull, bool* ruleTypeChanged = nullptr) { auto newRuleType = FindCommonBaseClass(rule->ruleType, newClauseType); if (explicitlyTypedRules.Contains(rule)) { if (rule->ruleType != newRuleType) { context.syntaxManager.AddError( ParserErrorType::RuleExplicitTypeIsNotCompatibleWithClauseType, context.astRules[rule]->codeRange, rule->Name(), (rule->ruleType ? rule->ruleType->Name() : WString::Empty), (newClauseType ? newClauseType->Name() : WString::Empty) ); return false; } } else { if (promptIfNull && !newRuleType) { context.syntaxManager.AddError( ParserErrorType::RuleCannotResolveToDeterministicType, context.astRules[rule]->codeRange, rule->Name(), (rule->ruleType ? rule->ruleType->Name() : WString::Empty), (newClauseType ? newClauseType->Name() : WString::Empty) ); return false; } if (ruleTypeChanged && newRuleType && rule->ruleType != newRuleType) { *ruleTypeChanged = true; } rule->ruleType = newRuleType; } return true; }; // 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) { auto newClauseType = context.clauseTypes.Values()[index]; if (!updateRuleType(rule, newClauseType, true)) { break; } } } } if (context.global.Errors().Count() > 0) return; bool ruleTypeChanged = true; while(ruleTypeChanged) { ruleTypeChanged = false; // 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 && !updateRuleType(rule, type, true, &ruleTypeChanged)) { 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) { auto ruleTypes = GetRuleTypes(cyclicRules); for (auto rule : cyclicRules) { context.syntaxManager.AddError( ParserErrorType::CyclicDependedRuleTypeIncompatible, context.astRules[rule]->codeRange, rule->Name(), ruleTypes ); } } else { for (auto rule : cyclicRules) { updateRuleType(rule, type, false, &ruleTypeChanged); } } } if (context.global.Errors().Count() > 0) break; } // 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 { auto ruleTypes = GetRuleTypes(context.clauseReuseDependencies.GetByIndex(index)); context.syntaxManager.AddError( ParserErrorType::ReuseClauseCannotResolveToDeterministicType, clause->codeRange, astRule->name.value, ruleTypes ); } } } } } } } } /*********************************************************************** .\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 { using StatePair = AutomatonBuilder::StatePair; protected: AutomatonBuilder automatonBuilder; VisitorContext& context; Ptr output; AstClassSymbol* clauseType; StatePair result; StatePair Build(GlrSyntax* node) { node->Accept(this); return result; } StatePair Build(const Ptr& node) { node->Accept(this); return result; } public: CompileSyntaxVisitor( VisitorContext& _context, Ptr _output, RuleSymbol* _ruleSymbol ) : automatonBuilder(_ruleSymbol) , context(_context) , output(_output) { } void AssignClause(const Ptr& node) { node->Accept(this); } protected: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { vint32_t field = -1; if (node->field) { auto propSymbol = FindPropSymbol(clauseType, node->field.value); field = output->fieldIds[propSymbol]; } switch (node->refType) { case GlrRefType::Id: { vint index = context.lexerManager.TokenOrder().IndexOf(node->literal.value); if (index != -1) { auto token = context.lexerManager.Tokens()[node->literal.value]; auto displayText = token->displayText == L"" ? token->Name() : L"\"" + token->displayText + L"\""; result = automatonBuilder.BuildTokenSyntax((vint32_t)index, displayText, {}, field); return; } } { vint index = context.syntaxManager.Rules().Keys().IndexOf(node->literal.value); if (index != -1) { auto rule = context.syntaxManager.Rules().Values()[index]; if (rule->isPartial) { result = automatonBuilder.BuildPartialRuleSyntax(rule); } else if (field == -1) { result = automatonBuilder.BuildDiscardRuleSyntax(rule); } else { result = automatonBuilder.BuildFieldRuleSyntax(rule, field); } return; } } CHECK_FAIL(L"Should not reach here!"); break; case GlrRefType::Literal: { vint index = context.literalTokens[node]; auto token = context.lexerManager.Tokens()[context.lexerManager.TokenOrder()[index]]; auto displayText = token->displayText == L"" ? token->Name() : L"\"" + token->displayText + L"\""; result = automatonBuilder.BuildTokenSyntax((vint32_t)index, displayText, {}, field); } break; case GlrRefType::ConditionalLiteral: { vint index = context.literalTokens[node]; auto token = context.lexerManager.Tokens()[context.lexerManager.TokenOrder()[index]]; auto condition = UnescapeLiteral(node->literal.value, L'\''); auto displayText = token->displayText == L"" ? token->Name() : L"\"" + token->displayText + L"\""; result = automatonBuilder.BuildTokenSyntax((vint32_t)index, displayText, condition, field); } break; default:; } } void Visit(GlrUseSyntax* node) override { auto rule = context.syntaxManager.Rules()[node->name.value]; result = automatonBuilder.BuildUseSyntax(rule); } void Visit(GlrLoopSyntax* node) override { result = automatonBuilder.BuildLoopSyntax( [this, node]() { return Build(node->syntax); }, [this, node]() { return Build(node->delimiter); }, node->delimiter ); } void Visit(GlrOptionalSyntax* node) override { result = automatonBuilder.BuildOptionalSyntax( node->priority == GlrOptionalPriority::PreferTake, node->priority == GlrOptionalPriority::PreferSkip, [this, node]() { return Build(node->syntax); } ); } template void CollectElements(GlrSyntax* node, List>& elements) { if (auto pair = dynamic_cast(node)) { CollectElements(pair->first.Obj(), elements); CollectElements(pair->second.Obj(), elements); } else { elements.Add([this, node]() { return Build(node); }); } } void Visit(GlrSequenceSyntax* node) override { List> elements; CollectElements(node, elements); result = automatonBuilder.BuildSequenceSyntax(elements); } void Visit(GlrAlternativeSyntax* node) override { List> elements; CollectElements(node, elements); result = automatonBuilder.BuildAlternativeSyntax(elements); } void Visit(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"GlrPushConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"GlrTestConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// StatePair BuildAssignments(StatePair pair, List>& assignments) { for (auto node : assignments) { auto propSymbol = FindPropSymbol(clauseType, node->field.value); auto enumSymbol = dynamic_cast(propSymbol->propSymbol); auto enumItem = (vint32_t)enumSymbol->ItemOrder().IndexOf(node->value.value); auto field = output->fieldIds[propSymbol]; pair = automatonBuilder.BuildAssignment(pair, enumItem, field, (node->type == GlrAssignmentType::Weak)); } return pair; } void Visit(GlrCreateClause* node) override { clauseType = context.clauseTypes[node]; result = automatonBuilder.BuildClause([this, node]() { return automatonBuilder.BuildCreateClause( output->classIds[clauseType], [this, node]() { return BuildAssignments(Build(node->syntax), node->assignments); } ); }); } void Visit(GlrPartialClause* node) override { clauseType = context.clauseTypes[node]; result = automatonBuilder.BuildClause([this, node]() { return automatonBuilder.BuildPartialClause( [this, node]() { return BuildAssignments(Build(node->syntax), node->assignments); } ); }); } void Visit(GlrReuseClause* node) override { clauseType = context.clauseTypes[node]; result = automatonBuilder.BuildClause([this, node]() { return automatonBuilder.BuildReuseClause( [this, node]() { return BuildAssignments(Build(node->syntax), node->assignments); } ); }); } WString FlagIndexToName(vint32_t flag) { return context.syntaxManager.lrpFlags[flag]; } void CollectFlagsInOrder(SortedList& flags, List>& placeholders) { CopyFrom( flags, From(placeholders) .Select([this](Ptr flag) { return (vint32_t)context.syntaxManager.lrpFlags.IndexOf(flag->flag.value); }) .Distinct() ); } void Visit(GlrLeftRecursionPlaceholderClause* node) override { SortedList flags; CollectFlagsInOrder(flags, node->flags); result = automatonBuilder.BuildClause([this, &flags]() { return automatonBuilder.BuildLrpClause( flags, { this,&CompileSyntaxVisitor::FlagIndexToName } ); }); } using StateBuilder = Func; StateBuilder CompileLriTarget(SortedList& flags, GlrLeftRecursionInjectClause* lriTarget) { StateBuilder useOrLriSyntax; auto rule = context.syntaxManager.Rules()[lriTarget->rule->literal.value]; if (flags.Count() == 0) { useOrLriSyntax = [this, rule]() { return automatonBuilder.BuildUseSyntax(rule); }; } else { useOrLriSyntax = [this, rule, &flags]() { return automatonBuilder.BuildLriSyntax( flags, rule, { this,&CompileSyntaxVisitor::FlagIndexToName } ); }; } if (!lriTarget->continuation) { return useOrLriSyntax; } else { auto cont = lriTarget->continuation; return [this, useOrLriSyntax, cont]() { bool optional = cont->type == GlrLeftRecursionInjectContinuationType::Optional; SortedList flags; CollectFlagsInOrder(flags, cont->flags); List targetRules; for (auto lriTarget : cont->injectionTargets) { targetRules.Add(CompileLriTarget(flags, lriTarget.Obj())); } return automatonBuilder.BuildLriClauseSyntax( useOrLriSyntax, optional, std::move(targetRules)); }; } } void Visit(GlrLeftRecursionInjectClause* node) override { result = automatonBuilder.BuildClause([this, node]() { SortedList flags; return automatonBuilder.BuildReuseClause(CompileLriTarget(flags, node)); }); } void Visit(GlrPrefixMergeClause* node) override { CHECK_FAIL(L"GlrPrefixMergeClause should have been removed after RewriteSyntax_PrefixMerge()!"); } }; /*********************************************************************** CompileSyntax ***********************************************************************/ void CompileSyntax(VisitorContext& context, Ptr output, Ptr syntaxFile) { for (auto rule : syntaxFile->rules) { auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; CompileSyntaxVisitor visitor(context, output, 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 GlrCondition::IVisitor , protected virtual GlrClause::IVisitor { protected: VisitorContext& context; VisitorSwitchContext& sContext; SortedList& accessedSwitches; RuleSymbol* ruleSymbol; GlrReuseClause* reuseClause = nullptr; public: ResolveNameVisitor( VisitorContext& _context, VisitorSwitchContext& _sContext, SortedList& _accessedSwitches, RuleSymbol* _ruleSymbol ) : context(_context) , sContext(_sContext) , accessedSwitches(_accessedSwitches) , ruleSymbol(_ruleSymbol) { } 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; } void ResolveClause(Ptr clause) { context.clauseToRules.Add(clause.Obj(), ruleSymbol); clause->Accept(this); } protected: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { switch (node->refType) { case GlrRefType::Id: { vint tokenIndex = context.lexerManager.TokenOrder().IndexOf(node->literal.value); vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->literal.value); if (tokenIndex == -1 && ruleIndex == -1) { context.syntaxManager.AddError( ParserErrorType::TokenOrRuleNotExistsInRule, node->codeRange, ruleSymbol->Name(), node->literal.value ); } } break; case GlrRefType::Literal: { if (node->literal.value.Length() > 2) { auto literalValue = UnescapeLiteral(node->literal.value, L'\"'); for (auto&& [tokenName, tokenIndex] : indexed(context.lexerManager.TokenOrder())) { auto tokenSymbol = context.lexerManager.Tokens()[tokenName]; if (tokenSymbol->displayText == literalValue) { if (tokenSymbol->discarded) { context.syntaxManager.AddError( ParserErrorType::LiteralIsDiscardedToken, node->codeRange, ruleSymbol->Name(), node->literal.value ); } else { context.literalTokens.Add(node, (vint32_t)tokenIndex); } return; } } } context.syntaxManager.AddError( ParserErrorType::LiteralNotValidToken, node->codeRange, ruleSymbol->Name(), node->literal.value ); } break; case GlrRefType::ConditionalLiteral: { if (node->literal.value.Length() > 2) { auto literalValue = UnescapeLiteral(node->literal.value, L'\''); auto&& lexer = context.GetCachedLexer(); List tokens; lexer.Parse(literalValue).ReadToEnd(tokens); if (tokens.Count() == 1 && tokens[0].token != -1 && tokens[0].completeToken) { auto tokenSymbol = context.lexerManager.Tokens()[context.lexerManager.TokenOrder()[tokens[0].token]]; if (tokenSymbol->displayText != L"") { context.syntaxManager.AddError( ParserErrorType::ConditionalLiteralIsDisplayText, node->codeRange, ruleSymbol->Name(), node->literal.value ); } if (tokenSymbol->discarded) { context.syntaxManager.AddError( ParserErrorType::ConditionalLiteralIsDiscardedToken, node->codeRange, ruleSymbol->Name(), node->literal.value ); } context.literalTokens.Add(node, (vint32_t)tokens[0].token); return; } } context.syntaxManager.AddError( ParserErrorType::ConditionalLiteralNotValidToken, node->codeRange, ruleSymbol->Name(), node->literal.value ); } break; default:; } } void VisitReuseSyntax(ParsingToken& name, bool addRuleReuseDependency) { vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(name.value); if (ruleIndex == -1) { context.syntaxManager.AddError( ParserErrorType::TokenOrRuleNotExistsInRule, name.codeRange, ruleSymbol->Name(), name.value ); } else { auto usedRuleSymbol = context.syntaxManager.Rules().Values()[ruleIndex]; if (addRuleReuseDependency) { if (!context.ruleReuseDependencies.Contains(ruleSymbol, usedRuleSymbol)) { context.ruleReuseDependencies.Add(ruleSymbol, usedRuleSymbol); } } if (reuseClause) { if (!context.clauseReuseDependencies.Contains(reuseClause, usedRuleSymbol)) { context.clauseReuseDependencies.Add(reuseClause, usedRuleSymbol); } } } } void Visit(GlrUseSyntax* node) override { VisitReuseSyntax(node->name, reuseClause != nullptr); } 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 VisitSwitchItems(List>& switches) { for (auto&& switchItem : switches) { if (!sContext.switches.Keys().Contains(switchItem->name.value)) { context.syntaxManager.AddError( ParserErrorType::SwitchNotExists, switchItem->name.codeRange, ruleSymbol->Name(), switchItem->name.value ); } else if (!accessedSwitches.Contains(switchItem->name.value)) { accessedSwitches.Add(switchItem->name.value); } } } void Visit(GlrPushConditionSyntax* node) override { VisitSwitchItems(node->switches); node->syntax->Accept(this); } void Visit(GlrTestConditionSyntax* node) override { for (auto&& branch : node->branches) { branch->condition->Accept(this); if (branch->syntax) { branch->syntax->Accept(this); } } } //////////////////////////////////////////////////////////////////////// // GlrCondition::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefCondition* node) override { if (!sContext.switches.Keys().Contains(node->name.value)) { context.syntaxManager.AddError( ParserErrorType::SwitchNotExists, node->name.codeRange, ruleSymbol->Name(), node->name.value ); } else if (!accessedSwitches.Contains(node->name.value)) { accessedSwitches.Add(node->name.value); } } void Visit(GlrNotCondition* node) override { node->condition->Accept(this); } void Visit(GlrAndCondition* node) override { node->first->Accept(this); node->second->Accept(this); } void Visit(GlrOrCondition* node) override { node->first->Accept(this); node->second->Accept(this); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// 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 { reuseClause = node; node->syntax->Accept(this); } void Visit(GlrLeftRecursionPlaceholderClause* node) override { for (auto flag : node->flags) { auto name = flag->flag.value; if (!ruleSymbol->lrFlags.Contains(name)) { ruleSymbol->lrFlags.Add(name); } } context.directLrpClauses.Add(ruleSymbol, node); } void VisitLriClause(GlrLeftRecursionInjectClause* node) { VisitReuseSyntax( node->rule->literal, (!node->continuation || node->continuation->type == GlrLeftRecursionInjectContinuationType::Optional) ); if (node->continuation) { for (auto lriTarget : node->continuation->injectionTargets) { VisitLriClause(lriTarget.Obj()); } } } void Visit(GlrLeftRecursionInjectClause* node) override { VisitLriClause(node); context.directLriClauses.Add(ruleSymbol, node); } void Visit(GlrPrefixMergeClause* node) override { VisitReuseSyntax(node->rule->literal, true); context.directPmClauses.Add(ruleSymbol, node); } }; /*********************************************************************** ResolveName ***********************************************************************/ bool IsLegalNameBeforeWithSwitch(const WString& name) { if (wcsstr(name.Buffer(), L"_SWITCH")) return false; if (wcsstr(name.Buffer(), L"SWITCH_")) return false; return true; } bool IsLegalNameBeforeWithPrefixMerge(const WString& name) { if (wcsstr(name.Buffer(), L"_LRI")) return false; if (wcsstr(name.Buffer(), L"_LRIP")) return false; if (wcsstr(name.Buffer(), L"LRI_")) return false; if (wcsstr(name.Buffer(), L"LRIP_")) return false; return true; } void ResolveName(VisitorContext& context, VisitorSwitchContext& sContext, Ptr syntaxFile) { for (auto switchItem : syntaxFile->switches) { if (sContext.switches.Keys().Contains(switchItem->name.value)) { context.syntaxManager.AddError( ParserErrorType::DuplicatedSwitch, switchItem->name.codeRange, switchItem->name.value ); } else { sContext.switches.Add( switchItem->name.value, { (switchItem->value == GlrSwitchValue::True), switchItem.Obj() }); } } for (auto rule : syntaxFile->rules) { context.astRules.Add(context.syntaxManager.Rules()[rule->name.value], rule.Obj()); } SortedList accessedSwitches; for (auto rule : syntaxFile->rules) { auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; ResolveNameVisitor visitor(context, sContext, accessedSwitches, ruleSymbol); if (rule->type) { ruleSymbol->ruleType = visitor.GetRuleClass(rule->type); } for (auto clause : rule->clauses) { visitor.ResolveClause(clause); } } { vint index = 0; for (auto&& switchName : sContext.switches.Keys()) { if (index == accessedSwitches.Count() || switchName != accessedSwitches[index]) { context.syntaxManager.AddError( ParserErrorType::UnusedSwitch, sContext.switches[switchName].value->codeRange, switchName ); } else { index++; } } } if (sContext.switches.Count() > 0) { for (auto rule : syntaxFile->rules) { if (!IsLegalNameBeforeWithSwitch(rule->name.value)) { context.syntaxManager.AddError( ParserErrorType::SyntaxInvolvesSwitchWithIllegalRuleName, rule->name.codeRange, rule->name.value ); } } } if (context.directPmClauses.Count() > 0) { for (auto rule : syntaxFile->rules) { if (!IsLegalNameBeforeWithPrefixMerge(rule->name.value)) { context.syntaxManager.AddError( ParserErrorType::SyntaxInvolvesPrefixMergeWithIllegalRuleName, rule->name.codeRange, rule->name.value ); } for (auto lrp : From(rule->clauses).FindType()) { for (auto p : lrp->flags) { if (!IsLegalNameBeforeWithPrefixMerge(p->flag.value)) { context.syntaxManager.AddError( ParserErrorType::SyntaxInvolvesPrefixMergeWithIllegalPlaceholderName, p->flag.codeRange, rule->name.value, p->flag.value ); } } } } } } } } } /*********************************************************************** .\PARSERGEN\COMPILESYNTAX_REWRITESYNTAX_PREFIXMERGE.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace compile_syntax; extern void CalculateFirstSet_IndirectStartRules(VisitorContext& context); extern void CalculateFirstSet_IndirectSimpleUseRules(VisitorContext& context); namespace rewritesyntax_prefixmerge { struct RewritingPrefixConflict { // all clauses are simple use clauses, RuleSymbol* in values are the rule referenced by keys SortedList unaffectedClauses; // clauses that are not affected by prefix extraction SortedList prefixClauses; // simple use clauses that are prefix themselves Group conflictedClauses; // c1 -> c2 if c1's prefix is prefix clause c2 }; struct PrefixRuleWithClause { RuleSymbol* ruleSymbol = nullptr; GlrClause* clause = nullptr; bool operator==(PrefixRuleWithClause& p) const { return ruleSymbol == p.ruleSymbol && clause == p.clause; } }; struct RewritingContext { List pmRules; // all rules that need to be rewritten Dictionary originRules; // rewritten RuleSymbol -> GlrRule ends with _LRI_Original, which is the same GlrRule object before rewritten Dictionary lriRules; // rewritten RuleSymbol -> GlrRule containing left_recursion_inject clauses Dictionary fixedAstRules; // RuleSymbol -> GlrRule relationship after rewritten Group extractPrefixClauses; // RuleSymbol -> {rule to be extracted, clause begins with rule} Dictionary, GlrRule*> extractedPrefixRules; // {rewritten RuleSymbol, prefix RuleSymbol} -> GlrRule ends with _LRI_Prefix Dictionary> extractedConflicts; // rewritten RuleSymbol -> all needed information if prefix extraction affects how it generates left_recursion_inject clauses }; Ptr GetConflict(const RewritingContext& rContext, RuleSymbol* ruleSymbol) { vint indexConflict = rContext.extractedConflicts.Keys().IndexOf(ruleSymbol); if (indexConflict == -1) { return nullptr; } else { return rContext.extractedConflicts.Values()[indexConflict]; } } Ptr EnsureGetConflict(RewritingContext& rContext, RuleSymbol* ruleSymbol) { auto conflict = GetConflict(rContext, ruleSymbol); if (!conflict) { conflict = Ptr(new RewritingPrefixConflict); rContext.extractedConflicts.Add(ruleSymbol, conflict); } return conflict; } /*********************************************************************** FillMissingPrefixMergeClauses ***********************************************************************/ void RemoveDirectReferences(RulePathDependencies& references, RuleSymbol* ruleSymbol, GlrClause* clause) { vint index = references.Keys().IndexOf(ruleSymbol); if (index != -1) { auto&& values = const_cast&>(references.GetByIndex(index)); for (vint i = values.Count() - 1; i >= 0; i--) { if (values[i].clause == clause) { values.RemoveAt(i); } } if (values.Count() == 0) { references.Remove(ruleSymbol); } } } void FillMissingPrefixMergeClauses(VisitorContext& vContext, SyntaxSymbolManager& syntaxManager, Ptr rewritten) { // find position of thses clauses in rules for (auto clauseRaw : vContext.clauseToConvertedToPrefixMerge) { auto ruleSymbol = vContext.clauseToRules[clauseRaw]; auto ruleRaw = vContext.astRules[ruleSymbol]; vint ruleIndex = rewritten->rules.IndexOf(ruleRaw); vint clauseIndex = ruleRaw->clauses.IndexOf(clauseRaw); auto clause = ruleRaw->clauses[clauseIndex]; // create new rule and replace the clause with prefix_merge auto newRule = Ptr(new GlrRule); rewritten->rules.Insert(ruleIndex, newRule); newRule->codeRange = clauseRaw->codeRange; newRule->name = ruleRaw->name; newRule->name.value += L"_LRI_Isolated_" + itow(clauseIndex); newRule->clauses.Add(clause); auto newPM = Ptr(new GlrPrefixMergeClause); newPM->codeRange = clauseRaw->codeRange; ruleRaw->clauses[clauseIndex] = newPM; { auto startRule = Ptr(new GlrRefSyntax); newPM->rule = startRule; startRule->refType = GlrRefType::Id; startRule->literal.value = newRule->name.value; } // remove direct references RemoveDirectReferences(vContext.directStartRules, ruleSymbol, clause.Obj()); RemoveDirectReferences(vContext.directSimpleUseRules, ruleSymbol, clause.Obj()); // fix rule and clause symbols auto newRuleSymbol = syntaxManager.CreateRule(newRule->name.value, ruleRaw->name.codeRange); newRuleSymbol->isPartial = ruleSymbol->isPartial; newRuleSymbol->ruleType = vContext.clauseTypes[clause.Obj()]; vContext.astRules.Add(newRuleSymbol, newRule.Obj()); vContext.clauseTypes.Add(newPM.Obj(), newRuleSymbol->ruleType); vContext.clauseToRules.Set(clause.Obj(), newRuleSymbol); vContext.clauseToRules.Add(newPM.Obj(), ruleSymbol); vContext.clauseToStartRules.Add(newPM.Obj(), newRuleSymbol); // fix directPmClauses // indirectPmClauses // directStartRules vContext.directPmClauses.Add(ruleSymbol, newPM.Obj()); vContext.indirectPmClauses.Add(ruleSymbol, newPM.Obj()); vContext.directStartRules.Add(ruleSymbol, { newRuleSymbol,newPM.Obj() }); for (auto key : syntaxManager.Rules().Values()) { if (vContext.indirectStartPathToLastRules.Contains({ key,ruleSymbol })) { vContext.indirectPmClauses.Add(key, newPM.Obj()); } } } // fix indirectStartRules // indirectSimpleUseRules // indirectStartPathToLastRules // indirectSimpleUsePathToLastRules vContext.indirectStartRules.Clear(); vContext.indirectSimpleUseRules.Clear(); vContext.indirectStartPathToLastRules.Clear(); vContext.indirectSimpleUsePathToLastRules.Clear(); CalculateFirstSet_IndirectStartRules(vContext); CalculateFirstSet_IndirectSimpleUseRules(vContext); } /*********************************************************************** CollectRewritingTargets ***********************************************************************/ void CollectRewritingTargets(const VisitorContext& vContext, RewritingContext& rContext, Ptr rewritten) { for (auto rule : rewritten->rules) { auto ruleSymbol = vContext.syntaxManager.Rules()[rule->name.value]; if (vContext.indirectPmClauses.Keys().Contains(ruleSymbol)) { rContext.pmRules.Add(ruleSymbol); vint indexStart = vContext.directStartRules.Keys().IndexOf(ruleSymbol); vint indexSimpleUse = vContext.directSimpleUseRules.Keys().IndexOf(ruleSymbol); if (indexStart != -1 && indexSimpleUse != -1) { // all clauses should be simple use to enable prefix detection if (vContext.directSimpleUseRules.GetByIndex(indexSimpleUse).Count() != rule->clauses.Count()) continue; Ptr conflict; for (auto [startRule, startClause] : vContext.directStartRules.GetByIndex(indexStart)) { // prefix_merge clauses and left recursive clauses are not involved in prefix detection/extraction if (dynamic_cast(startClause)) continue; if (vContext.leftRecursiveClauses.Contains(ruleSymbol, startClause)) continue; // find all clause pair "!X" and "Y ...", see if X is a prefix of Y for (auto [simpleUseRule, simpleUseClause] : vContext.directSimpleUseRules.GetByIndex(indexSimpleUse)) { // ignore if X is Y if (startRule == simpleUseRule) continue; // ignore if X is not a prefix of Y vint indexExtract = vContext.indirectStartPathToLastRules.Keys().IndexOf({ startRule,simpleUseRule }); if (indexExtract == -1) continue; // ignore if Y ::= X directly or indirectly for (auto [extractRule, extractClause] : vContext.indirectStartPathToLastRules.GetByIndex(indexExtract)) { // ignore if Y ::= X directly or indirectly if (vContext.directSimpleUseRules.Contains(extractRule, { simpleUseRule,extractClause })) continue; // prefix extraction needed if (!rContext.extractPrefixClauses.Contains(extractRule, { simpleUseRule,extractClause })) { rContext.extractPrefixClauses.Add(extractRule, { simpleUseRule,extractClause }); } // fill conflict information for ruleSymbol if (!conflict) { conflict = EnsureGetConflict(rContext, ruleSymbol); } if (!conflict->prefixClauses.Contains(simpleUseClause)) { conflict->prefixClauses.Add(simpleUseClause); } if (!conflict->conflictedClauses.Contains(startClause, simpleUseClause)) { conflict->conflictedClauses.Add(startClause, simpleUseClause); } } } } if (conflict) { for (auto clause : rule->clauses) { if (!conflict->prefixClauses.Contains(clause.Obj()) && !conflict->conflictedClauses.Contains(clause.Obj())) { conflict->unaffectedClauses.Add(clause.Obj()); } } } } } } } /*********************************************************************** CreateRewrittenRules ***********************************************************************/ void CreateRewrittenRules(const VisitorContext& vContext, RewritingContext& rContext, Ptr rewritten) { for (auto ruleSymbol : rContext.pmRules) { auto originRule = vContext.astRules[ruleSymbol]; rContext.originRules.Add(ruleSymbol, originRule); auto lri = Ptr(new GlrRule); rewritten->rules.Add(lri); rContext.lriRules.Add(ruleSymbol, lri.Obj()); lri->codeRange = originRule->name.codeRange; lri->name = originRule->name; originRule->name.value += L"_LRI_Original"; } for (auto [ruleSymbol, index] : indexed(rContext.extractPrefixClauses.Keys())) { auto originRule = vContext.astRules[ruleSymbol]; auto&& prefixClauses = rContext.extractPrefixClauses.GetByIndex(index); for (auto [prefixRuleSymbol, prefixClause] : From(prefixClauses) .OrderBy([](auto p1, auto p2) {return WString::Compare(p1.ruleSymbol->Name(), p2.ruleSymbol->Name()); })) { auto ep = Ptr(new GlrRule); rewritten->rules.Insert(rewritten->rules.IndexOf(originRule), ep); rContext.extractedPrefixRules.Add({ ruleSymbol,prefixRuleSymbol }, ep.Obj()); ep->codeRange = originRule->codeRange; ep->name.codeRange = originRule->name.codeRange; ep->name.value = ruleSymbol->Name() + L"_" + prefixRuleSymbol->Name() + L"_LRI_Prefix"; } } } /*********************************************************************** FixRuleTypes ***********************************************************************/ void FixRuleTypes(const VisitorContext& vContext, RewritingContext& rContext, SyntaxSymbolManager& syntaxManager) { CopyFrom(rContext.fixedAstRules, vContext.astRules); for (auto ruleSymbol : rContext.pmRules) { auto originRule = rContext.originRules[ruleSymbol]; auto lriRule = rContext.lriRules[ruleSymbol]; auto originSymbol = syntaxManager.CreateRule(originRule->name.value, originRule->codeRange); originSymbol->isPartial = ruleSymbol->isPartial; originSymbol->ruleType = ruleSymbol->ruleType; rContext.fixedAstRules.Set(originSymbol, originRule); rContext.fixedAstRules.Set(ruleSymbol, lriRule); } for (auto [pair, epRule] : rContext.extractedPrefixRules) { auto originRule = rContext.originRules[pair.key]; auto epRuleSymbol = syntaxManager.CreateRule(epRule->name.value, originRule->codeRange); epRuleSymbol->ruleType = pair.value->ruleType; rContext.fixedAstRules.Add(epRuleSymbol, epRule); } for (auto [ruleSymbol, rule] : rContext.fixedAstRules) { if (!rule->type) { rule->type.value = ruleSymbol->ruleType->Name(); } } for (auto ruleSymbol : syntaxManager.Rules().Values()) { ruleSymbol->assignedNonArrayField = false; ruleSymbol->lrFlags.Clear(); } } /*********************************************************************** RewriteExtractedPrefixRules ***********************************************************************/ void RewriteExtractedPrefixRules(const VisitorContext& vContext, RewritingContext& rContext, SyntaxSymbolManager& syntaxManager) { for (auto [pair, epRule] : rContext.extractedPrefixRules) { { auto lrpClause = Ptr(new GlrLeftRecursionPlaceholderClause); lrpClause->codeRange = epRule->codeRange; epRule->clauses.Add(lrpClause); auto lrp = Ptr(new GlrLeftRecursionPlaceholder); lrpClause->flags.Add(lrp); lrp->flag.value = L"LRIP_" + pair.key->Name() + L"_" + pair.value->Name(); syntaxManager.lrpFlags.Add(lrp->flag.value); } { auto reuseClause = Ptr(new GlrReuseClause); reuseClause->codeRange = epRule->codeRange; epRule->clauses.Add(reuseClause); auto useSyntax = Ptr(new GlrUseSyntax); reuseClause->syntax = useSyntax; useSyntax->name.value = rContext.originRules[pair.value]->name.value; } } } /*********************************************************************** RewriteRules (Common) ***********************************************************************/ using PMClauseRecord = GenericRuleClausePath; struct PMInjectRecord { RuleSymbol* pmRule = nullptr; RuleSymbol* injectIntoRule = nullptr; }; void RewriteRules_AddPmClause( const VisitorContext& vContext, RuleSymbol* ruleSymbol, GlrPrefixMergeClause* pmClause, Group& pmClauses ) { auto pmRule = vContext.clauseToRules[pmClause]; if (ruleSymbol == pmRule) { if (!pmClauses.Contains(pmClause->rule->literal.value, { ruleSymbol,pmClause })) { pmClauses.Add(pmClause->rule->literal.value, { ruleSymbol,pmClause }); } } else { for (auto [indirectStartRule, indirectClause] : vContext.indirectStartPathToLastRules[{ ruleSymbol, pmRule }]) { if (!pmClauses.Contains(pmClause->rule->literal.value, { ruleSymbol,pmClause })) { pmClauses.Add(pmClause->rule->literal.value, { ruleSymbol,pmClause }); } } } } Ptr RewriteRules_CollectUnaffectedIndirectPmClauses( const VisitorContext& vContext, const RewritingContext& rContext, RuleSymbol* initiatedRuleSymbol, RuleSymbol* ruleSymbol, SortedList& visited, Group& pmClauses ) { auto conflict = initiatedRuleSymbol == ruleSymbol ? GetConflict(rContext, ruleSymbol) : nullptr; if (!visited.Contains(ruleSymbol)) { visited.Add(ruleSymbol); if (conflict) { for (auto [simpleUseRule, simpleUseClause] : vContext.directSimpleUseRules[ruleSymbol]) { if (conflict->unaffectedClauses.Contains(simpleUseClause)) { RewriteRules_CollectUnaffectedIndirectPmClauses(vContext, rContext, initiatedRuleSymbol, simpleUseRule, visited, pmClauses); } else { vint indexConflicted = conflict->conflictedClauses.Keys().IndexOf(simpleUseClause); if (indexConflicted == -1) continue; auto&& prefixClauses = conflict->conflictedClauses.GetByIndex(indexConflicted); for (auto pmClause : From(vContext.indirectPmClauses[ruleSymbol]).Except( From(prefixClauses) .SelectMany([&](GlrClause* prefixClause) { return From(vContext.indirectPmClauses[vContext.simpleUseClauseToReferencedRules[prefixClause]]); }) )) { RewriteRules_AddPmClause(vContext, simpleUseRule, pmClause, pmClauses); } } } } else { for (auto pmClause : vContext.indirectPmClauses[ruleSymbol]) { RewriteRules_AddPmClause(vContext, ruleSymbol, pmClause, pmClauses); } } } return conflict; } void RewriteRules_CheckPath( const VisitorContext& vContext, RuleSymbol* startSymbol, RuleSymbol* endSymbol, bool& hasSimpleUseTransition, bool& hasNonSimpleUseTransition ) { // check the path from startSymbol to endSymbol // hasSimpleUseTransition and hasNonSimpleUseTransition must be false before non-recursive calling from outside // if a transition is found // either of one will be set to true // meaning such transition is counted bool isEndSymbolLeftRecursive = vContext.leftRecursiveClauses.Keys().Contains(endSymbol); if (isEndSymbolLeftRecursive) { // if endSymbol is left recursive // then we find a non-simple-use transition from startSymbol to endSymbol hasNonSimpleUseTransition = true; } if (startSymbol == endSymbol) { // if startSymbol is endSymbol // then we find a simple-use transition // which does not actually transit hasSimpleUseTransition = true; } else { // otherwise we look through all possible path from startSymbol to endSymbol vint index = vContext.indirectStartPathToLastRules.Keys().IndexOf({ startSymbol,endSymbol }); if (index != -1) { for (auto [lastRuleSymbol, clause] : vContext.indirectStartPathToLastRules.GetByIndex(index)) { if (vContext.simpleUseClauseToReferencedRules.Keys().Contains(clause)) { // if we find a simple-use clause // we check how all transitions look like from startSymbol to lastRuleSymbol RewriteRules_CheckPath(vContext, startSymbol, lastRuleSymbol, hasSimpleUseTransition, hasNonSimpleUseTransition); } else { // if we find a non-simple-use clause // then we find a non-simple-use transition from startSymbol to endSymbol hasNonSimpleUseTransition = true; } } } } } void RewriteRules_CollectFlags( const VisitorContext& vContext, RuleSymbol* ruleSymbol, const List& pmClauses, Dictionary& flags, bool& generateOptionalLri ) { for (auto [injectIntoRule, pmClause] : pmClauses) { auto pmRule = vContext.clauseToRules[pmClause]; bool hasSimpleUseTransition = false; bool hasNonSimpleUseTransition = false; RewriteRules_CheckPath(vContext, ruleSymbol, pmRule, hasSimpleUseTransition, hasNonSimpleUseTransition); if (hasSimpleUseTransition) { generateOptionalLri = true; } if (hasNonSimpleUseTransition) { flags.Add(L"LRI_" + pmRule->Name(), { pmRule,injectIntoRule }); } } } bool RewriteRules_HasMultiplePaths( const VisitorContext& vContext, RuleSymbol* fromRule, RuleSymbol* toRule, Dictionary, vint>& pathCounter ) { Pair key = { fromRule, toRule }; vint index = pathCounter.Keys().IndexOf(key); if (index != -1) return pathCounter.Values()[index]; RuleSymbol* currentRule = toRule; bool hasMultiplePaths = false; while (currentRule != fromRule) { index = vContext.indirectStartPathToLastRules.Keys().IndexOf({ fromRule,currentRule }); if (index == -1) goto FINISHED; auto&& lastRules = vContext.indirectStartPathToLastRules.GetByIndex(index); if (lastRules.Count() > 1) { hasMultiplePaths = true; goto FINISHED; } currentRule = lastRules[0].ruleSymbol; } FINISHED: pathCounter.Add(key, hasMultiplePaths); return hasMultiplePaths; } /*********************************************************************** RewriteRules (AST Creation) ***********************************************************************/ Ptr CreateLriClause( const WString& ruleName ) { auto lriClause = Ptr(new GlrLeftRecursionInjectClause); auto lriStartRule = Ptr(new GlrRefSyntax); lriClause->rule = lriStartRule; lriStartRule->refType = GlrRefType::Id; lriStartRule->literal.value = ruleName; return lriClause; } Ptr CreateLriContinuation( const VisitorContext& vContext, const RewritingContext& rContext, RuleSymbol* ruleSymbol, const PMInjectRecord& pmInjectRecord, const WString& flag, Dictionary, vint>& pathCounter, bool generateOptionalLri ) { auto lriCont = Ptr(new GlrLeftRecursionInjectContinuation); if (RewriteRules_HasMultiplePaths(vContext, ruleSymbol, pmInjectRecord.pmRule, pathCounter)) { lriCont->configuration = GlrLeftRecursionConfiguration::Multiple; } else { lriCont->configuration = GlrLeftRecursionConfiguration::Single; } if (generateOptionalLri) { lriCont->type = GlrLeftRecursionInjectContinuationType::Optional; } else { lriCont->type = GlrLeftRecursionInjectContinuationType::Required; } auto lriContFlag = Ptr(new GlrLeftRecursionPlaceholder); lriCont->flags.Add(lriContFlag); lriContFlag->flag.value = flag; auto lriContTarget = CreateLriClause(rContext.originRules[pmInjectRecord.injectIntoRule]->name.value); lriCont->injectionTargets.Add(lriContTarget); return lriCont; } /*********************************************************************** RewriteRules (Unaffected) ***********************************************************************/ void RewriteRules_GenerateUnaffectedLRIClauses( const VisitorContext& vContext, const RewritingContext& rContext, RuleSymbol* ruleSymbol, GlrRule* lriRule, Dictionary, vint>& pathCounter, Group& pmClauses, SortedList& knownOptionalStartRules ) { for (auto [pmName, pmIndex] : indexed(pmClauses.Keys())) { // if originRule is not left recursive // do not generate lriClause for the flag created for originRule, because there is no continuation // if a pmName does generate some lriClause // it becomes GLRICT::Optional // otherwise // it becomse GLRICT::Required // generate useSyntax instead of lriClause Dictionary flags; bool generateOptionalLri = false; RewriteRules_CollectFlags( vContext, ruleSymbol, pmClauses.GetByIndex(pmIndex), flags, generateOptionalLri ); if (generateOptionalLri && flags.Count() == 0) { auto reuseClause = Ptr(new GlrReuseClause); reuseClause->codeRange = lriRule->codeRange; lriRule->clauses.Add(reuseClause); auto useSyntax = Ptr(new GlrUseSyntax); reuseClause->syntax = useSyntax; useSyntax->name.value = pmName; } for (auto [flag, pmInjectRecord] : flags) { auto lriClause = CreateLriClause(pmName); lriRule->clauses.Add(lriClause); auto lriCont = CreateLriContinuation( vContext, rContext, ruleSymbol, pmInjectRecord, flag, pathCounter, generateOptionalLri ); lriClause->continuation = lriCont; if (generateOptionalLri) { generateOptionalLri = false; knownOptionalStartRules.Add(pmName); } } } } /*********************************************************************** RewriteRules (Affected) ***********************************************************************/ void RewriteRules_GenerateAffectedLRIClausesSubgroup( const VisitorContext& vContext, const RewritingContext& rContext, RuleSymbol* conflictedRuleSymbol, RuleSymbol* prefixRuleSymbol, SortedList& lripFlags, GlrRule* lriRule, Dictionary, vint>& pathCounter, SortedList& knownOptionalStartRules ) { Group pmClauses; { SortedList visited; auto conflict = RewriteRules_CollectUnaffectedIndirectPmClauses( vContext, rContext, prefixRuleSymbol, prefixRuleSymbol, visited, pmClauses ); if (conflict) { vContext.syntaxManager.AddError( ParserErrorType::PrefixExtractionAffectedRuleReferencedAnother, rContext.originRules[vContext.syntaxManager.Rules()[lriRule->name.value]]->codeRange, lriRule->name.value, conflictedRuleSymbol->Name(), prefixRuleSymbol->Name() ); return; } } for (auto [pmName, pmIndex] : indexed(pmClauses.Keys())) { // if originRule is not left recursive // left_recursion_inject directly into conflictedRuleSymbol // if a pmName does generate some lriClause // it becomes GLRICT::Optional // otherwise // it becomse GLRICT::Required // generate useSyntax instead of lriClause auto&& pmClauseRecords = pmClauses.GetByIndex(pmIndex); Dictionary flags; bool omittedSelf = false; bool generateOptionalLri = false; RewriteRules_CollectFlags( vContext, prefixRuleSymbol, pmClauseRecords, flags, generateOptionalLri ); if (generateOptionalLri) { // TODO: add test case for omittedSelf == true for (auto lripFlag : lripFlags) { auto lriClause = CreateLriClause(pmName); lriRule->clauses.Add(lriClause); auto lriCont = CreateLriContinuation( vContext, rContext, conflictedRuleSymbol, { prefixRuleSymbol,conflictedRuleSymbol }, lripFlag, pathCounter, false ); lriClause->continuation = lriCont; } } if (knownOptionalStartRules.Contains(pmName)) { generateOptionalLri = false; } for (auto [flag, pmInjectRecord] : flags) { { // Since there is no switches in pmClauses // So there is no switches in pmInjectRecord as well // because flags comes from pmClauses, collected by RewriteRules_CollectFlags above auto lriClause = CreateLriClause(pmName); lriRule->clauses.Add(lriClause); auto lriCont = CreateLriContinuation( vContext, rContext, prefixRuleSymbol, { pmInjectRecord.pmRule,prefixRuleSymbol }, flag, pathCounter, generateOptionalLri ); lriClause->continuation = lriCont; for (auto lripFlag : lripFlags) { auto lriCont2 = CreateLriContinuation( vContext, rContext, conflictedRuleSymbol, { prefixRuleSymbol,conflictedRuleSymbol }, lripFlag, pathCounter, true ); auto branchStart = lriCont->injectionTargets[0]; if (branchStart->continuation) { // TODO: add test case auto newBranchStart = CreateLriClause(branchStart->rule->literal.value); newBranchStart->continuation = lriCont2; lriCont->injectionTargets.Add(newBranchStart); } else { branchStart->continuation = lriCont2; } } if (generateOptionalLri) { generateOptionalLri = false; } } } } } void RewriteRules_GenerateAffectedLRIClauses( const VisitorContext& vContext, const RewritingContext& rContext, RuleSymbol* ruleSymbol, GlrRule* lriRule, Ptr conflict, Dictionary, vint>& pathCounter, SortedList& knownOptionalStartRules ) { for (auto [conflictedClause, conflictedIndex] : indexed(conflict->conflictedClauses.Keys())) { auto conflictedRuleSymbol = vContext.simpleUseClauseToReferencedRules[conflictedClause]; auto&& prefixClauses = conflict->conflictedClauses.GetByIndex(conflictedIndex); for (auto prefixClause : prefixClauses) { auto prefixRuleSymbol = vContext.simpleUseClauseToReferencedRules[prefixClause]; SortedList lripFlags; for (auto extracted : vContext.indirectStartPathToLastRules[{conflictedRuleSymbol, prefixRuleSymbol}]) { lripFlags.Add(L"LRIP_" + extracted.ruleSymbol->Name() + L"_" + prefixRuleSymbol->Name()); } RewriteRules_GenerateAffectedLRIClausesSubgroup( vContext, rContext, conflictedRuleSymbol, prefixRuleSymbol, lripFlags, lriRule, pathCounter, knownOptionalStartRules ); } } } /*********************************************************************** RewriteRules ***********************************************************************/ bool CompareLri(Ptr c1, Ptr c2); bool CompareLriTargest(List>& targets1, List>& targets2) { if (targets1.Count() != targets2.Count()) return false; for (auto [target, i] : indexed(targets1)) { if (!CompareLri(targets1[i], targets2[i])) return false; } return true; } bool CompareLri(Ptr c1, Ptr c2) { if (c1->rule->literal.value != c2->rule->literal.value) return false; if ((c1->continuation == nullptr) != (c2->continuation == nullptr)) return false; if (!c1->continuation) return true; auto cont1 = c1->continuation; auto cont2 = c2->continuation; if (cont1->flags.Count() != cont2->flags.Count()) return false; for (auto [flag, i] : indexed(cont1->flags)) { if (cont1->flags[i]->flag.value != cont2->flags[i]->flag.value) return false; } return CompareLriTargest(cont1->injectionTargets, cont2->injectionTargets); } void OptimizeLri(List>& lriClauses) { for (auto lriClause : lriClauses) { if (lriClause->continuation) { OptimizeLri(lriClause->continuation->injectionTargets); } } List> results, candidates; for (auto [prefixRuleName, subLriClauses] : From(lriClauses) .GroupBy([](auto lriClause) {return lriClause->rule->literal.value; }) ) { CopyFrom(candidates, From(subLriClauses).Reverse()); while (candidates.Count() > 0) { auto candidate = candidates[candidates.Count() - 1]; candidates.RemoveAt(candidates.Count() - 1); for (vint i = candidates.Count() - 1; i >= 0; i--) { auto compare = candidates[i]; if (CompareLriTargest(candidate->continuation->injectionTargets, compare->continuation->injectionTargets)) { List> flags; CopyFrom( flags, From(candidate->continuation->flags) .Concat(compare->continuation->flags) ); CopyFrom( candidate->continuation->flags, From(flags) .GroupBy([](auto flag) { return flag->flag.value; }) .Select([](auto pair) { return pair.value.First(); }) ); if (compare->continuation->configuration == GlrLeftRecursionConfiguration::Multiple) { candidate->continuation->configuration = GlrLeftRecursionConfiguration::Multiple; } if(compare->continuation->type==GlrLeftRecursionInjectContinuationType::Optional) { candidate->continuation->type = GlrLeftRecursionInjectContinuationType::Optional; } candidates.RemoveAt(i); } } results.Add(candidate); } } CopyFrom(lriClauses, results); } void RewriteRules(const VisitorContext& vContext, const RewritingContext& rContext, SyntaxSymbolManager& syntaxManager) { Dictionary, vint> pathCounter; for (auto [ruleSymbol, originRule] : rContext.originRules) { auto lriRule = rContext.lriRules[ruleSymbol]; Ptr conflict; Group pmClauses; { SortedList visited; conflict = RewriteRules_CollectUnaffectedIndirectPmClauses( vContext, rContext, ruleSymbol, ruleSymbol, visited, pmClauses ); } SortedList knownOptionalStartRules; RewriteRules_GenerateUnaffectedLRIClauses( vContext, rContext, ruleSymbol, lriRule, pathCounter, pmClauses, knownOptionalStartRules ); if (conflict) { RewriteRules_GenerateAffectedLRIClauses( vContext, rContext, ruleSymbol, lriRule, conflict, pathCounter, knownOptionalStartRules ); } List> otherClauses; List> lriClauses; for (auto clause : lriRule->clauses) { if (auto lriClause = clause.Cast()) { lriClauses.Add(lriClause); } else { otherClauses.Add(clause); } } if (lriClauses.Count() > 0) { OptimizeLri(lriClauses); CopyFrom( lriRule->clauses, From(otherClauses) .Concat( From(lriClauses).Select([](auto clause)->Ptr {return clause; }) ) ); } } } /*********************************************************************** FixPrefixMergeClauses ***********************************************************************/ void FixPrefixMergeClauses(const VisitorContext& vContext, const RewritingContext& rContext, SyntaxSymbolManager& syntaxManager) { for (auto ruleSymbol : vContext.directPmClauses.Keys()) { auto originRule = rContext.originRules[ruleSymbol]; auto lrpClause = Ptr(new GlrLeftRecursionPlaceholderClause); lrpClause->codeRange = originRule->codeRange; originRule->clauses.Insert(0, lrpClause); auto lrp = Ptr(new GlrLeftRecursionPlaceholder); lrp->flag.value = L"LRI_" + ruleSymbol->Name(); lrpClause->flags.Add(lrp); syntaxManager.lrpFlags.Add(lrp->flag.value); for (vint i = 0; i < originRule->clauses.Count(); i++) { if (auto pmClause = originRule->clauses[i].Cast()) { if (ruleSymbol->isPartial) { auto partialClause = Ptr(new GlrPartialClause); originRule->codeRange = originRule->codeRange; originRule->clauses[i] = partialClause; partialClause->type.value = ruleSymbol->ruleType->Name(); auto refSyntax = Ptr(new GlrRefSyntax); refSyntax->refType = GlrRefType::Id; refSyntax->literal.value = pmClause->rule->literal.value; partialClause->syntax = refSyntax; } else { auto reuseClause = Ptr(new GlrReuseClause); originRule->codeRange = originRule->codeRange; originRule->clauses[i] = reuseClause; auto useSyntax = Ptr(new GlrUseSyntax); useSyntax->name.value = pmClause->rule->literal.value; reuseClause->syntax = useSyntax; } } } } } /*********************************************************************** RenamePrefix ***********************************************************************/ class RenamePrefixVisitor : public Object , protected virtual GlrSyntax::IVisitor , protected virtual GlrClause::IVisitor { protected: const RewritingContext& rContext; RuleSymbol* ruleSymbol; const SyntaxSymbolManager& syntaxManager; public: RenamePrefixVisitor( const RewritingContext& _rContext, RuleSymbol* _ruleSymbol, const SyntaxSymbolManager& _syntaxManager ) : rContext(_rContext) , ruleSymbol(_ruleSymbol) , syntaxManager(_syntaxManager) { } void FixClause(Ptr clause) { clause->Accept(this); } protected: void FixStartRule(ParsingToken& ruleName) { auto startRuleSymbol = syntaxManager.Rules()[ruleName.value]; vint index = rContext.extractedPrefixRules.Keys().IndexOf({ ruleSymbol,startRuleSymbol }); if (index != -1) { auto epRule = rContext.extractedPrefixRules.Values()[index]; ruleName.value = epRule->name.value; return; } index = rContext.originRules.Keys().IndexOf(startRuleSymbol); if (index != -1) { auto originRule = rContext.originRules.Values()[index]; ruleName.value = originRule->name.value; } } //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { if (node->refType == GlrRefType::Id) { vint index = syntaxManager.Rules().Keys().IndexOf(node->literal.value); if (index != -1) { FixStartRule(node->literal); } } } void Visit(GlrUseSyntax* node) override { FixStartRule(node->name); } void Visit(GlrLoopSyntax* node) override { } void Visit(GlrOptionalSyntax* node) override { } void Visit(GlrSequenceSyntax* node) override { node->first->Accept(this); } void Visit(GlrAlternativeSyntax* node) override { } void Visit(GlrPushConditionSyntax* node) override { node->syntax->Accept(this); } void Visit(GlrTestConditionSyntax* node) override { } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrCreateClause* node) override { node->syntax->Accept(this); } void Visit(GlrPartialClause* node) override { node->syntax->Accept(this); } void Visit(GlrReuseClause* node) override { node->syntax->Accept(this); } void Visit(GlrLeftRecursionPlaceholderClause* node) override { } void Visit(GlrLeftRecursionInjectClause* node) override { } void Visit(GlrPrefixMergeClause* node) override { } }; void RenamePrefix(RewritingContext& rContext, const SyntaxSymbolManager& syntaxManager) { for (auto [ruleSymbol, originRule] : rContext.originRules) { RenamePrefixVisitor visitor(rContext, ruleSymbol, syntaxManager); for (auto clause : originRule->clauses) { // !(a; b) should be moved from rule X_LRI_Original to left_recursion_inject clauses in rule X if (auto reuseClause = clause.Cast()) { if (auto pushSyntax = reuseClause->syntax.Cast()) { reuseClause->syntax = pushSyntax->syntax; } } visitor.FixClause(clause); } } } } /*********************************************************************** RewriteSyntax ***********************************************************************/ Ptr RewriteSyntax_PrefixMerge(VisitorContext& context, SyntaxSymbolManager& syntaxManager, Ptr syntaxFile) { using namespace rewritesyntax_prefixmerge; // merge files to single syntax file auto rewritten = Ptr(new GlrSyntaxFile); CopyFrom(rewritten->rules, syntaxFile->rules); // find clauses that need to be converted to prefix_merge and fix VisitorContext FillMissingPrefixMergeClauses(context, syntaxManager, rewritten); // find rules that need to be rewritten using left_recursion_inject RewritingContext rewritingContext; CollectRewritingTargets(context, rewritingContext, rewritten); // create rewritten rules, rename origin rules CreateRewrittenRules(context, rewritingContext, rewritten); // fix rule types (fix syntaxManager.rules, clear RuleSymbol fields) FixRuleTypes(context, rewritingContext, syntaxManager); // create clauses in rewritten X_Y_LRI_Prefix rules RewriteExtractedPrefixRules(context, rewritingContext, syntaxManager); // create left_recursion_inject clauses in rewritten rules RewriteRules(context, rewritingContext, syntaxManager); // convert prefix_merge to left_recursion_placeholder and reuse clauses (fix syntaxManager.lrpFlags) FixPrefixMergeClauses(context, rewritingContext, syntaxManager); // rename rule references in origin rules RenamePrefix(rewritingContext, syntaxManager); return rewritten; } } } } /*********************************************************************** .\PARSERGEN\COMPILESYNTAX_REWRITESYNTAX_SWITCH.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace compile_syntax; namespace rewritesyntax_switch { struct GeneratedRule { GlrRule* ruleToExpand = nullptr; Ptr> switchValues; }; struct RewritingContext { Group> generatedRules; Group> expandedCombinedRules; Group> expandedFirstLevelRules; Dictionary> combinedRulesByName; Group validCombinedClauses; Group invalidCombinedClauses; }; class EmptySyntax : public GlrSyntax { public: void Accept(GlrSyntax::IVisitor* visitor) override { CHECK_FAIL(L"vl::glr::parsergen::rewritesyntax_switch::EmptySyntax::Accept(GlrSyntax::IVisitor*)#EmptySyntax should not be used!"); } }; Ptr> ApplySwitches(Ptr> currentValues, GlrPushConditionSyntax* node) { auto newValues = Ptr(new Dictionary); if (currentValues) { CopyFrom(*newValues.Obj(), *currentValues.Obj()); } for (auto switchItem : node->switches) { newValues->Set(switchItem->name.value, switchItem->value == GlrSwitchValue::True); } return newValues; } /*********************************************************************** EvaluateConditionVisitor **********************************************************************/ class EvaluateConditionVisitor : public Object , protected GlrCondition::IVisitor { // this visitor evaluates a condition with given switch values protected: Dictionary& workingSwitchValues; void Visit(GlrRefCondition* node) override { vint index = workingSwitchValues.Keys().IndexOf(node->name.value); CHECK_ERROR( index != -1, L"vl::glr::parsergen::rewritesyntax_switch::EvaluateConditionVisitor::Visit(GlrRefCondition*)#" L"Internal error: specified switch value is unevaluated" ); result = workingSwitchValues.Values()[index]; } void Visit(GlrNotCondition* node) override { node->condition->Accept(this); result = !result; } void Visit(GlrAndCondition* node) override { node->first->Accept(this); bool first = result; node->second->Accept(this); bool second = result; result = first && second; } void Visit(GlrOrCondition* node) override { node->first->Accept(this); bool first = result; node->second->Accept(this); bool second = result; result = first || second; } public: bool result = false; EvaluateConditionVisitor( Dictionary& _workingSwitchValues ) : workingSwitchValues(_workingSwitchValues) { } bool Evaluate(GlrCondition* condition) { condition->Accept(this); return result; } }; /*********************************************************************** ExpandSwitchSyntaxVisitor ***********************************************************************/ class ExpandSwitchSyntaxVisitor : public traverse_visitor::RuleAstVisitor { // this visitor look into all rules which is affected by switch values // and find all possible switch combination for these rules protected: struct Identification { RuleSymbol* workingRule = nullptr; Ptr> workingSwitchValues = nullptr; Ptr generatedRule; }; VisitorContext& vContext; VisitorSwitchContext& sContext; RewritingContext& rContext; SortedList scannedUnaffectedRules; Identification identification; protected: void TraverseRule(const ParsingToken& ruleName) { // check if it is a rule vint index = vContext.syntaxManager.Rules().Keys().IndexOf(ruleName.value); if (index == -1) return; auto ruleSymbol = vContext.syntaxManager.Rules().Values()[index]; auto rule = vContext.astRules[ruleSymbol]; // check if it is affected index = sContext.ruleAffectedSwitches.Keys().IndexOf(ruleSymbol); if (index == -1) { InspectIntoUnaffectedRule(rule); } else { InspectIntoAffectedRule( rule, sContext.ruleAffectedSwitches.GetByIndex(index), identification.workingSwitchValues ); } } void Traverse(GlrRefSyntax* node) override { if (node->refType == GlrRefType::Id) { TraverseRule(node->literal); } } void Traverse(GlrUseSyntax* node) override { TraverseRule(node->name); } void Visit(GlrTestConditionSyntax* node) override { CHECK_ERROR( identification.workingSwitchValues, L"vl::glr::parsergen::rewritesyntax_switch::ExpandSwitchSyntaxVisitor::Visit(GlrTestConditionSyntax*)#" L"Internal error: switch values are unevaluated" ); EvaluateConditionVisitor visitor(*identification.workingSwitchValues.Obj()); for (auto branch : node->branches) { // inspect into the branch only when it satisfies the condition if (!branch || visitor.Evaluate(branch->condition.Obj())) { InspectInto(branch->syntax.Obj()); } } } void Visit(GlrPushConditionSyntax* node) override { // inspect into the syntax with updated values auto oldValues = identification.workingSwitchValues; auto newValues = ApplySwitches(oldValues, node); identification.workingSwitchValues = newValues; traverse_visitor::RuleAstVisitor::Visit(node); identification.workingSwitchValues = oldValues; } public: ExpandSwitchSyntaxVisitor( VisitorContext& _vContext, VisitorSwitchContext& _sContext, RewritingContext& _rContext ) : vContext(_vContext) , sContext(_sContext) , rContext(_rContext) { } void InspectIntoAffectedRule( GlrRule* rule, const List& affectedSwitches, Ptr> currentSwitchValues ) { // an affected rule respond to switch values // collect switch values that the rule cares auto workingSwitchValues = Ptr(new Dictionary); for (auto&& name : affectedSwitches) { vint index = -1; if (currentSwitchValues) { index = currentSwitchValues->Keys().IndexOf(name); } if (index == -1) { workingSwitchValues->Set(name, sContext.switches[name].key); } else { workingSwitchValues->Set(name, currentSwitchValues->Values()[index]); } } // skip if the rule with collected switch values has been inspected auto workingRule = vContext.syntaxManager.Rules()[rule->name.value]; vint index = rContext.generatedRules.Keys().IndexOf(workingRule); if (index != -1) { for (auto generatedRule : rContext.generatedRules.GetByIndex(index)) { if (CompareEnumerable(*generatedRule->switchValues.Obj(), *workingSwitchValues.Obj()) == 0) { return; } } } // make a record of the collected switch values auto generatedRule = Ptr(new GeneratedRule); generatedRule->ruleToExpand = rule; generatedRule->switchValues = workingSwitchValues; rContext.generatedRules.Add(workingRule, generatedRule); // inspect into the rule with collected switch values auto oldId = identification; identification.workingRule = workingRule; identification.workingSwitchValues = workingSwitchValues; identification.generatedRule = generatedRule; InspectInto(rule); identification = oldId; } void InspectIntoUnaffectedRule(GlrRule* rule) { // an unaffected rule does not respond to switch values // skip if it has been inspected auto workingRule = vContext.syntaxManager.Rules()[rule->name.value]; if (scannedUnaffectedRules.Contains(workingRule)) return; scannedUnaffectedRules.Add(workingRule); auto oldId = identification; identification = {}; identification.workingRule = workingRule; InspectInto(rule); identification = oldId; } }; /*********************************************************************** ExpandClauseVisitor ***********************************************************************/ class ExpandClauseVisitor : public copy_visitor::RuleAstVisitor { // this visitor expand syntax with given switch values // the expanded syntax does not include GlrPushConditionSyntax // GlrTestConditionSyntax will be possibly converts to GlrAlternativeSyntax // only with branches whose condition is evaluated to true under given switch values // EmptySyntax will be generated for ?(true: ; | false: allOtherBranches) // CancelBranch will be thrown for ?(false: allBranches) protected: struct CancelBranch {}; VisitorContext& vContext; VisitorSwitchContext& sContext; Ptr> workingSwitchValues; protected: void FixRuleName(ParsingToken& name) { // check if it is an affected rule vint index = vContext.syntaxManager.Rules().Keys().IndexOf(name.value); if (index == -1) return; auto ruleSymbol = vContext.syntaxManager.Rules().Values()[index]; index = sContext.ruleAffectedSwitches.Keys().IndexOf(ruleSymbol); if (index == -1) return; // for an affected rule // the name referencing the rule need to be changed // by appending switch values after it SortedList switchNames; CopyFrom(switchNames, sContext.ruleAffectedSwitches.GetByIndex(index)); name.value += L"_SWITCH"; for (auto&& switchName : switchNames) { auto value = workingSwitchValues->Get(switchName); name.value += (value ? L"_1" : L"_0") + switchName; } } void ExpandSyntaxToList(Ptr syntax, List>& items) { try { items.Add(CopyNode(syntax.Obj())); } catch (CancelBranch) { } } void BuildAlt(bool optional, List>& items) { // build syntax [items...] if (items.Count() == 0) { // if there is no branch if (optional) { // optional of nothing is EmptySyntax result = Ptr(new EmptySyntax); return; } else { // non-optional of nothing results in an exception result = nullptr; throw CancelBranch(); } } else if (items.Count() == 1) { // if there is only on branch, just use it result = items[0]; } else { // otherwise create alternative syntax for them auto alt = Ptr(new GlrAlternativeSyntax); alt->first = items[0]; alt->second = items[1]; for (vint i = 2; i < items.Count(); i++) { auto newAlt = Ptr(new GlrAlternativeSyntax); newAlt->first = alt; newAlt->second = items[i]; alt = newAlt; } result = alt; } if (optional) { // make it optional if necessary auto opt = Ptr(new GlrOptionalSyntax); opt->syntax = result.Cast(); result = opt; } } protected: void Visit(GlrRefSyntax* node) override { // only need to fix rule name for GlrRefSyntax copy_visitor::RuleAstVisitor::Visit(node); if (node->refType == GlrRefType::Id) { FixRuleName(result.Cast()->literal); } } void Visit(GlrUseSyntax* node) override { // only need to fix rule name for GlrUseSyntax copy_visitor::RuleAstVisitor::Visit(node); FixRuleName(result.Cast()->name); } void Visit(GlrAlternativeSyntax* node) override { // alternative syntax converts to alternative syntax List> items; ExpandSyntaxToList(node->first, items); ExpandSyntaxToList(node->second, items); BuildAlt(false, items); } void Visit(GlrTestConditionSyntax* node) override { // test condition syntax converts alternative syntax with optional if necessary bool optional = false; List> items; EvaluateConditionVisitor visitor(*workingSwitchValues.Obj()); for (auto branch : node->branches) { if (!branch || visitor.Evaluate(branch->condition.Obj())) { if (branch->syntax) { ExpandSyntaxToList(branch->syntax, items); } else { optional = true; } } } BuildAlt(optional, items); } void Visit(GlrPushConditionSyntax* node) override { // push condition syntax will be replaced by the syntax inside it auto oldValues = workingSwitchValues; auto newValues = ApplySwitches(oldValues, node); workingSwitchValues = newValues; node->syntax->Accept(this); workingSwitchValues = oldValues; } public: ExpandClauseVisitor( VisitorContext& _vContext, VisitorSwitchContext& _sContext, Ptr> _workingSwitchValues ) : vContext(_vContext) , sContext(_sContext) , workingSwitchValues(_workingSwitchValues) { } Ptr ExpandClause(GlrClause* node) { try { return CopyNode(node); } catch (CancelBranch) { return nullptr; } } }; /*********************************************************************** DeductEmptySyntaxVisitor ***********************************************************************/ class DeductEmptySyntaxVisitor : public copy_visitor::RuleAstVisitor { // this visitor rewrite a syntax by removing EmptySyntax // but it is possible that the whole syntax is evaluated to EmptySyntax // in this case it is rewritten to EmptySyntax protected: Ptr CopyNodeSafe(Ptr node) { if (node.Cast()) { return node; } else { return CopyNode(node.Obj()); } } protected: void Visit(GlrRefSyntax* node) override { result = Ptr(node); } void Visit(GlrUseSyntax* node) override { result = Ptr(node); } void Visit(GlrLoopSyntax* node) override { node->syntax = CopyNodeSafe(node->syntax); node->delimiter = CopyNodeSafe(node->delimiter); result = Ptr(node); if (node->syntax.Cast()) { // if the loop body is empty, it is empty result = node->syntax; } else if (node->delimiter.Cast()) { node->delimiter = nullptr; } } void Visit(GlrOptionalSyntax* node) override { node->syntax = CopyNodeSafe(node->syntax); result = Ptr(node); if (node->syntax.Cast()) { // if the optional body is empty, it is empty result = node->syntax; } } void Visit(GlrSequenceSyntax* node) override { node->first = CopyNodeSafe(node->first); node->second = CopyNodeSafe(node->second); result = Ptr(node); bool first = !node->first.Cast(); bool second = !node->second.Cast(); if (first && second) { // if both are not empty, nothing need to worry } else if (first) { // if only first is not empty, it is second result = node->first; } else if (second) { // if only second is empty, it is second result = node->second; } else { // if both are empty, it is empty result = node->first; } } void Visit(GlrAlternativeSyntax* node) override { node->first = CopyNodeSafe(node->first); node->second = CopyNodeSafe(node->second); result = Ptr(node); bool first = !node->first.Cast(); bool second = !node->second.Cast(); if (first && second) { // if both are not empty, nothing need to worry } else if (first) { // if only first is not empty, it is [first] auto opt = Ptr(new GlrOptionalSyntax); opt->syntax = node->first; result = opt; } else if (second) { // if only second is not empty, it is [second] auto opt = Ptr(new GlrOptionalSyntax); opt->syntax = node->second; result = opt; } else { // if both are empty, it is empty result = node->first; } } void Visit(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"vl::glr::parsergen::rewritesyntax_switch::DeductEmptySyntaxVisitor::Visit(GlrPushConditionSyntax*)#This should have been removed."); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"vl::glr::parsergen::rewritesyntax_switch::DeductEmptySyntaxVisitor::Visit(GlrTestConditionSyntax*)#This should have been removed."); } }; /*********************************************************************** DeductAndVerifyClauseVisitor **********************************************************************/ class DeductAndVerifyClauseVisitor : public Object , protected GlrClause::IVisitor { // this visitor remove EmptySyntax in clauses // if it is not possible, it returns false protected: void Verify(Ptr& syntax) { auto deducted = DeductEmptySyntaxVisitor().CopyNode(syntax.Obj()); if (deducted.Cast()) { result = false; } else { syntax = deducted; result = true; } } void Visit(GlrCreateClause* node) override { Verify(node->syntax); } void Visit(GlrPartialClause* node) override { Verify(node->syntax); } void Visit(GlrReuseClause* node) override { Verify(node->syntax); } void Visit(GlrLeftRecursionPlaceholderClause* node) override { result = true; } void Visit(GlrLeftRecursionInjectClause* node) override { result = true; } void Visit(GlrPrefixMergeClause* node) override { result = true; } public: bool result = false; bool Evaluate(GlrClause* node) { node->Accept(this); return result; } }; /*********************************************************************** RewriteSyntax ***********************************************************************/ WString CreateRuleName(Ptr rule, const wchar_t* tag, Dictionary& switchValues) { auto ruleName = rule->name.value + tag; for (auto [name, value] : switchValues) { ruleName += (value ? L"_1" : L"_0") + name; } return ruleName; } Ptr CreateRule(RuleSymbol* ruleSymbol, Ptr rule, const WString& name) { auto newRule = Ptr(new GlrRule); newRule->codeRange = rule->codeRange; newRule->name = rule->name; newRule->name.value = name; newRule->type = rule->type; newRule->type.value = ruleSymbol->ruleType->Name(); return newRule; } Ptr CreateRule(RuleSymbol* ruleSymbol, Ptr rule, const wchar_t* tag, Dictionary& switchValues) { return CreateRule(ruleSymbol, rule, CreateRuleName(rule, tag, switchValues)); } void AddRules(RuleSymbol* ruleSymbol, Ptr rewritten, Group>& expandedRules) { vint index = expandedRules.Keys().IndexOf(ruleSymbol); if (index != -1) { for (auto expandedRule : From(expandedRules.GetByIndex(index)) .OrderBy([](auto a, auto b) { return WString::Compare(a->name.value, b->name.value); }) ) { rewritten->rules.Add(expandedRule); } } } void CreateRuleSymbols(SyntaxSymbolManager& syntaxManager, Group>& expandedRules) { for (auto ruleSymbol : From(expandedRules.Keys()) .OrderBy([](auto a, auto b) { return WString::Compare(a->Name(), b->Name()); }) ) { for (auto rule : expandedRules[ruleSymbol]) { auto newRuleSymbol = syntaxManager.CreateRule( rule->name.value, rule->name.codeRange ); } } } } Ptr RewriteSyntax_Switch(VisitorContext& context, VisitorSwitchContext& sContext, SyntaxSymbolManager& syntaxManager, Ptr syntaxFile) { using namespace rewritesyntax_switch; if (sContext.ruleAffectedSwitches.Count() == syntaxManager.Rules().Count()) { syntaxManager.AddError( ParserErrorType::NoSwitchUnaffectedRule, {} ); return nullptr; } RewritingContext rewritingContext; { // find out all expansion of rules affected by switch values ExpandSwitchSyntaxVisitor visitor(context, sContext, rewritingContext); for (auto rule : syntaxFile->rules) { auto ruleSymbol = syntaxManager.Rules()[rule->name.value]; if (!sContext.ruleAffectedSwitches.Keys().Contains(ruleSymbol)) { visitor.InspectIntoUnaffectedRule(rule.Obj()); } } } auto rewritten = Ptr(new GlrSyntaxFile); for (auto rule : syntaxFile->rules) { auto ruleSymbol = syntaxManager.Rules()[rule->name.value]; vint index = rewritingContext.generatedRules.Keys().IndexOf(ruleSymbol); if (index == -1) { // if a rule is unaffected // just remove GlrPushConditionSyntax in clauses // rules it references could be renamed auto newRule = Ptr(new GlrRule); newRule->codeRange = rule->codeRange; newRule->name = rule->name; newRule->type = rule->type; ExpandClauseVisitor visitor(context, sContext, nullptr); for (auto clause : rule->clauses) { if (auto newClause = visitor.ExpandClause(clause.Obj())) { newRule->clauses.Add(newClause); } } if (newRule->clauses.Count() == 0) { // a rewritten rule must have at least on clause syntaxManager.AddError( ParserErrorType::SwitchUnaffectedRuleExpandedToNoClause, rule->codeRange, rule->name.value ); } else { rewritten->rules.Add(newRule); } } else { // if a rule is affected // all instances of possible switch values will be converted to a new rule // such rule has switch values encoded in its name for(auto generatedRule : rewritingContext.generatedRules.GetByIndex(index)) { SortedList referencedCombinedRules; auto newRule = CreateRule(ruleSymbol, rule, L"_SWITCH", *generatedRule->switchValues.Obj()); // rewrite all clauses with given switch values for (auto clause : rule->clauses) { auto switchValues = generatedRule->switchValues; // if this clause is affected by some switches // prepare switch values for combined rules vint clauseIndex = sContext.clauseAffectedSwitches.Keys().IndexOf(clause.Obj()); if (clauseIndex == -1) { switchValues = Ptr(new Dictionary); } else { auto&& switches = sContext.clauseAffectedSwitches.GetByIndex(clauseIndex); if (switches.Count() != generatedRule->switchValues->Count()) { switchValues = Ptr(new Dictionary); for (auto&& switchName : switches) { switchValues->Add(switchName, generatedRule->switchValues->Get(switchName)); } } } if (switchValues == generatedRule->switchValues) { // if this clause is affected by all switches // expand this clause into the new rule ExpandClauseVisitor visitor(context, sContext, switchValues); if (auto newClause = visitor.ExpandClause(clause.Obj())) { if (DeductAndVerifyClauseVisitor().Evaluate(newClause.Obj())) { // only add the rewritten clause to the generated rule if it is valid // a clause could be invalid if all branches evaluated to nothing due to GlrTestConditionSyntax newRule->clauses.Add(newClause); } } } else { // if this clause is affected by some switches // expand this clause into a combined rule bool validClause = false; auto combinedRuleName = CreateRuleName(rule, L"_SWITCH_COMBINED", *switchValues.Obj()); if (rewritingContext.validCombinedClauses.Contains(combinedRuleName, clause.Obj())) { validClause = true; } else if (!rewritingContext.invalidCombinedClauses.Contains(combinedRuleName, clause.Obj())) { ExpandClauseVisitor visitor(context, sContext, switchValues); if (auto newClause = visitor.ExpandClause(clause.Obj())) { if (DeductAndVerifyClauseVisitor().Evaluate(newClause.Obj())) { // only add the rewritten clause to the generated rule if it is valid // a clause could be invalid if all branches evaluated to nothing due to GlrTestConditionSyntax Ptr combinedRule; vint ruleIndex = rewritingContext.combinedRulesByName.Keys().IndexOf(combinedRuleName); if (ruleIndex == -1) { combinedRule = CreateRule(ruleSymbol, rule, combinedRuleName); rewritingContext.expandedCombinedRules.Add(ruleSymbol, combinedRule); rewritingContext.combinedRulesByName.Add(combinedRuleName, combinedRule); } else { combinedRule = rewritingContext.combinedRulesByName.Values()[ruleIndex]; } combinedRule->clauses.Add(newClause); validClause = true; } } if (validClause) { rewritingContext.validCombinedClauses.Add(combinedRuleName, clause.Obj()); } else { rewritingContext.invalidCombinedClauses.Add(combinedRuleName, clause.Obj()); } } // this clause might be invalid in the current context if (validClause) { if (!referencedCombinedRules.Contains(combinedRuleName)) { referencedCombinedRules.Add(combinedRuleName); } } } } for (auto ruleName : referencedCombinedRules) { // add all used combined rules in order of name if (ruleSymbol->isPartial) { auto refSyntax = Ptr(new GlrRefSyntax); refSyntax->literal = rule->name; refSyntax->literal.value = ruleName; refSyntax->refType = GlrRefType::Id; auto partialClause = Ptr(new GlrPartialClause); partialClause->codeRange = rule->codeRange; partialClause->type = rule->name; partialClause->type.value = ruleSymbol->ruleType->Name(); partialClause->syntax = refSyntax; newRule->clauses.Add(partialClause); } else { auto useSyntax = Ptr(new GlrUseSyntax); useSyntax->name = rule->name; useSyntax->name.value = ruleName; auto reuseClause = Ptr(new GlrReuseClause); reuseClause->codeRange = rule->codeRange; reuseClause->syntax = useSyntax; newRule->clauses.Add(reuseClause); } } if (newRule->clauses.Count() == 0) { // a rewritten rule must have at least on clause syntaxManager.AddError( ParserErrorType::SwitchAffectedRuleExpandedToNoClause, rule->codeRange, rule->name.value, newRule->name.value ); } else { rewritingContext.expandedFirstLevelRules.Add(ruleSymbol, newRule); } } // add rules AddRules(ruleSymbol, rewritten, rewritingContext.expandedCombinedRules); AddRules(ruleSymbol, rewritten, rewritingContext.expandedFirstLevelRules); } } // add symbols for generated rules CreateRuleSymbols(syntaxManager, rewritingContext.expandedCombinedRules); CreateRuleSymbols(syntaxManager, rewritingContext.expandedFirstLevelRules); // remove symbols for rule affected by switch values // because they are expanded to other rules for (auto ruleSymbol : rewritingContext.generatedRules.Keys()) { syntaxManager.RemoveRule(ruleSymbol->Name()); } return rewritten; } } } } /*********************************************************************** .\PARSERGEN\COMPILESYNTAX_VALIDATEPREFIXMERGE.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace compile_syntax; /*********************************************************************** ValidateDirectPrefixMergeRuleVisitor ***********************************************************************/ class ValidateDirectPrefixMergeRuleVisitor : public Object , protected virtual GlrSyntax::IVisitor , protected virtual GlrClause::IVisitor { protected: VisitorContext& context; RuleSymbol* ruleSymbol; public: ValidateDirectPrefixMergeRuleVisitor( VisitorContext& _context, RuleSymbol* _ruleSymbol ) : context(_context) , ruleSymbol(_ruleSymbol) { } void ValidateClause(Ptr clause) { clause->Accept(this); } protected: void NotBeginWithARule(ParsingAstBase* node) { // TODO: Should accept and generate !prefix_merge equivalent effect for this clause automatically context.syntaxManager.AddError( ParserErrorType::RuleMixedPrefixMergeWithClauseNotSyntacticallyBeginWithARule, node->codeRange, ruleSymbol->Name() ); } void VerifyStartRule(ParsingAstBase* node, RuleSymbol* startRule) { if (ruleSymbol != startRule && !context.indirectPmClauses.Keys().Contains(startRule)) { // TODO: Should accept and generate !prefix_merge equivalent effect for this clause automatically // When this is not a left-recursive clause context.syntaxManager.AddError( ParserErrorType::RuleMixedPrefixMergeWithClauseNotBeginWithIndirectPrefixMerge, node->codeRange, ruleSymbol->Name(), startRule->Name() ); } } //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { if (node->refType != GlrRefType::Id) { NotBeginWithARule(node); } else { vint index = context.syntaxManager.Rules().Keys().IndexOf(node->literal.value); if (index == -1) { NotBeginWithARule(node); } else { VerifyStartRule(node, context.syntaxManager.Rules().Values()[index]); } } } void Visit(GlrUseSyntax* node) override { VerifyStartRule(node, context.syntaxManager.Rules()[node->name.value]); } void Visit(GlrLoopSyntax* node) override { NotBeginWithARule(node); } void Visit(GlrOptionalSyntax* node) override { NotBeginWithARule(node); } void Visit(GlrSequenceSyntax* node) override { node->first->Accept(this); } void Visit(GlrAlternativeSyntax* node) override { NotBeginWithARule(node); } void Visit(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"GlrPushConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"GlrTestConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrCreateClause* node) override { node->syntax->Accept(this); } void Visit(GlrPartialClause* node) override { node->syntax->Accept(this); } void Visit(GlrReuseClause* node) override { node->syntax->Accept(this); } void Visit(GlrLeftRecursionPlaceholderClause* node) override { NotBeginWithARule(node); } void Visit(GlrLeftRecursionInjectClause* node) override { NotBeginWithARule(node); } void Visit(GlrPrefixMergeClause* node) override { } }; /*********************************************************************** ValidateDeducingPrefixMergeRuleVisitor ***********************************************************************/ class ValidateDeducingPrefixMergeRuleVisitor : public Object , protected virtual GlrSyntax::IVisitor , protected virtual GlrClause::IVisitor { protected: using NonSimpleUseDeduction = Pair; VisitorContext& context; RuleSymbol* ruleSymbol; Ptr> result; bool couldBeEmpty = false; public: ValidateDeducingPrefixMergeRuleVisitor( VisitorContext& _context, RuleSymbol* _ruleSymbol ) : context(_context) , ruleSymbol(_ruleSymbol) { } void ValidateClause(Ptr clause) { clause->Accept(this); if (result) { for (auto [refName, refRuleSymbol] : *result.Obj()) { context.syntaxManager.AddError( ParserErrorType::RuleDeductToPrefixMergeInNonSimpleUseClause, clause->codeRange, ruleSymbol->Name(), refRuleSymbol->Name(), refName->value ); } } } protected: void TryAppendResult(const ParsingToken& name, RuleSymbol* refRuleSymbol) { if (context.directPmClauses.Keys().Contains(refRuleSymbol)) { if (!result) result = Ptr(new List); result->Add({ &name,refRuleSymbol }); } } void VisitRuleRef(const ParsingToken& name) { vint index = context.syntaxManager.Rules().Keys().IndexOf(name.value); if (index == -1) return; auto refRuleSymbol = context.syntaxManager.Rules().Values()[index]; TryAppendResult(name, refRuleSymbol); index = context.indirectSimpleUseRules.Keys().IndexOf(refRuleSymbol); if (index == -1) return; for (auto [simpleUseSymbol, _] : context.indirectSimpleUseRules.GetByIndex(index)) { TryAppendResult(name, simpleUseSymbol); } } void VisitPotentialEmptySyntax() { // a clause is not allowed to produce an empty sequence // since this syntax could produce an empty sequence // therefore there should be other non-parallel part of syntax in this clause that produces a non-empty sequence // it doesn't need to check the error here result = nullptr; couldBeEmpty = true; } //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { result = nullptr; couldBeEmpty = false; if (node->refType != GlrRefType::Id) return; VisitRuleRef(node->literal); } void Visit(GlrUseSyntax* node) override { result = nullptr; couldBeEmpty = false; VisitRuleRef(node->name); } void Visit(GlrLoopSyntax* node) override { VisitPotentialEmptySyntax(); } void Visit(GlrOptionalSyntax* node) override { VisitPotentialEmptySyntax(); } void Visit(GlrSequenceSyntax* node) override { node->first->Accept(this); auto firstResult = result; bool firstEmpty = couldBeEmpty; node->second->Accept(this); auto secondResult = result; auto secondEmpty = couldBeEmpty; couldBeEmpty = firstEmpty && secondEmpty; if (!firstEmpty && !secondEmpty) { result = nullptr; } else if (!firstEmpty) { result = firstResult; } else if (!secondEmpty) { result = secondResult; } else { result = nullptr; } } void Visit(GlrAlternativeSyntax* node) override { node->first->Accept(this); auto firstResult = result; bool firstEmpty = couldBeEmpty; node->second->Accept(this); auto secondResult = result; auto secondEmpty = couldBeEmpty; if (firstEmpty || secondEmpty) { VisitPotentialEmptySyntax(); } else { result = nullptr; couldBeEmpty = true; if (firstResult && secondResult) { CopyFrom(*firstResult.Obj(), *secondResult.Obj(), true); result = firstResult; } else if (firstResult) { result = firstResult; } else if (secondResult) { result = secondResult; } } } void Visit(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"GlrPushConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"GlrTestConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrCreateClause* node) override { node->syntax->Accept(this); } void Visit(GlrPartialClause* node) override { node->syntax->Accept(this); } void Visit(GlrReuseClause* node) override { if (!dynamic_cast(node->syntax.Obj())) { node->syntax->Accept(this); } } void Visit(GlrLeftRecursionPlaceholderClause* node) override { } void Visit(GlrLeftRecursionInjectClause* node) override { if (!node->continuation || node->continuation->type == GlrLeftRecursionInjectContinuationType::Optional) { VisitRuleRef(node->rule->literal); } } void Visit(GlrPrefixMergeClause* node) override { } }; /*********************************************************************** ValidatePrefixMerge ***********************************************************************/ void ValidatePrefixMerge(VisitorContext& context, Ptr syntaxFile) { for (auto rule : syntaxFile->rules) { auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; if (context.directPmClauses.Keys().Contains(ruleSymbol)) { ValidateDirectPrefixMergeRuleVisitor visitor(context, ruleSymbol); for (auto clause : rule->clauses) { visitor.ValidateClause(clause); } } { ValidateDeducingPrefixMergeRuleVisitor visitor(context, ruleSymbol); for (auto clause : rule->clauses) { visitor.ValidateClause(clause); } } vint indexPm = context.indirectPmClauses.Keys().IndexOf(ruleSymbol); vint indexLrp = context.indirectLrpClauses.Keys().IndexOf(ruleSymbol); vint indexLri = context.indirectLriClauses.Keys().IndexOf(ruleSymbol); if (indexPm != -1) { auto rulePm = context.clauseToRules[context.indirectPmClauses.GetByIndex(indexPm)[0]]; if (indexLrp != -1) { auto ruleLrp = context.clauseToRules[context.indirectLrpClauses.GetByIndex(indexLrp)[0]]; context.syntaxManager.AddError( ParserErrorType::RuleIndirectlyBeginsWithPrefixMergeMixedLeftRecursionMarkers, rule->name.codeRange, ruleSymbol->Name(), rulePm->Name(), ruleLrp->Name() ); } if (indexLri != -1) { auto ruleLri = context.clauseToRules[context.indirectLriClauses.GetByIndex(indexLri)[0]]; context.syntaxManager.AddError( ParserErrorType::RuleIndirectlyBeginsWithPrefixMergeMixedLeftRecursionMarkers, rule->name.codeRange, ruleSymbol->Name(), rulePm->Name(), ruleLri->Name() ); } if (ruleSymbol->isPartial) { context.syntaxManager.AddError( ParserErrorType::PartialRuleIndirectlyBeginsWithPrefixMerge, rule->name.codeRange, ruleSymbol->Name(), rulePm->Name() ); } if (!context.directPmClauses.Keys().Contains(ruleSymbol)) { for (auto clause : rule->clauses) { ParsingToken firstDirectLiteral; RuleSymbol* firstIndirectNonPmRule = nullptr; GlrPrefixMergeClause* firstIndirectlyPmClause = nullptr; // test if this clause directly begins with and literal vint index = context.clauseBeginsWithLiteral.Keys().IndexOf(clause.Obj()); if (index != -1) { firstDirectLiteral = context.clauseBeginsWithLiteral.GetByIndex(index)[0]; } // find all direct start rules from this clause index = context.clauseToStartRules.Keys().IndexOf(clause.Obj()); if (index != -1) { List visiting; SortedList visited; CopyFrom(visiting, context.clauseToStartRules.GetByIndex(index)); for (vint i = 0; i < visiting.Count(); i++) { auto visitingRule = visiting[i]; if (visited.Contains(visitingRule)) continue; visited.Add(visitingRule); // test if the visiting rule begins with prefix_merge index = context.indirectPmClauses.Keys().IndexOf(visitingRule); if (index != -1) { if (!firstIndirectlyPmClause) { firstIndirectlyPmClause = context.indirectPmClauses.GetByIndex(index)[0]; } } else { // if the visiting rule itself partial begins with prefix_merge // then an errors should be generated for this rule // here we assume it never happens in order to reduce the number of errors if (!firstIndirectNonPmRule) { firstIndirectNonPmRule = visitingRule; } } if ((firstDirectLiteral || firstIndirectNonPmRule) && firstIndirectlyPmClause) break; } } if (firstDirectLiteral && firstIndirectlyPmClause) { context.syntaxManager.AddError( ParserErrorType::ClausePartiallyIndirectlyBeginsWithPrefixMergeAndLiteral, clause->codeRange, ruleSymbol->Name(), context.clauseToRules[firstIndirectlyPmClause]->Name(), firstDirectLiteral.value ); } else if (firstIndirectNonPmRule && firstIndirectlyPmClause) { context.syntaxManager.AddError( ParserErrorType::ClausePartiallyIndirectlyBeginsWithPrefixMergeAndRule, clause->codeRange, ruleSymbol->Name(), context.clauseToRules[firstIndirectlyPmClause]->Name(), firstIndirectNonPmRule->Name() ); } else if (!context.leftRecursiveClauses.Contains(ruleSymbol, clause.Obj())) { // safe to add the clause since errors have been detected in ClausePartiallyIndirectlyBeginsWithPrefixMerge vint index = context.clauseToStartRules.Keys().IndexOf(clause.Obj()); if (index != -1) { for (auto ruleSymbol : context.clauseToStartRules.GetByIndex(index)) { if (context.indirectPmClauses.Keys().IndexOf(ruleSymbol) != -1) { goto SKIP_ADDING; } } } context.clauseToConvertedToPrefixMerge.Add(clause.Obj()); SKIP_ADDING:; } } } } } } } } } /*********************************************************************** .\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; GlrLeftRecursionPlaceholderClause* lrpClause = 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: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// 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() ); } } if (node->refType == GlrRefType::Id) { vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->literal.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(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 Visit(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"GlrPushConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"GlrTestConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// 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); } void Visit(GlrLeftRecursionPlaceholderClause* node) override { if (!lrpClause) { lrpClause = node; } else { context.syntaxManager.AddError( ParserErrorType::TooManyLeftRecursionPlaceholderClauses, node->codeRange, ruleSymbol->Name() ); } } void Visit(GlrLeftRecursionInjectClause* node) override { } void Visit(GlrPrefixMergeClause* node) override { } }; /*********************************************************************** 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: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { if (node->field) { existingFields = existingFields.Append(new Link(node)); } if (node->refType == GlrRefType::Id) { vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->literal.value); if (ruleIndex != -1) { auto fieldRule = context.syntaxManager.Rules().Values()[ruleIndex]; if (fieldRule->isPartial) { existingPartials = existingPartials.Append(new Link(node)); } } } } 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 Visit(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"GlrPushConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"GlrTestConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// 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); } void Visit(GlrLeftRecursionPlaceholderClause* node) override { } void Visit(GlrLeftRecursionInjectClause* node) override { } void Visit(GlrPrefixMergeClause* node) override { } }; /*********************************************************************** ValidateStructure ***********************************************************************/ void ValidateStructure(VisitorContext& context, Ptr syntaxFile) { for (auto rule : syntaxFile->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_VALIDATESWITCHESANDCONDITIONS.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace compile_syntax; /*********************************************************************** CollectRuleAffectedSwitchesVisitorBase ***********************************************************************/ class CollectRuleAffectedSwitchesVisitorBase : public traverse_visitor::RuleAstVisitor { protected: VisitorContext& context; VisitorSwitchContext& sContext; RuleSymbol* ruleSymbol = nullptr; GlrClause* currentClause = nullptr; List pushedSwitches; public: CollectRuleAffectedSwitchesVisitorBase( VisitorContext& _context, VisitorSwitchContext& _sContext ) : context(_context) , sContext(_sContext) { } void ValidateRule(Ptr rule) { ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; for (auto clause : rule->clauses) { currentClause = clause.Obj(); clause->Accept(this); currentClause = nullptr; } } protected: void Traverse(GlrPushConditionSyntax* node) override { for (auto switchItem : node->switches) { pushedSwitches.Add(switchItem->name.value); } } void Finishing(GlrPushConditionSyntax* node) override { for (vint i = 0; i < node->switches.Count(); i++) { pushedSwitches.RemoveAt(pushedSwitches.Count() - 1); } } }; /*********************************************************************** CollectRuleAffectedSwitchesFirstPassVisitor ***********************************************************************/ class CollectRuleAffectedSwitchesFirstPassVisitor : public CollectRuleAffectedSwitchesVisitorBase { public: CollectRuleAffectedSwitchesFirstPassVisitor( VisitorContext& _context, VisitorSwitchContext& _sContext ) : CollectRuleAffectedSwitchesVisitorBase(_context, _sContext) { } protected: //////////////////////////////////////////////////////////////////////// // GlrCondition::IVisitor //////////////////////////////////////////////////////////////////////// void Traverse(GlrRefCondition* node) override { if (!pushedSwitches.Contains(node->name.value)) { if (!sContext.clauseAffectedSwitches.Contains(currentClause, node->name.value)) { sContext.clauseAffectedSwitches.Add(currentClause, node->name.value); } if (!sContext.ruleAffectedSwitches.Contains(ruleSymbol, node->name.value)) { sContext.ruleAffectedSwitches.Add(ruleSymbol, node->name.value); } } } }; /*********************************************************************** CollectRuleAffectedSwitchesSecondPassVisitor ***********************************************************************/ class CollectRuleAffectedSwitchesSecondPassVisitor : public CollectRuleAffectedSwitchesVisitorBase { public: bool updated = false; CollectRuleAffectedSwitchesSecondPassVisitor( VisitorContext& _context, VisitorSwitchContext& _sContext ) : CollectRuleAffectedSwitchesVisitorBase(_context, _sContext) { } protected: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void VisitRule(const WString& name) { vint index = context.syntaxManager.Rules().Keys().IndexOf(name); if (index != -1) { auto refRuleSymbol = context.syntaxManager.Rules().Values()[index]; vint indexSwitch = sContext.ruleAffectedSwitches.Keys().IndexOf(refRuleSymbol); if (indexSwitch != -1) { for (auto&& name : sContext.ruleAffectedSwitches.GetByIndex(indexSwitch)) { if (!pushedSwitches.Contains(name)) { if (!sContext.clauseAffectedSwitches.Contains(currentClause, name)) { updated = true; sContext.clauseAffectedSwitches.Add(currentClause, name); } if (ruleSymbol != refRuleSymbol && !sContext.ruleAffectedSwitches.Contains(ruleSymbol, name)) { updated = true; sContext.ruleAffectedSwitches.Add(ruleSymbol, name); } } } } } } void Traverse(GlrRefSyntax* node) override { VisitRule(node->literal.value); } void Traverse(GlrUseSyntax* node) override { VisitRule(node->name.value); } }; /*********************************************************************** VerifySwitchesAndConditionsVisitor ***********************************************************************/ class CollectTestedSwitchesVisitor : public traverse_visitor::RuleAstVisitor { protected: VisitorContext& context; VisitorSwitchContext& sContext; public: SortedList testedSwitches; CollectTestedSwitchesVisitor( VisitorContext& _context, VisitorSwitchContext& _sContext ) : context(_context) , sContext(_sContext) { } protected: //////////////////////////////////////////////////////////////////////// // GlrCondition::IVisitor //////////////////////////////////////////////////////////////////////// void Traverse(GlrRefCondition* node) override { if (!testedSwitches.Contains(node->name.value)) { testedSwitches.Add(node->name.value); } } //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void VisitRule(const WString& name) { vint index = context.syntaxManager.Rules().Keys().IndexOf(name); if (index != -1) { auto refRuleSymbol = context.syntaxManager.Rules().Values()[index]; vint index = sContext.ruleAffectedSwitches.Keys().IndexOf(refRuleSymbol); if (index != -1) { for (auto switchName : sContext.ruleAffectedSwitches.GetByIndex(index)) { if (!testedSwitches.Contains(switchName)) { testedSwitches.Add(switchName); } } } } } void Traverse(GlrRefSyntax* node) override { VisitRule(node->literal.value); } void Traverse(GlrUseSyntax* node) override { VisitRule(node->name.value); } }; class VerifySwitchesAndConditionsVisitor : public traverse_visitor::RuleAstVisitor { protected: VisitorContext& context; VisitorSwitchContext& sContext; RuleSymbol* ruleSymbol = nullptr; public: VerifySwitchesAndConditionsVisitor( VisitorContext& _context, VisitorSwitchContext& _sContext ) : context(_context) , sContext(_sContext) { } void ValidateRule(Ptr rule) { ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; for (auto clause : rule->clauses) { clause->Accept(this); } } protected: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Traverse(GlrPushConditionSyntax* node) override { CollectTestedSwitchesVisitor visitor(context, sContext); node->syntax->Accept(&visitor); for (auto switchItem : node->switches) { if (!visitor.testedSwitches.Contains(switchItem->name.value)) { context.syntaxManager.AddError( ParserErrorType::PushedSwitchIsNotTested, node->codeRange, ruleSymbol->Name(), switchItem->name.value ); } } } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// void Traverse(GlrPrefixMergeClause* node) override { auto pmRuleSymbol = context.syntaxManager.Rules()[node->rule->literal.value]; vint index = sContext.ruleAffectedSwitches.Keys().IndexOf(pmRuleSymbol); if(index != -1) { context.syntaxManager.AddError( ParserErrorType::PrefixMergeAffectedBySwitches, node->codeRange, ruleSymbol->Name(), pmRuleSymbol->Name(), sContext.ruleAffectedSwitches.GetByIndex(index)[0] ); } } }; /*********************************************************************** ValidateSwitchesAndConditions ***********************************************************************/ void ValidateSwitchesAndConditions(VisitorContext& context, VisitorSwitchContext& sContext, Ptr syntaxFile) { for (auto rule : syntaxFile->rules) { CollectRuleAffectedSwitchesFirstPassVisitor visitor(context, sContext); visitor.ValidateRule(rule); } while (true) { CollectRuleAffectedSwitchesSecondPassVisitor visitor(context, sContext); for (auto rule : syntaxFile->rules) { visitor.ValidateRule(rule); } if (!visitor.updated) break; }; for (auto rule : syntaxFile->rules) { VerifySwitchesAndConditionsVisitor visitor(context, sContext); visitor.ValidateRule(rule); } } } } } /*********************************************************************** .\PARSERGEN\COMPILESYNTAX_VALIDATETYPES.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace compile_syntax; bool ConvertibleTo(AstClassSymbol* from, AstClassSymbol* to) { while (from) { if (from == to) return true; from = from->baseClass; } return false; } /*********************************************************************** 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; } } public: ValidateTypesVisitor( VisitorContext& _context, RuleSymbol* _ruleSymbol ) : context(_context) , ruleSymbol(_ruleSymbol) { } void ValidateClause(Ptr clause) { clause->Accept(this); } protected: //////////////////////////////////////////////////////////////////////// // GlrSyntax::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrRefSyntax* node) override { vint ruleIndex = node->refType == GlrRefType::Id ? context.syntaxManager.Rules().Keys().IndexOf(node->literal.value) : -1; 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(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(GlrPushConditionSyntax* node) override { CHECK_FAIL(L"GlrPushConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } void Visit(GlrTestConditionSyntax* node) override { CHECK_FAIL(L"GlrTestConditionSyntax should have been removed after RewriteSyntax_Switch()!"); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// 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()); } } void Visit(GlrLeftRecursionPlaceholderClause* node) override { } void Visit(GlrLeftRecursionInjectClause* node) override { } void Visit(GlrPrefixMergeClause* node) override { auto prefixRule = context.syntaxManager.Rules()[node->rule->literal.value]; if (prefixRule->isPartial) { context.syntaxManager.AddError( ParserErrorType::PartialRuleInPrefixMerge, node->rule->codeRange, ruleSymbol->Name(), node->rule->literal.value ); } } }; /*********************************************************************** LriVerifyTypesVisitor ***********************************************************************/ class LriVerifyTypesVisitor : public empty_visitor::ClauseVisitor { protected: VisitorContext& context; RuleSymbol* ruleSymbol; public: LriVerifyTypesVisitor( VisitorContext& _context, RuleSymbol* _ruleSymbol ) : context(_context) , ruleSymbol(_ruleSymbol) { } void ValidateClause(Ptr clause) { clause->Accept(this); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// void Visit(GlrLeftRecursionInjectClause* node) override { auto prefixRule = context.syntaxManager.Rules()[node->rule->literal.value]; if (prefixRule->isPartial) { context.syntaxManager.AddError( ParserErrorType::PartialRuleInLeftRecursionInject, node->rule->codeRange, ruleSymbol->Name(), node->rule->literal.value ); } for (auto lriTarget : node->continuation->injectionTargets) { auto target = lriTarget->rule; for (auto lriFlag : node->continuation->flags) { List lrpClauses; { vint index = context.indirectLrpClauses.Keys().IndexOf(context.syntaxManager.Rules()[target->literal.value]); if (index != -1) { CopyFrom( lrpClauses, From(context.indirectLrpClauses.GetByIndex(index)) .Where([lriFlag](auto&& lrp) { return !From(lrp->flags) .Where([lriFlag](auto&& flag) { return flag->flag.value == lriFlag->flag.value; }) .IsEmpty(); })); } } if (lrpClauses.Count() == 0) { context.syntaxManager.AddError( ParserErrorType::LeftRecursionPlaceholderNotFoundInRule, target->codeRange, ruleSymbol->Name(), lriFlag->flag.value, target->literal.value ); } else if (lrpClauses.Count() > 1 && node->continuation->configuration == GlrLeftRecursionConfiguration::Single) { context.syntaxManager.AddError( ParserErrorType::LeftRecursionPlaceholderNotUnique, target->codeRange, ruleSymbol->Name(), lriFlag->flag.value, target->literal.value ); } for (auto lrpClause : lrpClauses) { auto lrpClauseRule = context.clauseToRules[lrpClause]; if (!ConvertibleTo(prefixRule->ruleType, lrpClauseRule->ruleType)) { context.syntaxManager.AddError( ParserErrorType::LeftRecursionPlaceholderTypeMismatched, target->codeRange, ruleSymbol->Name(), lriFlag->flag.value, target->literal.value, lrpClauseRule->Name() ); } } } if (lriTarget->continuation) { Visit(lriTarget.Obj()); } } } }; /*********************************************************************** LriPrefixTestingVisitor ***********************************************************************/ class LriPrefixTestingVisitor : public empty_visitor::ClauseVisitor { protected: VisitorContext& context; RuleSymbol* ruleSymbol; Group lriEndings; public: LriPrefixTestingVisitor( VisitorContext& _context, RuleSymbol* _ruleSymbol ) : context(_context) , ruleSymbol(_ruleSymbol) { } void ValidateClause(Ptr clause) { clause->Accept(this); } //////////////////////////////////////////////////////////////////////// // GlrClause::IVisitor //////////////////////////////////////////////////////////////////////// void SearchLriEndings(List& visiting, GlrLeftRecursionInjectClause* node) { visiting.Add(node); if (!node->continuation || node->continuation->type == GlrLeftRecursionInjectContinuationType::Optional) { for (auto lri : visiting) { if (!lriEndings.Contains(lri, node->rule->literal.value)) { lriEndings.Add(lri, node->rule->literal.value); } } } if (node->continuation) { for (auto target : node->continuation->injectionTargets) { SearchLriEndings(visiting, target.Obj()); } } visiting.RemoveAt(visiting.Count() - 1); } void VerifyPrefix(GlrLeftRecursionInjectClause* node) { if (node->continuation) { for (auto t1 : node->continuation->injectionTargets) { auto k1 = context.syntaxManager.Rules()[t1->rule->literal.value]; vint i1 = lriEndings.Keys().IndexOf(t1.Obj()); if (i1 == -1) continue; for (auto t2 : node->continuation->injectionTargets) { auto k2 = context.syntaxManager.Rules()[t2->rule->literal.value]; vint i2 = lriEndings.Keys().IndexOf(t2.Obj()); if (i2 == -1) continue; if (t1 != t2 && context.indirectStartPathToLastRules.Keys().Contains({ k2, k1 })) { auto&& e1 = lriEndings.GetByIndex(i1); auto&& e2 = lriEndings.GetByIndex(i2); if (!From(e1).Intersect(e2).IsEmpty()) { context.syntaxManager.AddError( ParserErrorType::LeftRecursionInjectTargetIsPrefixOfAnotherSameEnding, node->codeRange, ruleSymbol->Name(), node->continuation->flags[0]->flag.value, k1->Name(), k2->Name() ); } } } } } } void Visit(GlrLeftRecursionInjectClause* node) override { { List visiting; SearchLriEndings(visiting, node); } VerifyPrefix(node); } }; /*********************************************************************** ValidateTypes ***********************************************************************/ void ValidateTypes(VisitorContext& context, Ptr syntaxFile) { for (auto rule : syntaxFile->rules) { auto ruleSymbol = context.syntaxManager.Rules()[rule->name.value]; ValidateTypesVisitor vtVisitor(context, ruleSymbol); for (auto clause : rule->clauses) { vtVisitor.ValidateClause(clause); { LriVerifyTypesVisitor lvtVisitor(context, ruleSymbol); lvtVisitor.ValidateClause(clause); } { LriPrefixTestingVisitor lptVisitor(context, ruleSymbol); lptVisitor.ValidateClause(clause); } } } } } } } /*********************************************************************** .\PARSERGEN\PARSERCPPGEN.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace stream; /*********************************************************************** GenerateParserFileNames ***********************************************************************/ Ptr GenerateParserFileNames(ParserSymbolManager& manager) { auto parserOutput = Ptr(new CppParserGenOutput); 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(const 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(const 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 GlrRefCondition::Accept(GlrCondition::IVisitor* visitor) { visitor->Visit(this); } void GlrNotCondition::Accept(GlrCondition::IVisitor* visitor) { visitor->Visit(this); } void GlrAndCondition::Accept(GlrCondition::IVisitor* visitor) { visitor->Visit(this); } void GlrOrCondition::Accept(GlrCondition::IVisitor* visitor) { visitor->Visit(this); } void GlrRefSyntax::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 GlrPushConditionSyntax::Accept(GlrSyntax::IVisitor* visitor) { visitor->Visit(this); } void GlrTestConditionSyntax::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); } void GlrLeftRecursionPlaceholderClause::Accept(GlrClause::IVisitor* visitor) { visitor->Visit(this); } void GlrLeftRecursionInjectClause::Accept(GlrClause::IVisitor* visitor) { visitor->Visit(this); } void GlrPrefixMergeClause::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::GlrCondition, glr::parsergen::GlrCondition) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrCondition::IVisitor, glr::parsergen::GlrCondition::IVisitor) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrRefCondition, glr::parsergen::GlrRefCondition) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrNotCondition, glr::parsergen::GlrNotCondition) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrAndCondition, glr::parsergen::GlrAndCondition) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrOrCondition, glr::parsergen::GlrOrCondition) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrSwitchValue, glr::parsergen::GlrSwitchValue) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrSwitchItem, glr::parsergen::GlrSwitchItem) 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::GlrRefType, glr::parsergen::GlrRefType) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrRefSyntax, glr::parsergen::GlrRefSyntax) 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::GlrPushConditionSyntax, glr::parsergen::GlrPushConditionSyntax) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrTestConditionBranch, glr::parsergen::GlrTestConditionBranch) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrTestConditionSyntax, glr::parsergen::GlrTestConditionSyntax) 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::GlrAssignmentType, glr::parsergen::GlrAssignmentType) 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::GlrLeftRecursionPlaceholder, glr::parsergen::GlrLeftRecursionPlaceholder) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrLeftRecursionPlaceholderClause, glr::parsergen::GlrLeftRecursionPlaceholderClause) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrLeftRecursionConfiguration, glr::parsergen::GlrLeftRecursionConfiguration) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrLeftRecursionInjectContinuationType, glr::parsergen::GlrLeftRecursionInjectContinuationType) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrLeftRecursionInjectContinuation, glr::parsergen::GlrLeftRecursionInjectContinuation) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrLeftRecursionInjectClause, glr::parsergen::GlrLeftRecursionInjectClause) IMPL_TYPE_INFO_RENAME(vl::glr::parsergen::GlrPrefixMergeClause, glr::parsergen::GlrPrefixMergeClause) 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::GlrCondition) CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) END_CLASS_MEMBER(vl::glr::parsergen::GlrCondition) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrRefCondition) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrCondition) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(name) END_CLASS_MEMBER(vl::glr::parsergen::GlrRefCondition) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrNotCondition) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrCondition) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(condition) END_CLASS_MEMBER(vl::glr::parsergen::GlrNotCondition) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrAndCondition) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrCondition) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(first) CLASS_MEMBER_FIELD(second) END_CLASS_MEMBER(vl::glr::parsergen::GlrAndCondition) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrOrCondition) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrCondition) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(first) CLASS_MEMBER_FIELD(second) END_CLASS_MEMBER(vl::glr::parsergen::GlrOrCondition) BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrSwitchValue) ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrSwitchValue) ENUM_NAMESPACE_ITEM(False) ENUM_NAMESPACE_ITEM(True) END_ENUM_ITEM(vl::glr::parsergen::GlrSwitchValue) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrSwitchItem) 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::parsergen::GlrSwitchItem) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrSyntax) CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) END_CLASS_MEMBER(vl::glr::parsergen::GlrSyntax) BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrRefType) ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrRefType) ENUM_NAMESPACE_ITEM(Id) ENUM_NAMESPACE_ITEM(Literal) ENUM_NAMESPACE_ITEM(ConditionalLiteral) END_ENUM_ITEM(vl::glr::parsergen::GlrRefType) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrRefSyntax) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(refType) CLASS_MEMBER_FIELD(literal) CLASS_MEMBER_FIELD(field) END_CLASS_MEMBER(vl::glr::parsergen::GlrRefSyntax) 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::GlrPushConditionSyntax) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(switches) CLASS_MEMBER_FIELD(syntax) END_CLASS_MEMBER(vl::glr::parsergen::GlrPushConditionSyntax) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrTestConditionBranch) CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(condition) CLASS_MEMBER_FIELD(syntax) END_CLASS_MEMBER(vl::glr::parsergen::GlrTestConditionBranch) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrTestConditionSyntax) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrSyntax) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(branches) END_CLASS_MEMBER(vl::glr::parsergen::GlrTestConditionSyntax) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrClause) CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) END_CLASS_MEMBER(vl::glr::parsergen::GlrClause) BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrAssignmentType) ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrAssignmentType) ENUM_NAMESPACE_ITEM(Strong) ENUM_NAMESPACE_ITEM(Weak) END_ENUM_ITEM(vl::glr::parsergen::GlrAssignmentType) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrAssignment) CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(type) 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::GlrLeftRecursionPlaceholder) CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(flag) END_CLASS_MEMBER(vl::glr::parsergen::GlrLeftRecursionPlaceholder) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrLeftRecursionPlaceholderClause) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrClause) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(flags) END_CLASS_MEMBER(vl::glr::parsergen::GlrLeftRecursionPlaceholderClause) BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrLeftRecursionConfiguration) ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrLeftRecursionConfiguration) ENUM_NAMESPACE_ITEM(Single) ENUM_NAMESPACE_ITEM(Multiple) END_ENUM_ITEM(vl::glr::parsergen::GlrLeftRecursionConfiguration) BEGIN_ENUM_ITEM(vl::glr::parsergen::GlrLeftRecursionInjectContinuationType) ENUM_ITEM_NAMESPACE(vl::glr::parsergen::GlrLeftRecursionInjectContinuationType) ENUM_NAMESPACE_ITEM(Optional) ENUM_NAMESPACE_ITEM(Required) END_ENUM_ITEM(vl::glr::parsergen::GlrLeftRecursionInjectContinuationType) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrLeftRecursionInjectContinuation) CLASS_MEMBER_BASE(vl::glr::ParsingAstBase) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(flags) CLASS_MEMBER_FIELD(configuration) CLASS_MEMBER_FIELD(type) CLASS_MEMBER_FIELD(injectionTargets) END_CLASS_MEMBER(vl::glr::parsergen::GlrLeftRecursionInjectContinuation) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrLeftRecursionInjectClause) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrClause) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(rule) CLASS_MEMBER_FIELD(continuation) END_CLASS_MEMBER(vl::glr::parsergen::GlrLeftRecursionInjectClause) BEGIN_CLASS_MEMBER(vl::glr::parsergen::GlrPrefixMergeClause) CLASS_MEMBER_BASE(vl::glr::parsergen::GlrClause) CLASS_MEMBER_CONSTRUCTOR(vl::Ptr(), NO_PARAMETER) CLASS_MEMBER_FIELD(rule) END_CLASS_MEMBER(vl::glr::parsergen::GlrPrefixMergeClause) 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(type) 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(switches) CLASS_MEMBER_FIELD(rules) END_CLASS_MEMBER(vl::glr::parsergen::GlrSyntaxFile) BEGIN_INTERFACE_MEMBER(vl::glr::parsergen::GlrCondition::IVisitor) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrCondition::IVisitor::*)(vl::glr::parsergen::GlrRefCondition* node)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrCondition::IVisitor::*)(vl::glr::parsergen::GlrNotCondition* node)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrCondition::IVisitor::*)(vl::glr::parsergen::GlrAndCondition* node)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrCondition::IVisitor::*)(vl::glr::parsergen::GlrOrCondition* node)) END_INTERFACE_MEMBER(vl::glr::parsergen::GlrCondition) 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::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)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrPushConditionSyntax* node)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrSyntax::IVisitor::*)(vl::glr::parsergen::GlrTestConditionSyntax* 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)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrClause::IVisitor::*)(vl::glr::parsergen::GlrLeftRecursionPlaceholderClause* node)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrClause::IVisitor::*)(vl::glr::parsergen::GlrLeftRecursionInjectClause* node)) CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::parsergen::GlrClause::IVisitor::*)(vl::glr::parsergen::GlrPrefixMergeClause* 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::GlrCondition) ADD_TYPE_INFO(vl::glr::parsergen::GlrCondition::IVisitor) ADD_TYPE_INFO(vl::glr::parsergen::GlrRefCondition) ADD_TYPE_INFO(vl::glr::parsergen::GlrNotCondition) ADD_TYPE_INFO(vl::glr::parsergen::GlrAndCondition) ADD_TYPE_INFO(vl::glr::parsergen::GlrOrCondition) ADD_TYPE_INFO(vl::glr::parsergen::GlrSwitchValue) ADD_TYPE_INFO(vl::glr::parsergen::GlrSwitchItem) ADD_TYPE_INFO(vl::glr::parsergen::GlrSyntax) ADD_TYPE_INFO(vl::glr::parsergen::GlrSyntax::IVisitor) ADD_TYPE_INFO(vl::glr::parsergen::GlrRefType) ADD_TYPE_INFO(vl::glr::parsergen::GlrRefSyntax) 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::GlrPushConditionSyntax) ADD_TYPE_INFO(vl::glr::parsergen::GlrTestConditionBranch) ADD_TYPE_INFO(vl::glr::parsergen::GlrTestConditionSyntax) ADD_TYPE_INFO(vl::glr::parsergen::GlrClause) ADD_TYPE_INFO(vl::glr::parsergen::GlrClause::IVisitor) ADD_TYPE_INFO(vl::glr::parsergen::GlrAssignmentType) 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::GlrLeftRecursionPlaceholder) ADD_TYPE_INFO(vl::glr::parsergen::GlrLeftRecursionPlaceholderClause) ADD_TYPE_INFO(vl::glr::parsergen::GlrLeftRecursionConfiguration) ADD_TYPE_INFO(vl::glr::parsergen::GlrLeftRecursionInjectContinuationType) ADD_TYPE_INFO(vl::glr::parsergen::GlrLeftRecursionInjectContinuation) ADD_TYPE_INFO(vl::glr::parsergen::GlrLeftRecursionInjectClause) ADD_TYPE_INFO(vl::glr::parsergen::GlrPrefixMergeClause) 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()) { auto loader = Ptr(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; } /*********************************************************************** MakeAndCondition ***********************************************************************/ MakeAndCondition& MakeAndCondition::first(const vl::Ptr& value) { node->first = value; return *this; } MakeAndCondition& MakeAndCondition::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::type(GlrAssignmentType value) { node->type = 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; } /*********************************************************************** MakeLeftRecursionInjectClause ***********************************************************************/ MakeLeftRecursionInjectClause& MakeLeftRecursionInjectClause::continuation(const vl::Ptr& value) { node->continuation = value; return *this; } MakeLeftRecursionInjectClause& MakeLeftRecursionInjectClause::rule(const vl::Ptr& value) { node->rule = value; return *this; } /*********************************************************************** MakeLeftRecursionInjectContinuation ***********************************************************************/ MakeLeftRecursionInjectContinuation& MakeLeftRecursionInjectContinuation::configuration(GlrLeftRecursionConfiguration value) { node->configuration = value; return *this; } MakeLeftRecursionInjectContinuation& MakeLeftRecursionInjectContinuation::flags(const vl::Ptr& value) { node->flags.Add(value); return *this; } MakeLeftRecursionInjectContinuation& MakeLeftRecursionInjectContinuation::injectionTargets(const vl::Ptr& value) { node->injectionTargets.Add(value); return *this; } MakeLeftRecursionInjectContinuation& MakeLeftRecursionInjectContinuation::type(GlrLeftRecursionInjectContinuationType value) { node->type = value; return *this; } /*********************************************************************** MakeLeftRecursionPlaceholder ***********************************************************************/ MakeLeftRecursionPlaceholder& MakeLeftRecursionPlaceholder::flag(const vl::WString& value) { node->flag.value = value; return *this; } /*********************************************************************** MakeLeftRecursionPlaceholderClause ***********************************************************************/ MakeLeftRecursionPlaceholderClause& MakeLeftRecursionPlaceholderClause::flags(const vl::Ptr& value) { node->flags.Add(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; } /*********************************************************************** MakeNotCondition ***********************************************************************/ MakeNotCondition& MakeNotCondition::condition(const vl::Ptr& value) { node->condition = 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; } /*********************************************************************** MakeOrCondition ***********************************************************************/ MakeOrCondition& MakeOrCondition::first(const vl::Ptr& value) { node->first = value; return *this; } MakeOrCondition& MakeOrCondition::second(const vl::Ptr& value) { node->second = 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; } /*********************************************************************** MakePrefixMergeClause ***********************************************************************/ MakePrefixMergeClause& MakePrefixMergeClause::rule(const vl::Ptr& value) { node->rule = value; return *this; } /*********************************************************************** MakePushConditionSyntax ***********************************************************************/ MakePushConditionSyntax& MakePushConditionSyntax::switches(const vl::Ptr& value) { node->switches.Add(value); return *this; } MakePushConditionSyntax& MakePushConditionSyntax::syntax(const vl::Ptr& value) { node->syntax = value; return *this; } /*********************************************************************** MakeRefCondition ***********************************************************************/ MakeRefCondition& MakeRefCondition::name(const vl::WString& value) { node->name.value = value; return *this; } /*********************************************************************** MakeRefSyntax ***********************************************************************/ MakeRefSyntax& MakeRefSyntax::field(const vl::WString& value) { node->field.value = value; return *this; } MakeRefSyntax& MakeRefSyntax::literal(const vl::WString& value) { node->literal.value = value; return *this; } MakeRefSyntax& MakeRefSyntax::refType(GlrRefType value) { node->refType = 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; } MakeRule& MakeRule::type(const vl::WString& value) { node->type.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; } /*********************************************************************** MakeSwitchItem ***********************************************************************/ MakeSwitchItem& MakeSwitchItem::name(const vl::WString& value) { node->name.value = value; return *this; } MakeSwitchItem& MakeSwitchItem::value(GlrSwitchValue value) { node->value = value; return *this; } /*********************************************************************** MakeSyntaxFile ***********************************************************************/ MakeSyntaxFile& MakeSyntaxFile::rules(const vl::Ptr& value) { node->rules.Add(value); return *this; } MakeSyntaxFile& MakeSyntaxFile::switches(const vl::Ptr& value) { node->switches.Add(value); return *this; } /*********************************************************************** MakeTestConditionBranch ***********************************************************************/ MakeTestConditionBranch& MakeTestConditionBranch::condition(const vl::Ptr& value) { node->condition = value; return *this; } MakeTestConditionBranch& MakeTestConditionBranch::syntax(const vl::Ptr& value) { node->syntax = value; return *this; } /*********************************************************************** MakeTestConditionSyntax ***********************************************************************/ MakeTestConditionSyntax& MakeTestConditionSyntax::branches(const vl::Ptr& value) { node->branches.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(GlrAndCondition* from, GlrAndCondition* 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->type = from->type; to->value = from->value; } void RuleAstVisitor::CopyFields(GlrClause* from, GlrClause* to) { } void RuleAstVisitor::CopyFields(GlrCondition* from, GlrCondition* 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(GlrLeftRecursionInjectClause* from, GlrLeftRecursionInjectClause* to) { CopyFields(static_cast(from), static_cast(to)); to->continuation = CopyNode(from->continuation.Obj()); to->rule = CopyNode(from->rule.Obj()); } void RuleAstVisitor::CopyFields(GlrLeftRecursionInjectContinuation* from, GlrLeftRecursionInjectContinuation* to) { to->configuration = from->configuration; for (auto&& listItem : from->flags) { to->flags.Add(CopyNode(listItem.Obj())); } for (auto&& listItem : from->injectionTargets) { to->injectionTargets.Add(CopyNode(listItem.Obj())); } to->type = from->type; } void RuleAstVisitor::CopyFields(GlrLeftRecursionPlaceholder* from, GlrLeftRecursionPlaceholder* to) { to->flag = from->flag; } void RuleAstVisitor::CopyFields(GlrLeftRecursionPlaceholderClause* from, GlrLeftRecursionPlaceholderClause* to) { CopyFields(static_cast(from), static_cast(to)); for (auto&& listItem : from->flags) { to->flags.Add(CopyNode(listItem.Obj())); } } 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(GlrNotCondition* from, GlrNotCondition* to) { CopyFields(static_cast(from), static_cast(to)); to->condition = CopyNode(from->condition.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(GlrOrCondition* from, GlrOrCondition* to) { CopyFields(static_cast(from), static_cast(to)); to->first = CopyNode(from->first.Obj()); to->second = CopyNode(from->second.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(GlrPrefixMergeClause* from, GlrPrefixMergeClause* to) { CopyFields(static_cast(from), static_cast(to)); to->rule = CopyNode(from->rule.Obj()); } void RuleAstVisitor::CopyFields(GlrPushConditionSyntax* from, GlrPushConditionSyntax* to) { CopyFields(static_cast(from), static_cast(to)); for (auto&& listItem : from->switches) { to->switches.Add(CopyNode(listItem.Obj())); } to->syntax = CopyNode(from->syntax.Obj()); } void RuleAstVisitor::CopyFields(GlrRefCondition* from, GlrRefCondition* to) { CopyFields(static_cast(from), static_cast(to)); to->name = from->name; } void RuleAstVisitor::CopyFields(GlrRefSyntax* from, GlrRefSyntax* to) { CopyFields(static_cast(from), static_cast(to)); to->field = from->field; to->literal = from->literal; to->refType = from->refType; } 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; to->type = from->type; } 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(GlrSwitchItem* from, GlrSwitchItem* to) { to->name = from->name; to->value = from->value; } 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())); } for (auto&& listItem : from->switches) { to->switches.Add(CopyNode(listItem.Obj())); } } void RuleAstVisitor::CopyFields(GlrTestConditionBranch* from, GlrTestConditionBranch* to) { to->condition = CopyNode(from->condition.Obj()); to->syntax = CopyNode(from->syntax.Obj()); } void RuleAstVisitor::CopyFields(GlrTestConditionSyntax* from, GlrTestConditionSyntax* to) { CopyFields(static_cast(from), static_cast(to)); for (auto&& listItem : from->branches) { to->branches.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(GlrSwitchItem* node) { auto newNode = vl::Ptr(new GlrSwitchItem); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrTestConditionBranch* node) { auto newNode = vl::Ptr(new GlrTestConditionBranch); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrAssignment* node) { auto newNode = vl::Ptr(new GlrAssignment); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrLeftRecursionPlaceholder* node) { auto newNode = vl::Ptr(new GlrLeftRecursionPlaceholder); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrLeftRecursionInjectContinuation* node) { auto newNode = vl::Ptr(new GlrLeftRecursionInjectContinuation); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrRule* node) { auto newNode = vl::Ptr(new GlrRule); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrSyntaxFile* node) { auto newNode = vl::Ptr(new GlrSyntaxFile); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrRefCondition* node) { auto newNode = vl::Ptr(new GlrRefCondition); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrNotCondition* node) { auto newNode = vl::Ptr(new GlrNotCondition); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrAndCondition* node) { auto newNode = vl::Ptr(new GlrAndCondition); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrOrCondition* node) { auto newNode = vl::Ptr(new GlrOrCondition); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrRefSyntax* node) { auto newNode = vl::Ptr(new GlrRefSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrUseSyntax* node) { auto newNode = vl::Ptr(new GlrUseSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrLoopSyntax* node) { auto newNode = vl::Ptr(new GlrLoopSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrOptionalSyntax* node) { auto newNode = vl::Ptr(new GlrOptionalSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrSequenceSyntax* node) { auto newNode = vl::Ptr(new GlrSequenceSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrAlternativeSyntax* node) { auto newNode = vl::Ptr(new GlrAlternativeSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrPushConditionSyntax* node) { auto newNode = vl::Ptr(new GlrPushConditionSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrTestConditionSyntax* node) { auto newNode = vl::Ptr(new GlrTestConditionSyntax); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrCreateClause* node) { auto newNode = vl::Ptr(new GlrCreateClause); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrPartialClause* node) { auto newNode = vl::Ptr(new GlrPartialClause); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrReuseClause* node) { auto newNode = vl::Ptr(new GlrReuseClause); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrLeftRecursionPlaceholderClause* node) { auto newNode = vl::Ptr(new GlrLeftRecursionPlaceholderClause); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrLeftRecursionInjectClause* node) { auto newNode = vl::Ptr(new GlrLeftRecursionInjectClause); CopyFields(node, newNode.Obj()); this->result = newNode; } void RuleAstVisitor::Visit(GlrPrefixMergeClause* node) { auto newNode = vl::Ptr(new GlrPrefixMergeClause); CopyFields(node, newNode.Obj()); this->result = newNode; } vl::Ptr RuleAstVisitor::CopyNode(GlrCondition* node) { if (!node) return nullptr; node->Accept(static_cast(this)); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrSyntax* node) { if (!node) return nullptr; node->Accept(static_cast(this)); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrClause* node) { if (!node) return nullptr; node->Accept(static_cast(this)); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrSwitchItem* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrTestConditionBranch* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrAssignment* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrLeftRecursionPlaceholder* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrLeftRecursionInjectContinuation* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrRule* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrSyntaxFile* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrAlternativeSyntax* node) { if (!node) return nullptr; return CopyNode(static_cast(node)).Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrAndCondition* 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(GlrLeftRecursionInjectClause* node) { if (!node) return nullptr; return CopyNode(static_cast(node)).Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrLeftRecursionPlaceholderClause* 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(GlrNotCondition* 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(GlrOrCondition* 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(GlrPrefixMergeClause* node) { if (!node) return nullptr; return CopyNode(static_cast(node)).Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrPushConditionSyntax* node) { if (!node) return nullptr; return CopyNode(static_cast(node)).Cast(); } vl::Ptr RuleAstVisitor::CopyNode(GlrRefCondition* 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(GlrTestConditionSyntax* 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 { /*********************************************************************** ConditionVisitor ***********************************************************************/ // Visitor Members ----------------------------------- void ConditionVisitor::Visit(GlrRefCondition* node) { } void ConditionVisitor::Visit(GlrNotCondition* node) { } void ConditionVisitor::Visit(GlrAndCondition* node) { } void ConditionVisitor::Visit(GlrOrCondition* node) { } /*********************************************************************** SyntaxVisitor ***********************************************************************/ // Visitor Members ----------------------------------- void SyntaxVisitor::Visit(GlrRefSyntax* 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) { } void SyntaxVisitor::Visit(GlrPushConditionSyntax* node) { } void SyntaxVisitor::Visit(GlrTestConditionSyntax* node) { } /*********************************************************************** ClauseVisitor ***********************************************************************/ // Visitor Members ----------------------------------- void ClauseVisitor::Visit(GlrCreateClause* node) { } void ClauseVisitor::Visit(GlrPartialClause* node) { } void ClauseVisitor::Visit(GlrReuseClause* node) { } void ClauseVisitor::Visit(GlrLeftRecursionPlaceholderClause* node) { } void ClauseVisitor::Visit(GlrLeftRecursionInjectClause* node) { } void ClauseVisitor::Visit(GlrPrefixMergeClause* 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(GlrAndCondition* 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"type"); switch (node->type) { case vl::glr::parsergen::GlrAssignmentType::Strong: WriteString(L"Strong"); break; case vl::glr::parsergen::GlrAssignmentType::Weak: WriteString(L"Weak"); break; default: WriteNull(); } EndField(); BeginField(L"value"); WriteToken(node->value); EndField(); } void RuleAstVisitor::PrintFields(GlrClause* node) { } void RuleAstVisitor::PrintFields(GlrCondition* 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(GlrLeftRecursionInjectClause* node) { BeginField(L"continuation"); Print(node->continuation.Obj()); EndField(); BeginField(L"rule"); Print(node->rule.Obj()); EndField(); } void RuleAstVisitor::PrintFields(GlrLeftRecursionInjectContinuation* node) { BeginField(L"configuration"); switch (node->configuration) { case vl::glr::parsergen::GlrLeftRecursionConfiguration::Multiple: WriteString(L"Multiple"); break; case vl::glr::parsergen::GlrLeftRecursionConfiguration::Single: WriteString(L"Single"); break; default: WriteNull(); } EndField(); BeginField(L"flags"); BeginArray(); for (auto&& listItem : node->flags) { BeginArrayItem(); Print(listItem.Obj()); EndArrayItem(); } EndArray(); EndField(); BeginField(L"injectionTargets"); BeginArray(); for (auto&& listItem : node->injectionTargets) { BeginArrayItem(); Print(listItem.Obj()); EndArrayItem(); } EndArray(); EndField(); BeginField(L"type"); switch (node->type) { case vl::glr::parsergen::GlrLeftRecursionInjectContinuationType::Optional: WriteString(L"Optional"); break; case vl::glr::parsergen::GlrLeftRecursionInjectContinuationType::Required: WriteString(L"Required"); break; default: WriteNull(); } EndField(); } void RuleAstVisitor::PrintFields(GlrLeftRecursionPlaceholder* node) { BeginField(L"flag"); WriteToken(node->flag); EndField(); } void RuleAstVisitor::PrintFields(GlrLeftRecursionPlaceholderClause* node) { BeginField(L"flags"); BeginArray(); for (auto&& listItem : node->flags) { BeginArrayItem(); Print(listItem.Obj()); EndArrayItem(); } EndArray(); 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(GlrNotCondition* node) { BeginField(L"condition"); Print(node->condition.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(GlrOrCondition* node) { BeginField(L"first"); Print(node->first.Obj()); EndField(); BeginField(L"second"); Print(node->second.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(GlrPrefixMergeClause* node) { BeginField(L"rule"); Print(node->rule.Obj()); EndField(); } void RuleAstVisitor::PrintFields(GlrPushConditionSyntax* node) { BeginField(L"switches"); BeginArray(); for (auto&& listItem : node->switches) { BeginArrayItem(); Print(listItem.Obj()); EndArrayItem(); } EndArray(); EndField(); BeginField(L"syntax"); Print(node->syntax.Obj()); EndField(); } void RuleAstVisitor::PrintFields(GlrRefCondition* node) { BeginField(L"name"); WriteToken(node->name); EndField(); } void RuleAstVisitor::PrintFields(GlrRefSyntax* node) { BeginField(L"field"); WriteToken(node->field); EndField(); BeginField(L"literal"); WriteToken(node->literal); EndField(); BeginField(L"refType"); switch (node->refType) { case vl::glr::parsergen::GlrRefType::ConditionalLiteral: WriteString(L"ConditionalLiteral"); break; case vl::glr::parsergen::GlrRefType::Id: WriteString(L"Id"); break; case vl::glr::parsergen::GlrRefType::Literal: WriteString(L"Literal"); break; default: WriteNull(); } 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(); BeginField(L"type"); WriteToken(node->type); 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(GlrSwitchItem* node) { BeginField(L"name"); WriteToken(node->name); EndField(); BeginField(L"value"); switch (node->value) { case vl::glr::parsergen::GlrSwitchValue::False: WriteString(L"False"); break; case vl::glr::parsergen::GlrSwitchValue::True: WriteString(L"True"); break; default: WriteNull(); } 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(); BeginField(L"switches"); BeginArray(); for (auto&& listItem : node->switches) { BeginArrayItem(); Print(listItem.Obj()); EndArrayItem(); } EndArray(); EndField(); } void RuleAstVisitor::PrintFields(GlrTestConditionBranch* node) { BeginField(L"condition"); Print(node->condition.Obj()); EndField(); BeginField(L"syntax"); Print(node->syntax.Obj()); EndField(); } void RuleAstVisitor::PrintFields(GlrTestConditionSyntax* node) { BeginField(L"branches"); BeginArray(); for (auto&& listItem : node->branches) { BeginArrayItem(); Print(listItem.Obj()); EndArrayItem(); } EndArray(); EndField(); } void RuleAstVisitor::PrintFields(GlrUseSyntax* node) { BeginField(L"name"); WriteToken(node->name); EndField(); } void RuleAstVisitor::Visit(GlrRefCondition* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"RefCondition", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Visit(GlrNotCondition* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"NotCondition", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Visit(GlrAndCondition* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"AndCondition", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Visit(GlrOrCondition* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"OrCondition", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } 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(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(GlrPushConditionSyntax* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"PushConditionSyntax", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Visit(GlrTestConditionSyntax* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"TestConditionSyntax", 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(); } void RuleAstVisitor::Visit(GlrLeftRecursionPlaceholderClause* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"LeftRecursionPlaceholderClause", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Visit(GlrLeftRecursionInjectClause* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"LeftRecursionInjectClause", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Visit(GlrPrefixMergeClause* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"PrefixMergeClause", node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); } RuleAstVisitor::RuleAstVisitor(vl::stream::StreamWriter& _writer) : vl::glr::JsonVisitorBase(_writer) { } void RuleAstVisitor::Print(GlrCondition* node) { if (!node) { WriteNull(); return; } node->Accept(static_cast(this)); } 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(GlrSwitchItem* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"SwitchItem", node); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Print(GlrTestConditionBranch* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"TestConditionBranch", node); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Print(GlrAssignment* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"Assignment", node); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Print(GlrLeftRecursionPlaceholder* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"LeftRecursionPlaceholder", node); PrintFields(static_cast(node)); EndObject(); } void RuleAstVisitor::Print(GlrLeftRecursionInjectContinuation* node) { if (!node) { WriteNull(); return; } BeginObject(); WriteType(L"LeftRecursionInjectContinuation", 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(GlrAndCondition* node) {} void RuleAstVisitor::Traverse(GlrAssignment* node) {} void RuleAstVisitor::Traverse(GlrClause* node) {} void RuleAstVisitor::Traverse(GlrCondition* node) {} void RuleAstVisitor::Traverse(GlrCreateClause* node) {} void RuleAstVisitor::Traverse(GlrLeftRecursionInjectClause* node) {} void RuleAstVisitor::Traverse(GlrLeftRecursionInjectContinuation* node) {} void RuleAstVisitor::Traverse(GlrLeftRecursionPlaceholder* node) {} void RuleAstVisitor::Traverse(GlrLeftRecursionPlaceholderClause* node) {} void RuleAstVisitor::Traverse(GlrLoopSyntax* node) {} void RuleAstVisitor::Traverse(GlrNotCondition* node) {} void RuleAstVisitor::Traverse(GlrOptionalSyntax* node) {} void RuleAstVisitor::Traverse(GlrOrCondition* node) {} void RuleAstVisitor::Traverse(GlrPartialClause* node) {} void RuleAstVisitor::Traverse(GlrPrefixMergeClause* node) {} void RuleAstVisitor::Traverse(GlrPushConditionSyntax* node) {} void RuleAstVisitor::Traverse(GlrRefCondition* node) {} void RuleAstVisitor::Traverse(GlrRefSyntax* node) {} void RuleAstVisitor::Traverse(GlrReuseClause* node) {} void RuleAstVisitor::Traverse(GlrRule* node) {} void RuleAstVisitor::Traverse(GlrSequenceSyntax* node) {} void RuleAstVisitor::Traverse(GlrSwitchItem* node) {} void RuleAstVisitor::Traverse(GlrSyntax* node) {} void RuleAstVisitor::Traverse(GlrSyntaxFile* node) {} void RuleAstVisitor::Traverse(GlrTestConditionBranch* node) {} void RuleAstVisitor::Traverse(GlrTestConditionSyntax* node) {} void RuleAstVisitor::Traverse(GlrUseSyntax* node) {} void RuleAstVisitor::Finishing(vl::glr::ParsingAstBase* node) {} void RuleAstVisitor::Finishing(GlrAlternativeSyntax* node) {} void RuleAstVisitor::Finishing(GlrAndCondition* node) {} void RuleAstVisitor::Finishing(GlrAssignment* node) {} void RuleAstVisitor::Finishing(GlrClause* node) {} void RuleAstVisitor::Finishing(GlrCondition* node) {} void RuleAstVisitor::Finishing(GlrCreateClause* node) {} void RuleAstVisitor::Finishing(GlrLeftRecursionInjectClause* node) {} void RuleAstVisitor::Finishing(GlrLeftRecursionInjectContinuation* node) {} void RuleAstVisitor::Finishing(GlrLeftRecursionPlaceholder* node) {} void RuleAstVisitor::Finishing(GlrLeftRecursionPlaceholderClause* node) {} void RuleAstVisitor::Finishing(GlrLoopSyntax* node) {} void RuleAstVisitor::Finishing(GlrNotCondition* node) {} void RuleAstVisitor::Finishing(GlrOptionalSyntax* node) {} void RuleAstVisitor::Finishing(GlrOrCondition* node) {} void RuleAstVisitor::Finishing(GlrPartialClause* node) {} void RuleAstVisitor::Finishing(GlrPrefixMergeClause* node) {} void RuleAstVisitor::Finishing(GlrPushConditionSyntax* node) {} void RuleAstVisitor::Finishing(GlrRefCondition* node) {} void RuleAstVisitor::Finishing(GlrRefSyntax* node) {} void RuleAstVisitor::Finishing(GlrReuseClause* node) {} void RuleAstVisitor::Finishing(GlrRule* node) {} void RuleAstVisitor::Finishing(GlrSequenceSyntax* node) {} void RuleAstVisitor::Finishing(GlrSwitchItem* node) {} void RuleAstVisitor::Finishing(GlrSyntax* node) {} void RuleAstVisitor::Finishing(GlrSyntaxFile* node) {} void RuleAstVisitor::Finishing(GlrTestConditionBranch* node) {} void RuleAstVisitor::Finishing(GlrTestConditionSyntax* node) {} void RuleAstVisitor::Finishing(GlrUseSyntax* node) {} void RuleAstVisitor::Visit(GlrRefCondition* 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(GlrNotCondition* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(static_cast(node)); InspectInto(node->condition.Obj()); Finishing(static_cast(node)); Finishing(static_cast(node)); Finishing(static_cast(node)); } void RuleAstVisitor::Visit(GlrAndCondition* 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(GlrOrCondition* 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(GlrRefSyntax* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(node->field); Traverse(node->literal); 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(GlrPushConditionSyntax* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(static_cast(node)); for (auto&& listItem : node->switches) { InspectInto(listItem.Obj()); } InspectInto(node->syntax.Obj()); Finishing(static_cast(node)); Finishing(static_cast(node)); Finishing(static_cast(node)); } void RuleAstVisitor::Visit(GlrTestConditionSyntax* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(static_cast(node)); for (auto&& listItem : node->branches) { InspectInto(listItem.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::Visit(GlrLeftRecursionPlaceholderClause* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(static_cast(node)); for (auto&& listItem : node->flags) { InspectInto(listItem.Obj()); } Finishing(static_cast(node)); Finishing(static_cast(node)); Finishing(static_cast(node)); } void RuleAstVisitor::Visit(GlrLeftRecursionInjectClause* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(static_cast(node)); InspectInto(node->continuation.Obj()); InspectInto(node->rule.Obj()); Finishing(static_cast(node)); Finishing(static_cast(node)); Finishing(static_cast(node)); } void RuleAstVisitor::Visit(GlrPrefixMergeClause* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(static_cast(node)); InspectInto(node->rule.Obj()); Finishing(static_cast(node)); Finishing(static_cast(node)); Finishing(static_cast(node)); } void RuleAstVisitor::InspectInto(GlrCondition* node) { if (!node) return; node->Accept(static_cast(this)); } 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(GlrSwitchItem* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(node->name); Finishing(static_cast(node)); Finishing(static_cast(node)); } void RuleAstVisitor::InspectInto(GlrTestConditionBranch* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); InspectInto(node->condition.Obj()); InspectInto(node->syntax.Obj()); Finishing(static_cast(node)); Finishing(static_cast(node)); } 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(GlrLeftRecursionPlaceholder* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); Traverse(node->flag); Finishing(static_cast(node)); Finishing(static_cast(node)); } void RuleAstVisitor::InspectInto(GlrLeftRecursionInjectContinuation* node) { if (!node) return; Traverse(static_cast(node)); Traverse(static_cast(node)); for (auto&& listItem : node->flags) { InspectInto(listItem.Obj()); } for (auto&& listItem : node->injectionTargets) { InspectInto(listItem.Obj()); } 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); Traverse(node->type); 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()); } for (auto&& listItem : node->switches) { 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 = 14441; // 198067 bytes before compressing static const vl::vint dataBlock = 256; static const vl::vint dataRemain = 105; static const vl::vint dataSolidRows = 56; static const vl::vint dataRows = 57; static const char* compressed[] = { "\xB3\x05\x03\x00\x61\x38\x00\x00\x25\x00\x01\x82\x80\x08\x0B\x82\x81\x82\x06\x89\x82\x88\x0A\x86\x06\x84\x0A\x0A\x97\x0A\x9C\x0A\x82\x12\x85\x13\x0A\xAD\x0A\x92\x1A\x81\x2A\x84\x2B\x0A\xDC\x0A\x9F\x2A\x83\x32\x84\x34\x0A\x8C\x4A\x8F\x4A\x82\x4A\x84\x4B\x0A\xA1\x4A\x87\x5A\x86\x56\x84\x5B\x0A\xFD\x14\x86\x8F\x7D\x9E\x9F\x9E\x0A\x80\x3F\x9F\x91\xA3\xA2\x9F\xA2\x46\xFF\x48\xA6\xAB\xA3\xA1\xA6\xA2\x0A\xC9\x8A\xB1\xA9\xA7\xA7\xA3\xA0\x0A\x81\x14\xAC\xAB\xAE\xA5\xAE\xA8\x09\xD2\x96\xA0\xAF\xAF\xA9\xB1\xAA\x65\xE4\xA7\xBC\xAB\xB6\xAD\xB6\xB0\x3C\xE8\xAF\xA6\xB1\xBC\xB6\x82\xAD\x09\xF8\xB5\xAE\xBB\xB8\xBB\x80\xB1\x69\xD3\xB3\xAA\xBD\xBC\xBB\xBE\xB9\x85\x84\xC3\x82\x09\xA9\xC3\xB0\xC1\x89\x90\xC7\xD6\xB3\xCC\xBD\xCA\xBF\x02\x80\xC3\xD2\xC9\xC8\xC7\xCA\xC3\x9D\x94\xE1\xD6\xC3\xD0\xCD\x80\xCD\x91\x8F\xEA\xCE\xCC\xD3\xCF\xD4\xD7\xAD\xA9\xF1\xDF\xCA\xC5\xD0\xD1\xD3\x9E\xB6\xF5\xD8\xD2\xD4\xDC\xD2\xDF\xA6\xC2\xB9\xC0\xE7\xDA\xE1\xDE\xE3\xBF\xC8\xC1\xE8\xD4\xDC\xCC\xE3\xDD\xCA\xC5\xCC\xFA\xDE\xE1\xE8\xE9\xE9\xCF\xD5\xD8\xF6", "\xEA\xEB\xE0\xEF\xD7\xB2\xB0\xC9\x83\x0D\xC2\xF1\xF1\xF3\xCD\xE0\xE9\xF3\xD4\xEA\xF5\xF6\xF6\xD9\xEE\xF1\xEA\x84\x05\xF0\xF5\xF7\xE6\xEB\xF9\xF8\xF7\xFB\xF9\x85\x02\xF6\x7A\x7D\x7F\x77\xF0\x40\x06\x01\x80\xFC\x42\x8A\x81\x82\x0C\xBE\x73\x83\x76\x10\x9E\x71\x87\x71\x13\x89\x75\x87\x72\x12\x99\x84\x86\x86\x16\x9C\x88\x87\x86\x20\x9D\x81\x8B\x87\x22\xA5\x84\x8B\x89\xD2\x5E\x89\x8B\x88\x2B\x89\x77\x00\x82\x0E\x8B\x81\x8D\x83\x04\xBB\x73\x8F\x8D\x35\x8F\x8A\x8B\x75\x3B\x9D\x7C\x88\x8F\x3F\xBE\x86\x89\x8B\x28\x80\x93\x92\x91\x45\x82\x99\x92\x7C\x39\xB2\x8D\x90\x8D\x17\x84\x92\x94\x92\xC5\x4C\x49\x5D\x81\x51\x94\x9A\x96\x92\x53\x9C\x9B\x94\x93\x59\x9E\x92\x98\x98\x3D\xA4\x91\x92\x99\x47\xA3\x98\x95\x99\x6B\xA7\x9D\x99\x9A\x68\x8B\x9F\x9A\x9C\x36\x8F\x98\x8D\x98\x71\x9D\x99\x9C\x74\x09\x30\x86\x9F\x9F\x78\xB3\x9A\x9E\xA0\x5F\x84\xAA\x99\x9D\x81\x88\xAC\x9A\xA2\x6E\x8C\xA0\x9E\xA1\x7B\x87\xAA\x8D\xA3\x93\x8F\xA5\x9E\x02\x7E\x89\xA5\xA4\x9D\x9B\x83\xAE\xA0\xA7\x4E\x9A\xA3\x43\x02\x99\x8B\xAD\xA5\xA1\x9F\x9E\xA6\x40\x03", "\xA5\x94\xA1\xAA\xA9\xAF\xAE\xA0\x94\xAC\xB3\xB2\xA1\x41\x03\xAD\x96\xA7\xAA\xA4\xB1\xBA\xAD\xAC\xA8\xB5\xBE\xA2\x42\x43\x57\xA9\xA8\xAB\xAE\x91\x8C\x9F\x01\xAE\xC0\xB7\x94\xAE\xB3\xB6\x80\xAF\xB2\xB4\xD1\xA2\xA1\xB1\xB3\xD4\x82\xB0\xB6\xB6\xD9\x98\xB6\xB7\xB6\xDE\x93\xBF\xB5\xB7\xAA\xBF\xA5\xBB\xB5\xE7\xA0\xB9\xB8\xB9\xC7\x8E\x90\x04\xB3\xEB\xA3\xB2\xBE\xB8\xF4\x95\xB3\xB5\x04\xF0\xAD\xB8\xBA\xBE\xEA\xBC\xB0\x02\x04\xF9\xBC\xAB\xBD\x75\x13\x3E\x90\x45\xB1\xC8\x90\xAA\xC2\xB1\x02\xFD\xBD\xC0\xBB\x0F\xF3\xB6\xBF\xC4\xDC\x92\xC5\xC5\xBD\x17\xD4\xC1\xBA\xC6\xF1\x98\xCB\xC5\xC6\x20\xDF\xC2\xC9\xC7\xD1\x95\x01\xC1\xB2\x0B\xC9\xCC\xC0\xCA\x2B\xE9\xC6\xBA\xBF\xE3\x96\x0E\x9E\x44\x08\xEF\xC1\xC6\xC7\x24\xE1\xC9\xCF\xC8\x30\xF8\xCD\xCC\xC7\x3F\xFA\xC1\xD0\xCF\x37\xC0\xD5\xD2\xD0\x47\xC4\xDC\xCA\xCA\x03\x88\x47\x5E\xCB\x03\xCB\xD6\xCE\xD4\x51\xD0\xD1\x41\x06\x27\xD6\xD0\xC4\xD5\x38\x9A\x09\xD5\xCB\x60\xCC\xD3\xD6\xD6\x16\xCA\xD4\xDA\xCF\x49\xFB\xCA\xDB\xD0\x6B\xE9\xDC\xDB\xDB\x6E\xF1\xDC\xD7\xD6\x67\xC6\xD3\xDF\x76\x1B", "\x1F\xD2\xD9\xD5\x61\xE3\xDD\xDC\xDF\x03\xBB\x4F\xD3\xDF\x0E\xF7\xD3\xB5\x07\x7A\xFE\xD3\x82\x07\x7E\x9F\x09\xE0\xE0\x8A\xD1\xE0\xE7\xE4\x85\xF5\xD8\xD2\xE1\x76\xD6\xE6\xD8\xE1\x74\xDC\xE5\xD9\xDB\x98\xD7\xEA\xE4\xE8\xA3\xF0\xD3\xDC\x08\x8F\xD5\xEE\xE4\xDA\xA1\xDB\xEB\xDE\xEA\xAF\xC0\x01\x0A\x9F\x16\x75\xC4\xE5\xE7\xB1\xDF\xE6\xE9\xE9\x72\xFC\xED\xE8\xE9\xAB\xD9\xE1\xF2\xE8\xC3\xEE\xE2\xE4\xEC\xC7\xF8\xE3\x43\x08\xA9\xCA\xF7\xEE\xEE\xBD\xC5\xFB\xB8\x09\xCD\xD0\xFF\xEE\xBF\x00\x76\xE8\xF3\xF3\xAC\xFE\xEE\xF6\xF4\xBB\xE0\xF1\xF5\xEE\xDD\xE2\xF7\xF7\xF8\xC9\xD6\xFA\xD6\x09\xD5\xE5\xF4\xFA\xF0\xEF\xC4\xF1\xFE\xF1\xDC\xF0\xF9\xFA\xFB\xF7\xF6\xF5\xFE\xFC\xF9\xFC\xFB\xFC\xFD\xDB\x61\x82\xF3\x02\x8A\x7C\xF3\x57\x25\x7D\xFA\x64\x83\xB4\x28\x08\x80\xFF\x4A\x81\x81\x03\x91\x81\x01\xF3\x70\x78\x0A\xA1\x7E\x82\xE8\x7F\x7D\x05\xFD\x70\x80\x09\xB8\x7A\x83\x17\x9C\x83\x06\xA0\x89\x83\x07\x8E\x86\x83\x10\x93\x82\x08\xD0\x39\x05\x06\x9D\x82\x05\x2E\x83\x86\x09\x9D\x8A\x84\x12\xA7\x7F\x86\xDF\x78\x80\x0E\x86\x8C\x87\xD8\x6B\x01", "\x86\x21\x96\x85\x0E\xAB\x85\x84\x14\xA7\x85\x86\x33\x92\x86\x11\xB4\x8F\x83\x24\x81\x8E\x89\xD5\x2C\x04\x10\xC5\x88\x89\x25\x8A\x8D\x8A\x58\x8D\x8A\x15\xCF\x8B\x8A\x2A\x9A\x89\x8B\x29\x9F\x8A\x18\xE1\x84\x8D\x23\xA3\x8E\x8C\x65\x8C\x89\x1A\xD7\x87\x8C\x35\xA8\x8F\x8D\x6E\x91\x8F\xBA\x1A\x2A\x7B\x08\xAE\x03\x8A\x3B\x9A\x86\x42\x2F\x08\x8F\x21\x82\x8D\x87\x44\x99\x8D\x20\xFE\x80\x8A\x41\x82\x20\x06\x7D\x80\x93\x1F\x86\x21\x07\x44\xB1\x74\x23\x75\x80\x8C\x1C\xEC\x8B\x8C\x2E\x92\x92\x8E\x96\x8D\x8C\x25\x93\x99\x93\x4A\x9E\x8E\x93\x86\x85\x90\x21\xDD\x81\x29\x19\x0D\x7C\x06\x8E\x83\x92\x22\xA2\x9B\x94\x52\xA3\x97\x92\x9B\x98\x59\x0D\x29\x9B\x90\x55\xBA\x8D\x95\xB0\x9D\x90\x27\x9F\x9B\x97\x50\xAE\x90\x97\x9A\x9A\x94\x26\xBC\x93\x98\x5F\xB9\x94\x98\xB1\x89\x9A\x30\xEB\x56\x07\xE6\x77\x05\x79\x38\x0D\x79\x0E\x7E\x4A\x06\x5A\xAC\x91\x76\x3B\x16\x98\x00\x3C\x0E\x4F\x1E\x1A\x9B\x5C\x3E\x1E\x4F\x0F\x7E\x40\x08\x6D\x81\x0F\x9B\xC1\x88\x9B\x32\xEB\x9A\x9D\x76\x86\x99\x9D\xEF\x80\x97\x2B\xF0\x93\x9E\x79\x9C\x72\x08\xE8\x96", "\x9F\x2D\xFB\x96\x97\x7E\xB5\x97\x9F\xD7\x9E\x9D\x40\xB7\x73\x09\x7C\xBD\x95\x9E\x07\xB5\x4C\x11\x06\xA5\x98\xAD\x45\x0C\xA1\xCA\x8E\x9C\x42\x8D\xA0\x98\x7D\x82\xA7\x97\xFC\x80\xA0\x46\x97\xA3\x5C\x23\x10\xA4\x9D\xF1\x89\xA1\x46\x83\xA4\xA5\x8D\x9A\xA7\x98\x21\xBD\x83\x11\x1F\xA2\xA3\x8A\xA2\xA4\xA3\xF4\x8E\xA4\x45\xA3\xA6\xA5\x92\xA8\xA3\xA2\x11\xAC\x48\x12\x4D\x79\x09\xE6\x4A\x0D\x79\x4B\x1E\x4C\x13\x2C\xAC\x49\x26\x1A\x9E\x09\xDA\x8F\x0A\x9F\x50\x04\xA9\x02\x5E\x25\x8E\x52\x1E\x4F\x14\x4D\xA2\xA7\x9C\xB8\xA0\xA4\x57\xA5\x88\x15\x54\xA4\xA7\x9B\x95\xA8\xAB\x5F\xAD\xA5\x57\xB1\xA3\xAC\x8B\xA7\xA4\xAC\x30\xB0\x81\x15\x7E\x40\x25\x3A\x97\x0C\xAB\x69\xAF\xA7\x59\xE6\xA6\xA6\xB4\xB3\xAA\xAE\x75\xB4\xAD\x4D\x80\x08\x0A\xB8\xB7\xAB\xA6\x71\xA0\xB3\x5F\xD6\xA1\xAD\x94\x84\xB4\xA6\x59\x1E\xAD\x5E\xF8\xAB\xAE\xAF\xA5\xAC\xB1\x8E\xA1\xB3\x61\x97\xAA\x0A\xC5\x8D\xB6\xAE\x8B\xA2\xB1\x66\x93\xB3\xB0\xB0\x8F\xB2\xB3\x97\xBA\xAD\x15\xDB\x0D\x78\x91\x11\x96\x3B\x5D\x0D\x7A\x17\x7E\x44\x25\xD3\xA2\xB2\x8B\x60\x1A\x99\x18\x7E", "\x42\x0C\xCB\x9B\x3E\x24\x75\x84\x0E\x9F\x65\x06\xB6\xCC\xA1\xB0\xB2\xBE\xB1\xB1\x67\xE2\xA2\xB2\xCF\x85\xBC\xB8\xC3\xA6\xB2\x71\xC9\xB9\xAA\xE5\x88\xBB\xB3\x5C\x86\x0D\x6F\xC7\x37\x0D\xE9\x80\xBF\xB5\xD8\xB7\xBA\x76\xA0\xB2\xB8\xE8\x8F\xBF\xB7\xDC\xA1\xBA\x78\xD9\xBD\x82\x94\x2E\xB4\x5B\x69\x16\xB9\x78\xC7\x3A\x0C\xF5\x9C\xB6\xBB\xCE\xB1\xBD\x73\xF3\xBC\x73\x35\x2E\xBB\xB9\x38\x4C\x0F\x7D\xDF\xBD\xBB\xBD\xAD\x0D\x79\x6E\x0D\x7B\x1B\x4D\x70\x0E\x3F\x71\x0B\xBF\xBE\x92\x0E\x36\xF3\x0E\x4E\x3A\x08\xC2\x21\x75\x1E\x4E\x1D\x7E\x47\x0E\x6D\xB8\x0F\xC1\x85\xB4\xBF\x67\xEF\xB0\xBC\x0E\xFD\xBF\xC3\xE3\xBB\xBA\x87\xDA\x89\x0E\x0C\xDB\xC0\xBF\x1D\xC8\xC4\x88\xE4\xB3\xC4\x16\xEA\xC1\xC4\xEB\xA9\x3A\x1E\x4D\x7B\x0E\x13\xC7\xBA\xBE\x19\xD9\xC7\x89\xFC\xBE\x3A\x3E\x36\xC4\xB9\x3A\xD7\xC6\x86\xC2\xCC\x73\x3E\x3F\xC0\xBE\x43\xC0\xCB\x8E\xB8\xCB\xC9\x24\xC8\xC9\xC8\x4A\xC4\xC9\xEC\x7E\x07\xC9\x14\xFC\xC6\xC5\x57\xC2\xC4\x17\xFF\x05\xCB\x15\xDA\xC9\xCB\x31\xC1\xCD\x8B\xDF\xCC\xC8\x29\xE6\xCA\xA3\x80\x1D\xC8\x8C\xE3\xC8\x5B\x40", "\x2A\xCA\xAF\x82\x0F\xCC\x99\xCE\xC1\x83\x41\x32\xCA\xCC\x28\xC4\x13\x9D\xEC\xCC\xCF\x17\xD8\xCE\x97\x85\x1B\xCE\x9F\xF3\xC5\x4E\x43\x02\xD7\xBB\x87\x07\xD1\x99\xD1\xC7\x76\x44\x0A\xD4\xCE\x55\x89\x13\xA3\xD0\xCF\xC9\x01\x4A\x13\xD2\x4D\xD4\xD2\x95\x8B\xD5\xD3\x33\xDD\xD4\xD1\x9F\xC1\xD7\x5E\x8B\x1D\x78\x95\x27\xB9\x38\x8D\x0D\x7A\x23\x7E\x4C\x25\x53\xFD\xCD\x88\x90\x1A\x99\x24\x7E\x4E\x24\x57\xE8\xC3\x12\x7E\x54\x12\x9F\x15\x18\xD2\x4F\xDB\xD4\xCE\x30\x36\xD4\x98\xEB\x57\x13\x5E\xE0\xD7\xD7\x9A\xDE\xC8\x9E\xD5\x38\x13\xE6\x59\x15\x79\x9A\x0D\x7B\x26\x7E\x4C\x12\x63\xC2\x85\x13\xDA\x9E\x12\x9F\x1F\x15\xCA\x50\x3E\x4A\x26\x75\x82\x16\xB5\xC8\xD9\xD3\x72\xC3\x23\x14\xE3\xCA\xDB\xAB\x9C\xD4\xDC\x27\x64\x11\xDD\x6B\xC3\xD3\xB2\xEC\xDA\xDC\x79\xEB\xDB\x94\xA5\x10\xDF\x9F\x90\xD1\xDF\x61\xF6\xDF\xDF\xFE\xDF\xBA\x29\x7A\xD4\xD0\x73\xC7\xDB\x5C\x34\x22\xD8\xBD\xFD\xDB\xE1\x7D\xC9\xDC\xE1\xFC\xCE\xE2\xC1\xA2\xD5\xDF\x87\x68\x15\xCA\xA9\x04\xE3\xBC\x91\xE5\xE0\x5F\xD5\xE5\xE1\x1D\xF4\x46\x2A\x1A\xE7\xDF\x87\xD2\xE6\xE3", "\x10\xE6\xE5\xC8\x94\xE9\xE4\x9A\xAB\x14\xE4\x00\xE0\xE7\xC6\xAA\xE3\xE7\x89\xED\xDC\x46\xAC\x0D\x79\x2B\x4D\x76\x26\x85\xCA\x27\x15\x7E\x50\x14\xCC\x8F\x61\x16\x6D\xB2\x16\x4F\xB3\x15\xC8\x2D\x7E\x45\x16\x3F\x78\x26\xE7\x34\xE5\xE5\xEC\x37\x1D\x78\x5C\x0D\x79\x17\xCD\x7A\x16\x9F\x3B\x13\xE8\x26\x7C\x12\x9B\xBD\x1E\x4E\x2F\x55\xCF\x16\x3F\x40\x1E\x4F\xC1\x1D\xE8\xC7\xB5\xE8\xE5\x93\xC7\xE5\xE5\x6D\xEB\xE7\xCD\xAC\xE7\x38\x61\x0D\x7B\x18\xCD\x64\x19\xF3\x45\x1E\x4E\x63\x2A\xED\x4E\xC7\x1A\x98\x32\x7E\x49\x19\x2A\xCA\x1E\x4F\xCB\x1E\x4C\x33\x5A\x9D\x18\x3F\x4E\x1F\xEF\x36\xFF\xE3\xDA\xD2\xE1\xEE\xB6\xC7\xDF\x19\x7E\x50\x18\xE4\x95\xF4\xF3\xB7\xEE\xEC\xEE\x72\xF2\xF1\xD4\xB1\xEA\x21\x68\x0D\x7A\x1A\xCD\x73\x19\xF3\x54\x1E\x4F\x6A\x1B\xF4\x46\xD6\x1A\x9B\x35\x7E\x48\x1B\x2A\xD9\x1E\x4F\xDA\x1E\x4F\x36\x2F\xF0\xF4\xCB\xFD\xF5\xF3\xBF\xE4\xF7\xE8\x81\xE2\xE6\xE0\xC0\x04\x1B\xCD\x7D\x19\xF3\x5E\x1D\x79\x6F\x3E\x48\x1C\xBC\xFF\x4D\x38\x5A\x92\x1C\x3F\x63\x1D\xCA\xE4\x1E\x4D\x39\x7E\x46\x1C\x6D\xA7\x1E\x4F\xE8\x11\xFA", "\xE8\x91\xF0\xEE\xCF\xE1\xF5\xFC\xC1\xE4\xFB\xE4\xC2\xF4\xFD\xCF\xC0\x01\x1D\xE2\xE8\xFF\x5E\xEA\x1E\x4F\x75\x31\xFE\xFD\xE3\xFC\xF0\xFB\xFA\xFA\xFD\xE1\xC5\xF8\xC5\xEC\x0D\x3C\xED\x0D\x3C\xEE\x0D\x3C\xEF\x0E\x27\xF0\x07\x7F\xC9\x11\x0F\xDA\x42\x0F\x7E\x23\x0F\x55\x64\x0F\x7E\x25\x0F\x7E\x26\x0F\x0A\x8E\x7B\x73\x79\x81\xF9\x76\x7E\x18\x8B\x81\x25\x57\x0F\x17\x86\x7C\x1E\x8A\x81\xF2\x73\x82\x26\x85\x82\x28\x88\x7F\x29\x87\x7E\x7A\x58\x0F\x7E\x29\x0F\x21\x8B\x7F\x1C\x82\x82\x2B\x8D\x81\x35\x84\x83\x2A\x8E\x7E\xFA\x01\x83\xFD\x7D\x7E\x2C\x8F\x83\x36\x89\x83\x27\x4B\x0F\x3C\x8F\x7F\x3D\x8C\x7F\x46\x89\x84\xEB\x77\x84\x33\x82\x83\xE9\x7A\x84\xFE\x7B\x84\xBE\x4C\x0F\x45\x82\x85\x56\x81\x85\x58\x8E\x83\x41\x80\x84\x38\x8C\x85\x4E\x84\x82\x42\x80\x5A\xFD\x0E\x27\xFE\x05\x85\x59\x88\x84\x57\x8A\x85\x5D\x8B\x85\x6C\x8E\x61\x55\x60\x00\x7A\x12\x10\x71\x8D\x84\x4C\x8F\x84\x69\x88\x86\x67\x84\x87\x50\x8A\x86\x5F\x81\x00\x73\x80\x00\xE4\x15\x27\x04\x0F\x87\x81\x83\x20\x07\x04\x88\x05\x2A\x00\x88\x89\x10\x0D\x0B\x88\x7C\x85", "\x44\x10\x0F\x87\x00\x2C\x39\x15\x0E\x88\x03\x18\x01\x96\x82\x10\x1B\x0F\x87\x7F\x8B\x57\x1C\x09\x89\x01\x1F\x01\xA0\x80\x00\x22\x03\x8A\x27\x81\x86\x6B\x89\x8A\x5F\x87\x8A\x5E\x85\x87\x60\x8D\x8A\x7B\x88\x87\x8F\x81\x8B\x7A\x8A\x10\x25\x0C\x89\x74\x66\x02\xB8\x89\x87\x76\x8C\x8B\xAF\x8D\x86\xAB\x87\x83\xC1\x88\x8A\x5F\x87\x02\xBB\x83\x8B\x77\x85\x8B\xBE\x8C\x8A\xC0\x8E\x8A\xE3\x28\x02\xC7\x82\x8B\xD2\x8A\x8C\xC8\x8B\x8C\xC2\x8E\x8C\xD7\x84\x8B\xBD\x85\x8D\xDC\x83\x10\x29\x01\x8D\xD4\x83\x8D\xDB\x82\x8E\xBF\x8A\x8A\xD8\x8E\x7E\x2A\x00\x8E\xE3\x81\x8E\xEC\x88\x23\x2B\x0A\x8E\xE5\x83\x8C\xB0\x83\x4A\x2C\x00\x8F\x2D\x00\x8F\xCC\x85\x1C\x2E\x08\x8F\xD9\x89\x8C\xEB\x8F\x8F\xF1\x87\x8E\xF3\x86\x8D\xC4\x82\x90\xCD\x8A\x8D\x01\x98\x90\x2F\x0C\x8F\x05\x98\x90\xFD\x50\x03\x0C\x93\x90\xB1\x31\x03\x11\x97\x90\xFE\x89\x90\x17\x99\x8F\xF2\x86\x91\x04\x92\x91\xBE\x62\x03\x15\x96\x8E\x0E\x9E\x5B\x33\x01\x92\x1B\x9A\x44\x34\x06\x92\x06\x92\x92\x19\x93\x2D\x35\x0A\x92\x23\x9D\x90\x2D\x92\x93\x1D\x9C\x91\xDD\x8D\x8E\x19\x86\x03", "\x30\x93\x93\x1E\x98\x93\x1A\x9B\x92\x27\x91\x94\x40\x93\x94\x31\x9D\x93\x25\x57\x03\x3B\x9D\x4A\x38\x09\x94\x37\x90\x90\xE3\x29\x03\x4C\x94\x8E\x3F\x95\x94\x36\x92\x95\xFD\x8E\x8B\x3A\x01\x95\x3E\x97\x95\x4D\x9F\x27\x3B\x0A\x95\x4E\x9C\x95\x56\x94\x93\x5D\x93\x95\x74\x6C\x03\x60\x9B\x57\x3D\x09\x96\x66\x95\x93\x2C\x9E\x96\x42\x94\x95\x6F\x95\x96\x62\x97\x3B\x3E\x0C\x96\x5A\x4F\x03\x78\x94\x96\x63\x96\x94\x18\x9A\x69\x40\x0B\x97\x7E\x9D\x96\x74\x9C\x97\x5B\x96\x98\x61\x98\x98\x7F\x95\x98\x83\x9E\x1D\x41\x02\x98\x1D\x42\x04\x90\x93\x97\x7D\x91\x1C\x43\x03\x99\x71\x9C\x93\x55\x97\x98\x8D\x9A\x98\xFD\x54\x04\x98\x94\x94\x9A\x94\x99\x02\x15\x04\xA1\x92\x97\x99\x90\x97\xA2\x9A\x9A\xA8\x95\x44\x46\x07\x9A\x5A\x37\x04\xB0\x9C\x9A\xA3\x99\x9A\x8C\x9B\x99\x89\x9D\x99\xBA\x98\x9B\x00\x08\x04\xB3\x91\x3B\x49\x0F\x9B\x95\x94\x9A\xB9\x9C\x9B\xE3\x2A\x04\xC2\x9C\x99\xC6\x95\x97\xC5\x94\x9C\x8B\x97\x51\x4B\x09\x9C\xCD\x96\x9B\xC3\x94\x9D\xCA\x95\x1C\x4C\x02\x9D\xCF\x97\x9D\xD0\x1D\x04\xDA\x94\x98\xD5\x9B\x9A\xB7\x9E\x9C\xE0", "\x9A\x51\x4E\x0F\x9D\xCC\x9B\x9D\x00\x9F\x04\xE8\x9E\x99\xE9\x95\x9E\xD3\x92\x9E\xE1\x9C\x24\x50\x0D\x9E\xDC\x21\x05\xF6\x9B\x9C\xEE\x9B\x9F\xBB\x94\x9E\xEF\x9F\x9F\xFC\x9D\x41\x52\x09\x9F\xEB\x23\x05\x04\xA6\x9D\xF1\x9D\x9A\x0A\xA5\x9B\xF2\x9C\x9D\x0D\xA2\x6A\x54\x07\xA0\x0F\xAA\x9E\x14\xA0\x9F\x15\xA0\xA0\xFD\x9E\x2F\x55\x02\xA1\x0B\xA4\x9B\x1E\xA3\x9E\x08\xA7\xA1\x01\xAE\x9F\x23\xA1\xA2\x16\xA3\x82\x56\x0C\xA1\x0C\xAD\xA1\x20\xA3\xA1\x27\xA8\xA1\x18\x87\x05\x2A\xAF\xA1\xF3\x9B\xA2\x36\xA4\xA3\x0E\xAC\xA2\x35\xA8\xA3\x09\xA7\xA3\x06\x18\x05\xF0\x89\x05\x33\xAD\xA2\x3A\xA9\xA3\x3E\xAB\xA3\x44\xA7\xA4\x02\x1A\x05\x43\xA8\xA4\x4E\xA6\xA4\x3C\xA2\xA2\x7E\x9B\x05\x4D\xA0\xA5\x49\xA1\xA5\x2F\xA5\xA2\x2E\xA0\xA3\x24\xA9\xA1\x5B\xAA\x98\x5C\x00\x8F\x5D\x05\xA5\x3D\xA8\xA5\x5C\xA6\xA2\x67\xAF\xA5\x5E\xA5\xA4\x65\xA7\xA5\x6E\xAF\xA4\x25\x5E\x05\x64\xA2\xA5\xFA\x99\x1C\x5F\x03\xA7\x23\x80\x06\x78\xA9\xA6\x6C\xA4\xA7\x5D\xA5\xA7\x80\xAF\xA7\x82\xA0\x1D\x61\x0B\xA7\x5A\xA8\x90\x62\x06\xA8\x72\x73\x06\x8A\xA1\xA8\x68\xA7", "\xA8\x4A\xA1\x10\x64\x0D\xA8\x83\xAA\xA6\x8E\xAF\x30\x65\x04\xA9\xD0\x16\x06\x9A\xA6\xA9\x95\xAD\xA7\xDB\x17\x06\x9D\xA0\xAA\x7C\xA1\xA9\x7F\x28\x06\xA3\xA6\xAA\x59\xAB\xA6\x0A\x19\x06\xA9\xA9\x10\x6A\x0F\xAA\x6F\xA6\xA5\x70\xAF\x27\x6B\x02\xAB\xB5\xAB\xAA\x97\xAC\x24\x6C\x08\xAB\xB4\xAF\xAB\x6D\xA9\xAB\xA5\xAE\x8B\x6D\x0E\xAB\xC1\xA0\xAC\x11\x4E\x06\xF0\x8F\x06\xC6\xAE\xA7\x8F\xAC\xAA\x66\xA0\xA9\xD1\xA0\xAD\xB3\xA7\xAC\xD6\xAE\xAC\xAE\x80\x07\xF0\x81\x07\xCD\xA3\x2E\x72\x0D\xAD\xC3\xA5\xAD\xD8\xA4\xAA\xD2\xA2\xAE\xBA\xAA\x44\x73\x00\xAE\xE5\xA2\xAC\xEB\xA4\x23\x74\x0A\xAE\xD4\xAC\xAE\xF1\xA8\xAC\xE7\xAF\xAC\xBC\x95\x07\xF0\xAB\xAB\xAA\xA9\x9E\x76\x09\xAF\x9F\xAB\xAF\xED\xA7\xAD\xF5\xAE\xA9\xF6\xAF\xAF\xD3\xAA\xAF\x07\xBA\x44\x77\x0E\xAF\x05\xB1\xA2\x78\x0C\xB0\x04\xB1\xB1\x4C\x29\x07\xF0\x8A\x07\x10\xBC\x24\x7B\x07\xB1\x00\xB3\xAF\x02\xB1\xAE\xF2\xA8\xB0\x5D\x9C\x07\x1A\xB9\xB0\x0D\xB2\xB1\xA3\x4D\x07\x23\xB6\xAE\x1E\xB4\xAF\x2B\xBD\xB1\x01\xB3\xAE\x1B\xB0\xB2\x1F\xBA\x44\x7E\x09\xB2\x33\xB5\xB2\xE4\xAC\xB1", "\x30\xB4\xB2\x26\xBC\xB3\x39\xB1\x1C\x7F\x00\x8F\x80\x00\x8F\x81\x06\xB3\x2C\xBF\xB2\x03\xBF\xB3\x06\xBA\xB2\xEE\x72\x08\x46\xBE\xB2\x3A\xB9\xB4\x05\x23\x08\xF0\x84\x08\x4F\xBB\xB3\x4C\xB1\xB5\xDE\x15\x08\xA6\x8E\x1D\x88\x0D\xB5\xC7\x1B\x08\x60\xB9\x1C\x8E\x03\x8A\x91\x03\xB6\x32\xB2\x10\x94\x02\x89\x5A\x39\x09\xA3\x8C\x09\xA3\x8F\x09\x73\xA0\x0A\xA3\x83\x0A\xA3\x86\x0A\x68\xBB\xB4\x37\xBD\xB3\x36\x79\x0A\xF0\x8A\x0A\x57\xB2\xB5\xAD\x4B\x0A\x81\xBD\xB2\x58\xBB\xB7\x4A\xB8\xB3\xA6\xAC\x0A\x85\xB8\xB4\x86\xB2\xB8\x03\x2D\x0A\x8D\xBA\xB5\x8E\xB5\xB9\x94\xB7\xB9\x69\xB0\xB5\x99\xB7\xB8\x47\xB2\x77\xAE\x0D\xAC\xAF\x03\xB9\x9B\xB0\xB9\x88\xB1\xB3\xC5\x10\x0B\xCD\xA1\x0B\xA2\xBA\xB7\x9D\xB3\xBA\x8F\xBE\x1D\xB2\x0D\xAC\xDE\x05\x1F\x06\x15\x88\xCD\x12\x15\x8C\x19\x10\xEF\x2B\x19\xB9\xB6\x10\x32\x3C\x30\x52\x1D\x27\x09\x1C\x40\x9B\x16\xBB\xD4\x18\xBB\x0A\x1B\xBB\x91\x1D\xBB\x03\x1F\xBB\xBB\x21\xBC\x0A\x14\xBC\x91\x13\x89\x91\x12\x15\xD4\xB7\xBB\x49\x17\xBD\xC7\xB9\x14\xC6\xB9\x1D\x52\x1D\xBD\xDC\x1F\xBD\x81\x12\xBE\x9B", "\x14\xBE\xD5\xBC\xBD\xE3\xB8\xBE\xE5\xB9\x14\xCC\xB2\x10\xCA\xBD\x1C\xE0\xB2\x15\xE6\xB8\xBD\x46\x11\xBF\xF2\xB6\x14\xED\xB1\x10\xCE\xB6\x33\xD0\xB3\xBC\x81\x16\xBF\xF7\xBF\x13\x00\xC1\xC0\x3D\x13\xC0\x04\xC9\xBF\x00\x0F\xBE\xD4\x16\xC0\x01\xC8\xC0\xFB\xB3\x30\xFD\xB6\x10\xD2\xB0\xBF\xE9\xB8\xBF\xC9\xB1\x18\x0E\xC6\x28\x11\xC3\x10\x13\xC4\x1D\xDA\xBE\xBD\xD9\xB5\xC1\x43\x1F\x22\xEB\xB6\xC1\xC2\x66\x25\xE7\xB6\x14\xC2\xB6\x10\x08\xC6\xBD\x22\xCF\x13\x1F\xC1\xBE\x49\x14\xC2\x29\xC3\x14\x08\xCD\x89\x52\x18\xC2\xF4\xB3\x14\x2B\xCB\x18\xFF\xBF\xC2\x3E\x1C\xC0\xF7\xB2\xC4\xF2\xB4\xC4\xF3\xBB\xBD\x26\xC6\x10\x0A\xC9\x1D\x46\xCA\xBE\x35\xCF\x13\x19\xC0\xBC\x49\x1D\xC3\x02\x1D\xC1\x4C\xC0\xC4\x05\xC8\xC5\xFF\x0D\xC4\x49\xC3\x10\x4B\xCC\x1D\x5C\xC6\xC3\x0A\x1F\xC0\x0E\x3B\xC1\x55\xC1\x18\x31\xC4\xC0\x30\xCA\xC5\x34\xCB\xC3\x50\xCA\x10\x00\x3B\x19\x3A\xC8\xC4\x3C\xCA\x10\xA8\x3B\x19\x69\xCA\xC6\x3D\x19\xC7\x7A\xCD\xC6\x74\xCF\xC6\x09\x11\xC7\x91\x13\xC7\x20\xCA\xC2\x76\xCF\xC3\x25\xC3\x14\x61\xC2\xC0\x5A\xCB\xC8\x41\xCD", "\xC8\x90\xC9\xC8\x80\xCA\xC4\x88\xCF\xC4\x8F\xC2\xC9\x97\xC6\xC9\x3D\x11\xC5\xCF\xB3\xC5\xD1\xB1\x18\xB4\xBA\xC9\xFF\x0C\xC7\x6A\xC8\xC0\x79\x3C\xBB\x0A\x17\xCA\x9D\xC6\xC8\x09\x16\x4A\x52\xCC\xCA\x06\x1E\xCA\x91\x1D\x89\x8F\x14\xC5\x01\x18\x4A\x78\xCA\xC5\x9D\x88\xC3\x9E\xC9\x10\xB8\xC3\xBD\x5A\xC6\xCA\x18\xC9\xCA\x1A\xCD\xCB\xB1\xC3\xCC\x09\x1A\xCA\xCD\x12\xCC\xAF\xC5\xC7\xAD\xC5\xC9\x6E\xC9\xC9\xD1\xC9\xC5\x98\xC4\xCD\xA2\xCE\xC8\xD6\xC3\xCD\x5B\xC1\xCC\x0A\x18\x2F\xC5\xB1\xC9\xD7\xCC\xCD\x09\x1B\x2C\xDF\xC5\xCD\xDB\xC6\xCE\xD8\xCF\x0F\x08\xC6\x32\xE5\xC1\xCE\xE8\xC2\xCE\x06\x1E\x38\xED\xCA\xCD\xE9\xC9\xCE\x08\xC3\x3B\xF3\xCF\xC7\xD2\xCA\xCF\xD9\xCC\xCF\xEA\xCD\xCD\xD0\xCE\xCF\xF5\xC0\xCF\x03\x1E\xCD\x91\x13\xD0\xEF\xC6\xCE\x08\xC4\x33\xAB\xCE\xCC\x06\x10\x43\xF9\xC5\xC8\x8A\xC0\xCE\xDA\xCB\xD0\xC5\xC0\xCB\x03\x10\xD1\x07\xD4\xD1\x02\xD4\xD0\x02\x1C\xD0\xFC\xB6\xCC\x19\xD8\xCC\x06\x1C\x38\x11\xD2\xC3\xF5\xBC\xD1\x12\xDC\xC8\x0A\xDA\x10\x26\xDB\xD1\x09\xDE\xCE\xA2\xC8\xC0\x5F\xC8\xBC\x09\x1F\xD2\x14\xC1\xD3", "\xF4\xCE\xD1\xFA\xB7\xD1\x0E\xDC\xC1\x68\xCA\xC5\xA4\xC4\xC0\x08\xD2\xD3\x15\xD0\xD0\x27\xDA\xC7\x9B\xCA\x10\xE4\xC0\xD3\x33\xDA\x10\xEC\xCE\xD4\x47\xD9\x10\xF2\xC2\xD5\xFE\xC7\xCF\x01\xDB\xD2\x3E\x18\xC0\x06\xD9\xD3\x4F\xD9\x10\x5D\xDB\xC0\x3C\xD0\x00\x20\xD0\xC1\x22\xD2\x10\x1A\xDE\xD5\x53\xD6\x10\x65\xD5\xC6\x67\xD1\x10\x69\xD2\xD6\x2D\xD9\x10\x6D\xD0\x31\x66\xC0\xD7\x3E\xDF\x13\xB6\xC0\x00\x71\xDE\xD6\x18\xD8\xD6\x79\xDE\x13\x7B\xDD\xD7\xDC\x1D\x89\x2D\xCF\xD6\x00\x0F\x43\x9B\x14\xCB\x81\x1B\xD7\x8A\xD3\xCB\x01\x3E\xD8\x59\xD8\xD2\x62\xC0\xD6\x24\xD3\x10\x4D\xDB\xCC\x50\xD7\xD9\x02\x15\xD5\x9A\xD9\x10\xF8\xCB\xBC\x48\xD2\xDA\x96\xD8\xCA\x74\xD1\xD8\x3D\x13\xD8\x9C\xD1\x10\x75\xD1\x26\x77\xDC\xD7\xAB\xD4\xD6\xA8\xDF\x0F\xAA\xDD\xCC\x7A\xDA\x10\xD9\x49\xCB\x73\xD6\x10\xCA\xC4\x1D\xCC\xCD\xD0\xB7\xDF\xCC\xA6\xDC\xDB\xB1\xDD\xDB\x7E\xDF\xD3\x02\x12\xCB\x6A\xDD\xD1\x3A\xDC\xDC\x46\xDE\xDC\x3B\xDB\xDB\x05\xD3\xD9\x4A\xD7\xCE\xCF\xDA\xD5\x4B\xD3\xCE\xD4\xDA\xD4\x45\xDB\xD6\x03\x11\xD5\xCB\xD8\xDD\xD6\xD1\xDD\x5F", "\xD1\xCF\xDB\xDA\xC7\xDD\xD7\xD5\x0A\x11\xDA\xE1\xD4\xD9\x2C\xD7\xDD\xEE\xDB\xD5\xA3\xDD\xDE\xD5\xD9\xDE\xE2\xDC\xD5\xE7\xDA\xC6\xF6\xD1\xDF\xD9\xDC\xD6\xB3\xD5\xDB\x56\xD2\xDE\xFB\xD5\xDD\x16\xD6\xDB\x82\xDA\x10\x84\xD7\xC4\x02\xEA\xD2\xFC\xDF\xCF\xA7\xD6\xE0\xA9\xD8\xE0\x41\xD6\xCE\xBB\xCD\xD8\x2E\xD3\xE1\xA2\xC6\xD8\x16\xE7\xD3\x18\xEE\xDD\x02\x18\xD3\x72\xD0\xDF\xF5\xDC\xE0\x04\xE7\xE1\x49\xDC\xDD\x24\xEA\xD4\x34\xD1\xDB\x20\xE7\xC5\xCD\xDB\xE0\xD2\xD2\x10\x64\xC6\xD7\x88\xD6\xC5\xDC\x18\xC0\x2D\xE0\xC6\x29\xE8\xDE\x3B\xE5\xCA\x26\xE1\xE0\x0D\xE3\xE0\x2A\xE7\xC1\xC3\xD3\x10\x39\xEA\xE0\x41\xED\xE3\x07\xC3\xC6\xFF\xDF\xC9\xBA\xD2\xE2\x28\xEF\xE2\x49\xE2\xE5\x23\xE4\xE5\x43\xE5\xDA\x40\xE5\xE5\x50\xEA\xC7\x08\xC9\xD9\x21\xE4\xDE\x60\xEA\xDE\x09\x10\xDE\x5F\xE0\xDD\x66\xE7\xDF\x0A\x1E\xD9\x65\xE0\xE3\x5B\xEE\xE3\xA0\xD9\xDF\x44\xDA\xE4\x0D\xC3\xDF\x6B\xE3\xE5\x6D\xEB\xE4\x58\xE4\xDF\x51\xE7\xE7\x73\xEF\xE0\xC0\xD7\xE0\x09\x19\xE0\x4E\xC1\xE6\x6C\xEE\xE1\xAC\xDD\xE4\x81\xE0\xE7\x01\xC2\xE4\x5C\xE1\x11\x88\xEF", "\xD0\x8A\xE3\xC4\x72\xE2\xE9\x56\xEC\xE3\x95\xEE\xE6\x06\x11\xD6\x2E\xEC\xE7\x94\xE5\xDE\x98\xD1\xE9\x45\xC3\xE9\xF2\xBB\xCE\xA0\xE8\xE4\x5A\xE6\xE8\x00\x0A\xE6\x9B\xE4\xE8\x76\xE8\xEA\xEC\xD5\xE7\xA7\xE7\xE6\x0D\xE8\xDF\x27\xE6\xE9\x9C\xE3\xEA\x74\xEB\xEA\xB2\xE1\xEB\x68\xEE\xE7\x21\xDF\xD7\x78\xD5\xEB\xFA\xD2\xEA\x36\xDE\xDF\x10\xE4\xDB\x12\xE2\xEC\x71\xE7\xE9\x78\xE6\xEC\x7F\xE1\xE1\x89\xEF\xE4\xDA\xCC\xD8\x9B\x1B\xD7\x47\xE1\xC2\xE6\xC3\xD4\x01\xCF\x18\xAF\xDD\x42\xD2\xEE\xCF\xDA\xED\xE9\xAC\xEC\xEB\xAD\xEB\xEB\x7B\xE3\xEE\x57\xE9\xE9\xA5\xE3\xE8\xE6\xED\xE8\xDA\xDA\xEC\x8B\xE4\xEC\xEC\xBB\xD9\xF0\xE2\xEE\xED\xE8\xE9\x03\x1A\xEA\x3A\xEC\xEC\xF1\xE1\xE3\x01\x1F\xEA\xBA\xE5\xE8\xF7\xED\xEC\xD3\xD5\xEF\xA1\xEC\xEF\xF7\xB4\xEB\x59\xE7\xEE\x03\xFD\xE7\xCE\xEF\xEB\xC8\xD1\xEC\x0B\xF6\xEB\xE8\xEE\xEE\x0F\xF6\xD6\xC0\xE0\xDB\x06\xF6\xEA\x0C\xFD\xEB\x17\xF7\xDC\xC1\xD0\xE9\x1B\xFC\xEE\x02\xFE\xF1\x05\xF3\xF1\xF8\xE2\x10\x5E\xE1\xF0\xB3\xE4\xEF\x28\xF4\xF0\x9D\xDB\xEE\x5D\xC2\x10\x00\xFB\xEF\x9E\xE2\x10\x9A\xE6\xF3", "\xA8\xE9\xF3\x1C\xF6\xF1\x03\x1D\xDA\x3D\x2F\xDA\x82\xE9\xD2\xFE\xE2\xDB\xC7\xE0\xE0\x7A\xEE\xF3\x1F\xDF\xE8\x23\xD3\xF2\x33\xF1\x10\x3C\xF3\xEF\xEF\xE4\xDA\x06\x14\xE6\xD9\x18\xC0\xFA\xE5\xEC\x03\x15\xF3\x5A\xF8\xF3\xB1\xD1\xF5\x4F\xF6\xF4\xCF\xE8\xEC\xD1\xE4\xF5\x3F\xFC\xF4\x80\xD5\xE4\x4B\xF7\xF4\xC9\xE0\xCC\xD9\xEC\xC6\x63\xDE\x35\x72\xCA\xC5\x7B\xDD\x48\xDF\xE2\xDE\xE1\xE2\xBF\x7E\xC6\xF2\x02\x12\xF7\x83\xC4\xF7\x0A\x16\xF7\x2F\xFD\xEF\xB7\xED\xF3\xC3\xE5\xF4\x60\xF3\xD1\x08\xF8\xEB\x53\xF9\xF4\x87\xF7\xF3\x01\x16\xF5\x3A\xFD\xF0\x09\xF9\xE6\x32\xFA\xF8\x90\xF2\x3B\x97\xFF\xDE\x3B\xFB\xF9\xFB\xCC\xF7\x50\xFE\xF9\xFD\xC0\xFA\x62\xF0\xF1\x21\xFD\xF4\x83\xF6\xEF\xA4\xF0\xF4\x41\x22\xF4\xA2\xF3\xDE\x62\xEF\xF1\x34\xE9\xF1\x43\xF8\xF9\x15\xFF\xF8\x9D\xFE\xF4\x95\xD6\x10\x2B\xF3\xF9\xA4\xF2\xF9\x86\xF0\xF3\xA1\x8F\xFA\x58\xDA\xFB\x93\xC7\xF2\x8E\xF2\xFC\x00\x09\xF8\x9C\xF1\xFB\x67\xFC\xF6\x65\xF9\xFC\x0E\xFF\xFC\x63\xF8\xF4\xB0\xE9\xEE\xD4\xF6\xFA\x80\xE2\xF2\x6E\xF2\xCA\x79\xF2\x15\x7B\xFD\xF2\x58\x1F\xF7\xE6", "\xCB\xD7\x8F\x1F\xFD\xD8\xE2\xCA\xE1\xF5\xE2\xE3\xFD\x1C\x84\xCD\xE0\xE6\xFF\xFA\x8C\xE8\xFB\x94\xF7\xF0\x85\xF2\xF5\xEA\xE6\xFC\x9F\xF5\xEE\xA4\xFD\xFB\xC1\xF4\xF8\xB7\x7A\xF9\x40\x7E\x92\x7C\xFF\x05\x80\xFB\x66\x6F\xFA\x7B\xF4\x46\x80\xEC\x74\xF3\x72\x7E\xBC\x61\x7B\xCC\x7B\xFF\x64\x77\x09\x8C\x00\xA1\x7D\x02\x90\x7D\x25\x7A\xFC\x72\x7C\xD7\x68\xD8\x35\x7D\xF3\x79\x80\x14\x82\xE9\x47\x74\xE8\x7C\xFD\x52\x7E\xEA\x6B\x80\x22\x85\xF4\x58\x79\x88\x7A\xF1\x11\x0D\x28\x7A\x66\xE8\x7E\x28\x14\x77\xC8\x0B\xD7\x79\x79\x85\x75\x76\x0A\x09\xEF\x48\x61\xC3\x6D\xFA\x08\x6F\x0B\x8B\x81\xA7\x7A\x20\x07\x11\xBB\x7A\x01\x83\x09\xC1\x17\x80\xF3\x7B\xD9\x59\x7D\xF7\x7F\xFF\x27\x81\x08\x94\x7F\xA4\x7E\x69\x26\x80\xFB\x71\x00\x80\x82\xF3\x62\x08\x47\x81\xF5\x54\x83\xFA\x7D\xF5\x16\x82\xD9\x6B\x08\x0E\x83\xF1\x5D\x83\xE5\x71\xDB\x52\x83\xF5\x74\x78\x5C\x80\xFF\x48\x7E\xDF\x6A\x10\x59\x83\x14\x8D\x82\x5B\x85\xFF\x71\x6C\x26\x84\x00\xCF\x82\x12\x88\x75\xFE\x7A\x0D\x87\x09\x30\x87\xFF\x61\x79\x1E\x81\x7B\x6E\x87\x0C\x90\x82\x14\x89", "\xF2\x11\x7F\x1C\x9C\x83\x55\x85\xF2\x63\x73\x32\x88\x08\xE9\x81\xD8\x63\x80\x80\x85\x11\xA0\x81\x0A\x89\xEA\x07\x84\x12\x8F\x80\xBB\x79\xDF\x4C\x85\x4B\x82\x06\xFA\x83\xF0\x6A\x7B\x01\x0E\x0C\xAC\x78\x3B\x86\x05\xA4\x7C\xD7\x7E\x84\x00\x04\x0E\x84\x7B\x3E\x86\xFB\x57\x83\xBF\x71\x6D\x81\x83\x14\x9D\x78\x42\x8A\xFC\x27\x85\xD8\x67\x18\x5F\x81\x20\x24\x14\x50\x80\x00\x31\x86\xEF\x74\x85\xA5\x85\x08\x9E\x7A\x5E\x8A\x0A\xAD\x87\x24\x88\x83\xA4\x79\x02\xBD\x6F\x4B\x42\x09\xC0\x86\x22\x99\x7F\xB9\x85\x17\x8D\x86\x52\x8F\x0C\xEB\x83\xD5\x6A\x08\xC5\x87\x03\x8E\x87\x38\x82\x0C\xDE\x83\x67\x66\x08\xA2\x87\x17\x94\x86\x6E\x87\x00\xD6\x87\x8D\x6D\x08\xB0\x83\x1A\xB3\x85\x72\x8B\xF6\x55\x7D\xDB\x7F\x86\x03\x09\x1B\x92\x81\x75\x84\x0F\xA9\x80\xEB\x69\x13\xAE\x7C\x17\xA1\x86\x38\x8C\x0F\xF5\x80\x25\x97\x87\x49\x11\x1F\x91\x86\x5F\x8D\x0F\xAB\x85\x22\x8C\x7C\x1B\x81\xE8\x5D\x80\x4B\x8A\x05\x85\x8A\x31\x9D\x86\x2A\x80\xE4\x5B\x7E\xD4\x70\x0F\xFB\x80\x27\x8C\x85\xC7\x7D\x1D\x9A\x7E\x68\x75\x02\xEC\x81\x42\x04\x88\xFE\x80\x19", "\x9B\x87\x31\x80\x10\xDD\x12\x40\x95\x88\x01\x0A\x1E\x8A\x81\x71\x8E\x10\x99\x8B\x08\x8E\x87\xD1\x7E\x23\xA0\x86\x75\x82\x12\xEC\x87\x4B\x9B\x88\x64\x7D\x23\x97\x86\x5F\x70\x04\x93\x89\xDA\x7D\x7E\xA8\x75\x24\x9B\x13\x93\x82\x13\x83\x08\xAB\x1C\x85\x47\x89\x1A\x89\x8B\xE6\x01\x03\x99\x86\x40\x18\x15\x24\x83\x20\x18\x1A\x5E\x80\x15\xB0\x8A\x41\x13\x8A\x40\x8E\x9F\x5C\x76\xC4\x64\x3D\x44\x82\x4D\x80\x00\x3C\x80\x1F\xBE\x81\xD8\x61\x16\x81\x8B\x58\x9E\x8A\x4A\x6B\x2B\x99\x79\x9A\x69\xFE\x28\x75\x59\x86\x89\x67\x89\x1A\xAF\x8B\xA1\x81\x17\xCC\x8A\x50\x63\x6B\x73\x8A\x4C\x2F\x6D\x1F\x8B\x13\xAC\x60\xDA\x61\x08\x7C\x8C\x3B\x0D\x8A\x97\x80\x00\x55\x88\x4E\x9B\x6B\x58\x8E\x2E\x85\x7A\xA1\x8A\x17\x8B\x8B\x62\x6D\x7F\xCD\x0A\xB2\x68\x8A\x3D\x63\x03\x91\x8E\xCB\x6D\x0E\x37\x84\x06\x97\x8D\xA2\x8F\x14\xFF\x88\x00\x09\x8C\x9C\x8F\x56\x1E\x8C\xD0\x8D\x17\xA3\x15\x6C\x7B\x85\xD1\x84\x31\xAA\x8A\x16\x8E\x01\xF2\x6D\x42\x08\x8D\x28\x88\x00\x30\x8D\xD0\x81\x11\xB3\x7C\x6B\x91\x6D\x4B\x8C\x36\xB9\x8D\xD2\x82\x10\x3B\x8D\x61\x70", "\x8C\xD4\x0B\xAF\x7B\x87\xB6\x8E\xCF\x19\x8E\x65\x89\x08\xC3\x8E\x28\x03\x8C\xD7\x86\x10\x33\x8C\x6F\x9A\x85\xB1\x6A\x35\x80\x7D\x98\x8F\x1C\xB5\x8C\x07\x94\x7D\xB8\x89\x3B\x88\x8B\x0E\x7E\xCF\x7B\x68\x2E\x8A\x8C\x99\x7C\x34\xB6\x8D\x20\x81\x10\x7C\x21\x54\x87\x24\xE9\x87\x22\x87\x89\x96\x8C\x1C\xF1\x84\x4D\x83\x84\x2C\x88\x15\x89\x8F\x87\x81\x1F\x86\x8A\x23\x8E\x8A\x01\x08\x24\xB6\x8F\x63\x80\x1F\x94\x86\x32\x8E\x70\x06\x0A\x25\x98\x81\x91\x81\x12\x85\x84\x19\x9A\x87\xEF\x8F\x0E\xAE\x85\x03\x93\x10\x89\x91\x30\x9F\x8A\x7F\x80\x3F\xA9\x84\x07\x9E\x04\x94\x85\x84\x84\x8C\xF3\x8A\x1B\xB5\x8E\xFA\x86\x21\xE9\x8D\x43\x85\x90\x0A\x97\xF7\x4C\x89\x37\x80\x22\x8F\x90\x25\x90\x84\x12\x91\x43\xB3\x87\x9A\x85\x0F\x86\x90\x8A\x84\x8C\xFA\x8C\x43\xAC\x91\x19\x96\x20\xD9\x78\x2A\x82\x90\x49\x86\x44\xA9\x80\x1B\x91\xF6\x2A\x93\x4A\x8D\x91\x21\x90\x22\xBC\x91\x14\x94\x21\xE4\x84\x25\x96\x85\x12\x90\x47\x98\x84\x0D\x97\x24\x9E\x90\x89\x9B\x8F\x04\x91\xEC\x48\x92\xC2\x8F\x1D\xB4\x8E\x73\x87\x87\x1F\x8D\x48\xAC\x8F\x65\x83\x0C", "\xD1\x86\x92\x9D\x84\x50\x97\x2B\xBF\x8E\x04\x6E\x23\x83\x93\x86\x8C\x92\x29\x83\x4C\xAD\x82\x2D\x95\x22\xD5\x85\x97\x91\x8D\x5F\x90\x23\xAB\x90\x03\x9A\x26\xC8\x8C\x9B\x81\x93\xFE\x89\xB6\x44\x17\x06\x9A\x1E\xF7\x8C\x61\x92\x8E\xE5\x7F\x1D\xB4\x8D\x38\x9B\x1E\xED\x90\x42\x99\x7E\x3D\x8C\x23\x94\x88\xDA\x85\x26\xB9\x91\x85\x96\x87\x9E\x8D\x35\x9C\x93\xFC\x87\x27\xB2\x92\x81\x80\x94\xA2\x66\xFA\x55\x8E\x42\x9E\x27\xF3\x92\xF2\x78\x94\xDA\x62\x53\x98\x93\x99\x8D\x27\xFC\x8F\xA7\x91\x94\x4E\x92\x10\x81\x93\x33\x9D\x1E\x9A\x89\xA2\x99\x89\x8B\x93\x53\x95\x94\x34\x97\x29\xA8\x94\x82\x85\x95\x51\x92\x42\xA0\x95\xEE\x82\x28\xD9\x0F\x72\x93\x94\x00\x00\x71\x3C\x84\x61\x91\x0D\xE2\x8F\x75\x8C\x81\xE6\x8D\x58\x9E\x8D\x64\x90\x1E\xA8\x76\xB1\x8A\x88\x19\x7C\x59\x9E\x61\xB1\x6F\x2C\xBD\x81\xB4\x9B\x70\x06\x0C\x58\x8D\x0F\xC0\x85\xDD\x5C\x96\x52\x7E\x96\x7A\x63\xAF\x44\x63\xBD\x63\x25\xBE\x89\x40\x0D\x26\x38\x81\x21\x28\x96\xCD\x84\xD5\x20\x66\x16\x60\x97\x6A\x63\xAF\x4F\x27\x74\x96\x10\x51\x24\xBD\x83\x08\xEC\x1F\x5E\x82", "\x09\x7C\x9C\x2E\x86\x08\x46\x1A\x97\x01\x0B\x9A\x00\x98\x00\x02\x30\xFD\x97\x40\x02\x1C\xC7\x8C\xB8\x5B\x0C\x78\x94\xC0\x7B\x68\x24\x26\x98\x72\x40\x5B\x8B\x1E\x89\x9A\xF2\x14\x99\x40\x14\x23\x10\x99\x20\x19\x1F\x8C\x90\x00\x55\x91\x76\x1B\x6B\x31\x94\x3C\x80\x00\xBF\x79\x30\x83\x08\xC9\x81\x8E\x15\x0E\x62\xA4\x44\x95\x9B\x27\xA5\x9B\xB0\x0A\x99\x52\x23\x60\xB1\x98\x8E\x93\xE3\x2F\x6D\xCD\x88\x6C\x8C\x8B\xAF\x79\x99\x87\x0A\x32\xA1\x9A\xB9\x80\x00\x77\x23\x60\xB3\x24\xA1\x9A\x32\xC3\x98\xC7\x86\x9A\xCD\x0A\x0B\x20\x5E\xE0\x83\xFE\x1A\x73\x78\x14\x0F\x7E\x10\x81\x60\x5F\xC0\x8E\x34\xB5\x5C\xD4\x89\x08\x81\x89\x6B\xB9\x81\xAD\x9F\x1F\x0A\x0B\xD4\x9E\x9A\x57\x9E\x6A\x98\x9A\x85\x03\x04\x86\x09\x60\x85\x9B\x03\x0F\x6C\xA1\x9A\x1F\x6F\x34\xE3\x99\x42\x12\x9A\x6B\x9A\x20\x30\x9A\xB7\x96\x10\x61\x7D\xF8\x6F\x7F\xEF\x7B\xAF\x58\x15\xD7\x8A\x10\x3E\x8E\xDE\x8A\x08\x57\x96\x37\x86\x8C\x81\x0F\x37\xFC\x99\x42\x1E\x9B\x0A\x0B\x6F\x8D\x8F\xBE\x9A\x10\x05\x9F\xE2\x87\x9C\x8D\x99\x71\x80\x9C\xC6\x99\x10\x0E\x9E\x69\x90\x9C", "\x95\x9A\x72\x86\x9D\x55\x11\x39\x89\x0A\xE2\x97\x9C\x9C\x99\x21\x2D\x98\xC2\x9A\x39\x8F\x9D\xE8\x86\x08\xA3\x99\x20\x16\x9C\x81\x01\x38\xE8\x85\xE3\x72\x9B\x60\x9C\x6E\x9F\x75\xB7\x91\x3B\xE6\x98\x53\x6A\x08\x73\x9E\x76\xBA\x5C\xCA\x94\xC9\x18\x9E\x41\x03\x9C\x01\x0F\x8B\x7E\x8C\xE1\x94\xE4\x27\x9E\x17\x7C\x9D\xC7\x9E\x77\x89\x9E\xE3\x9E\xBE\x48\x9F\xCB\x9B\x9D\xCA\x9F\x79\xBD\x9C\xE6\x91\x10\x29\x9D\x61\x8E\x9D\xA8\x98\x7B\xA6\x87\x9C\x72\xC8\x03\x09\xF7\x98\x82\xA5\x98\x74\x86\x8B\x35\x9E\x39\x93\x9D\xF4\x82\x8D\x59\x95\x7C\x9B\x9D\xF1\x99\x3E\x86\x0B\xE7\x8C\x9D\xCE\x9C\x52\xAA\x9E\xD3\x9C\x3E\x86\x0A\x2F\x8F\x9F\xD0\x8F\x7C\x92\x87\xF9\x92\x3E\xBD\x8C\xF9\x8E\x9F\xE6\x9C\x7A\xBB\x9E\x00\xAB\x3E\xFE\x9E\xE8\x9F\x9F\x03\x08\x7F\xB2\x8D\xF8\x90\x00\x56\x9F\xFD\x81\xA0\xF5\x9B\x20\x16\x9E\x8F\x90\x00\x12\x7F\x8C\x7D\x7D\xB9\x99\x6D\x8C\x73\xD7\x91\x10\x19\xA2\x40\x01\x8C\x17\xA0\x77\xB5\x9C\x0D\xAC\x13\x81\x08\x06\xA3\xA1\x1F\xA6\xD1\x5C\xA0\xB0\x88\x42\x80\x8E\x0A\xBC\x7D\x22\xA5\x6D\xBA\x9C\x52\x94\x40\xF4", "\x9E\x01\xB4\xA1\x09\xA0\x82\xB7\xA1\x81\x00\x3C\x84\x09\xF8\x90\x9F\xFA\x99\x1C\x8A\xA1\xD6\x96\x27\xFC\x9C\x10\xA2\xA0\x42\xA2\x87\x81\x08\xDF\x89\x44\x85\xA3\x12\xAA\x08\x4D\xA6\x86\x8F\xA3\x22\xA5\x43\xFD\x9F\x14\xB9\x9E\x54\xA1\x87\x8E\xA2\x00\x0E\x1B\xD6\x9D\x14\xB6\xA2\x5C\xA2\x7B\x82\x08\xF1\x83\x44\x8C\xA0\x19\xAA\xA2\x61\xA4\x11\x4A\x09\x33\xAB\x45\xBE\x8C\x1B\xB2\xA2\x69\xA7\x2A\xBF\xA1\xFC\x92\x40\xEF\xA0\x18\xAE\xA3\x73\xA3\x81\xBA\x9E\x3B\xA7\x44\x91\xA3\x18\xB9\xA3\x44\xA0\x8B\xB2\xA2\x23\xA4\x47\xFE\xA1\xF5\x8B\xA3\x80\xA4\x81\x96\x9F\x93\x91\x10\x65\xA2\xFE\x8C\xA4\x00\x06\x91\x82\xA1\x1E\xA0\x49\x92\xA6\x21\xA3\x99\x89\xA7\x91\x99\xA4\x01\xA5\x49\xE8\xA2\x6F\x9D\xA4\x6D\xA2\x21\x20\xA4\x38\xAF\x49\x9B\xA7\x25\xAB\xA4\xA6\xA3\x87\x92\x9E\x93\x99\x4A\xD7\xA2\x04\xAC\xA0\x82\x98\x96\xB2\xA4\xFD\x9E\x1B\xDD\xA2\x22\xB7\xA5\xC9\x64\x98\x6A\xA3\x5C\xAC\x4B\x8A\x9A\x2F\xA3\x08\xC6\x68\x00\x01\xA7\x60\xA6\x3D\xC4\xA6\x2E\xA2\xA4\x77\xA6\x93\x8A\x09\x1E\xA1\x48\xC9\xA5\x28\xAF\xA6\xA4\xA2\x99\x90\xA7", "\x57\xA3\x4D\xAB\xA5\x1F\xAA\xA5\x87\xA1\x21\x08\x98\x6C\xA0\x00\x5B\xA6\x2B\xBD\x8C\xDA\xA4\x81\x9E\xA7\x38\xA7\x30\xE2\xA6\x39\xBA\x9F\xE3\xA6\x37\xA9\xA6\x31\xA1\x10\x6B\xA7\x01\xA1\xA7\xFA\x9E\x7A\x96\xA4\x6E\xA3\x4F\xDF\xA4\xFA\x95\xA2\xD7\xA6\x9E\x91\xA4\x69\xA8\x4F\x85\xA4\x3D\xBC\xA7\x5A\xA1\x9A\x84\xA4\x3D\xA2\x40\xF5\xA4\x39\xB6\xA6\x8D\xA0\xA0\x88\xA9\x7D\xA5\x4D\xD9\xA5\xB6\x8A\x08\xDA\x97\xC3\x6D\xA5\x83\xAF\x09\xFD\xA4\x41\xB7\xA4\x77\x66\xA2\x8D\xA6\x89\xA3\x50\x9B\xAB\x3D\xBA\x84\x1D\xAC\x81\xBD\xA1\x8C\xA1\x50\xCE\xA7\xEF\x9F\x71\x25\xA9\x9F\x94\xA9\x4A\x81\x52\xFA\x9C\x49\xA2\x08\x06\xAE\x37\xB9\x71\x98\xA6\xF9\x2D\xAA\x00\xAF\xA9\x09\xAD\xA1\x80\x01\x99\xAA\x50\x95\xA9\x4A\xBE\xA7\xFA\xA0\xA7\x8C\xA8\x81\xA6\x10\x42\xA8\x4D\xAD\x97\x36\xAF\x92\xBC\xA8\x9D\xAB\x54\xC4\xA8\x48\xBA\xA8\x0C\xA6\xA8\xBD\xA9\x9D\xA3\x51\xBE\x8E\xBE\x67\xAA\x45\xAD\xAA\xA8\xA8\x98\xA3\x55\xD6\x9F\x55\xBD\xAA\x87\x61\xA9\x9C\xA6\xEB\x9D\x54\xA6\xA8\x35\xA8\x80\x50\xA9\x9E\xA1\xAB\xB4\xA2\x40\xE4\xAA\x56\xAF\xA7\x68", "\xAF\xA7\x97\xA9\xB1\xAB\x56\xF2\xAA\x47\xAD\xA0\xEB\x69\x65\x89\x08\xE6\x1B\x57\x8A\x09\x57\x86\x08\x1B\x9B\x62\x89\x09\xBF\xA3\x10\x01\xAF\xBE\x87\x20\xFE\x59\x21\x1E\x76\x9D\x89\xD8\x0A\x0B\xCC\x83\x08\x18\x9D\xB0\xB6\x44\x85\x01\x34\x86\x0A\xB4\x81\x08\x88\x21\x21\x19\xAC\x46\x2B\x11\x1D\xAD\x42\x02\x7C\x03\x0C\xB0\x82\x08\xC3\xA1\x10\x22\xAE\xC6\x8A\x08\xCA\x6B\xB4\xA8\xAD\xC9\xAF\x59\x8A\x0B\x2F\x63\x08\x48\x9A\x20\x31\xAD\xD2\xAC\x5A\x86\x0B\x6C\xA0\x00\xA6\xA8\x00\x24\xAC\x00\x0B\x2E\xC6\x73\x5B\xA6\x08\xBD\xA9\xE6\x62\xAA\x7D\xA1\x5C\x81\x0A\x54\xBA\xA9\xC5\xAC\xAA\x83\xAF\x95\xAD\x43\xC9\xAF\x57\xBA\xA9\xCD\xAD\xAE\x9C\xAA\xE8\xAA\x10\x49\xAD\x59\xAA\xA9\xBE\x8E\xB9\xBF\xAD\x81\x09\x5C\xC7\xAE\x53\xA2\x08\xD6\xAB\xBB\xA0\xAF\x9A\xAC\x56\x97\xA5\x77\xA2\xAF\xE7\x93\xAB\xB9\xA9\xEF\xA9\x5E\xC8\xA9\x79\xBC\xA6\xE7\xAB\xB9\x99\xAE\xE9\xAB\x5E\xE6\xAB\x78\xAE\xAF\x76\xAC\x81\xA1\xAE\xF9\xA5\x5D\xFD\xAE\xBA\x8A\xAF\x43\xAE\xBE\xAD\xAF\xB8\xA3\x5D\xEC\xAC\x6F\xB4\xAF\x01\xB0\xBB\xBE\xAF\x92\x68\x5E\x87\xB0", "\x7E\xA5\xB0\x02\xB6\xC1\x99\xAA\xFE\xAF\x5F\x95\xB0\x83\xB4\xB0\xC8\xA7\xBE\x84\xB1\xFA\xAA\x60\xF0\xA8\x77\xA8\xB0\x58\xAF\xAC\x9F\xB0\x0E\x78\x61\xA2\xB2\x86\xAF\xAA\xF9\xAA\xAD\x96\xB1\x81\x0E\x5D\x91\xB2\xF5\x9B\xAF\xEF\xAA\x9F\xAF\xB0\xF2\xA9\x62\xED\xAB\x82\xAC\xB1\x0D\xB6\x7A\xB3\x97\x7A\x9A\x10\x05\x9B\x40\x15\x26\x09\x09\xB7\x46\x08\x6E\x2C\x34\xCB\x98\xD3\x80\x00\xAE\x04\x2F\x9D\x44\xF0\x58\x36\xED\x7C\xF8\x4F\x05\x4A\xB1\x86\xBE\x5D\x23\xB4\xC4\x41\x09\x27\x5E\x85\x41\x08\x7C\x70\x05\x28\xBC\x34\xBD\xA1\x96\xAA\x08\xB1\x04\xCB\x80\x8F\x2B\x97\x64\x80\x02\x2C\x02\xB3\x03\x0D\x13\x79\x79\x32\xB3\x0B\x68\xB1\x0A\xAF\x73\x65\xB1\x21\x34\x04\x37\xBE\x42\xF0\xB1\x9C\xA3\x08\xB5\x04\xCE\xAB\xA8\x7E\x97\x67\x81\x0A\x2D\x1A\xB3\x57\x93\xB5\x05\xB3\x44\x4A\x10\x24\x2F\xA0\xA9\x08\xB7\x02\xCF\xBB\x6B\xB5\x27\x68\x86\x08\x2E\x1A\xB3\x4D\xB1\x20\x3F\x28\xA6\x9C\xCB\x47\x0F\xFB\x61\x2A\x94\xB5\x40\x20\x5F\xC7\xAD\x67\xB9\x06\x9E\xAA\xA0\x8B\xAD\xCF\x80\x00\x5D\x0A\x67\x81\x8E\x90\xA2\xB5\xBB\x05\xD4\xB8\x6C\x51", "\xB2\x10\x3C\x06\x9E\xBE\x8D\x40\xB4\xD5\xBD\x04\x48\xBA\x10\x5E\x25\xA6\xB5\x13\x91\xB0\x00\x23\x27\x5B\xB6\x88\x0A\x0B\x39\x2C\xB5\x00\x06\x17\x3A\xB3\xF0\x75\x50\x40\xB7\x2F\x0F\xB5\x0A\x0E\xA3\x00\xB6\x60\x08\x6C\x89\x0B\x4E\x20\xB6\xC1\x05\xD9\x86\x08\xA5\x2D\x68\x83\x0A\x30\x0A\xB4\x0A\x0B\xAB\x00\xB7\x61\x0F\x69\x8A\x09\x62\x20\xB6\xC4\x02\xCF\xBD\xA0\xE9\x2C\x6B\xCE\x12\x6F\x81\x34\xC0\xB5\x18\x12\xB7\x81\x06\x68\x40\xB6\x31\x0B\xB7\x02\x09\xD1\x00\xB7\x63\x0A\x67\xB9\x7A\x7E\x20\xB6\xC8\x05\xDE\x8A\x09\x02\x30\x6C\xC9\x06\x9E\xB4\xA0\x07\x30\xD8\x8A\x06\x3D\xBE\x0B\x83\x39\xB9\xB4\x11\xDF\x99\x20\x1E\x37\x83\xB8\x23\x5F\x60\x83\x20\xB6\xCB\x02\xCF\x9F\x63\x08\x30\x6C\xCC\x06\x9E\xB6\x9E\x46\x30\xD8\x8D\x07\x8B\xB9\x13\x40\xB4\x00\x0E\x06\x1C\xB9\x21\x3A\x32\x60\xBF\x0C\x21\xBA\x41\x03\xB9\xAC\xB0\x1A\x26\xB9\x81\x04\x6A\x40\xB5\x34\x0B\xB9\x02\x0D\xE5\xAC\xB4\x69\x02\x71\x8A\x0B\xB3\x20\xB6\xD3\x05\xE6\x89\x09\x69\x30\x6C\xD4\x06\x9E\xB2\x7C\xD8\x30\xD8\x95\x06\x7D\xB9\x10\x3B\x38\xB0\xBB\x0E\x92\x7C", "\xDB\x00\xB6\x6B\x04\x70\x8A\x09\xBE\x2C\xB8\x7F\x11\xE7\x63\x38\x60\xB7\x0D\x7F\xB6\x42\x19\x39\xC0\xB0\x1B\x3A\xB3\xDE\x7B\x74\x40\xB5\x36\x1A\xB3\x31\x66\xEA\x10\xBB\xED\x03\xE3\x58\x38\xB0\xBA\x06\x7A\xB5\xEC\x9E\xB9\x6D\x09\x76\x8A\x0A\xD6\x20\xB6\xDC\x05\xED\x89\x09\xB7\xBC\x6A\xDD\x06\x9E\xB3\x05\x95\x89\x20\x2B\x7E\xEF\x05\x66\x95\xB4\xB7\x01\x0A\x79\x8D\xEF\x9A\x27\xA0\x0C\x30\xC5\x0C\xE0\xBE\x13\xE0\x59\xF0\x92\xB3\x81\x0B\x77\xC7\x0D\x50\x11\x61\x7E\xB9\x38\x16\xB3\xC5\xB0\x3B\xF5\x11\x50\x19\xB5\x91\xBD\x38\x06\x8F\xCA\xB3\x43\xCE\x11\x50\x01\x7F\x9D\x47\xFD\x7B\x80\xC4\xBD\x3C\x41\x0A\x02\xB9\xBC\xFE\x14\x6A\x85\x11\xA0\x07\x25\xA8\xBF\xC3\x10\xBC\xAB\xBC\x81\xAE\xBC\x26\x19\x6B\xF9\x79\x99\xB5\x22\x76\x99\xF6\xBB\xA5\xCE\xB4\x23\x5F\x99\x42\x01\x7F\x8A\xBC\x69\xB9\x79\xC2\xB0\x1D\x61\x7D\x60\x86\xBE\xBA\xBD\xEA\x71\x9B\xAB\x14\x79\xC0\xA8\x00\x01\x8C\xEF\x7D\xF1\x89\x0F\xA0\x01\x4C\xC1\xBC\x0C\xB5\x23\xA2\xB9\xF9\x83\x09\x88\xAD\x41\x85\x13\x17\x61\xBD\xCB\xBF\x4F\x01\x0A\x7D\x75\xFC\x7E\x89\x9E", "\x71\x98\x03\xAA\xFA\x92\xBC\x85\x0C\x57\x83\x1F\x80\x09\xB8\x70\x41\x8F\x96\xBE\xC8\x89\x5B\xB3\xBC\x02\xA8\xBF\x16\xAC\xF8\x95\x0F\xA0\x0B\x5B\x9D\x44\x9F\xBC\xBC\x03\x0C\x82\x9D\x45\x2B\x9B\xD7\x5B\x0D\x50\x16\x71\xF6\xBD\x4E\x37\xAA\x03\xCA\x10\x21\xB7\x9B\xA6\x08\x91\xA8\xFF\xA6\xB7\x3C\xAC\x80\xAD\x25\x0F\xA5\xC0\x7C\xBC\xB2\x9A\x27\x1E\xAE\x1B\x95\xC2\x65\xA1\xBF\xA9\xA9\x20\x09\xC1\x0C\xBA\x77\xDA\xBE\x40\x0F\xAD\x02\x0D\xCA\x9B\x8D\xEE\xBE\x61\x80\xC0\x8D\x01\x0A\x3B\xB3\x20\x2A\xC1\x12\xAC\x42\xAD\xC1\x9D\xA3\x10\x41\x09\xD6\xB2\xC1\x5A\xBD\x7C\x9F\x8D\x0F\xDF\x62\xEA\xBE\xF0\x8A\x09\x5D\xB6\x7E\x83\x11\xF5\xA5\x9E\x6C\x98\x07\xFE\xB5\x1E\xCB\x1D\x5C\xBD\x0D\xD3\x9E\x24\xA2\x09\xC9\x09\x62\xB5\x84\x83\x0B\x43\x34\x9D\x0F\xB4\x05\xD0\x87\xD9\x92\x85\x86\x0B\x4A\x30\x3A\x03\x14\x7B\xA6\xC1\x80\x0F\x6C\xBC\xBD\x40\x03\x2A\x60\xC6\x7B\x88\xC3\x17\xC3\x4A\x3E\x87\x85\x82\xC2\x09\x0E\xA8\x29\xC2\x1A\x1E\x0B\xF0\xBE\x07\xC3\x08\x48\x2A\x76\x82\x09\xA8\x23\x87\x81\x08\x05\xA1\xC2\xD0\x09\x28\x13\x2A\x3D\xC8", "\x23\x35\x78\xF8\x54\xA0\xF3\xBD\xFD\x6F\x2A\x42\xCF\x27\x39\xAF\x21\xC1\xBF\x77\xC2\x20\x06\xB4\x33\xC0\x00\x2D\x2D\x15\xC2\x08\xFF\x92\x6C\x93\xB3\x45\x86\x79\x8A\x0B\x6C\x38\xC2\xB1\x1D\xAE\x55\x97\xE9\xB5\x12\x5A\x25\x5D\x61\xA6\x91\xC2\x52\x7B\x2C\x26\xCE\x1D\x62\x8C\x24\xA9\xC5\x7F\x15\xBA\x20\xC4\x27\x10\x49\xE5\x91\x99\xA9\x2F\x32\xA1\x79\x01\xA6\x5B\xC7\x64\xF7\xB6\x26\xC9\x1E\xE3\xA7\xDA\x4E\xBD\x51\x29\xE3\x42\xA8\x2C\xD5\x22\x39\x73\x14\xEB\xBF\x84\x03\x60\x7D\xC1\x0B\x89\xB3\x00\xB0\x15\xD9\xC1\x84\x0C\x6F\xEE\xBF\x40\x01\xB8\x97\xC1\x20\x0F\x6C\x68\xC9\x85\xBE\xC1\x27\xC9\x08\x0F\xBE\x1A\xF4\x10\x4E\xB2\x82\xB4\xB2\x26\x43\xC3\x00\x06\xC1\x35\x22\x8A\xB9\x8D\x80\x01\x04\xC5\xC7\x09\x0A\xA8\x8E\xC3\x63\xCA\x45\x35\x7B\x90\x8B\xC6\x34\x2D\xE6\x46\xC7\x69\xC4\x53\x35\x1E\x41\x19\xAD\xF4\xC0\x82\x39\xAC\xA6\x2F\x8D\x86\x09\x85\x2C\xC4\xDB\x0D\xB2\x91\xC3\xD0\xAE\x57\xE8\xC5\x8D\x28\xC8\xDE\x0F\x61\x83\x09\x18\x69\x5B\xD7\xC1\x17\xC3\x08\x5C\x30\x22\xC7\x0F\x18\xCF\x80\x8C\xCB\x8A\xAC\xC3\x09\x0E\xCE", "\x1A\xC9\xE4\x07\x6A\x9D\xCA\x40\x19\xAD\xE5\x25\x20\xC3\x08\x79\xB4\x89\xDB\x0C\x11\xCB\xC8\x27\xCE\xB5\xA8\xC6\x99\xB0\x93\xB8\x10\x15\xD5\xC9\xB8\xAA\x21\x04\xB3\x8B\xC2\x10\x2D\x35\x4B\xDE\x0E\x5F\xC4\x12\xF9\xAD\x70\x2A\x92\x82\x08\xAE\x23\xC9\xC1\x08\xD3\x82\xCA\x85\x0B\x59\x9E\xBE\x42\x05\x36\x8C\xC4\xE7\xAD\xC6\x6A\xB6\x10\x14\xC9\xE0\x68\xC7\x41\xBC\x12\xE0\x37\x76\xCA\x6D\xD5\xC9\x43\xC9\x08\x97\xAA\xFC\x8A\x08\x74\x3C\x88\x89\x39\x3B\xDF\xB6\x5E\xC9\x21\x3B\xAD\xF6\xBE\x94\xAD\x27\xFF\xA7\xAD\x45\xCD\xA4\x19\xC4\xC6\xB8\x8E\x99\x39\xD7\x95\x13\x82\xB4\x12\xF3\xCA\x17\xC8\x23\x41\x09\xCF\x29\xCB\x03\x15\xB6\x0C\xC5\xBD\xC7\x83\xED\xCA\x41\x09\x3A\x77\xCE\xD1\xBD\xC0\x72\xB4\x89\x8E\xC1\x40\x16\x71\xB0\xC4\xEE\x9C\xC7\xD8\x14\xD8\x10\xCC\x3F\xC3\x08\x5C\x3E\x19\xDB\x0F\x6D\xC2\x10\x04\xC8\x4F\xC1\x08\x5F\x3B\x16\xF4\x11\xF6\x22\x9A\xDA\xC7\x57\xDF\xCC\xC1\xB4\x15\xC7\x0E\x5F\xCB\x83\x89\x08\x67\xC1\x08\x16\xCE\x30\xC3\x09\xB3\x35\x9A\xFF\x11\x33\xCD\xC7\xAF\xCA\xC2\xB2\xCC\x81\x06\x77\x35\xCF\x76\x18", "\xC6\x49\xC3\x20\x39\xCD\x94\xC8\x9A\xFA\x3A\x6F\xDE\x0E\xE1\xC1\x38\xC2\x09\xDC\xC2\x29\xFB\xBF\x28\x39\xCD\x28\xC5\x2F\xCA\x08\xBF\x37\x9C\xC7\x0C\x3B\xCA\xCE\xA6\xC9\x21\x3B\xC9\xDD\xC1\x10\x03\x3D\x75\xC9\x0E\x07\xC8\x37\xCA\x08\xA2\xC8\x9A\x87\x3F\x77\xC1\x0E\x25\x35\x36\xF9\xCD\xA6\xC0\x92\x86\x0B\xE2\x35\xCD\x8F\x3D\x36\xCF\xC9\x5F\xCB\x9C\xD7\xC9\x5C\xC0\x00\x9A\x3D\x36\xE8\x3D\xDA\xC4\x65\x39\xC5\x7D\xC0\xCB\xE8\xC4\xF5\x35\xCD\xD8\x35\x9B\xEE\x32\x7F\xC1\x08\xE4\xC5\xB1\xB7\xCF\x2A\x2F\x8E\x80\x00\x7B\xD2\xCE\x75\x15\xF6\x27\xCF\xE2\x0D\xA0\xA0\xAD\x7B\xCE\x12\xB9\x3B\x42\xD0\x0F\x06\xD1\x96\x81\xC9\x72\x08\x3E\x1A\xD5\x3A\x21\xCA\x85\xC7\xA1\x82\x08\xF3\x21\xD1\x4C\x17\x41\xC0\x9A\x74\xC0\x7D\x28\xD1\x81\x16\xD0\x01\x0C\x44\xD0\xD0\x83\x05\x7D\x2E\xD1\x9D\x12\xC8\x9D\xC8\x1D\xD9\x3E\xCD\xC1\x91\xA7\xCC\x77\xC0\x00\xDB\x3E\x19\xE8\xB9\xC9\xC3\x10\x38\xD0\x6C\xC8\xC7\xDD\x3C\x47\xC7\x0E\x23\xDA\x9B\xA5\xD1\x40\x1F\x3E\x4A\xD1\x39\x0C\xD2\xE2\xCF\xA3\xE1\x3D\x94\xC1\x0E\x4C\xD1\x3A\xE2\xCB\x84\x00\x7F", "\x57\xD1\x71\x0C\xD2\xDB\xCE\x49\xC0\x00\xFA\x3E\xA5\xD0\x0C\x93\xC4\xCF\x3F\xD6\xFE\x25\xD3\xEA\x0C\xA4\xAA\xD0\x2C\xC1\x40\x75\x23\x00\x75\xCC\x74\xB2\x8E\x81\x08\x93\xD0\xD1\x5B\xD6\x20\x07\x41\x3A\x29\x80\x35\xCD\xBB\xB5\xD3\x00\x04\x49\xDD\xD1\xCB\xC2\x10\x0E\x41\x1D\x30\x40\xB5\xCC\x25\xC4\xD3\x13\xCA\x10\x37\xAE\x87\xC1\x0E\x14\x46\x46\xF6\xAD\xD5\xA7\x9F\xA0\x43\x9A\xC1\x0A\xC9\xAE\x5E\xA8\xCD\x2A\x29\x5C\xCA\xC4\x1C\xC6\x08\x2E\x46\x19\xCE\x35\x3A\x29\x5C\xD2\xC7\x30\xC9\x08\x30\x45\x8E\x3B\x41\xDA\xC2\x69\x75\x20\x47\xCC\xBE\xF7\xCC\x0A\x4E\xC7\x4B\x3E\xAA\xC7\xA7\x8F\xC3\x43\x75\x25\x0C\x75\xCC\x9A\xC2\x81\x82\x0A\xA6\xC3\x08\x9E\xCF\x47\xF1\xBF\x9F\xC7\x1C\x26\x34\x25\xDF\xD5\x31\xCF\x3E\xC3\x44\xA4\xC5\x1C\x31\x35\x62\xC3\x08\xC8\xD7\x48\xF7\xCE\x04\x0F\x87\x7A\xBD\x50\x1C\x35\x8C\xC1\x5A\xCD\xD3\x19\xD6\x14\xD5\xD5\x81\x17\xB9\xC7\xD2\x21\x14\xD2\x31\xD1\x89\x4C\xD4\x74\x19\xCA\x38\xCA\x5B\xDA\xD2\x58\xC4\x01\x5E\xD5\x9D\x1B\xCA\xE9\xD2\x27\xE8\xC6\x4C\x46\xAE\xD5\x0F\xD3\xA1\xD7\x09\x08\x4D\xE2", "\xD3\x4F\x45\xAF\xC1\x0A\x5D\xD8\xD7\x06\x0E\x4D\xC4\xD4\xE3\xAE\xAE\xFF\xC7\x1F\x48\x60\x46\xB8\x30\xD0\xD6\xFB\xC8\x9A\xBA\x44\x23\xC9\x47\xB5\xCF\xE8\x0F\xD6\x5F\xDB\x47\x68\xC5\x3D\x4C\xC4\x10\x4D\x36\xD4\x3B\x89\xD1\x30\x94\xD4\x6A\xC0\x49\x97\xD2\x21\x3A\xC0\x81\x0E\x63\xE2\xD1\x15\x25\xC9\x01\x0F\x55\xF9\xD3\x8B\x28\xB2\x80\x02\xB6\xCF\xD4\x4A\x21\x4C\xF4\xAD\x05\xD3\x2D\x21\xCC\xA0\xD6\xB5\xC7\x67\x3E\xE5\x49\x03\xD1\x41\x7A\xD7\xCC\xDB\xD4\xD3\x11\xEC\x35\x23\x97\xC9\xDC\x68\xC6\x4E\x5C\xD9\xE3\x13\x5C\xE5\xC1\xFB\xC0\x95\x1C\xDB\x9F\x03\x3B\x4E\xDA\x69\xCF\xC3\x1F\xD7\x97\x4E\xDB\x76\x18\x3B\x51\xD8\x12\xC3\xD8\x00\x07\x99\x4E\xDA\x6F\x55\xCD\xDE\xCA\x61\xC2\x09\x5F\xB6\x10\x0B\x28\xCD\xD0\x20\x64\xDB\x20\x38\x27\xB3\xD7\x42\x6B\xD9\xDD\x88\xC7\xC8\x4E\x6A\xDE\x0F\xC6\x3E\xB4\xEE\xD8\x76\xCB\xD9\x02\x0C\x3D\x72\xDB\xE3\x0B\x9F\xE2\xD9\x40\x16\xDB\x26\xCC\x5B\xC2\x09\x08\x5E\xB4\xC2\x51\x6D\xD3\x3D\x4E\xDF\x26\xC2\x08\xB3\xD0\xB4\x90\x22\xE2\xDF\xDB\xE8\xC5\x8A\x0C\xDD\x81\x01\x82\xF8\xD9\x40\x14\x52", "\x21\xD9\x21\x31\xCD\x1C\xD7\x9F\xE1\x51\xBF\xCA\x08\x20\xD4\x12\xDB\xDD\x9F\xDF\xA3\xFA\x53\xE7\xC9\x08\x2D\xD6\x6F\xC0\x01\xD1\xDB\xBA\xE8\xC7\xA4\x47\xDD\x06\x09\x48\xE2\xDD\x1B\xB2\xA6\xA8\x54\xEC\xC3\x08\x5D\xD3\x76\xC9\x08\xA9\xD0\x8B\xBD\x57\xED\xC2\x08\x72\xD2\x77\xC6\x09\x75\xDB\xB5\xDA\x57\xEF\xC1\x08\x0C\x44\x11\xEC\xDC\x99\xD6\xB9\xE9\xC5\xC1\xCE\x12\x91\xD2\x78\xC3\x08\x9F\xDD\xBC\x8F\x5B\xF1\xC0\x00\xA9\xD2\x7A\xE8\x8F\xFB\xC2\xB2\x0C\xC7\xD0\x55\xCD\xB8\xD2\x75\xEC\xDC\x3C\xD0\x8B\xCE\x58\x23\xC6\x04\x07\xD8\x77\xAC\x5A\xCD\xD5\xB1\xF7\xCF\xD7\x4C\xC4\x8C\x01\x7D\xFF\xBD\xF5\xD6\x10\x4A\xB6\x41\x1D\x29\x6C\xDD\x83\x36\xDF\x81\x01\x94\xBF\xD1\x15\x3D\xDF\x9C\xD8\x35\xE5\x5B\xEB\xDC\x00\x4F\xDE\x40\x00\xE0\xA4\xDA\x4C\xD2\x04\x03\xED\x70\xF4\xDC\xFF\xCA\x08\xAC\xD8\x16\xD6\x04\x06\xEF\x27\x15\x44\x23\xC8\xE0\xDB\xD5\x79\xDA\x04\x0A\xEB\x1D\x19\x00\x05\xF8\xE0\xBC\xDB\x6B\xDE\x04\x0E\xEE\x1D\x1D\x03\x07\xF2\xC9\xF7\xCA\x14\x24\xE1\xE3\x01\x02\x27\xE2\x76\xC8\xC7\x78\x5F\x7A\xF7\x45\x0B\xE3\x9E\xE8", "\xC4\xE0\x57\xDE\xDF\x44\x86\xDA\xAC\x74\xCF\xB9\x0C\xC5\xEC\x55\xCD\xF7\x46\x69\xD8\xE0\xF2\xDB\xB5\xB4\x04\x05\xF8\x05\xF2\xDE\x20\x20\xD8\xD5\xD8\xC1\x83\xD7\xA9\xC6\x08\xBA\x04\x82\xFE\x05\x24\xE3\x10\x48\x4A\xD7\xCA\x08\xF8\xDD\x71\xE7\x21\x2C\xE4\xB9\xE8\xC4\x30\x1A\x4E\x93\xB1\x67\xE8\xCD\x60\x09\xB7\x7E\x16\x52\xDD\xE2\xF7\xCC\x18\x1A\x4F\x33\xE2\x10\x68\xC2\x16\xFD\x20\x6E\xE3\x20\x32\xC3\x37\xE5\x1C\x45\x04\x15\xF4\x11\x73\xE0\x8D\xE8\xCD\x63\x0A\x9D\x79\xC2\x18\xFF\xD1\xC8\x02\x3B\x54\xCA\x3C\xC1\xB9\xDA\x21\xB0\xC1\xE0\x3F\xD1\x19\x2B\xE1\xE4\x08\x96\x0C\xC7\x21\xE9\xE0\x82\xD9\x20\x0D\x07\x45\xE1\x1C\x01\x4E\xD3\xCF\xE4\xAD\xDF\x3E\xD1\x06\x4A\xE5\x1C\x26\x4E\x23\xF4\xDD\x91\xE0\x00\x15\x06\x4E\xE0\x1D\x41\x4F\x27\xFB\xDD\xE8\xC1\x1B\x24\xE5\xEA\x0E\x9D\x27\xE7\xF0\xC8\xC7\xDD\x03\x95\xC1\x0A\xFC\x4E\xCA\x83\x08\xF3\xD0\xC5\xE1\x02\x96\xCA\x09\x0D\x55\xCB\x82\x08\xF5\xD0\xC5\xE5\x02\x97\xC9\x08\xC3\xD4\x89\x98\xE6\xC0\xCF\xE2\xB8\xDC\x82\xED\x07\x3B\xE1\x10\x63\x53\x25\xEC\xD8\x3F\xD7\x1D\x14\xE1", "\x79\x0C\xCC\x80\x01\xA2\x4F\xE6\x00\xD7\x3E\xF5\x06\x0A\xE9\x0F\x55\xE6\xA8\x4E\xDA\x4F\x2E\x20\x18\xE4\x58\xCB\x0F\x55\xE7\x76\x1E\xDD\x80\xD1\x9C\xDE\xC8\xD4\xCD\x0F\x66\xE6\x77\x05\x56\xB5\xCA\x9D\xE5\x4D\xC8\xDE\xCE\xC7\x0C\xB3\x55\x23\xF2\xE3\xC0\xBF\xD1\x00\x09\xBF\x09\xC5\x40\x06\xDE\xE9\xE2\x5C\xE8\xC7\x01\x0D\xCF\x85\x10\xB7\x58\xE7\x28\xE0\x35\xC5\x01\x82\xE5\x27\x5F\x54\x42\xEF\xE1\xF7\xCF\x00\x0C\xE9\x01\x19\xAE\x0F\xEA\x41\x1F\xE5\x5B\xD9\x01\x13\xE8\x27\x1F\xAE\x16\xEB\x40\x07\xE6\xA4\xC7\x35\x9B\xE9\xA7\x83\xD2\x81\x08\xBE\x51\xE7\xD0\xE2\x4C\xCF\x01\x92\xEB\xFC\x2C\xEB\xC2\x48\xE9\xD9\xE0\x35\xD3\x00\x96\xE5\x01\x2C\xE8\xC5\x55\xCD\x83\xC2\x9C\xE8\xC7\x0B\x09\xBF\x23\xC3\x40\x19\x58\x75\x21\xA7\xEB\xE7\x1F\xD8\x01\x3D\xE9\x81\x1D\xDE\xED\xC2\xA8\xF3\xE7\xFB\xC9\x01\x46\xE9\x9D\x15\x59\x41\xE8\x94\xCD\xDE\x0D\x0E\xD4\x83\x11\xD0\x51\xEA\xA8\xE7\x3E\xDB\x01\xAA\xEE\x24\x5F\xDC\xA0\xCA\xEA\xB7\x60\x1D\xDC\x00\xAE\xE4\x23\x45\x58\x56\xE3\xB2\xE8\xC5\x03\x24\xEA\x1C\x16\xBE\xDF\xE9\x0D\xF7\xCF\x1E", "\x03\xAD\xFF\x12\xAA\x57\xD6\x9F\xE8\x3A\xDF\x00\x72\xE8\x04\x2C\xE8\xAB\x58\xD3\xA9\xE9\x28\xE2\x01\x72\xEB\x04\x2C\xE8\xF4\xDD\xD7\xB1\xEB\x8F\xC5\x01\x72\xEE\x04\x2C\xE9\xF7\xDC\x95\x8A\x08\x1F\xC8\xCD\x28\x02\xAE\xE3\x17\xAE\xC3\x10\x60\xE9\xF3\xC9\x01\xF9\x59\x30\xAD\x00\xC9\xEE\x1D\x0C\xB6\x41\x0F\xEC\x3F\xD6\x05\x1C\xED\x68\x1E\xD9\x95\xEC\x3A\xCF\x01\x99\xE8\xB5\xA3\xED\xE4\x0D\x56\x3A\xEB\x7D\xD4\x01\xF9\x5B\x06\xC6\x08\x45\x05\xCD\xAD\xEF\x50\xE2\xD3\x37\x01\xB6\xC5\x11\xF8\xDC\xB3\xB6\xEF\x52\xE8\xCD\x3A\x02\xB7\xF5\x13\x47\x05\xDB\xD2\xE8\x2C\xDD\x01\xC2\xEB\x40\x27\x5B\xDA\xCE\xDB\x81\x09\x08\xE8\xE6\x02\x08\x08\x09\xEE\x27\x13\x09\x45\xEE\x2F\x68\xC7\x43\x03\xBA\xF4\x11\x4A\x06\xDD\xE8\xEB\x7D\xC6\x02\xDA\xE8\x47\x17\x05\xEE\xE3\xBD\xE8\xC5\x12\x01\xEF\x7F\x16\x6D\x4C\xEE\xA6\xC8\x8E\xCC\x00\x7A\xEF\x02\x2C\xEB\x13\x23\x45\xE6\xE0\x00\x44\xE0\x74\xE1\x08\x51\x00\xBD\xD4\x02\x96\xE3\xC2\xBD\xED\xFB\xC8\xCD\x56\x00\xBD\xD9\x02\x96\xE1\x0A\x23\x45\x5F\x29\x08\xE3\xE3\x6B\xDB\x02\x96\xEB\x1D\x24\x05", "\x35\xE7\xF0\xFF\xC0\x1D\xDD\x02\x06\xFE\x1D\x31\xE0\x7D\xC1\x08\x10\xF6\x0A\xE8\xC7\x2F\x04\xE1\xC7\x0E\xDF\x55\xCD\x19\xF7\xC4\xA2\xD3\x30\x0D\xE1\xC9\x0C\xE1\x40\xF1\x02\xEF\x3E\xE3\x03\x12\xF1\x1C\x12\x5C\x8A\xF7\xEE\xF7\xCD\x0C\x2C\xF1\xE2\x01\xBA\x2F\xF2\x77\xE8\xCD\x67\x03\xC6\xD0\x0E\xD5\x56\xE3\xE5\xEF\x7D\xC9\x03\x3A\xF5\x3A\x38\xBB\x1E\xFB\xBD\xA8\xCF\x1A\x0C\xE9\x6D\x04\xA5\xF5\x04\x03\xFE\xD7\xCD\xDF\x1B\x0C\xE9\x71\x04\xA5\xC8\xE2\x9E\xD1\xE2\xE5\x8C\x3A\xD3\x03\x2C\xED\x0E\x2C\xE9\x5D\x03\x8A\x68\xCB\x40\x0B\xC4\xA8\xCF\x0E\x2B\xEC\x6C\x1E\xE5\xCB\x50\x3A\xD8\x03\xA9\xE9\x21\x3C\x03\x31\xF5\x1C\x15\x2D\x42\x15\xF2\xCD\xDB\xB4\x0A\x08\x30\xFF\xA3\xFD\x00\x9B\xFE\x17\x93\xC3\x20\x2E\xF2\xD4\xCE\x07\x69\xF2\x41\x02\x04\x77\xF5\x3A\x26\x2C\xD7\xE8\x9A\x83\x06\x9F\xEE\x12\x53\xE4\x67\xC3\xF5\xDB\xE1\xCA\x87\x07\xA1\xF4\x11\x64\xE4\x11\xCB\xF5\xDF\xEF\xA3\x8B\x07\xA3\xF8\x11\x76\xE2\xD1\xC6\xEF\xAD\xDF\x08\x17\xF7\x9F\x01\xE4\x9A\xF1\xAB\xE8\xCD\x49\x0E\xE9\xDB\x0F\x32\x03\x45\x93\xF1\xAC\xF7\xCF\x4B", "\x05\xEA\xDE\x0E\x33\x08\xF5\xF2\xD7\x3E\xDB\x05\x56\xF7\x1C\x1B\xE5\xA8\xF7\xE8\xE8\xC7\x13\x34\xF5\xE4\x04\x0D\x30\xF7\x0E\xF7\xCF\xA3\x06\xD3\xE7\x04\x96\xE7\x0D\x14\xE1\xAA\xF5\xEF\x75\xCE\xD3\xED\x04\x96\xEB\x0D\x46\xF7\x7F\xFF\xD1\xAF\x06\xD3\xF3\x04\x96\xEF\x0D\x14\xE1\x5E\xC3\x08\xA9\x2F\x3E\xF5\x05\x20\xFC\x24\x16\xC7\x40\x1F\xC4\x74\xE4\x8B\x1E\xF6\x81\x02\x98\xE1\xF5\x11\x20\xF7\x03\x09\xB6\x37\xCF\x5B\x0C\xED\x85\x11\xB9\xE9\xF7\xE8\xC1\x17\x2D\xF7\x3A\x18\x5B\x06\x08\x6F\x37\xCF\xBB\x02\xAE\xFC\x05\x79\xF6\xEF\x9E\xC5\x21\xF1\x16\xE3\x00\x1E\x77\xF6\x83\x0F\xEE\xA6\xDB\xB4\x04\x07\xF0\x44\x31\xC3\x08\x59\xC6\xEE\xC1\x0A\x2F\x1C\xF7\x0B\xFA\x21\x3A\x2D\xFB\xC0\x0C\x01\xF4\x93\x06\x2F\x84\xF7\x47\xC1\x07\xFC\x56\x7B\x8A\x09\x30\xEC\xC4\x18\xF8\x58\xE8\xC6\x63\x0C\xF1\x85\x11\x3A\x14\xE0\x21\xF8\x91\xE2\xD3\x65\x05\xF2\xF5\x13\x32\xE0\xF9\x3E\xD2\x4C\xD0\x07\x96\xF3\x20\x71\x06\x03\xE2\x08\x29\xF8\x92\xCD\xDF\x6A\x04\xF3\xCE\x12\x3D\x17\xF9\x01\x09\xE7\xF9\xC9\xFB\xCA\x0D\x3D\xF8\x8D\x05\xE7\x4E\xDA", "\xE8\xD1\xE1\xAD\xDF\x0D\x46\xF9\x5F\xDE\xF4\x4A\xFA\x47\xCE\xFB\x3F\x14\x00\x50\xF8\x04\xE8\xC7\xE9\x03\xEA\xDB\x0E\x04\x06\xF5\x9F\xC9\x28\xEE\x07\x5A\xFE\x3B\x0C\x01\xAE\xF0\x5C\xE8\xC7\x3C\x01\xFB\xC7\x08\x02\x24\xFB\x11\xB8\x9A\xF8\x04\xDA\xE9\x0E\x14\x03\xED\xD1\xEE\x74\xCD\x0F\x6F\xF9\x70\x05\xEA\x30\xFA\xD4\xFF\xD0\x01\x0D\xBD\x1D\xFA\x36\xB2\xFB\xCE\xE8\x1D\xC7\x01\xBE\xF5\x20\x7A\xE9\xDE\xEF\xE5\xF7\xCC\x01\x04\xFD\x3A\x14\x02\x00\xFC\x00\x04\xDE\xF7\xEB\xF9\x4B\xFD\x01\x11\xD9\x87\xFF\x40\x10\xFC\x21\xEE\x77\x53\xFC\x27\x1C\x02\x0E\xFD\x80\x3A\xEA\xDD\x5E\xA7\xF4\x10\xA1\xF7\x9B\xBF\xD0\x07\x01\xFD\x5A\x1A\xE8\xF7\xE5\xAD\xDD\x01\x1B\xFC\x8D\x10\x01\x8E\xFB\xF5\xD1\xFC\x11\x0E\xFA\xB8\x10\x6C\xF6\xFC\x02\x0A\xF6\xD9\xFD\x81\x07\x02\x35\xFF\x9F\x18\x01\x8E\xF8\xA3\xD1\xFC\x16\x0E\xFB\xDB\x0C\x0F\x01\xFE\xE8\xC1\x06\x05\xFE\xEF\x02\xDD\xB8\xFD\x40\x02\xFE\xBB\xF8\xBC\x8B\xFF\xE3\x04\x04\x0E\xFD\x78\xDF\xD1\x3B\x00\xF5\xDC\x1C\xA1\xF0\xD2\xF8\xC6\x2D\xFE\xFD\x41\x05\x7B\x48\x60\x24\x03\xF5\xDC\xFC\x76", "\xFE\xFD\x48\x02\xFC\xCA\x09\x26\x05\xFE\xEC\xEF\x7D\xCA\x02\xBE\xFF\x09\x2A\xFF\x84\x02\x05\x6D\xFD\x6B\xB7\xCF\x51\x06\xF7\xD6\x03\xF9\xF6\x10\x57\x02\xFD\xFC\xAC\xF7\x64\x16\x0E\xFB\x5D\x01\xFC\x7F\x40\x0C\x05\x3F\x7F\x03\x06\x7D\x71\xFD\x41\x04\x5F\x02\xEF\x74\x06\x05\x80\x02\x04\x89\x79\xF4\x4F\x7B\x62\x6A\x19\x0E\xFB\x6B\x01\x10\x81\x40\x06\x06\x08\x80\x02\x06\x13\x7B\x00\x80\x00\x6D\x02\xEF\x72\x07\x19\x80\x00\x03\x91\x73\x01\x86\x76\x62\x68\x1D\x0E\xFB\x79\x01\x24\x80\x1C\x03\xF5\x64\x66\x06\x07\xAC\x17\x9F\x7B\x01\xDA\x7E\x41\x0C\x07\x24\x80\x5A\x79\x1D\x16\x5F\x09\x04\xB8\x60\x9F\x75\x03\x89\x0F\xAC\x66\x40\x0B\x03\x8D\x7C\x5A\x0F\x7F\x10\xAB\x3F\x7B\x27\x13\xE7\x76\x10\x06\x81\x44\x80\xE7\x05\xFA\x42\x04\x32\x80\x6A\x6F\x07\x3F\x80\x02\x04\x20\x04\x02\xB6\x01\x72\x75\x35\x67\x6E\x28\x63\x82\x00\x15\x88\x23\x22\x79\x75\x12\x16\x8A\xB6\x28\x63\x83\x02\x17\x8F\x27\x28\x79\x3C\x6E\x18\x81\x10\x18\x6B\xA8\x64\x21\x06\x06\x9B\x07\x7B\x00\x7A\x70\x9C\x42\x04\x3D\x83\x8F\x65\x08\x2F\x81\xD3\x0A\x82\x19\x10", "\x2B\x1A\xF7\x66\x21\x06\x06\x87\x02\x24\x81\x9F\x75\x47\x09\x67\x02\x07\x84\x19\xBF\x68\x2B\x0A\x06\x3A\x6D\x04\xB1\x0E\x8A\x83\x40\x0C\x07\xA8\x66\x89\x02\x19\x8A\x08\x24\x80\x7F\x02\x5C\x77\x9D\x45\x82\x48\x81\x07\x17\x09\x81\x04\x8D\x82\xC1\x70\x41\x06\x82\x06\x05\x1D\x82\xA6\x4C\x02\x78\x81\xB4\x07\xFD\x42\x04\x7A\x83\x22\x89\x3C\x17\x18\x09\x05\x7A\x6A\x0A\x82\x04\x8D\x00\x09\x8B\x1D\x2E\x82\x03\x06\x28\x81\xCA\x4F\x02\xA5\x80\xB7\x04\x0B\x82\x04\x33\x1B\x21\x8C\x45\x3D\x82\x36\x81\x26\x8A\x44\x00\x83\x03\x07\xC0\x7F\xA3\x50\x02\x66\x81\x24\x04\x02\x80\x02\x72\x77\x7C\x65\x0C\xA8\x63\x93\x02\x19\x84\x09\x24\x80\x81\x02\x5C\x7E\x63\x3C\x80\xE8\x62\x25\x09\x0B\x98\x0B\x19\x5D\x30\x8E\x0B\x85\x11\xDD\x83\x4F\x72\x0C\x9C\x11\xFD\x66\x41\x0C\x0A\xAF\x82\x02\x11\x46\x66\x10\x29\x19\xDF\x81\x50\x07\x09\x32\x82\xDE\x04\x3B\x81\x0A\xA8\x63\x99\x03\x36\x8B\x2E\x32\x83\x03\x06\x81\x68\x0E\x91\x10\xFA\x83\x40\x02\x92\x7B\x83\xE3\x09\x3F\x82\x10\x06\x83\x62\x6A\x26\x06\x06\x9B\x02\x24\x80\xA0\x75\x47\x31\x19\x09\x04", "\x41\x81\xCA\x5D\x02\x66\x82\x27\x04\x02\x86\x7A\x75\x13\x3F\x85\x0B\xA8\x63\xA0\x02\x3D\x8E\x2F\x03\x69\x02\x06\x45\x8E\x09\xA7\x10\x1C\x85\x40\x0C\x10\x80\x84\xD3\x08\x9D\x63\x10\x25\x83\xFE\x6E\x16\x1F\xA7\x58\x64\xE3\x81\x11\x1A\xA8\x74\x81\xE8\x61\x28\x0A\x11\x8F\x0C\x2F\x85\x40\x03\xAA\x64\x84\xD1\x0B\x4D\x83\x10\x34\x6A\x38\x84\xB7\x0A\x13\x83\x84\xE8\x62\x28\x06\x06\xA3\x02\x24\x80\x21\x02\xD7\x6D\x6A\xFD\x7B\x7D\x65\x0A\x26\x81\xA6\x00\x09\x85\x08\x32\x75\x3C\x87\x45\x87\x9F\x68\x02\x33\x84\x93\x0C\xAB\x41\x04\x51\x87\x47\x8D\x41\x17\x85\x00\x00\x52\x89\x12\x90\x10\xC6\x6A\x23\x85\x97\x66\x81\xAA\x00\x3C\x87\x1C\x0F\x82\x03\x05\xAA\x17\x9F\x6C\x02\x55\x85\x81\x0E\x93\x43\x04\x51\x83\x8F\x6D\x0A\x26\x81\xAE\x02\x59\x89\x1C\x31\x85\x02\x06\xB3\x68\x9A\x70\x02\xDD\x2E\x6C\x7E\x24\x35\x1A\x06\x06\xAE\x1D\x0E\x9A\x0D\x80\x87\x40\x0C\x06\x9F\x85\x27\x12\x60\x86\x10\x07\x65\xA8\x67\x2C\x06\x17\x98\x0B\x87\x86\x51\x68\x8E\x75\x02\x8F\x87\xBA\x01\x6C\x01\x86\x2D\x84\x93\x06\x08\x32\x75\x97\x86\x61\x89\x19\x85", "\x08\x8E\x79\x1D\x1D\x6C\x3B\x81\xE8\x63\x2D\x06\x06\xB8\x02\x24\x80\x22\x02\xD7\x60\x6B\x03\x05\xB5\x13\x18\x9C\x0E\xAC\x86\x40\x01\x6D\x2F\x86\xB1\x0F\x6C\x86\x10\x28\x85\x62\x6A\x2E\x06\x06\xBB\x02\x24\x81\x22\x02\xD7\x52\x65\xAD\x87\x67\x8C\x39\x00\x87\xB2\x86\x70\x81\x3B\x2E\x86\x06\x07\xBF\x6F\xA3\x7D\x02\x6D\x85\x42\x0A\x08\x32\x75\xC8\x84\x5C\x88\x8E\x7E\x02\x24\x80\x30\x04\x02\x96\x7A\xB5\x64\xBA\x62\x10\x10\x65\x3D\x84\xB6\x0A\x1D\x81\x04\xDA\x18\x6D\x89\x3C\x21\x87\xC9\x84\x3A\x62\x0C\x0D\x87\x06\x05\x23\x02\xD7\x64\x87\xD2\x87\x7D\x63\x0C\x24\x80\xC5\x00\x09\x8E\x08\x2C\x74\x4A\x5E\x41\x0C\x1D\x88\x86\x1D\x11\x7D\x83\x10\x2C\x87\x5A\x86\x12\x1B\x70\x46\x04\xA3\x85\x77\x8B\x2E\x30\x6B\x02\x04\x59\x6B\xC7\x68\x87\x4E\x08\x81\x81\x10\x0A\x86\x80\x70\x82\x89\x17\x84\x78\x0A\x05\x64\x81\xCA\x49\x03\x0E\x89\x40\x02\x09\x2C\x74\x06\x8B\x40\x0C\x20\xBD\x87\xFE\x08\x25\x08\x21\x91\x88\xC6\x86\x93\x06\x09\x2C\x74\xEF\x19\x42\x02\x6E\x37\x67\xCA\x01\x5F\x8A\x35\x37\x6B\x03\x05\x89\x82\x20\xBE\x0B\x06\x5E\x41", "\x07\x22\xA8\x66\xCD\x02\x8A\x8C\x39\x26\x65\x03\x06\x72\x82\xF3\x55\x88\x7F\x08\x8E\x80\x05\xA8\x63\xD1\x00\x09\x83\x0D\x24\x80\x98\x02\x5C\x7A\x23\x81\x04\x78\x85\x28\x75\x0D\x26\x81\xD6\x00\x09\x89\x09\x32\x75\x53\x5E\x41\x09\x21\xA2\x69\xD8\x00\x8F\x8A\x09\x10\x89\x0A\x07\x86\x81\xCA\x59\x03\x3C\x8B\xAC\x7C\xB3\x51\x89\x9E\x84\xD1\x7C\x23\x9E\x02\xE8\x77\xCB\x19\x10\x17\x1C\xF7\x67\x36\x0C\x23\x9B\x07\x58\x5E\x41\x06\x26\xAF\x88\x0F\x0D\xC2\x63\x10\x28\x89\xA8\x64\x37\x05\x19\xBE\x0B\x7F\x67\x40\x02\x74\x37\x67\xDE\x02\x19\x8F\x0D\x37\x89\xD5\x07\x9E\x86\x10\x05\x1D\xE2\x87\xED\x02\x28\xB8\x59\x21\x8A\xA1\x8A\x10\x08\x66\x70\x88\x93\x04\x28\x86\x04\x12\x6F\x3E\x81\x0E\x00\x8A\x41\x05\xA4\x88\x28\x85\x8A\x02\x12\xA5\x82\x10\x0C\x8A\xF8\x86\x12\x1C\x29\xAA\x7C\xA1\x73\x38\x03\xFD\x49\x07\xA1\x03\xD4\x7F\x29\x81\x04\x09\x79\xE4\x78\x0E\x23\x8A\xC1\x06\x29\x06\x2A\x8A\x04\xA9\x8B\x07\x8D\x0E\x2C\x8A\xC5\x07\x2A\x0F\x2A\x83\x56\xE8\x62\x3C\x04\x2B\x90\x07\xB0\x01\xFE\x29\x6B\x67\x8A\x43\x7C\x6A\x67\x0F\x3B\x8A", "\xD5\x06\x2D\x0E\x2B\x8B\x8A\x31\x7D\x28\x7C\x0F\x04\x8B\x41\x07\xBE\x79\x10\x3F\x8A\x57\x7F\x7D\x61\x00\x3C\x45\x7E\x7E\x41\x02\x0C\x37\x8A\x06\x07\xD2\x71\xF9\x46\x00\xD4\x89\x81\x07\x0C\x18\x8B\x1A\x7B\x7D\x6B\x00\x1D\x8B\x75\x08\x33\x00\x2E\xA2\x78\xA1\x70\x04\x04\x2E\x83\x08\xD1\x03\xB9\x8A\xCF\x62\x69\x15\x03\xBA\x8E\x24\x16\x03\xEE\x89\x06\x70\x8B\x5A\x00\xF2\x88\x8D\x0B\x0D\x35\x8B\xCF\x77\x07\x8F\x01\x39\x8B\x38\x08\x38\x0C\x2F\xA8\x63\x24\x00\xC0\x8F\x27\x25\x03\x03\x8F\x7D\x69\x02\x06\x8C\xDB\x06\x3A\x05\x2F\x98\x7E\xDE\x7E\x40\x0E\x02\x0C\x8C\xDE\x07\x3B\x0F\x30\xA8\x63\x33\x00\xC5\x87\x1C\x34\x03\x17\x8F\x7D\x68\x03\x1A\x8C\xC9\x05\x3E\x05\x2F\x8A\x81\x3F\x69\x0F\x0A\x67\x5B\x07\xFE\x02\x5C\x70\x2C\x8F\x81\xA1\x72\x0F\x07\x32\x92\x08\x2A\x8D\xAC\x78\x9A\x7F\x00\x20\x8E\xE4\x5E\xFB\x40\x8B\xBA\x7D\xC4\x81\x10\x04\x01\x35\x8D\x71\x05\x00\x37\x8C\x32\x8F\x8F\x69\x04\x3D\x8C\xD0\x06\x02\x00\x34\xB9\x6B\xE8\x62\x13\x04\x34\x95\x07\x0F\x03\xD1\x88\xEB\x77\x67\x53\x03\xD2\x81\x14\x14\x00\x4E\x8E\x8F\x78", "\x9A\x58\x01\x52\x8F\x1A\x55\x35\x82\x04\xA7\x81\x28\x7D\x05\x2F\x8C\xC7\x06\x07\x06\x06\x80\x8B\xDD\x7F\xA7\x63\x10\x1E\x01\x06\x8F\x18\x0C\x17\x58\x3D\xDD\x2C\xB4\x8F\xEB\x68\x66\x65\x02\xC1\x8A\x06\x2B\x8D\xB6\x21\xDB\x88\x2C\xAF\x8D\x3F\x68\x1B\x06\x30\xB1\x01\x74\x8E\x6B\x66\x37\x89\x04\xC0\x8A\x02\x8A\x33\x80\x00\x73\x02\xC1\x88\x07\x3D\x8D\x8C\x13\xDF\x87\x98\x4D\x79\xB0\x62\x1E\x06\x30\xBF\x01\x88\x8D\x15\x7A\x38\x83\x04\x81\x8C\x3A\x61\x08\x06\x8C\x86\x01\xE4\x82\x10\x3D\x00\x93\x8F\xA6\x84\x01\xA1\x72\x88\x02\xC1\x8D\x08\x1A\x8E\x01\x07\x10\x0D\x39\x81\x04\xC0\x8A\x07\x83\x38\x8F\x02\x06\x8C\x25\x04\x3A\x80\x00\x49\x03\xE9\x80\x00\x29\x8E\xD9\x82\xC1\x8B\x09\x2F\x8E\xF2\x7F\xB3\x8A\x10\x1D\x5D\x06\x05\xD3\x18\x29\x91\x10\xBC\x8C\xE5\x89\x28\x82\x10\xBE\x8E\x41\x00\x74\x37\x67\x9D\x00\xD8\x8C\x2D\x0F\x1D\x17\x58\x6A\x6E\x09\x0A\x8F\xC1\x05\x15\x06\x06\x8C\x8F\x7A\x89\xAE\x7F\x3A\xA1\x02\xAF\x8F\xFE\x75\x47\x22\x5D\x06\x07\xA1\x82\xA6\x63\x02\x7A\x58\x29\x0F\x3A\x97\x01\x66\x82\xD9\x56\x10\x1B\x6C\xA8", "\x66\x29\x00\x3D\xAB\x0B\xE6\x8D\xF5\x87\x9F\x67\x02\x7A\x58\x2A\x0F\x3A\x82\x80\x75\x12\x64\x62\x10\x28\x8F\x3F\x6A\x2A\x0B\x3E\xBE\x0B\xF6\x8D\x40\x0E\x3D\xA1\x72\xAB\x02\x9E\x5C\x0A\x2F\x8E\x59\x03\x6E\x87\x64\x46\x60\xF2\x2F\xE1\x57\x64\x48\x30\x1E\x5D\xAF\x6D\xFE\x39\x5D\x0E\x90\x3C\x69\x1A\x2E\x5E\xFF\x03\xE6\x51\x41\xB4\x32\x16\x92\x04\x90\x1C\x41\x5E\x79\x44\x80\x4B\xA8\x7C\x65\xC3\x69\x6D\x64\xCB\x0C\x90\x5F\x5A\x6B\x06\xC4\x06\x59\x5A\x6C\x53\x0A\x7F\x7F\x03\xAA\x5D\xF8\x54\xCB\x01\x46\x58\x06\xED\x5F\xFD\x31\x30\x31\x91\x99\x54\x43\x8F\x5E\x65\x59\xAE\x52\x16\x3A\x90\x52\x05\xAE\x58\x15\x3E\x90\x97\x5D\x99\x50\x88\x4A\x05\x43\x93\x3F\x01\xFE\x18\x05\x47\x93\xE7\x52\x44\xA5\x59\x02\x4B\x84\x45\xBE\x19\x5F\xD8\x40\x13\x9E\x27\x00\x00\x18\x60\x53\x05\x45\x99\x3C\xB4\x33\x5E\x39\x45\xA4\x4D\x41\x07\x5E\x3E\x43\x9E\x91\x5D\x90\x17\x9D\x39\x46\x04\x5F\x92\x18\x99\x39\x7C\x6C\x54\x91\x0B\x5A\x3A\x61\x5F\x69\x90\x23\x6D\x46\xAF\x6D\x63\x90\x5D\x61\x47\x82\x04\x47\x93\x5E\x35\x47\x8A\x04\x77\x91\x6D\x6F\x46", "\xB7\x6D\x7B\x90\x08\x9D\x47\x9A\x61\x06\x07\x5E\x3C\x40\xB5\x40\x61\x93\x91\x51\xFF\x33\x91\xED\x3F\x5E\x3F\xFE\x3F\x91\x4E\x93\x19\x91\x20\x66\x5E\x8E\x06\x02\x52\xBF\x27\x5E\x90\x91\x1D\x19\x60\x6D\x3F\x57\x4A\x58\x09\x49\x92\x05\xAD\x5C\xEB\x53\x45\x9D\x92\x68\x50\x56\x0D\x81\x55\x05\xA3\x91\x52\x0E\x1B\x58\x05\x3D\x52\x58\x09\x4A\x92\x05\x5E\x59\x50\x0D\x43\x74\x32\xD6\x4E\x58\x01\x4B\x92\x05\xD6\x4C\x56\x05\x4B\x81\x05\xB7\x93\xED\x4E\x1A\x2F\x61\x3E\x05\xEF\x34\x43\xBE\x92\x41\x04\x30\x9A\x4B\xAA\x6E\x00\x02\x30\x9B\x42\x70\x90\xBD\x3C\x32\x9C\x46\xBD\x3E\x4B\x4C\x33\x91\x4C\xAA\x91\xC5\x90\x34\x9E\x4C\x83\x93\xAD\x67\x0A\x54\xCB\x3D\x3E\xD7\x93\x14\x98\x4D\x8F\x93\x96\x93\x36\x94\x4D\x91\x90\xD1\x93\x91\x5D\xFB\x18\x05\xE3\x90\x37\x9C\x34\x65\x93\xDF\x91\xFB\x3E\x4D\xAB\x50\xE4\x91\x0F\x61\x4E\xAD\x63\xEF\x90\x1F\x97\x42\x69\x93\x53\x6F\xF2\x49\x1E\x2C\x45\x49\x07\x17\x38\x15\x3F\x47\x0C\x4B\xED\x2B\x66\x41\x05\x76\x61\x55\x01\x50\x89\x05\xF0\x5C\x56\x00\x7F\x74\x32\x3E\x4C\x50\x09\x50\xBD\x04\x58\x59", "\x50\x0D\x50\xB7\x5F\xED\x3F\x43\x9D\x3E\x40\x47\x12\x96\xFD\x45\x66\x55\x94\x46\x41\x99\x54\x41\x62\x05\x1B\x96\x54\x02\x80\x53\x8D\x53\x93\x47\x9C\x33\x47\x59\x2F\x4B\x51\x05\x52\xBE\x04\x92\x3C\x2D\x39\x52\x81\x05\x2B\x97\x0A\x61\x42\x8A\x5F\x47\x5B\xCD\x4C\x14\x32\x94\x46\x07\x8C\x38\x15\x36\x94\x41\x04\x4E\x9B\x41\x4C\x4D\x3A\x95\x42\x0D\x53\x89\x44\x4C\x04\x63\x4F\x0F\x35\x35\x58\x04\x51\x91\x14\x06\x95\x47\x58", }; vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); } const wchar_t* RuleParserRuleName(vl::vint index) { static const wchar_t* results[] = { L"Cond0", L"Cond1", L"Cond2", L"Cond", L"SwitchItem", L"Switches", L"OptionalBody", L"TestBranch", L"Token", L"Syntax0", L"Syntax1", L"Syntax2", L"Syntax", L"AssignmentOp", L"Assignment", L"Clause", L"Placeholder", L"RuleName", L"LriConfig", L"LriContinuationBody", L"LriContinuation", L"LriTarget", L"Rule", L"File", }; return results[index]; } const wchar_t* RuleParserStateLabel(vl::vint index) { static const wchar_t* results[] = { L"[0][Cond0] BEGIN ", L"[1][Cond0] END [ENDING]", L"[2][Cond0]< \"!\" @ Cond0 >", L"[3][Cond0]< \"!\" Cond0 @ >", L"[4][Cond0]< ID @ >", L"[5][Cond0]<< \"(\" !Cond \")\" @ >>", L"[6][Cond0]<< \"(\" !Cond @ \")\" >>", L"[7][Cond0]<< \"(\" @ !Cond \")\" >>", L"[8][Cond1] BEGIN ", L"[9][Cond1] END [ENDING]", L"[10][Cond1]< Cond1 \"&&\" @ Cond0 >", L"[11][Cond1]< Cond1 \"&&\" Cond0 @ >", L"[12][Cond1]< Cond1 @ \"&&\" Cond0 >", L"[13][Cond1]<< !Cond0 @ >>", L"[14][Cond2] BEGIN ", L"[15][Cond2] END [ENDING]", L"[16][Cond2]< Cond2 \"||\" @ Cond1 >", L"[17][Cond2]< Cond2 \"||\" Cond1 @ >", L"[18][Cond2]< Cond2 @ \"||\" Cond1 >", L"[19][Cond2]<< !Cond1 @ >>", L"[20][Cond] BEGIN ", L"[21][Cond] END [ENDING]", L"[22][Cond]<< !Cond2 @ >>", L"[23][SwitchItem] BEGIN ", L"[24][SwitchItem] END [ENDING]", L"[25][SwitchItem]< \"!\" @ ID >", L"[26][SwitchItem]< \"!\" ID @ >", L"[27][SwitchItem]< ID @ >", L"[28][Switches] BEGIN ", L"[29][Switches] END [ENDING]", L"[30][Switches]\"switch\" @ { SwitchItem ; \",\" } \";\"", L"[31][Switches]\"switch\" { SwitchItem ; \",\" @ } \";\"", L"[32][Switches]\"switch\" { SwitchItem ; \",\" } \";\" @", L"[33][Switches]\"switch\" { SwitchItem @ ; \",\" } \";\"", L"[34][OptionalBody] BEGIN ", L"[35][OptionalBody] END [ENDING]", L"[36][OptionalBody]\"[\" @ Syntax \"]\"", L"[37][OptionalBody]\"[\" Syntax \"]\" @", L"[38][OptionalBody]\"[\" Syntax @ \"]\"", L"[39][TestBranch] BEGIN ", L"[40][TestBranch] END [ENDING]", L"[41][TestBranch]< Cond \":\" ( Syntax1 @ | \";\" ) >", L"[42][TestBranch]< Cond \":\" ( Syntax1 | \";\" @ ) >", L"[43][TestBranch]< Cond \":\" @ ( Syntax1 | \";\" ) >", L"[44][TestBranch]< Cond @ \":\" ( Syntax1 | \";\" ) >", L"[45][Token] BEGIN ", L"[46][Token] END [ENDING]", L"[47][Token]CONDITIONAL_LITERAL @", L"[48][Token]ID @", L"[49][Token]STRING @", L"[50][Syntax0] BEGIN ", L"[51][Syntax0] END [ENDING]", L"[52][Syntax0]< \"!\" @ ID >", L"[53][Syntax0]< \"!\" ID @ >", L"[54][Syntax0]< \"!(\" @ { SwitchItem ; \",\" } \";\" Syntax \")\" >", L"[55][Syntax0]< \"!(\" { SwitchItem ; \",\" @ } \";\" Syntax \")\" >", L"[56][Syntax0]< \"!(\" { SwitchItem ; \",\" } \";\" @ Syntax \")\" >", L"[57][Syntax0]< \"!(\" { SwitchItem ; \",\" } \";\" Syntax \")\" @ >", L"[58][Syntax0]< \"!(\" { SwitchItem ; \",\" } \";\" Syntax @ \")\" >", L"[59][Syntax0]< \"!(\" { SwitchItem @ ; \",\" } \";\" Syntax \")\" >", L"[60][Syntax0]< \"+\" @ OptionalBody >", L"[61][Syntax0]< \"+\" OptionalBody @ >", L"[62][Syntax0]< \"-\" @ OptionalBody >", L"[63][Syntax0]< \"-\" OptionalBody @ >", L"[64][Syntax0]< \"?(\" @ TestBranch { \"|\" TestBranch } \")\" >", L"[65][Syntax0]< \"?(\" TestBranch @ { \"|\" TestBranch } \")\" >", L"[66][Syntax0]< \"?(\" TestBranch { \"|\" @ TestBranch } \")\" >", L"[67][Syntax0]< \"?(\" TestBranch { \"|\" TestBranch @ } \")\" >", L"[68][Syntax0]< \"?(\" TestBranch { \"|\" TestBranch } \")\" @ >", L"[69][Syntax0]< \"{\" @ Syntax [ \";\" Syntax ] \"}\" >", L"[70][Syntax0]< \"{\" Syntax @ [ \";\" Syntax ] \"}\" >", L"[71][Syntax0]< \"{\" Syntax [ \";\" @ Syntax ] \"}\" >", L"[72][Syntax0]< \"{\" Syntax [ \";\" Syntax @ ] \"}\" >", L"[73][Syntax0]< \"{\" Syntax [ \";\" Syntax ] \"}\" @ >", L"[74][Syntax0]< OptionalBody @ >", L"[75][Syntax0]< Token @ [ \":\" ID ] >", L"[76][Syntax0]< Token [ \":\" @ ID ] >", L"[77][Syntax0]< Token [ \":\" ID @ ] >", L"[78][Syntax0]<< \"(\" !Syntax \")\" @ >>", L"[79][Syntax0]<< \"(\" !Syntax @ \")\" >>", L"[80][Syntax0]<< \"(\" @ !Syntax \")\" >>", L"[81][Syntax1] BEGIN ", L"[82][Syntax1] END [ENDING]", L"[83][Syntax1]< Syntax1 @ Syntax0 >", L"[84][Syntax1]< Syntax1 Syntax0 @ >", L"[85][Syntax1]<< !Syntax0 @ >>", L"[86][Syntax2] BEGIN ", L"[87][Syntax2] END [ENDING]", L"[88][Syntax2]< Syntax2 \"|\" @ Syntax1 >", L"[89][Syntax2]< Syntax2 \"|\" Syntax1 @ >", L"[90][Syntax2]< Syntax2 @ \"|\" Syntax1 >", L"[91][Syntax2]<< !Syntax1 @ >>", L"[92][Syntax] BEGIN ", L"[93][Syntax] END [ENDING]", L"[94][Syntax]<< !Syntax2 @ >>", L"[95][AssignmentOp] BEGIN ", L"[96][AssignmentOp] END [ENDING]", L"[97][AssignmentOp]\"=\" @", L"[98][AssignmentOp]\"?=\" @", L"[99][Assignment] BEGIN ", L"[100][Assignment] END [ENDING]", L"[101][Assignment]< ID @ AssignmentOp ID >", L"[102][Assignment]< ID AssignmentOp @ ID >", L"[103][Assignment]< ID AssignmentOp ID @ >", L"[104][Clause] BEGIN ", L"[105][Clause] END [ENDING]", L"[106][Clause]< \"!\" \"prefix_merge\" \"(\" @ RuleName \")\" >", L"[107][Clause]< \"!\" \"prefix_merge\" \"(\" RuleName \")\" @ >", L"[108][Clause]< \"!\" \"prefix_merge\" \"(\" RuleName @ \")\" >", L"[109][Clause]< \"!\" \"prefix_merge\" @ \"(\" RuleName \")\" >", L"[110][Clause]< \"!\" @ \"prefix_merge\" \"(\" RuleName \")\" >", L"[111][Clause]< \"!\" @ RuleName LriContinuation >", L"[112][Clause]< \"!\" RuleName @ LriContinuation >", L"[113][Clause]< \"!\" RuleName LriContinuation @ >", L"[114][Clause]< \"left_recursion_placeholder\" \"(\" @ Placeholder { \",\" Placeholder } \")\" >", L"[115][Clause]< \"left_recursion_placeholder\" \"(\" Placeholder @ { \",\" Placeholder } \")\" >", L"[116][Clause]< \"left_recursion_placeholder\" \"(\" Placeholder { \",\" @ Placeholder } \")\" >", L"[117][Clause]< \"left_recursion_placeholder\" \"(\" Placeholder { \",\" Placeholder @ } \")\" >", L"[118][Clause]< \"left_recursion_placeholder\" \"(\" Placeholder { \",\" Placeholder } \")\" @ >", L"[119][Clause]< \"left_recursion_placeholder\" @ \"(\" Placeholder { \",\" Placeholder } \")\" >", L"[120][Clause]< Syntax \"as\" \"partial\" @ ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[121][Clause]< Syntax \"as\" \"partial\" ID @ [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[122][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" @ { Assignment ; \",\" } \"}\" ] >", L"[123][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" @ } \"}\" ] >", L"[124][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" @ ] >", L"[125][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment @ ; \",\" } \"}\" ] >", L"[126][Clause]< Syntax \"as\" @ \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[127][Clause]< Syntax \"as\" @ ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[128][Clause]< Syntax \"as\" ID @ [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[129][Clause]< Syntax \"as\" ID [ \"{\" @ { Assignment ; \",\" } \"}\" ] >", L"[130][Clause]< Syntax \"as\" ID [ \"{\" { Assignment ; \",\" @ } \"}\" ] >", L"[131][Clause]< Syntax \"as\" ID [ \"{\" { Assignment ; \",\" } \"}\" @ ] >", L"[132][Clause]< Syntax \"as\" ID [ \"{\" { Assignment @ ; \",\" } \"}\" ] >", L"[133][Clause]< Syntax @ \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[134][Clause]< Syntax @ \"as\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[135][Clause]< Syntax @ [ \"{\" { Assignment ; \",\" } \"}\" ] >", L"[136][Clause]< Syntax [ \"{\" @ { Assignment ; \",\" } \"}\" ] >", L"[137][Clause]< Syntax [ \"{\" { Assignment ; \",\" @ } \"}\" ] >", L"[138][Clause]< Syntax [ \"{\" { Assignment ; \",\" } \"}\" @ ] >", L"[139][Clause]< Syntax [ \"{\" { Assignment @ ; \",\" } \"}\" ] >", L"[140][Placeholder] BEGIN ", L"[141][Placeholder] END [ENDING]", L"[142][Placeholder]< ID @ >", L"[143][RuleName] BEGIN ", L"[144][RuleName] END [ENDING]", L"[145][RuleName]< ID @ >", L"[146][LriConfig] BEGIN ", L"[147][LriConfig] END [ENDING]", L"[148][LriConfig]\"left_recursion_inject\" @", L"[149][LriConfig]\"left_recursion_inject_multiple\" @", L"[150][LriContinuationBody] BEGIN ", L"[151][LriContinuationBody] END [ENDING]", L"[152][LriContinuationBody]LriConfig \"(\" @ Placeholder { \",\" Placeholder } \")\" LriTarget { \"|\" LriTarget }", L"[153][LriContinuationBody]LriConfig \"(\" Placeholder @ { \",\" Placeholder } \")\" LriTarget { \"|\" LriTarget }", L"[154][LriContinuationBody]LriConfig \"(\" Placeholder { \",\" @ Placeholder } \")\" LriTarget { \"|\" LriTarget }", L"[155][LriContinuationBody]LriConfig \"(\" Placeholder { \",\" Placeholder @ } \")\" LriTarget { \"|\" LriTarget }", L"[156][LriContinuationBody]LriConfig \"(\" Placeholder { \",\" Placeholder } \")\" @ LriTarget { \"|\" LriTarget }", L"[157][LriContinuationBody]LriConfig \"(\" Placeholder { \",\" Placeholder } \")\" LriTarget @ { \"|\" LriTarget }", L"[158][LriContinuationBody]LriConfig \"(\" Placeholder { \",\" Placeholder } \")\" LriTarget { \"|\" @ LriTarget }", L"[159][LriContinuationBody]LriConfig \"(\" Placeholder { \",\" Placeholder } \")\" LriTarget { \"|\" LriTarget @ }", L"[160][LriContinuationBody]LriConfig @ \"(\" Placeholder { \",\" Placeholder } \")\" LriTarget { \"|\" LriTarget }", L"[161][LriContinuation] BEGIN ", L"[162][LriContinuation] END [ENDING]", L"[163][LriContinuation]< \"[\" @ LriContinuationBody \"]\" >", L"[164][LriContinuation]< \"[\" LriContinuationBody \"]\" @ >", L"[165][LriContinuation]< \"[\" LriContinuationBody @ \"]\" >", L"[166][LriContinuation]< LriContinuationBody @ >", L"[167][LriTarget] BEGIN ", L"[168][LriTarget] END [ENDING]", L"[169][LriTarget]< \"(\" @ RuleName LriContinuation \")\" >", L"[170][LriTarget]< \"(\" RuleName @ LriContinuation \")\" >", L"[171][LriTarget]< \"(\" RuleName LriContinuation \")\" @ >", L"[172][LriTarget]< \"(\" RuleName LriContinuation @ \")\" >", L"[173][LriTarget]< RuleName @ >", L"[174][Rule] BEGIN ", L"[175][Rule] END [ENDING]", L"[176][Rule]< ID @ [ \":\" ID ] { \"::=\" Clause } \";\" >", L"[177][Rule]< ID [ \":\" @ ID ] { \"::=\" Clause } \";\" >", L"[178][Rule]< ID [ \":\" ID @ ] { \"::=\" Clause } \";\" >", L"[179][Rule]< ID [ \":\" ID ] { \"::=\" @ Clause } \";\" >", L"[180][Rule]< ID [ \":\" ID ] { \"::=\" Clause @ } \";\" >", L"[181][Rule]< ID [ \":\" ID ] { \"::=\" Clause } \";\" @ >", L"[182][File] BEGIN ", L"[183][File] END [ENDING]", L"[184][File]< [ Switches @ ] Rule { Rule } >", L"[185][File]< [ Switches ] Rule @ { Rule } >", L"[186][File]< [ Switches ] 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 ParseWithString(input, this, codeIndex); }; vl::Ptr RuleParser::ParseFile(vl::collections::List& tokens, vl::vint codeIndex) const { return ParseWithTokens(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()) { auto loader = Ptr(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::Ptr(new GlrEnumItem); CopyFields(node, newNode.Obj()); this->result = newNode; } void TypeAstVisitor::Visit(GlrClassProp* node) { auto newNode = vl::Ptr(new GlrClassProp); CopyFields(node, newNode.Obj()); this->result = newNode; } void TypeAstVisitor::Visit(GlrAstFile* node) { auto newNode = vl::Ptr(new GlrAstFile); CopyFields(node, newNode.Obj()); this->result = newNode; } void TypeAstVisitor::Visit(GlrEnum* node) { auto newNode = vl::Ptr(new GlrEnum); CopyFields(node, newNode.Obj()); this->result = newNode; } void TypeAstVisitor::Visit(GlrClass* node) { auto newNode = vl::Ptr(new GlrClass); CopyFields(node, newNode.Obj()); this->result = newNode; } vl::Ptr TypeAstVisitor::CopyNode(GlrType* node) { if (!node) return nullptr; node->Accept(static_cast(this)); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr TypeAstVisitor::CopyNode(GlrEnumItem* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr TypeAstVisitor::CopyNode(GlrClassProp* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; return this->result.Cast(); } vl::Ptr TypeAstVisitor::CopyNode(GlrAstFile* node) { if (!node) return nullptr; Visit(node); this->result->codeRange = node->codeRange; 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 = 2564; // 39168 bytes before compressing static const vl::vint dataBlock = 256; static const vl::vint dataRemain = 4; static const vl::vint dataSolidRows = 10; static const vl::vint dataRows = 11; static const char* compressed[] = { "\x00\x99\x00\x00\xFC\x09\x00\x00\x25\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\xD0\x07\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\xB0\xA3\xA4\xA9\xA2\xAB\x47\x83\x89\xAC\xA3\x9A\xA9\xAE\xAC\x4F\xDA\x91\xA0\xB3\xAA\xB1\xAB\x90\x03\x81\x1C\xAA\xAF\xAE\xB3\xAA\xB7\x59\x82\x9B\xBE\xAC\xB5\xBB\xB5\xBB\x74\xF8\xA4\xAD\xB2\xBB\xB0\xB9\xB0\x7D\xE7\x81\xCF\xB3\xC1\xB9\x81\xB9\x7B\xF6\xB9\xAB\xC9\xC2\xBF\xBF\xB2\x85\x80\xC7\xDE\xB1\xC8\xCB\xC8\xC1\x97\x84\xD9\xC6\xC2\x94\xCB\xCC\xC9\x9D\x98\xE1\xDA\xC3\xD4\xCC\xC5\xC7\x7C\x9F\xD6\xC5\xD0\xD7\xD1\xCB\xD4\x00\x6A\x89\x92\xDD\xC4\xC4\xD4\xC5\xB5\xB9\xF7\xCE\xCF\xD0\xDF\xDC\xDB\xBD\xBC\xEA\xD0\xDE\xD3\xE2\xDF\xE0\xC0\xC6\xC2\xEC\xDB\xD5\xE0\xE6\xE2\x9E\xCF\xC7\xEA\xE9\xE2\xEB\xE4\xE7\xD8\xD1\xD9\xE2", "\xDB\xEC\xD1\xEE\xD3\xDA\xE1\xDC\xE2\xFE\xEC\xF0\xF1\xF1\xE8\xE5\xE9\xE7\xFA\xF5\xF4\xF7\xF7\xA0\x82\x0A\x94\xDF\xDA\xDC\xE4\xFB\xD4\xF8\xD6\xF5\xEF\xED\xD6\xF2\xFF\xEB\x40\x8E\x7A\x80\xF0\x4D\x7F\x7E\x81\x01\xAB\x63\x03\x7C\xD7\x47\x80\x75\x82\x0F\x83\x88\x82\x84\x11\x85\x85\x84\x81\x18\x93\x86\x87\x74\xFB\x7A\x7D\x7E\x86\x19\x97\x80\x8B\x88\x22\xA5\x8C\x87\x87\x26\x8D\x80\x87\x89\x0E\xAC\x8B\x8A\x8A\x14\xAE\x81\x8C\x8C\x1B\xB4\x81\x8A\x8C\x35\xBC\x7D\x8A\x8D\x24\xB8\x87\x8C\x8F\x29\xBA\x8F\x8A\x90\x33\x84\x99\x8E\x87\x3B\x86\x9F\x8E\x92\x3D\x80\x9E\x8D\x93\x4C\x81\x98\x93\x90\x53\x85\x95\x97\x91\xF5\x59\x97\x7E\x96\x01\x4C\x43\x6E\x93\x60\x91\x9F\x92\x94\x5C\x9D\x85\x98\x8A\x63\xA9\x9B\x71\x01\x0C\xA2\x91\x9B\x95\x4B\xB0\x90\x96\x9C\x64\x9B\x96\x9D\x7E\x67\x91\x76\x01\x9B\x74\xAA\x9E\x9B\x9F\x7D\xAF\x99\x9C\x95\x83\x96\x95\x9B\x46\x5F\x80\xA5\xA0\x96\x77\xA6\x9D\xA0\x9A\x82\x8F\xA9\x91\xA0\xD5\x48\x46\x40\x7D\x92\x84\xAD\xA1\x02\x7C\x8B\xA1\x9E\xA7\x73\xA0\xA5\x9C\x9E\x99\x86\xA5\xA8\xA3\xA4\xA9\xAE\xA2\xAA", "\x90\x8A\xA7\xAB\xA7\xAF\xA1\xA1\xAF\xA8\xAB\xB5\xAD\xA8\xA5\xB8\xA2\xAE\x9D\xAE\xB3\xBB\xA5\x9A\x02\x9D\xBD\xA1\xA4\xAB\x93\xBA\xA3\xB2\xAD\xC5\x82\xBE\xA8\xB1\x9A\x8C\xB6\xAA\xB3\xA8\x88\xBD\xB1\xAD\x0E\x49\xAC\xAC\xB4\xB0\x98\xB2\xAE\xB6\xB4\xB7\xA6\xB3\xB2\xD2\x8F\xB1\xB9\xB4\xDE\x8D\xAC\x02\x42\xF2\x60\xB5\xB8\xB7\xBE\x8A\xB7\xB7\xB8\xD9\xB0\xBB\xB6\xBC\xDD\x89\xBC\xBB\xB1\xEB\xB4\xBD\xBB\xBD\xEA\xB6\xBA\xBF\xB1\x0E\x01\xBC\xBF\xBB\xF9\x85\xCE\xBE\xC1\xD3\x88\xC2\xBA\xC2\xE4\x87\xCE\xC1\xC2\x0F\xCB\xC1\xC5\xC3\xD3\x8F\x02\xC3\xBF\xFD\x90\xCA\xC6\xC4\x1B\xD4\xCC\xC7\xC7\x1E\xE1\xC1\xBC\xC3\x23\xD3\xC5\xC9\xC7\x27\xE0\xC9\xCA\xC8\xF3\xA4\xCD\xCA\xC9\xAB\x50\x07\xC6\xCB\xF5\xA8\xCF\xCA\xCD\x35\xEA\xC7\xCE\xCE\x39\xEC\xCD\xCC\x68\x11\x33\xC0\xCF\xCF\x3B\xFE\xCB\xBC\xC6\x04\xC3\xD7\xD0\xCD\x4B\xCA\xD8\xBE\xD3\x19\xFC\xCD\xD0\xCE\x53\xD2\xD7\xB0\x44\xD6\x9F\xB9\xD0\xD5\x4F\xDC\xD1\xD6\xD1\x5D\xD6\xDF\xD7\xCA\x64\xC5\xD0\x6B\x04\x42\xDE\xDB\xD6\xD8\x6B\xE0\xD3\xDA\xD9\x70\xC4\xD2\xDD\xD5\x6E\xED\xD5\xDB\xDC\x61", "\xF5\xDA\xD7\xDE\xEE\xBC\xD3\xC2\xDF\x48\xC0\xEC\xD1\xDE\x77\xF4\xD5\xE0\xE1\x71\xC6\xE9\xE0\xE2\x78\xEF\xDD\xE2\xDD\x8B\xCE\xEA\xE3\xE3\x82\xD1\x74\x05\xDA\x6C\xD5\xEA\xDA\xE6\xA4\x55\x08\xE6\xDE\x7D\xE1\xEF\xDE\xE8\x81\xE4\xE3\xE2\xE4\x8C\xC7\xD6\x04\xBA\xA9\xCB\x78\x07\xE7\x87\xE8\xE2\xEC\xE4\x94\xE6\xE0\xD4\xED\x93\xF9\xED\xEB\xEC\x9C\xE0\xE3\xEB\xEF\xA5\xC0\xF7\xE8\xEE\xBB\xC4\xF5\x76\x44\x59\xF6\xEB\xE6\xF2\x99\xCC\xFE\xED\xF0\xD0\xC3\xFD\xED\xEC\xC6\xD5\xF3\xF7\xBC\x1A\x30\xE1\xE6\xF5\xCE\xD4\xF7\xF5\xED\xC2\xF7\xEF\xF6\xEE\xBC\xDD\xFB\xF7\xF8\xC5\xE8\xF5\xF9\xF8\xD3\x9B\x0A\xF4\xF8\xD1\xE2\xF6\xF8\xFC\xD2\xF3\xF4\xF8\xF7\xEC\xCD\xF9\xFF\xF3\xF5\xFB\xFE\xF6\xFD\xE9\x60\x83\xFA\x50\x7C\x03\xF7\x77\x78\x70\x1D\x06\x81\x00\xFE\x77\x7C\x01\xB8\x79\x7E\xCB\x6C\x80\xFD\x72\x72\x83\x03\x8E\x82\x7D\x0F\x9D\x7C\x04\xFA\x70\x00\x0F\x0A\x83\x80\x1A\x81\x84\x05\x9B\x8F\x79\x0F\x1F\x81\x83\x23\x82\x85\x04\xA4\x8F\x7F\x0A\x8B\x84\x85\x0D\x81\x20\x08\x27\x88\x83\x1A\xA4\x74\x22\xC9\x6E\x84\x08\xA9\x8C\x87\x15\xAA\x84", "\x83\x3F\x9C\x7D\x74\x22\x04\x87\x0B\x86\x88\x78\x23\x05\x8A\x0E\xA8\x8E\x87\x1E\x80\x8E\x89\x42\x82\x34\x09\x4A\x80\x87\x09\x8D\x8F\x8A\x4F\x98\x89\x14\xD9\x8C\x8B\x2D\x9E\x8D\x85\x55\x9C\x40\x40\x39\x80\x00\x13\x14\x89\x88\x60\x88\x8D\x0C\xE1\x8F\x84\x35\x96\x8D\x8B\x69\x90\x89\x1C\xDA\x83\x8E\x38\xAB\x8E\x8D\x16\x8B\x8A\x0D\xFA\x87\x88\x36\xBB\x84\x8E\x77\x92\x8D\x20\x80\x9F\x8D\x2F\x83\x96\x8E\x85\x95\x8C\x67\x27\x07\x8D\x11\x96\x24\x8C\x78\x8D\x8E\x20\x89\x97\x90\x43\x94\x97\x92\x79\x9E\x8C\x13\x88\x97\x69\x14\x0D\x94\x90\x99\x91\x93\x1F\x9C\x92\x92\x50\xA5\x94\x94\xA3\x96\x91\x28\x93\x9B\x94\x53\xA9\x92\x91\xB0\x95\x90\x18\xAA\x0F\x92\x0E\xAB\x05\x96\xAA\x87\x95\x2E\xAF\x92\x97\x5E\x98\x92\x97\xB1\x9F\x94\x2F\xB4\x58\x22\x32\xAD\x07\x62\x2E\x18\x95\x30\xAD\x98\x95\x4D\xBB\x96\x99\xCB\x80\x9A\x2F\xCC\x9F\x99\x3D\x9A\x96\x9A\xA2\x90\x9B\x34\xD2\x92\x98\x6D\xB0\x7F\x05\xCA\x9B\x9B\x30\xD4\x91\x9B\x71\x9C\x9C\x9C\xE2\x9E\x99\x26\xB0\x01\x9D\x6E\x98\x9C\x95\xE7\x91\x9E\x39\xF3\x9A\x9C\x79\xB5\x99\x21\x31\x17", "\x62\x0C\x17\x63\x07\x76\xA8\x9E\x9D\x7D\x99\x9B\x3B\xAE\x97\x9F\x82\x83\xA5\x99\x07\xB5\x99\x40\xF0\x94\x9F\x84\xA5\x9E\xA0\x0B\xAB\x84\x0D\x54\x85\x07\x8B\x76\x07\x62\x37\x1E\x9E\x3D\x8E\xA9\x9C\x8E\x80\xA4\x8F\x20\xB7\x99\x44\xE2\x58\x06\x2A\xB9\x07\x62\x3A\x17\x63\x0E\x1A\xAD\xA1\x91\x8A\xA1\xA4\x02\xAE\xA7\x43\x9E\xA9\x92\x2D\x2C\x71\x21\xC0\x51\x4A\x4C\x1C\x59\x20\xAC\x7B\x2C\x4D\x5E\x32\x25\xBA\x06\x2C\xA6\x3A\x7B\xA2\x21\x29\xBE\x2B\x50\x83\x29\xA6\xA3\xA9\x25\xA8\x03\x3E\xA4\x6A\x4B\xA2\x21\xA6\xA2\x57\xA8\x3D\xBC\x28\x50\xFB\x28\x44\xAC\x86\x25\x01\x40\x5E\xAB\x40\x60\xAE\x2A\x4C\x68\x2F\x39\x50\xA2\x23\xB9\x65\xA7\xA7\xBD\x29\xA9\x20\x6B\xBB\x2E\x59\xB1\x3C\x2B\xB7\x80\x01\xAE\x53\xAA\x23\x56\xD7\xAF\xA9\x86\x21\xAD\xAF\x09\x24\xAE\x53\xA6\x26\xAE\xC1\xA8\x33\xAF\xAF\x3D\xA8\x60\x86\x29\xA9\xC1\xA3\x26\xAE\x76\xA2\xAA\x5E\xDC\x24\xAB\x80\x08\xB3\x38\x95\xA0\x02\x97\x7B\x29\xB3\xCD\xBC\xAC\xB0\x48\xBC\x2B\x5C\xF3\xA2\xAD\x83\x1A\xAC\x2B\x8A\xA0\xB5\x42\x0D\xB8\x35\xB9\xAC\x2E\xAE\x96\x47\xB0\x6A\xA9", "\x2B\x41\xA0\xA9\x25\xB3\x5C\x35\xB4\x57\xB7\xBA\x20\xCF\xAF\x32\xB7\xA8\x32\xB1\x42\x11\xB9\x24\xDF\x83\x3A\x26\x97\xAF\x3A\x4C\x46\xBA\xB9\x94\x09\xBA\x26\xC2\xA6\x20\x70\xBF\xB3\xB6\x93\x38\xB2\xA9\x0A\x33\xBB\x70\x5A\xBD\xB8\xEB\xBD\xB4\xB2\xD9\xB9\xB5\x75\xA3\x29\xB2\xE2\xA6\x27\xB9\xD0\xA6\x24\x77\xE9\xBE\xBB\x84\x0C\xBA\x26\xEB\xAC\xBF\x47\x57\xBB\x2F\xF8\xB2\xBD\x23\xE5\xA7\xB6\x6D\xEA\xB3\xBD\xF9\x9F\xBE\x2B\xF6\xB7\xBC\x7D\xA8\x31\xC0\xF9\xB9\xBE\x2B\x76\xA1\x68\x82\x8A\x2A\xC0\xB7\x8A\x26\xAA\xAF\x36\xAC\x84\xC3\x36\xAE\x44\x4E\xC1\x21\x16\xC8\x35\x85\xDC\x2E\x83\xB3\xA9\x2D\xAD\x03\x39\xB1\x66\xDC\xBC\xB9\xE4\xBB\x48\xC3\x0A\x39\xC2\x69\xC3\xB9\xC4\x85\x1B\xC4\xC5\x09\x31\xB5\x55\xAD\xC8\xA6\x1A\xC6\x23\xC2\x04\x3E\xAC\x8A\x89\x25\x5A\x83\x2A\xC1\x20\x3D\xC3\x22\x8C\xF0\xAE\xC2\x21\xC5\xCE\xC3\x53\x17\x61\x48\x43\xC7\xC9\x81\x14\x0F\x62\x99\xB7\x01\x93\xF4\xA5\x3A\xEE\xA6\x83\xCA\x0A\x35\x0B\xC5\x56\xC8\xCA\x85\x16\x0F\x62\xCC\xB3\x89\x93\xA4\xB1\x3A\xE6\x8C\x93\xCC\x6B\x4A\x23\x2D\xCD\xC5\xC0\xD0", "\x33\xAC\x96\x6C\xCB\x3B\x89\x86\x29\x99\x2E\xC6\x27\x0A\x17\x73\xCF\x40\x60\x96\xCF\x81\x18\x09\xCF\x0A\x3C\xCD\x9F\x81\x29\x0B\x8B\x7C\x03\xCA\x6D\xCB\x34\x96\xA3\xB0\xC5\x46\x59\xB4\xCC\xA2\x21\x24\x77\x90\xD2\x5C\xEE\x99\xB6\x39\x99\x8C\xBA\x9E\x8D\x51\x24\xE6\x94\xD1\x5A\x9B\xC1\x20\x8E\x98\xD9\xCD\x84\x17\xD1\x3A\x3F\xC0\x02\x79\xA4\x39\x93\x54\xC9\xD0\x36\x21\x29\xD7\x5C\xCC\xC9\xB3\x90\x33\xD6\xC5\xCB\x39\x90\x93\xAF\xD8\xCA\x1C\xF3\xA9\xC8\x02\x2F\xD3\xC5\x76\xA8\xBD\x48\xCA\x26\xB0\x02\x3F\xD1\xBC\x38\xC9\xD4\x52\xC3\x80\xD8\x01\x28\xDA\xAA\x19\x90\xDA\x00\x32\x65\x3A\x1C\x41\x62\xA9\xCB\x35\xDB\x06\xE5\x4C\x43\xD7\xC6\x23\xA9\xA2\x32\xDB\xBB\xB9\xD7\x21\x8D\xC0\x7A\xB6\x86\x28\xAE\x4E\xCA\x27\x72\xDB\xC0\x5E\xC5\x09\x2B\xDD\x6F\xEF\x81\xDC\x03\x2D\xDF\xB4\x8A\x2B\x75\x78\xEF\x5E\xDB\x02\x33\xDE\x7E\x19\x92\xAA\x81\x30\xDB\xE0\x0A\x2F\x74\x24\xFE\x57\xE1\x81\x0A\xE0\xE1\xC7\x69\xDD\xAD\x1E\x71\xB1\x73\xE0\x5A\xD8\x09\x34\xE2\x41\x78\xDE\xDD\xEA\x2E\x7E\xDF\x03\x33\xD2\x42\x1A\xE3\x20\x80\xFB\xDD\x3A", "\x09\x80\xE7\x42\x17\x6D\xDE\x83\x28\x68\xDB\x0A\x37\xCB\xA5\x47\x52\xCB\x84\x2D\xE6\xDE\x03\x8F\xE3\x40\x24\xED\xE3\x07\x88\x7E\x20\x1F\xF0\xE2\x7E\x33\x8A\xE4\x55\x41\xEB\x20\x1D\xC2\xEA\x35\xC7\xE2\x21\x02\xB0\xE3\x80\x4E\xE6\x21\xCA\xCA\xED\x50\x22\x85\xED\x56\x53\xE8\xEA\xC5\x8F\x89\xE9\x81\x0D\xE5\xE7\x03\x22\xCF\xCC\xD5\x39\xB9\xB9\x9D\xEA\x20\x44\xF4\xE9\x48\xB2\xEE\xEB\xAD\xC3\x23\x8C\x63\xFA\x3D\xA8\xD4\xC6\x20\xB6\xE8\xEE\xED\x7D\x89\xEF\x40\x59\x7F\xE9\x07\xB8\x86\x20\x70\xF8\xE6\x41\x66\x8B\xE1\x69\x7F\xEB\x20\x84\xEA\xEC\x00\x67\xC1\xEE\xC0\x49\x89\x21\x4C\xE7\xE6\x7E\x0F\x92\xDC\x1B\xDF\xC1\x21\x62\xE3\x22\xD5\x8A\xF0\xCE\xE9\x87\x59\xF0\x02\x2F\xF2\xE2\x9A\x89\xF1\x81\x11\xF5\x56\x1C\x47\x9B\xD5\xCC\xC3\xAE\xC6\xDA\xF0\xEF\x01\x22\xD1\xC8\xC7\x54\xF3\xB7\xF0\xF0\x00\xFB\x97\xEA\x73\x76\xA3\xAF\xDA\xC2\x25\xF4\x60\xE2\x23\x44\xBA\xF1\x3A\x5F\xD5\x22\x21\x73\xEE\xDA\x41\x17\xA4\xF8\xD1\x15\xDF\xCD\x0A\x3E\x91\xDF\x83\x25\xA5\xE6\xE2\x5B\xCD\x06\x32\xFA\xE2\xAC\xB1\xD9\x63\x45\x98\xF0\xB7\xE7\xD1", "\x42\x3C\xDA\x20\x7D\xC0\x01\xB3\xDF\xE8\xF3\xED\xBF\x01\xBD\xEA\x35\xDD\xFB\x09\x29\xFE\x40\x49\xF1\x3B\x90\x02\x0D\xFD\xFA\x3C\xE1\x40\x19\xB5\xCE\x83\x2A\xF2\xF1\x45\x0C\x52\x74\x6A\x10\xA0\x72\x79\x03\x16\x04\x12\x7E\x1C\x05\x7B\x7F\x0A\x1D\x7F\xEA\x73\x7D\x02\x18\x04\x09\x86\x39\x12\x7E\x80\xF3\x77\x7B\x4A\x03\x81\xA2\x17\x73\xF0\x76\x10\xB2\x72\x10\xFF\x72\x78\x03\x1C\x04\x02\x8B\x67\x04\x87\x7B\x4D\x0A\x81\xA4\x1A\x73\x1D\x86\x82\x09\x10\x7C\x06\x82\x10\x4F\x0A\x82\x9C\x1C\x77\x95\x79\x10\x1F\x81\x10\xF4\x76\x6C\x09\x11\x05\x34\x80\x1A\x51\x71\x62\x0A\x1C\x4E\x4D\x68\x69\xD0\x53\x68\x68\x64\x17\xCA\x6E\x11\xAE\x56\x6B\x8B\x6F\x84\x53\x6D\x84\x3F\x80\x12\xE3\x6D\x5E\x4D\x62\x62\x21\x18\x85\x12\x7E\x5A\x5A\x83\x7E\x6B\x1F\x6A\xFF\x0C\x5D\x68\x12\x86\x92\x68\x65\x64\x88\x7F\x47\x6F\x5E\x35\x1A\x86\xC5\x58\x65\xCC\x58\x16\x6F\x8D\x69\x6E\x83\x87\x53\x65\x6C\x2E\x16\x87\x23\x15\x76\x21\x1A\x87\x93\x54\x46\x00\x09\x5C\x68\x10\x88\x21\x1B\x83\x2E\x14\x88\x23\x13\x77\x68\x18\x88\xB1\x6B\x16\xCD\x62\x13\xA9\x68", "\x16\x8F\x88\x65", }; 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 ParseWithString(input, this, codeIndex); }; vl::Ptr TypeParser::ParseFile(vl::collections::List& tokens, vl::vint codeIndex) const { return ParseWithTokens(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 vl::Ptr(new vl::glr::parsergen::GlrAlternativeSyntax); case ParserGenClasses::AndCondition: return vl::Ptr(new vl::glr::parsergen::GlrAndCondition); case ParserGenClasses::Assignment: return vl::Ptr(new vl::glr::parsergen::GlrAssignment); case ParserGenClasses::AstFile: return vl::Ptr(new vl::glr::parsergen::GlrAstFile); case ParserGenClasses::Class: return vl::Ptr(new vl::glr::parsergen::GlrClass); case ParserGenClasses::ClassProp: return vl::Ptr(new vl::glr::parsergen::GlrClassProp); case ParserGenClasses::CreateClause: return vl::Ptr(new vl::glr::parsergen::GlrCreateClause); case ParserGenClasses::Enum: return vl::Ptr(new vl::glr::parsergen::GlrEnum); case ParserGenClasses::EnumItem: return vl::Ptr(new vl::glr::parsergen::GlrEnumItem); case ParserGenClasses::LeftRecursionInjectClause: return vl::Ptr(new vl::glr::parsergen::GlrLeftRecursionInjectClause); case ParserGenClasses::LeftRecursionInjectContinuation: return vl::Ptr(new vl::glr::parsergen::GlrLeftRecursionInjectContinuation); case ParserGenClasses::LeftRecursionPlaceholder: return vl::Ptr(new vl::glr::parsergen::GlrLeftRecursionPlaceholder); case ParserGenClasses::LeftRecursionPlaceholderClause: return vl::Ptr(new vl::glr::parsergen::GlrLeftRecursionPlaceholderClause); case ParserGenClasses::LoopSyntax: return vl::Ptr(new vl::glr::parsergen::GlrLoopSyntax); case ParserGenClasses::NotCondition: return vl::Ptr(new vl::glr::parsergen::GlrNotCondition); case ParserGenClasses::OptionalSyntax: return vl::Ptr(new vl::glr::parsergen::GlrOptionalSyntax); case ParserGenClasses::OrCondition: return vl::Ptr(new vl::glr::parsergen::GlrOrCondition); case ParserGenClasses::PartialClause: return vl::Ptr(new vl::glr::parsergen::GlrPartialClause); case ParserGenClasses::PrefixMergeClause: return vl::Ptr(new vl::glr::parsergen::GlrPrefixMergeClause); case ParserGenClasses::PushConditionSyntax: return vl::Ptr(new vl::glr::parsergen::GlrPushConditionSyntax); case ParserGenClasses::RefCondition: return vl::Ptr(new vl::glr::parsergen::GlrRefCondition); case ParserGenClasses::RefSyntax: return vl::Ptr(new vl::glr::parsergen::GlrRefSyntax); case ParserGenClasses::ReuseClause: return vl::Ptr(new vl::glr::parsergen::GlrReuseClause); case ParserGenClasses::Rule: return vl::Ptr(new vl::glr::parsergen::GlrRule); case ParserGenClasses::SequenceSyntax: return vl::Ptr(new vl::glr::parsergen::GlrSequenceSyntax); case ParserGenClasses::SwitchItem: return vl::Ptr(new vl::glr::parsergen::GlrSwitchItem); case ParserGenClasses::SyntaxFile: return vl::Ptr(new vl::glr::parsergen::GlrSyntaxFile); case ParserGenClasses::TestConditionBranch: return vl::Ptr(new vl::glr::parsergen::GlrTestConditionBranch); case ParserGenClasses::TestConditionSyntax: return vl::Ptr(new vl::glr::parsergen::GlrTestConditionSyntax); case ParserGenClasses::UseSyntax: return vl::Ptr(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::AndCondition_first: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrAndCondition::first, object, field, value, cppFieldName); case ParserGenFields::AndCondition_second: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrAndCondition::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::LeftRecursionInjectClause_continuation: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrLeftRecursionInjectClause::continuation, object, field, value, cppFieldName); case ParserGenFields::LeftRecursionInjectClause_rule: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrLeftRecursionInjectClause::rule, object, field, value, cppFieldName); case ParserGenFields::LeftRecursionInjectContinuation_flags: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrLeftRecursionInjectContinuation::flags, object, field, value, cppFieldName); case ParserGenFields::LeftRecursionInjectContinuation_injectionTargets: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrLeftRecursionInjectContinuation::injectionTargets, object, field, value, cppFieldName); case ParserGenFields::LeftRecursionPlaceholderClause_flags: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrLeftRecursionPlaceholderClause::flags, 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::NotCondition_condition: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrNotCondition::condition, object, field, value, cppFieldName); case ParserGenFields::OptionalSyntax_syntax: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrOptionalSyntax::syntax, object, field, value, cppFieldName); case ParserGenFields::OrCondition_first: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrOrCondition::first, object, field, value, cppFieldName); case ParserGenFields::OrCondition_second: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrOrCondition::second, 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::PrefixMergeClause_rule: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrPrefixMergeClause::rule, object, field, value, cppFieldName); case ParserGenFields::PushConditionSyntax_switches: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrPushConditionSyntax::switches, object, field, value, cppFieldName); case ParserGenFields::PushConditionSyntax_syntax: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrPushConditionSyntax::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); case ParserGenFields::SyntaxFile_switches: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrSyntaxFile::switches, object, field, value, cppFieldName); case ParserGenFields::TestConditionBranch_condition: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrTestConditionBranch::condition, object, field, value, cppFieldName); case ParserGenFields::TestConditionBranch_syntax: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrTestConditionBranch::syntax, object, field, value, cppFieldName); case ParserGenFields::TestConditionSyntax_branches: return vl::glr::AssemblerSetObjectField(&vl::glr::parsergen::GlrTestConditionSyntax::branches, 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::LeftRecursionPlaceholder_flag: return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrLeftRecursionPlaceholder::flag, 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::RefCondition_name: return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRefCondition::name, 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_literal: return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRefSyntax::literal, 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::Rule_type: return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRule::type, object, field, token, tokenIndex, cppFieldName); case ParserGenFields::SwitchItem_name: return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrSwitchItem::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, bool weakAssignment) { auto cppFieldName = ParserGenCppFieldName((ParserGenFields)field); switch((ParserGenFields)field) { case ParserGenFields::Assignment_type: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrAssignment::type, object, field, enumItem, weakAssignment, cppFieldName); case ParserGenFields::Class_ambiguity: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrClass::ambiguity, object, field, enumItem, weakAssignment, cppFieldName); case ParserGenFields::ClassProp_propType: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrClassProp::propType, object, field, enumItem, weakAssignment, cppFieldName); case ParserGenFields::LeftRecursionInjectContinuation_configuration: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrLeftRecursionInjectContinuation::configuration, object, field, enumItem, weakAssignment, cppFieldName); case ParserGenFields::LeftRecursionInjectContinuation_type: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrLeftRecursionInjectContinuation::type, object, field, enumItem, weakAssignment, cppFieldName); case ParserGenFields::OptionalSyntax_priority: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrOptionalSyntax::priority, object, field, enumItem, weakAssignment, cppFieldName); case ParserGenFields::RefSyntax_refType: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrRefSyntax::refType, object, field, enumItem, weakAssignment, cppFieldName); case ParserGenFields::SwitchItem_value: return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrSwitchItem::value, object, field, enumItem, weakAssignment, cppFieldName); default: return vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName); } } const wchar_t* ParserGenTypeName(ParserGenClasses type) { const wchar_t* results[] = { L"AlternativeSyntax", L"AndCondition", L"Assignment", L"AstFile", L"Class", L"ClassProp", L"Clause", L"Condition", L"CreateClause", L"Enum", L"EnumItem", L"LeftRecursionInjectClause", L"LeftRecursionInjectContinuation", L"LeftRecursionPlaceholder", L"LeftRecursionPlaceholderClause", L"LoopSyntax", L"NotCondition", L"OptionalSyntax", L"OrCondition", L"PartialClause", L"PrefixMergeClause", L"PushConditionSyntax", L"RefCondition", L"RefSyntax", L"ReuseClause", L"Rule", L"SequenceSyntax", L"SwitchItem", L"Syntax", L"SyntaxFile", L"TestConditionBranch", L"TestConditionSyntax", L"Type", L"UseSyntax", }; vl::vint index = (vl::vint)type; return 0 <= index && index < 34 ? results[index] : nullptr; } const wchar_t* ParserGenCppTypeName(ParserGenClasses type) { const wchar_t* results[] = { L"vl::glr::parsergen::GlrAlternativeSyntax", L"vl::glr::parsergen::GlrAndCondition", 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::GlrCondition", L"vl::glr::parsergen::GlrCreateClause", L"vl::glr::parsergen::GlrEnum", L"vl::glr::parsergen::GlrEnumItem", L"vl::glr::parsergen::GlrLeftRecursionInjectClause", L"vl::glr::parsergen::GlrLeftRecursionInjectContinuation", L"vl::glr::parsergen::GlrLeftRecursionPlaceholder", L"vl::glr::parsergen::GlrLeftRecursionPlaceholderClause", L"vl::glr::parsergen::GlrLoopSyntax", L"vl::glr::parsergen::GlrNotCondition", L"vl::glr::parsergen::GlrOptionalSyntax", L"vl::glr::parsergen::GlrOrCondition", L"vl::glr::parsergen::GlrPartialClause", L"vl::glr::parsergen::GlrPrefixMergeClause", L"vl::glr::parsergen::GlrPushConditionSyntax", L"vl::glr::parsergen::GlrRefCondition", L"vl::glr::parsergen::GlrRefSyntax", L"vl::glr::parsergen::GlrReuseClause", L"vl::glr::parsergen::GlrRule", L"vl::glr::parsergen::GlrSequenceSyntax", L"vl::glr::parsergen::GlrSwitchItem", L"vl::glr::parsergen::GlrSyntax", L"vl::glr::parsergen::GlrSyntaxFile", L"vl::glr::parsergen::GlrTestConditionBranch", L"vl::glr::parsergen::GlrTestConditionSyntax", L"vl::glr::parsergen::GlrType", L"vl::glr::parsergen::GlrUseSyntax", }; vl::vint index = (vl::vint)type; return 0 <= index && index < 34 ? results[index] : nullptr; } const wchar_t* ParserGenFieldName(ParserGenFields field) { const wchar_t* results[] = { L"AlternativeSyntax::first", L"AlternativeSyntax::second", L"AndCondition::first", L"AndCondition::second", L"Assignment::field", L"Assignment::type", 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"LeftRecursionInjectClause::continuation", L"LeftRecursionInjectClause::rule", L"LeftRecursionInjectContinuation::configuration", L"LeftRecursionInjectContinuation::flags", L"LeftRecursionInjectContinuation::injectionTargets", L"LeftRecursionInjectContinuation::type", L"LeftRecursionPlaceholder::flag", L"LeftRecursionPlaceholderClause::flags", L"LoopSyntax::delimiter", L"LoopSyntax::syntax", L"NotCondition::condition", L"OptionalSyntax::priority", L"OptionalSyntax::syntax", L"OrCondition::first", L"OrCondition::second", L"PartialClause::assignments", L"PartialClause::syntax", L"PartialClause::type", L"PrefixMergeClause::rule", L"PushConditionSyntax::switches", L"PushConditionSyntax::syntax", L"RefCondition::name", L"RefSyntax::field", L"RefSyntax::literal", L"RefSyntax::refType", L"ReuseClause::assignments", L"ReuseClause::syntax", L"Rule::clauses", L"Rule::name", L"Rule::type", L"SequenceSyntax::first", L"SequenceSyntax::second", L"SwitchItem::name", L"SwitchItem::value", L"SyntaxFile::rules", L"SyntaxFile::switches", L"TestConditionBranch::condition", L"TestConditionBranch::syntax", L"TestConditionSyntax::branches", L"Type::name", L"UseSyntax::name", }; vl::vint index = (vl::vint)field; return 0 <= index && index < 60 ? 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::GlrAndCondition::first", L"vl::glr::parsergen::GlrAndCondition::second", L"vl::glr::parsergen::GlrAssignment::field", L"vl::glr::parsergen::GlrAssignment::type", 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::GlrLeftRecursionInjectClause::continuation", L"vl::glr::parsergen::GlrLeftRecursionInjectClause::rule", L"vl::glr::parsergen::GlrLeftRecursionInjectContinuation::configuration", L"vl::glr::parsergen::GlrLeftRecursionInjectContinuation::flags", L"vl::glr::parsergen::GlrLeftRecursionInjectContinuation::injectionTargets", L"vl::glr::parsergen::GlrLeftRecursionInjectContinuation::type", L"vl::glr::parsergen::GlrLeftRecursionPlaceholder::flag", L"vl::glr::parsergen::GlrLeftRecursionPlaceholderClause::flags", L"vl::glr::parsergen::GlrLoopSyntax::delimiter", L"vl::glr::parsergen::GlrLoopSyntax::syntax", L"vl::glr::parsergen::GlrNotCondition::condition", L"vl::glr::parsergen::GlrOptionalSyntax::priority", L"vl::glr::parsergen::GlrOptionalSyntax::syntax", L"vl::glr::parsergen::GlrOrCondition::first", L"vl::glr::parsergen::GlrOrCondition::second", L"vl::glr::parsergen::GlrPartialClause::assignments", L"vl::glr::parsergen::GlrPartialClause::syntax", L"vl::glr::parsergen::GlrPartialClause::type", L"vl::glr::parsergen::GlrPrefixMergeClause::rule", L"vl::glr::parsergen::GlrPushConditionSyntax::switches", L"vl::glr::parsergen::GlrPushConditionSyntax::syntax", L"vl::glr::parsergen::GlrRefCondition::name", L"vl::glr::parsergen::GlrRefSyntax::field", L"vl::glr::parsergen::GlrRefSyntax::literal", L"vl::glr::parsergen::GlrRefSyntax::refType", 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::GlrRule::type", L"vl::glr::parsergen::GlrSequenceSyntax::first", L"vl::glr::parsergen::GlrSequenceSyntax::second", L"vl::glr::parsergen::GlrSwitchItem::name", L"vl::glr::parsergen::GlrSwitchItem::value", L"vl::glr::parsergen::GlrSyntaxFile::rules", L"vl::glr::parsergen::GlrSyntaxFile::switches", L"vl::glr::parsergen::GlrTestConditionBranch::condition", L"vl::glr::parsergen::GlrTestConditionBranch::syntax", L"vl::glr::parsergen::GlrTestConditionSyntax::branches", L"vl::glr::parsergen::GlrType::name", L"vl::glr::parsergen::GlrUseSyntax::name", }; vl::vint index = (vl::vint)field; return 0 <= index && index < 60 ? 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"SWITCH", 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"OPEN_PUSH", L"OPEN_TEST", L"AND", L"OR", L"COMMA", L"COLON", L"SEMICOLON", L"INFER", L"ALTERNATIVE", L"USE", L"ASSIGN", L"WEAK_ASSIGN", L"POSITIVE", L"NEGATIVE", L"LS_PH", L"LS_I", L"LS_IM", L"LS_PM", L"ID", L"STRING", L"CONDITIONAL_LITERAL", 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"switch", L"token", L"as", L"partial", L"(", L")", L"[", L"]", L"{", L"}", L"!(", L"?(", L"&&", L"||", L",", L":", L";", L"::=", L"|", L"!", L"=", L"?=", L"+", L"-", L"left_recursion_placeholder", L"left_recursion_inject", L"left_recursion_inject_multiple", L"prefix_merge", nullptr, 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"switch", L"token", L"as", L"partial", L"/(", L"/)", L"/[", L"/]", L"/{", L"/}", L"!/(", L"/?/(", L"&&", L"/|/|", L",", L":", L";", L"::=", L"/|", L"!", L"=", L"/?=", L"/+", L"-", L"left_recursion_placeholder", L"left_recursion_inject", L"left_recursion_inject_multiple", L"prefix_merge", L"[a-zA-Z_][a-zA-Z0-9_]*", L"(\"[^\"]*\")+", 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 = 2299; // 36189 bytes before compressing static const vl::vint dataBlock = 256; static const vl::vint dataRemain = 251; static const vl::vint dataSolidRows = 8; static const vl::vint dataRows = 9; static const char* compressed[] = { "\x5D\x8D\x00\x00\xF3\x08\x00\x00\x87\x00\x01\x81\x21\x84\x81\x80\x20\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\x25\x04\xA6\x0A\x94\x87\x11\x96\x82\x28\x30\x84\x89\x13\x9C\x82\x14\x9B\x04\xAB\x39\x84\x8C\x14\x9C\x83\x16\x3F\x84\xAE\x02\xA4\x87\x15\xA2\x82\x30\x04\xB9\x04\x8A\x1C\xA4\x83\x1D\x4F\x84\xBC\x12\xA4\x85\x1D\xAA\x82\x3E\x58\x84\x9F\x1B\xAC\x83\x82\x83\x04\x83\x81\x9A\x24\x83\x2D\xB2\x82\x5C\x68\x84\x9D\x2B\xB4\x82\x2E\xB7\x04\xDF\x31\xA4\x80\x34\xB8\x83\x30\x77\x84\xA2\x3A\xB4\x83\x31\xBE\x82\x64\x00\xC4\x85\x33\xC4\x82\x32\xC3\x04\xE7\x09\xC4\x88\x34\xC4\x83\x34\x8F\x84\xAA\x32\xC4\x83\x35\xCA\x82\x6C\x18\xC4\x8D\x3B\xCC\x82\x36\xCF\x04\xEF\x21\xC4\x80\x3C\xD0\x83\x38\xA7\x84\xB2\x2A\xD4\x83\x39\xD6\x82\x74\x30\xC4\x95\x33\xDC\x82\x3A\xDB\x04\xF7\x39\xC4\x88\x3C\xDC\x83\x3C\x04\xFA\x04\x9B\x33\xE4\x80\x3E\xE3\x04\xFD\x09\xE4\x8E\x3C\x83\x7F\x7F\x10\x00\x0F\xEF\xEC\x0C\x81\xEB\x80\xD3\xFF\x57\xF2", "\xE3\xEB\xEE\x8D\x80\x1A\x4E\xD3\xF1\xE1\x83\x0E\x84\x87\xD8\xD3\xD6\x04\x82\x0C\x83\x0A\xF1\xCF\x9D\x30\xFF\x73\x0C\x80\x0B\xF9\x15\x73\xCF\x13\xF9\x09\x89\xF5\xE7\x13\x7F\x7F\x3D\x7F\x02\x89\x41\x40\x81\x00\x02\x04\x40\x82\x03\x0B\x8E\x83\x81\x0F\x80\x08\x80\x82\x18\x11\x83\x84\x41\x07\x16\x84\x41\x01\x04\x46\x01\x84\x01\x1A\x90\x81\x41\x45\x01\x51\x08\x46\x80\xD9\x69\x8A\x8B\x8A\x2C\xAD\x8E\x8B\x8B\x30\xB0\x8E\x44\x8A\x31\xAE\x83\x8C\x77\x35\xB7\x89\x77\x8D\x3C\x9F\x41\x41\x8F\x3F\xBE\x80\x00\x90\x43\x82\x9E\x06\x90\x44\x84\x9C\x45\x90\x4C\x85\x9D\x90\x91\x35\x91\x92\x97\x94\x54\x95\x9F\x3E\x8E\x56\xAB\x88\x95\x8E\xF3\x49\x98\x93\x97\x4F\xA0\x90\x01\x48\x61\xA5\x9E\x93\x99\x5E\xA6\x90\x95\x96\x6C\xAD\x9E\x99\x8B\x5B\xAF\x91\x9E\x8C\x5D\xA2\x99\x98\x9A\x76\xA2\x94\x4A\x9A\x79\xBC\x96\x9B\x9B\x80\x81\xAC\x9B\x9C\x6D\x84\xA6\x8F\x7C\x27\x7E\x98\x9E\xA2\x77\x8D\xAD\x9F\xA2\x90\xAB\x92\xA3\xA4\x94\xAF\x86\xA1\x96\x97\xAC\x81\x9E\xA3\x8C\x8F\xAC\xA5\xA4\x9E\x84\x44\x0A\x98\x95\xA5\xA6\xAB\x8E\xF3\x6E\x99\xA6\x96", "\x75\x9D\xAE\xA8\xA8\x66\xA9\x4F\xAB\xA7\x92\xA7\xA6\xAE\xA0\xAB\x94\x99\xAD\x8A\x71\xAB\x43\xAD\xA8\xBF\xA6\x9E\x49\xB0\x90\xB7\xA6\xB3\xB1\xC8\x89\xBA\xB3\xB2\xCC\x8D\xBE\xB3\xB3\xD0\x91\xB2\xB7\xB4\xD4\x95\xB6\xB7\xB5\xD8\x99\xBA\xB7\xB6\xDC\x9D\xBE\xB7\xB7\xE0\xA1\xB2\xBB\xB8\xD0\xB1\x44\x8C\xB9\xE8\xA9\xBF\xB0\x4D\xE7\x86\xB7\x4D\xBB\xEA\xB1\xB4\xB6\x4E\xF0\xB2\xB6\xBF\xBD\xF8\xB9\xBA\xBD\x76\x3D\x75\xBB\xBF\xBF\x00\xC1\xC2\xA0\x50\xFE\x82\xC6\xC3\xC1\x08\xC9\xCA\xC3\xC2\x0C\xCD\xCE\xC3\xC3\x10\xD1\xC2\xC7\xB2\xBB\x92\x95\xC7\x74\x9B\x8F\xA3\x50\xB1\xB4\x80\xB0\xAF\xC7\x13\xE8\xA5\xC2\xC5\xA9\x96\xAD\xAB\xC7\x1D\xDC\xCE\xC5\xCA\x67\x96\x96\x51\x40\x2F\xC0\x01\xCF\xCC\x47\x70\xC5\xCC\x00\x49\x76\xCA\xCE\xCC\x37\xF4\xCB\xCE\xCF\x3C\xFF\xCD\xCF\xD0\x42\xC5\xD1\xD3\xD1\x40\xC9\xD4\xD0\xD2\x4B\xCA\xD6\xD2\xD3\x4C\xCF\xDD\xD3\xD4\x52\xC2\x81\x0C\x41\x57\xC1\x49\xD4\x00\x5B\xDD\xD8\xD7\xD7\x5A\xE0\xDC\xD4\x41\x32\x22\xDE\xD5\xD8\x68\xE3\xD9\xDB\xD9\x6A\xED\xDC\xDB\xDB\x66\xF1\xDB\xDA\xDC\x6E\xF4\xD0\xDF\xDC\x78", "\xF5\xD9\xDF\xDD\x7A\xFD\xDC\xDC\xDF\x2C\xB3\x04\x42\xE0\x02\x84\xE8\x8F\x3F\x86\xE1\xCA\xE3\xE2\x35\xB4\x05\xC8\xE3\x90\xD6\xB7\xC4\x97\x23\xD8\xC7\xC9\x0D\x2B\xD9\xEA\xCB\xE6\x2D\xCB\xE3\xE5\x8C\x9F\xD9\xCC\xE4\xCB\xA4\xDA\xE5\xB2\xE7\x8F\xD8\xA9\xEA\xA6\x27\xE5\xE3\xEA\xE9\xAE\xC7\xE3\xC7\xE7\x74\x95\xEF\x71\x9C\x36\x30\xEA\xEF\xEB\xC4\x8C\xE4\xEE\xC9\xB6\xD7\x9D\xEB\xEE\x28\xC4\xF4\x93\x0D\x1E\xFE\xEB\xE9\x95\xA1\xC3\xFC\xED\xF1\xAF\xB8\x06\xF3\xF2\x0D\xFF\xE7\xA1\xF0\xA2\xD0\xFF\xC7\x52\xCF\xF1\xE7\x9E\xF2\xC1\xF5\xE2\xEC\xF0\x87\xDE\xFF\xA1\x53\xDD\xC4\xF0\xFB\xF8\x83\x94\xFC\xAE\xF3\xDA\xE6\xFF\xA8\x54\xCF\xEB\xF8\xAE\xFB\x22\xE5\xFF\xA3\x54\xE9\xFD\xFA\xF5\xE4\x00\x81\x82\x00\x83\x84\x81\x02\x86\x87\x80\x08\x89\x82\x02\x8B\x80\x46\xAB\x21\x7C\x81\x05\x96\x78\x9C\x78\x76\x72\x01\x6C\x61\x2B\xFE\x72\x7F\xFF\x55\x40\x6B\x0E\xB7\x61\x67\x51\x61\x86\x07\xD5\x62\x84\xAA\x65\x84\x84\x23\x87\x86\x0A\xA9\x8C\x84\x13\xAD\x80\x85\x37\x77\x54\x57\x0F\x80\x83\x86\x7F\x6E\x6E\x38\x89\x6D\xD9\x7B\x69\x86\xBF\x7D\x87", "\x86\x3C\x81\x8A\x0F\xC2\x80\x89\x21\x86\x8D\x88\x48\x9F\x86\xD8\x51\x5F\x2A\xF6\x75\x87\x61\x86\x69\x73\x74\x52\x8F\x38\x2A\x8F\x88\x81\x62\x20\x01\x16\xD9\x3B\x8B\xE9\x19\x8F\x8B\x61\x21\x8E\x40\x62\x8A\x8A\x32\xA0\x8B\x8C\x68\x85\x8D\x1A\xE7\x8A\x8D\x36\xAC\x8F\x8D\x66\x91\x8F\x1A\xF2\x8E\x8C\x3A\xB0\x8B\x8E\x78\x95\x8D\x1E\xF7\x8A\x8F\x3E\xBC\x8C\x8D\x07\x72\x80\xEB\x58\x70\x7F\xD8\x42\x0B\x7A\x19\x94\x81\xC2\x02\x9C\x54\x42\x96\x80\x91\xF1\x66\x77\x10\x6A\x78\x74\x1A\x93\x86\x91\xFA\x69\x92\x99\x44\x00\x92\x96\x76\x79\x50\xCD\x6F\x92\x26\x91\x93\x94\x46\xBB\x5E\x94\xEF\x78\x91\xFE\x1A\x8C\x95\x47\x45\x0E\x74\x9F\x80\x51\x28\x99\x9F\x62\x23\x1D\x97\x96\xAF\x51\x96\x9C\x0A\x92\x78\x51\xA4\x97\x97\xAD\x81\x23\x11\x30\x95\x92\x27\x96\x4B\x96\xAB\x8F\x50\x12\x38\x90\x98\x62\x97\x8F\x99\x57\x88\x95\xFE\x24\x6E\x97\x60\x8D\x9F\x55\x49\x0E\x9B\x94\x4A\x04\x20\x6E\x81\x26\x9B\x00\x00\x9E\x38\xDD\x94\x9D\x80\x0B\x0D\x9C\xE1\x88\x9F\x38\xDF\x9A\x9D\x76\xAC\x9F\x9D\xE9\x90\x9F\x3A\xF1\x94\x9F\x79\xB6\x9E\x9D\xF5\x98", "\x9F\x3D\xF2\x9A\x9F\x7E\xBC\x9F\x9F\xF9\x80\xA3\x3E\x81\xA4\xA1\xEC\x0C\x0C\x20\x07\xA1\x21\x42\x80\x0B\xA1\x86\x88\xA7\xA1\x0A\xB0\xA0\x43\x84\x2D\x08\x89\x8E\xA1\xA2\x18\xB3\xA1\x46\x97\xAA\xA3\x8E\x9C\xA7\xA3\x16\xA1\xA7\x46\xA2\xAE\xA2\x92\xA0\xA3\xA4\x28\xA5\xA5\x4A\xA7\xAA\xA5\x96\xAC\xA4\xA5\x5C\x84\x8D\x4C\x82\x4F\x8E\x3B\xB6\xA3\x8F\x37\xBE\x8D\x4E\xB5\xA8\xA7\x9E\xBA\xA6\xA7\x3C\xBF\xA6\x50\xC1\xA4\xA8\x3A\x81\x94\x97\xE2\x74\x98\x2D\xAC\x6E\x08\x66\x96\x9D\x56\xB3\x68\xA8\xF9\x4A\xA9\x99\x52\x84\x7F\x09\x94\x8A\x72\x34\x95\x86\x99\x46\x8B\xAE\xA9\x60\xBD\x75\x31\xF7\x7A\x94\xAE\xB7\x40\x0A\x61\xB7\x9A\x5A\xDB\xA7\x5E\xB6\xBD\x95\xAB\x2A\x59\x7B\x53\x8F\x51\x0B\xB4\x90\xAA\x62\x6E\xA8\x9A\x59\xC4\x72\x0A\xBB\x99\xA9\x64\x79\xBC\x96\x5C\xC4\x73\x0A\xBF\x9C\x72\x97\xAA\x5C\x94\x15\x05\x96\xB1\xB5\x9A\x9A\x4A\x03\xB1\xB0\x3A\xE7\x92\xA0\x7F\x84\xA2\xB2\x95\xB9\xB3\x65\x96\xB8\xB3\xCD\x9A\xB5\xB3\xA0\xBC\xB2\x68\x9F\xB2\xAA\x2A\x73\x80\xAE\xD0\x8F\x63\x4B\xA6\xAC\xB5\x8C\x95\xA3\xA5\xAD\xAE\xA5\x6C\xAB", "\xB0\xB7\xDA\xB2\xB6\xB6\xB4\xB7\xB6\x6E\xB9\xBC\xB7\xD9\x92\xA4\x89\xA5\xA9\xB6\x70\xE4\xA8\xB4\xAA\x91\x4B\xB0\x56\xBE\x7D\x15\x49\x73\xAC\x50\x82\xB4\xB1\xC9\xAE\xB2\x58\xDA\xA1\xB9\x41\x85\xBC\xAB\x55\xBF\x96\x15\x0D\xBA\x82\xC4\x85\x57\xB9\xD5\x9C\xBA\x78\xCD\x4E\xBB\xF6\x65\xAF\x39\x57\x03\xBE\x74\xEA\xA5\xBC\xD5\x67\xBF\xAD\x73\xB1\xBB\x9D\x58\x02\x49\xF6\x87\x98\xBC\x5F\xB2\xBE\xC7\x59\x00\x92\xFB\x8C\x78\xBF\xD9\xB1\xBF\xC7\x64\x21\xBA\xFF\xBA\x50\xC0\x7B\xBA\xBE\x82\x9D\x74\xBA\x4B\x96\xBE\xB8\xB7\x6D\xB2\x59\x0B\xC7\xAF\x88\x41\xB1\x78\x69\x21\xBC\x85\xEA\xB6\xC1\x29\x7A\xA9\xC2\x8A\x4C\x2F\x86\xFE\x7D\xC2\x08\xE0\x70\xBA\xEB\xA2\xC3\x8D\x6F\x29\x97\xE6\xB2\x90\xC1\x20\xC9\xC6\x7A\x9E\x9E\xC5\x5D\xAF\xBA\xC5\x62\x52\x2F\x88\xD7\xBB\x91\xEA\x9E\xAE\xC4\x44\x55\x2F\x8E\xB8\xCE\xC1\x7F\x57\xC4\xC7\x6F\xA1\xC3\x8C\x8F\x58\x2F\xC3\xB5\xC1\xB1\x37\xCF\x53\x5E\x43\xCD\xBF\x27\xDF\xB9\xCA\x54\xDC\x72\x5F\x2D\xCD\xC0\x24\xC9\xAF\xB8\x28\xC4\xCA\x8C\xDC\xC0\xB0\x1F\xF1\xA8\xC6\xF0\xAB\xCA\xA2\x01\x35\x7E\x2B", "\xE6\xB8\xC9\xC8\xA3\xCF\x7A\x84\x3D\xCD\x2E\xC4\xB8\xC8\xA6\x67\x31\x96\xBF\x95\xC4\x30\xD8\xCA\xCE\x02\xCA\x32\x93\xF6\xCE\xB9\x3F\xF7\x4D\x31\x7B\xDD\xBA\x9B\xEE\xB0\xCF\x30\xDE\x60\x32\x89\xC4\x57\xA2\xF7\xB6\xD0\x35\xC0\xD2\xD2\x84\xCF\xC5\xA5\xBB\xC3\x33\x02\xD3\xD7\xBF\x9B\xD7\xD2\x99\x16\x3B\xC1\x3E\xD4\x70\xC9\x99\x3A\xC2\xA8\xAB\xD4\xC7\x4C\xF6\xC5\xD1\xAA\xD1\x77\x67\x1C\x7C\x33\x51\xA6\xD7\xC4\xA1\xC2\xC2\x68\x7B\xC7\xD7\x2F\xE7\xD2\xC9\xD1\xA5\x35\xA9\x9F\xD7\xC1\xF7\xA8\x31\xD2\x9E\xCE\xD4\x94\xB0\xD9\xBF\xF5\xAB\x30\xD9\x0C\xC5\xCD\x91\xE7\xC1\xD4\xD7\x10\xDE\x9A\xBD\xD3\xAA\x9F\xCD\xD4\x49\xD8\x17\xDF\xB1\x78\xA6\xCD\x2A\xCC\xD0\xD9\x33\x74\x37\xDB\xD3\xB2\xDA\x97\xDA\xDF\xD7\x04\xC0\x07\x36\xE8\xCB\xBD\xB6\xD7\x74\xDC\x77\xEC\x62\x37\xF1\xD5\xC0\xC4\x47\xC8\xCF\x7C\xE2\x4D\x37\xE9\xD1\xAB\xB4\xE3\xDD\xDE\x56\xCF\x50\x38\xC9\xCA\xDF\x9D\xD1\x42\x39\x58\xD6\xD2\xCC\xF3\xD7\x91\xBD\xB1\xC2\xCC\xE2\x3C\xD4\xD8\x1E\xC8\xCE\x98\xC4\x47\x39\x1D\xD1\xE7\xC1\xDB\xC5\xDE\x72\x7E\xD1\xE1\x70\xC3\xE3\x9A", "\x21\xF6\xDF\xC3\x9E\x6D\x38\x32\xC2\xE3\xDD\xF4\xC5\xE3\x9D\x7F\x0B\xE5\x3A\xCA\xE5\xD0\x13\xE9\xCF\x28\x80\x15\xE6\x98\xC1\x64\xDF\x29\xF4\xE1\xCF\xC4\x41\x11\x2A\xCA\xDF\xCA\x39\xFB\xE0\x33\x82\x10\xDC\x0B\xE2\xD8\xE5\xED\xC2\xE8\xC9\xF2\xD8\xE2\x13\xFE\xD2\xE7\x6A\xA3\x13\xD0\x98\xD7\xE6\x4D\xC9\xEB\xEB\x01\x24\x11\x5A\x9F\xEF\xC7\xA0\xD8\xEA\xC0\x85\x1D\xE4\xD9\xD4\xDF\xEA\x45\x46\x10\xEC\xEC\xB5\xEA\xD9\xD7\xEA\xE8\x68\xD6\x4E\x1F\x7F\x1E\x1F\x34\x7F\x1F\x0B\x7E\x39\xEB\x1D\x2A\x5F\x0C\x40\x05\x2F\x79\x85\x01\x25\x21\x01\x30\x21\x40\x01\x40\x00\x12\x40\x07\x22\x01\x2F\x3D\x40\x32\x50\x00\xCA\xEB\x39\x20\xED\x21\x21\x7D\x01\x27\x3F\x80\x15\x40\x3C\x04\x26\x3D\xAC\x28\x26\x24\xD2\xCD\x4E\x43\xFE\x7F\x38\x00\x7B\x32\x44\x00\x24\x38\x00\x26\x53\xF2\x90\x14\xF4\x4D\xCA\xE5\x21\x20\x89\x40\x03\xA8\x0A\x5D\x41\x57\x79\x3D\x49\x94\xF4\xF3\xEE\x90\x5A\x40\x62\x74\xF6\xF4\x00\x1B\x4F\x99\x06\x47\x4C\x0E\x6F\x50\x44\xAF\x59\x40\xB1\x05\x21\x77\x25\x46\xE4\x58\xF2\x3E\x7F\x76\x1F\x57\x49\x80\x00", }; 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 = Ptr(new CppSyntaxGenOutput); 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"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.WriteLine(manager.Global().name + L"AstInsReceiver>"); writer.WriteLine(prefix + L"\t, protected vl::glr::automaton::IExecutor::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(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 ParseWithString<" + astType + L", " + 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 ParseWithTokens<" + astType + L", " + 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; if (result == 0) { if (e1->input.condition && e2->input.condition) { result = (vint)WString::Compare(e1->input.condition.Value(), e2->input.condition.Value()); } else if (e1->input.condition) { result = 1; } else if (e2->input.condition) { result = -1; } } 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; } void SyntaxSymbolManager::RemoveRule(const WString& name) { rules.Remove(name); } 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 = Ptr(new StateSymbol(rule, clauseId)); states.Add(symbol); return symbol.Obj(); } 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 = Ptr(new EdgeSymbol(from, to)); edges.Add(symbol); return symbol.Obj(); } 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\SYNTAXSYMBOLWRITER.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; /*********************************************************************** AutomatonBuilder ***********************************************************************/ AutomatonBuilder::AutomatonBuilder(RuleSymbol* _ruleSymbol) : ruleSymbol(_ruleSymbol) { } /*********************************************************************** AutomatonBuilder (Syntax) ***********************************************************************/ AutomatonBuilder::StatePair AutomatonBuilder::BuildTokenSyntax(vint32_t tokenId, const WString& displayText, Nullable condition, vint32_t field) { 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 = tokenId; edge->input.condition = condition; if (field != -1) { edge->insAfterInput.Add({ AstInsType::Token }); edge->insAfterInput.Add({ AstInsType::Field,field }); } } clauseDisplayText += displayText; endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildRuleSyntaxInternal(RuleSymbol* rule, vint32_t field, automaton::ReturnRuleType ruleType) { #define ERROR_MESSAGE_PREFIX L"vl::glr::parsergen::AutomatonBuilder::BuildRuleSyntaxInternal(RuleSymbol*, vint32_t, ReturnRuleType)#" 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->input.ruleType = ruleType; switch (ruleType) { case automaton::ReturnRuleType::Field: CHECK_ERROR(field != -1, ERROR_MESSAGE_PREFIX L"Field must set for ReturnRuleType::Field."); edge->insAfterInput.Add({ AstInsType::Field,field }); break; case automaton::ReturnRuleType::Partial: CHECK_ERROR(field == -1, ERROR_MESSAGE_PREFIX L"Field must not set for ReturnRuleType::Partial."); break; case automaton::ReturnRuleType::Discard: CHECK_ERROR(field == -1, ERROR_MESSAGE_PREFIX L"Field must not set for ReturnRuleType::Discard."); edge->insAfterInput.Add({ AstInsType::DiscardValue }); break; case automaton::ReturnRuleType::Reuse: CHECK_ERROR(field == -1, ERROR_MESSAGE_PREFIX L"Field must not set for ReturnRuleType::Reuse."); edge->insAfterInput.Add({ AstInsType::ReopenObject }); break; } } switch (ruleType) { case automaton::ReturnRuleType::Reuse: clauseDisplayText += L"!" + rule->Name(); break; default: clauseDisplayText += rule->Name(); break; } endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; #undef ERROR_MESSAGE_PREFIX } AutomatonBuilder::StatePair AutomatonBuilder::BuildFieldRuleSyntax(RuleSymbol* rule, vint32_t field) { return BuildRuleSyntaxInternal(rule, field, automaton::ReturnRuleType::Field); } AutomatonBuilder::StatePair AutomatonBuilder::BuildPartialRuleSyntax(RuleSymbol* rule) { return BuildRuleSyntaxInternal(rule, -1, automaton::ReturnRuleType::Partial); } AutomatonBuilder::StatePair AutomatonBuilder::BuildDiscardRuleSyntax(RuleSymbol* rule) { return BuildRuleSyntaxInternal(rule, -1, automaton::ReturnRuleType::Discard); } AutomatonBuilder::StatePair AutomatonBuilder::BuildUseSyntax(RuleSymbol* rule) { return BuildRuleSyntaxInternal(rule, -1, automaton::ReturnRuleType::Reuse); } AutomatonBuilder::StatePair AutomatonBuilder::BuildLoopSyntax(const StateBuilder& loopBody, const StateBuilder& loopDelimiter, bool hasDelimiter) { /* * +--------------------+ * | V * S --+--+--(loopBody)--+--+--> E * ^ | * +--------------+ */ /* * +-------------------------+ * | V * S --+--+--( loopBody )--+--+--> E * ^ | * +--(loopDelimiter)--+ */ StatePair pair, bodyPair, delimiterPair; pair.begin = CreateState(); pair.end = CreateState(); startPoses.Add(pair.begin, clauseDisplayText.Length()); clauseDisplayText += L"{ "; bodyPair = loopBody(); if (hasDelimiter) { clauseDisplayText += L" ; "; delimiterPair = loopDelimiter(); } clauseDisplayText += L" }"; CreateEdge(pair.begin, bodyPair.begin); CreateEdge(bodyPair.end, pair.end); CreateEdge(pair.begin, pair.end); if (hasDelimiter) { CreateEdge(bodyPair.end, delimiterPair.begin); CreateEdge(delimiterPair.end, bodyPair.begin); } else { CreateEdge(bodyPair.end, bodyPair.begin); } endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildOptionalSyntax(bool preferTake, bool preferSkip, const StateBuilder& optionalBody) { /* * +------------------+ * | V * S --+--(optionalBody)--+--> E */ StatePair pair; pair.begin = CreateState(); pair.end = CreateState(); startPoses.Add(pair.begin, clauseDisplayText.Length()); if (!preferTake && !preferSkip) { clauseDisplayText += L"[ "; } else if (preferTake) { clauseDisplayText += L"+[ "; } else if (preferSkip) { clauseDisplayText += L"-[ "; } auto bodyPair = optionalBody(); clauseDisplayText += L" ]"; auto takeEdge = CreateEdge(pair.begin, bodyPair.begin); CreateEdge(bodyPair.end, pair.end); auto skipEdge = CreateEdge(pair.begin, pair.end); if (preferTake) { takeEdge->important = true; } if (preferSkip) { skipEdge->important = true; } endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildSequenceSyntax(collections::List& elements) { /* * S --(a)--> ? --(b)--> E */ CHECK_ERROR(elements.Count() > 0, L"vl::glr::parsergen::AutomatonBuilder::BuildSequenceSyntax(List&)#Elements must not be empty."); auto pair = elements[0](); for (vint i = 1; i < elements.Count(); i++) { clauseDisplayText += L" "; auto nextPair = elements[i](); CreateEdge(pair.end, nextPair.begin); pair.end = nextPair.end; } return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildAlternativeSyntax(collections::List& elements) { /* * +--(a)--+ * | V * S --+--(b)--+--> E */ CHECK_ERROR(elements.Count() > 0, L"vl::glr::parsergen::AutomatonBuilder::BuildAlternativeSyntax(List&)#Elements must not be empty."); StatePair pair; pair.begin = CreateState(); pair.end = CreateState(); startPoses.Add(pair.begin, clauseDisplayText.Length()); clauseDisplayText += L"( "; for (vint i = 0; i < elements.Count(); i++) { if (i > 0) clauseDisplayText += L" | "; auto branchPair = elements[i](); CreateEdge(pair.begin, branchPair.begin); CreateEdge(branchPair.end, pair.end); } clauseDisplayText += L" )"; endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } /*********************************************************************** AutomatonBuilder (Clause) ***********************************************************************/ AutomatonBuilder::StatePair AutomatonBuilder::BuildClause(const StateBuilder& compileSyntax) { ruleSymbol->NewClause(); clauseDisplayText = L""; startPoses.Clear(); endPoses.Clear(); auto pair = compileSyntax(); 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); } return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildAssignment(StatePair pair, vint32_t enumItem, vint32_t field, bool weakAssignment) { auto withState = CreateState(); auto edge = CreateEdge(pair.end, withState); edge->insBeforeInput.Add({ AstInsType::EnumItem,enumItem }); edge->insBeforeInput.Add({ (weakAssignment ? AstInsType::FieldIfUnassigned : AstInsType::Field),field}); endPoses.Add(withState, clauseDisplayText.Length()); return { pair.begin,withState }; } AutomatonBuilder::StatePair AutomatonBuilder::BuildCreateClause(vint32_t classId, const StateBuilder& compileSyntax) { StatePair pair; pair.begin = CreateState(); pair.end = CreateState(); startPoses.Add(pair.begin, clauseDisplayText.Length()); clauseDisplayText += L"< "; auto bodyPair = compileSyntax(); clauseDisplayText += L" >"; { auto edge = CreateEdge(pair.begin, bodyPair.begin); edge->insBeforeInput.Add({ AstInsType::BeginObject,classId }); } { auto edge = CreateEdge(bodyPair.end, pair.end); edge->insBeforeInput.Add({ AstInsType::EndObject }); } endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildPartialClause(const StateBuilder& compileSyntax) { return compileSyntax(); } AutomatonBuilder::StatePair AutomatonBuilder::BuildReuseClause(const StateBuilder& compileSyntax) { StatePair pair; pair.begin = CreateState(); pair.end = CreateState(); startPoses.Add(pair.begin, clauseDisplayText.Length()); clauseDisplayText += L"<< "; auto bodyPair = compileSyntax(); 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; } AutomatonBuilder::StatePair AutomatonBuilder::BuildLrpClause(collections::SortedList& flags, const Func& flagName) { /* * S --+--(lrp:(a,b))--+--> E */ 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::LrPlaceholder; CopyFrom(edge->input.flags, flags); } clauseDisplayText += L"lrp:("; for (vint i = 0; i < flags.Count(); i++) { if (i > 0) clauseDisplayText += L","; clauseDisplayText += flagName(flags[i]); } clauseDisplayText += L")"; endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildLriSyntax(collections::SortedList& flags, RuleSymbol* rule, const Func& flagName) { 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::LrInject; CopyFrom(edge->input.flags, flags); edge->input.rule = rule; edge->input.ruleType = automaton::ReturnRuleType::Reuse; edge->insAfterInput.Add({ AstInsType::ReopenObject }); } clauseDisplayText += L"lri:("; for (vint i = 0; i < flags.Count(); i++) { if (i > 0) clauseDisplayText += L","; clauseDisplayText += flagName(flags[i]); } clauseDisplayText += L")->" + rule->Name(); endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildLriSkip() { 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::Epsilon; } clauseDisplayText += L"lri:"; endPoses.Add(pair.end, clauseDisplayText.Length()); return pair; } AutomatonBuilder::StatePair AutomatonBuilder::BuildLriClauseSyntax(StateBuilder useOrLriSyntax, bool optional, collections::List&& continuations) { /* * +--(lri:c:ReopenObject)--+ * | | * +--(lri:a:ReopenObject)--+--(lri:d:ReopenObject)--+--+ * | | | | * | +------------------------+ | {<-- if optional} * | V * S --(rule:ReopenObject)--+--(lri:b:ReopenObject)------------------------------+--> E * | ^ * +----------------------------------------------------+ {<-- if optional} */ if (optional) { continuations.Add([this]() { return BuildLriSkip(); }); } List seqs; seqs.Add(useOrLriSyntax); seqs.Add([this, &continuations]() { return BuildAlternativeSyntax(continuations); }); return BuildSequenceSyntax(seqs); } } } } /*********************************************************************** .\SYNTAX\SYNTAXSYMBOL_AUTOMATON.CPP ***********************************************************************/ namespace vl { namespace glr { namespace parsergen { using namespace collections; using namespace stream; /*********************************************************************** 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 astInsInOrder; // 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.stringLiteralBuffer { MemoryStream stringLiteralBuffer; { StreamWriter stringLiteralWriter(stringLiteralBuffer); for (auto edge : edgesInOrder) { if (edge->input.condition) { stringLiteralWriter.WriteString(edge->input.condition.Value()); } } } { stringLiteralBuffer.SeekFromBegin(0); StreamReader stringLiteralReader(stringLiteralBuffer); executable.stringLiteralBuffer = stringLiteralReader.ReadToEnd(); } } // executable.edges executable.edges.Resize(edgesInOrder.Count()); vint32_t stringLiteralIndex = 0; 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()); if (edge->input.condition) { vint32_t length = (vint32_t)edge->input.condition.Value().Length(); edgeDesc.condition.start = stringLiteralIndex; edgeDesc.condition.count = length; stringLiteralIndex += length; } switch (edge->importancy) { case EdgeImportancy::HighPriority: edgeDesc.priority = automaton::EdgePriority::HighPriority; break; case EdgeImportancy::LowPriority: edgeDesc.priority = automaton::EdgePriority::LowPriority; break; default:; } edgeDesc.insBeforeInput.start = (vint32_t)astInsInOrder.Count(); CopyFrom(astInsInOrder, edge->insBeforeInput, true); edgeDesc.insBeforeInput.count = (vint32_t)astInsInOrder.Count() - edgeDesc.insBeforeInput.start; edgeDesc.insAfterInput.start = (vint32_t)astInsInOrder.Count(); CopyFrom(astInsInOrder, edge->insAfterInput, true); edgeDesc.insAfterInput.count = (vint32_t)astInsInOrder.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; default:; } returnDesc.ruleType = edge->input.ruleType; returnDesc.insAfterInput.start = (vint32_t)astInsInOrder.Count(); CopyFrom(astInsInOrder, edge->insAfterInput, true); returnDesc.insAfterInput.count = (vint32_t)astInsInOrder.Count() - returnDesc.insAfterInput.start; if (returnDesc.insAfterInput.count == 0) returnDesc.insAfterInput.start = -1; } // executable.returnIndices CopyFrom(executable.returnIndices, returnIndicesInOrder); // executable.astInstructions CopyFrom(executable.astInstructions, astInsInOrder); } } } } /*********************************************************************** .\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 _cond0 = manager.CreateRule(L"Cond0"); auto _cond1 = manager.CreateRule(L"Cond1"); auto _cond2 = manager.CreateRule(L"Cond2"); auto _cond = manager.CreateRule(L"Cond"); auto _switchItem = manager.CreateRule(L"SwitchItem"); auto _switches = manager.CreateRule(L"Switches"); auto _optionalBody = manager.CreateRule(L"OptionalBody"); auto _testBranch = manager.CreateRule(L"TestBranch"); auto _token = manager.CreateRule(L"Token"); 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 _assignmentOp = manager.CreateRule(L"AssignmentOp"); auto _assignment = manager.CreateRule(L"Assignment"); auto _clause = manager.CreateRule(L"Clause"); auto _placeholder = manager.CreateRule(L"Placeholder"); auto _ruleName = manager.CreateRule(L"RuleName"); auto _lriConfig = manager.CreateRule(L"LriConfig"); auto _lriContinuationBody = manager.CreateRule(L"LriContinuationBody"); auto _lriContinuation = manager.CreateRule(L"LriContinuation"); auto _lriTarget = manager.CreateRule(L"LriTarget"); auto _rule = manager.CreateRule(L"Rule"); auto _file = manager.CreateRule(L"File"); _switches->isPartial = true; _optionalBody->isPartial = true; _token->isPartial = true; _assignmentOp->isPartial = true; _lriConfig->isPartial = true; _lriContinuationBody->isPartial = true; manager.parsableRules.Add(_file); manager.ruleTypes.Add(_file, L"vl::glr::parsergen::GlrSyntaxFile"); using T = ParserGenTokens; using C = ParserGenClasses; using F = ParserGenFields; /////////////////////////////////////////////////////////////////////////////////// // Condition /////////////////////////////////////////////////////////////////////////////////// // ID:name as RefCondition Clause{ _cond0 } = create(tok(T::ID, F::RefCondition_name), C::RefCondition); // "(" !Cond ")" Clause{ _cond0 } = tok(T::OPEN_ROUND) + use(_cond) + tok(T::CLOSE_ROUND); // "!" Cond0:syntax as NotCondition Clause{ _cond0 } = create(tok(T::USE) + rule(_cond0, F::NotCondition_condition), C::NotCondition); // !Cond0 Clause{ _cond1 } = use(_cond0); // Cond1:first "&&" Cond0:second as AndCondition Clause{ _cond1 } = create(rule(_cond1, F::AndCondition_first) + tok(T::AND) + rule(_cond0, F::AndCondition_second), C::AndCondition); // !Cond1 Clause{ _cond2 } = use(_cond1); // Cond2:first "||" Cond1:second as OrCondition Clause{ _cond2 } = create(rule(_cond2, F::OrCondition_first) + tok(T::OR) + rule(_cond1, F::OrCondition_second), C::OrCondition); // !Cond2 Clause{ _cond } = use(_cond2); /////////////////////////////////////////////////////////////////////////////////// // Switch /////////////////////////////////////////////////////////////////////////////////// // ID:name as SwitchItem {value = True} Clause{ _switchItem } = create(tok(T::ID, F::SwitchItem_name), C::SwitchItem).with(F::SwitchItem_value, GlrSwitchValue::True); // "!" ID:name as SwitchItem {value = False} Clause{ _switchItem } = create(tok(T::USE) + tok(T::ID, F::SwitchItem_name), C::SwitchItem).with(F::SwitchItem_value, GlrSwitchValue::False); // "switch" {SwitchItem:switches ; ","} ";" as partial File Clause{ _switches } = partial(tok(T::SWITCH) + loop(rule(_switchItem, F::SyntaxFile_switches), tok(T::COMMA)) + tok(T::SEMICOLON)); /////////////////////////////////////////////////////////////////////////////////// // Syntax (primitive) /////////////////////////////////////////////////////////////////////////////////// // "[" Syntax:syntax "]" as partial OptionalSyntax Clause{ _optionalBody } = partial(tok(T::OPEN_SQUARE) + rule(_syntax, F::OptionalSyntax_syntax) + tok(T::CLOSE_SQUARE)); // ID:literal as partial RefSyntax {refType = Id} Clause{ _token } = partial(tok(T::ID, F::RefSyntax_literal)).with(F::RefSyntax_refType, GlrRefType::Id); // STRING:literal as partial RefSyntax {refType = Literal} Clause{ _token } = partial(tok(T::STRING, F::RefSyntax_literal)).with(F::RefSyntax_refType, GlrRefType::Literal); // CONDITIONAL_LITERAL:literal as partial RefSyntax {refType = ConditionalLiteral} Clause{ _token } = partial(tok(T::CONDITIONAL_LITERAL, F::RefSyntax_literal)).with(F::RefSyntax_refType, GlrRefType::ConditionalLiteral); // Token [":" ID:field] as RefSyntax Clause{ _syntax0 } = create(prule(_token) + opt(tok(T::COLON) + tok(T::ID, F::RefSyntax_field)), C::RefSyntax); // "!" 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 (conditional) /////////////////////////////////////////////////////////////////////////////////// // "!(" {SwitchItem:switches ; ","} ";" Syntax:syntax ")" as PushConditionSyntax Clause{ _syntax0 } = create(tok(T::OPEN_PUSH) + loop(rule(_switchItem, F::PushConditionSyntax_switches), tok(T::COMMA)) + tok(T::SEMICOLON) + rule(_syntax, F::PushConditionSyntax_syntax) + tok(T::CLOSE_ROUND), C::PushConditionSyntax); // Condition:condition ":" (Syntax1:syntax | ";") as TestConditionBranch Clause{ _testBranch } = create(rule(_cond, F::TestConditionBranch_condition) + tok(T::COLON) + (rule(_syntax1, F::TestConditionBranch_syntax) | tok(T::SEMICOLON)), C::TestConditionBranch); // "?(" TestBranch:branches {"|" TestBranch:branches} ")" as TestConditionSyntax Clause{ _syntax0 } = create(tok(T::OPEN_TEST) + rule(_testBranch, F::TestConditionSyntax_branches) + loop(tok(T::ALTERNATIVE) + rule(_testBranch, F::TestConditionSyntax_branches)) + tok(T::CLOSE_ROUND), C::TestConditionSyntax); /////////////////////////////////////////////////////////////////////////////////// // Syntax (others) /////////////////////////////////////////////////////////////////////////////////// // "(" !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); /////////////////////////////////////////////////////////////////////////////////// // Clause /////////////////////////////////////////////////////////////////////////////////// // "=" as partial Assignment {type = Strong} Clause{ _assignmentOp } = partial(tok(T::ASSIGN)).with(F::Assignment_type, GlrAssignmentType::Strong); // "?=" as partial Assignment {type = Weak} Clause{ _assignmentOp } = partial(tok(T::WEAK_ASSIGN)).with(F::Assignment_type, GlrAssignmentType::Weak); // ID:field AssignmentOp STRING:value as Assignment Clause{ _assignment } = create(tok(T::ID, F::Assignment_field) + prule(_assignmentOp) + 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); /////////////////////////////////////////////////////////////////////////////////// // Clause (left recursive) /////////////////////////////////////////////////////////////////////////////////// // ID:flag as LeftRecursionPlaceholder Clause{ _placeholder } = create(tok(T::ID, F::LeftRecursionPlaceholder_flag), C::LeftRecursionPlaceholder); // ID:literal as RefSyntax {refType = ID} Clause{ _ruleName } = create(tok(T::ID, F::RefSyntax_literal), C::RefSyntax).with(F::RefSyntax_refType, GlrRefType::Id); // "left_recursion_placeholder" "(" RuleName:flags {"," ruleName:flags} ")" as LeftRecursionPlaceholderClause Clause{ _clause } = create( tok(T::LS_PH) + tok(T::OPEN_ROUND) + rule(_placeholder, F::LeftRecursionPlaceholderClause_flags) + loop(tok(T::COMMA) + rule(_placeholder, F::LeftRecursionPlaceholderClause_flags)) + tok(T::CLOSE_ROUND), C::LeftRecursionPlaceholderClause); // "left_recursion_inject" as partial LeftRecursionInjectContinuation {configuration = Single} Clause{ _lriConfig } = partial(tok(T::LS_I)).with(F::LeftRecursionInjectContinuation_configuration, GlrLeftRecursionConfiguration::Single); // "left_recursion_inject_multiple" as partial LeftRecursionInjectContinuation {configuration = Multiple} Clause{ _lriConfig } = partial(tok(T::LS_IM)).with(F::LeftRecursionInjectContinuation_configuration, GlrLeftRecursionConfiguration::Multiple); // LriConfig "(" Placeholder:flag {"," Placeholder:flag} ")" LriTarget:injectionTargets {"|" LriTarget:injectionTargets} as partial LeftRecursionInjectContinuation Clause{ _lriContinuationBody } = partial( prule(_lriConfig) + tok(T::OPEN_ROUND) + rule(_placeholder, F::LeftRecursionInjectContinuation_flags) + loop(tok(T::COMMA) + rule(_placeholder, F::LeftRecursionInjectContinuation_flags)) + tok(T::CLOSE_ROUND) + rule(_lriTarget, F::LeftRecursionInjectContinuation_injectionTargets) + loop(tok(T::ALTERNATIVE) + rule(_lriTarget, F::LeftRecursionInjectContinuation_injectionTargets)) ); // LriContinuationBody as LeftRecursionInjectionContinuation {type = Required} Clause{ _lriContinuation } = create(prule(_lriContinuationBody), C::LeftRecursionInjectContinuation).with(F::LeftRecursionInjectContinuation_type, GlrLeftRecursionInjectContinuationType::Required); // "[" LriContinuationBody as LeftRecursionInjectionContinuation "]" {type = Optional} Clause{ _lriContinuation } = create(tok(T::OPEN_SQUARE) + prule(_lriContinuationBody) + tok(T::CLOSE_SQUARE), C::LeftRecursionInjectContinuation).with(F::LeftRecursionInjectContinuation_type, GlrLeftRecursionInjectContinuationType::Optional); // RuleName:rule as LeftRecursionInjectClause Clause{ _lriTarget } = create(rule(_ruleName, F::LeftRecursionInjectClause_rule), C::LeftRecursionInjectClause); // "(" RuleName:rule LriContinuation:continuation ")" as LeftRecursionInjectClause Clause{ _lriTarget } = create(tok(T::OPEN_ROUND) + rule(_ruleName, F::LeftRecursionInjectClause_rule) + rule(_lriContinuation, F::LeftRecursionInjectClause_continuation) + tok(T::CLOSE_ROUND), C::LeftRecursionInjectClause); // "!" RuleName:rule LriContinuation:continuation as LeftRecursionInjectClause Clause{ _clause } = create(tok(T::USE) + rule(_ruleName, F::LeftRecursionInjectClause_rule) + rule(_lriContinuation, F::LeftRecursionInjectClause_continuation), C::LeftRecursionInjectClause); // "!" "prefix_merge" "(" RuleName:rule ")" as PrefixMergeClause Clause{ _clause } = create(tok(T::USE) + tok(T::LS_PM) + tok(T::OPEN_ROUND) + rule(_ruleName, F::PrefixMergeClause_rule) + tok(T::CLOSE_ROUND), C::PrefixMergeClause); /////////////////////////////////////////////////////////////////////////////////// // File /////////////////////////////////////////////////////////////////////////////////// // ID:name {"::=" Clause:clauses} ";" as Rule Clause{ _rule } = create(tok(T::ID, F::Rule_name) + opt(tok(T::COLON) + tok(T::ID, F::Rule_type)) + loop(tok(T::INFER) + rule(_clause, F::Rule_clauses)) + tok(T::SEMICOLON), C::Rule); // [Switches] Rule:rules {Rule:rules} as SyntaxFile Clause{ _file } = create(opt(prule(_switches)) + 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"); _classPropType->isPartial = true; _classBody->isPartial = true; 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 = Ptr(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: case EdgeInputType::LrPlaceholder: case EdgeInputType::LrInject: { // a new edge is created, accumulating multiple epsilon edges, ending with such edge auto targetNewState = CreateCompactState(edge->To()); if (!visited.Contains(targetNewState)) { visited.Add(targetNewState); } auto newEdge = Ptr(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; case EdgeInputType::Ending: // Ending is ignored because it doesn't exist in epsilon-NFA break; default: CHECK_FAIL(L"Unhandled!"); } accumulatedEdges.RemoveAt(accumulatedEdges.Count() - 1); } if (walkingOldState->endingState) { // if accumulated epsilon edges lead to the epsilon-NFA ending state // create an Ending edge to the compact-NFA ending state // when a non-epsilon edge connects to the ending state directly // this is triggered by examing the epsilon-NFA ending state directly // at this moment accumulatedEdges is an empty collection auto newEdge = Ptr(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.Obj()); endState->inEdges.Remove(newEdge.Obj()); 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 = Ptr(new StateSymbol(rule, state->ClauseId())); newState->label = state->label; newStates.Add(newState); oldToNew.Add(state, newState.Obj()); newToOld.Add(newState.Obj(), state); return newState.Obj(); } } void BuildEpsilonEliminatedEdges( StateSymbol* newState, StateSymbol* endState, List& visited) { List accumulatedEdges; BuildEpsilonEliminatedEdgesInternal(newToOld[newState], newState, endState, visited, accumulatedEdges); } }; /*********************************************************************** SyntaxSymbolManager::BuildLeftRecEdge ***********************************************************************/ 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 = newEdge->insBeforeInput.Count() - 1; i >= 0; i--) { if (newEdge->insBeforeInput[i].type == AstInsType::BeginObject) { newEdge->insBeforeInput.Insert(i, { AstInsType::LriStore }); newEdge->insBeforeInput.Insert(i + 2, { AstInsType::LriFetch }); } } for (vint i = newEdge->insAfterInput.Count() - 1; i >= 0; i--) { if (newEdge->insAfterInput[i].type == AstInsType::BeginObject) { newEdge->insBeforeInput.Insert(i, { AstInsType::LriStore }); newEdge->insBeforeInput.Insert(i + 2, { AstInsType::LriFetch }); } } } /*********************************************************************** 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 = Ptr(new EdgeSymbol(state, lrecEdge->To())); newEdges.Add(newEdge); BuildLeftRecEdge(newEdge.Obj(), endingEdge, lrecEdge); } } for (auto lrecEdge : lrecEdges) { lrecEdge->From()->outEdges.Remove(lrecEdge); lrecEdge->To()->inEdges.Remove(lrecEdge); newEdges.Remove(lrecEdge); } } /*********************************************************************** SyntaxSymbolManager::EliminateSingleRulePrefix ***********************************************************************/ 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, eliminatedEdges; // identify prefix edge and continuation edge // prefix edges are clauses (x) // continuation edges are all qualified clauses with prefix (x) except prefix edges 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 [ruleSymbol, prefixIndex] : indexed(prefixEdges.Keys())) { auto&& prefixEdgesOfRule = prefixEdges.GetByIndex(prefixIndex); CHECK_ERROR(prefixEdgesOfRule.Count() == 1, L"Multiple prefix edges under the same rule is not supported yet."); // TODO: // prefixEdge means the clause could consume only one rule // multiple prefixEdge could be // the rule has multiple such clauses // there is one clause but it looks like "([a] | [b]) c" // where both [a] and [b] create an epsilon edge to c // and after removing epsilon edges they become both edge consuming c // in this case we need to create a prefix edges to replace all others // it also means unresolvable ambiguity // maybe a better solution is to define it as a kind of invalid syntax } // for all prefixEdge and continuationEdge under the same rule // if their insBeforeInput are different // move prefixEdge's insBeforeInput to insAfterInput with help from LriStore and LriFetch SortedList compatibleInsBeforeInputPrefixRules; for (auto [ruleSymbol, prefixIndex] : indexed(prefixEdges.Keys())) { // see if all prefixEdges are compatible auto&& prefixEdgesOfRule = prefixEdges.GetByIndex(prefixIndex); auto prefixEdge = prefixEdgesOfRule[0]; for (auto otherPrefixEdge : From(prefixEdgesOfRule).Skip(1)) { if (CompareEnumerable(prefixEdge->insBeforeInput, otherPrefixEdge->insBeforeInput) != 0) { goto INCOMPATIBLE; } } // see if all continuationEdges are compatible for (auto continuationEdge : continuationEdges) { if (continuationEdge->input.rule == prefixEdge->input.rule) { if (CompareEnumerable(prefixEdge->insBeforeInput, continuationEdge->insBeforeInput) != 0) { goto INCOMPATIBLE; } } } compatibleInsBeforeInputPrefixRules.Add(ruleSymbol); INCOMPATIBLE:; } // for all prefixEdge that fails the above test // combine insBeforeInput with insAfterInput with the help from LriStore and LriFetch // properly move instructions from prefixEdge to endingEdge for (auto [ruleSymbol, prefixIndex] : indexed(prefixEdges.Keys())) { bool compatible = compatibleInsBeforeInputPrefixRules.Contains(ruleSymbol); for (auto prefixEdge : prefixEdges.GetByIndex(prefixIndex)) { List ins; if (!compatible && prefixEdge->insBeforeInput.Count() > 0) { ins.Add({ AstInsType::LriStore }); CopyFrom(ins, prefixEdge->insBeforeInput, true); ins.Add({ AstInsType::LriFetch }); prefixEdge->insBeforeInput.Clear(); } CopyFrom(ins, prefixEdge->insAfterInput, true); prefixEdge->insAfterInput.Clear(); auto endingEdge = prefixEdge->To()->OutEdges()[0]; CopyFrom(ins, endingEdge->insBeforeInput, true); CopyFrom(endingEdge->insBeforeInput, ins); } } // for all qualified continuationEdge // create a new edge to run continuationEdge's instruction properly after prefixEdge // remove continuationEdge for (auto continuationEdge : continuationEdges) { vint prefixIndex = prefixEdges.Keys().IndexOf(continuationEdge->input.rule); if (prefixIndex == -1) continue; bool compatible = compatibleInsBeforeInputPrefixRules.Contains(continuationEdge->input.rule); bool eliminated = false; for (auto prefixEdge : prefixEdges.GetByIndex(prefixIndex)) { // important and insSwitch happen before shifting into the rule if (continuationEdge->important != prefixEdge->important) continue; eliminated = true; auto state = prefixEdge->To(); auto newEdge = Ptr(new EdgeSymbol(state, continuationEdge->To())); newEdges.Add(newEdge); newEdge->input.type = EdgeInputType::LeftRec; newEdge->important = continuationEdge->important; if (compatible) { CopyFrom(newEdge->insAfterInput, continuationEdge->insAfterInput); } else if (continuationEdge->insBeforeInput.Count() > 0) { // for incompatible continuationEdge // combine insBeforeInput with insAfterInput with the help from LriStore and LriFetch newEdge->insAfterInput.Add({ AstInsType::LriStore }); CopyFrom(newEdge->insAfterInput, continuationEdge->insBeforeInput, true); newEdge->insAfterInput.Add({ AstInsType::LriFetch }); CopyFrom(newEdge->insAfterInput, continuationEdge->insAfterInput, true); } } if (eliminated) { eliminatedEdges.Add(continuationEdge); } } for (auto eliminatedEdge : eliminatedEdges) { vint prefixIndex = prefixEdges.Keys().IndexOf(eliminatedEdge->input.rule); if (prefixIndex == -1) continue; eliminatedEdge->From()->outEdges.Remove(eliminatedEdge); eliminatedEdge->To()->inEdges.Remove(eliminatedEdge); newEdges.Remove(eliminatedEdge); } } /*********************************************************************** 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 = Ptr(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.Obj(), visited); } // optimize EliminateLeftRecursion(rule, compactStartState, compactEndState.Obj(), newStates, newEdges); EliminateSingleRulePrefix(rule, compactStartState, compactEndState.Obj(), 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: case EdgeInputType::LrPlaceholder: // multiple Rule edges followed by one Token or LrPlaceholder edge create a cross-referenced edge if (edge->returnEdges.Count() == 0) { auto newEdge = Ptr(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; case EdgeInputType::Epsilon: case EdgeInputType::Ending: case EdgeInputType::LeftRec: // Epsilon edges do not exist in compact-NFA // Ending and LeftRec edges are not involved break; case EdgeInputType::LrInject: CHECK_FAIL(L"LrInject is impossible from a start state"); break; default: CHECK_FAIL(L"Unhandled!"); } } } /*********************************************************************** SyntaxSymbolManager::FixLeftRecursionInjectEdge ***********************************************************************/ void SyntaxSymbolManager::FixLeftRecursionInjectEdge(StateSymbol* startState, EdgeSymbol* injectEdge) { // search for all qualified placeholder edge starts from inject targets List placeholderEdges; for (auto outEdge : startState->OutEdges()) { if (outEdge->input.type == EdgeInputType::LrPlaceholder) { if (!From(outEdge->input.flags).Intersect(injectEdge->input.flags).IsEmpty()) { placeholderEdges.Add(outEdge); } } } // calculate all return edges and ending states for each placeholder edge // return edges: // injectEdge // return edge begins from inject target // ... // return edge begins from most inner rule that contains placeholder // ending states: // to state of return edge begins from inject target // ... // to state of return edge begins from most inner rule that contains placeholder // to state from placeholder edge Array> endingStatesArray(placeholderEdges.Count()); Array> returnEdgesArray(placeholderEdges.Count()); for(auto [placeholderEdge, index] : indexed(placeholderEdges)) { auto& endingStates = endingStatesArray[index]; auto& returnEdges = returnEdgesArray[index]; // check if placeholderEdge does nothing more than using rules if (placeholderEdge->insAfterInput.Count() > 0) { goto FAILED_INSTRUCTION_CHECKING; } for (vint i = 0; i <= placeholderEdge->returnEdges.Count(); i++) { auto returnEdge = i == 0 ? injectEdge : placeholderEdge->returnEdges[i - 1] ; auto endingState = i == placeholderEdge->returnEdges.Count() ? placeholderEdge->To() : placeholderEdge->returnEdges[i]->To() ; for (auto outEdge : endingState->OutEdges()) { if (outEdge->input.type == EdgeInputType::Ending && outEdge->insAfterInput.Count() > 0) { goto FAILED_INSTRUCTION_CHECKING; } } returnEdges.Add(returnEdge); endingStates.Add(endingState); } continue; FAILED_INSTRUCTION_CHECKING: AddError( ParserErrorType::LeftRecursionPlaceholderMixedWithSwitches, {}, injectEdge->fromState->Rule()->Name(), lrpFlags[injectEdge->input.flags[0]], startState->Rule()->Name() ); return; } // calculate all acceptable input from inject edge // key: // token // the number of return edges carried into this edge, at least 1 // value: // index of placeholder edge // the LeftRec edge before the Token edge (optional) // the Token edge that consume this input using InputKey = Pair; using InputValue = Tuple; Group acceptableInputs; for(auto [placeholderEdge, index] : indexed(placeholderEdges)) { auto& endingStates = endingStatesArray[index]; auto& returnEdges = returnEdgesArray[index]; for (vint i = returnEdges.Count() - 1; i >= 0; i--) { auto endingState = endingStates[i]; auto returnEdge = returnEdges[i]; EdgeSymbol* endingEdge = nullptr; for (auto outEdge : endingState->OutEdges()) { switch (outEdge->input.type) { case EdgeInputType::Ending: endingEdge = outEdge; break; // find if there is any LeftRec from this state case EdgeInputType::LeftRec: { // compact everything on top of this LeftRec and create an Input for (auto tokenEdge : outEdge->To()->OutEdges()) { if (tokenEdge->input.type == EdgeInputType::Token) { acceptableInputs.Add({ tokenEdge->input.token,i + 1 }, { index,outEdge,tokenEdge }); } } } break; // find if there is any Token from this state case EdgeInputType::Token: acceptableInputs.Add({ outEdge->input.token,i + 1 }, { index,nullptr,outEdge }); break; default:; } } if (!endingEdge) { // stop searching if any Token edge are found break; } } } for (auto [input, inputIndex] : indexed(acceptableInputs.Keys())) { auto [inputToken, returnEdgeCount] = input; auto&& placeholderRecords = acceptableInputs.GetByIndex(inputIndex); // group inputs by lrEdge, tokenEdge, carried return edges // if there are multiple inputs from the same key // it means such input creates an ambiguity // // it usually happens in clauses like Prefix lri(flags) Target // where multiple valid flags found in Target at the same time // // if we could indentify some inputs here where excluded return edges are all reuse edges // then we can only create edges for one of them struct Entry { EdgeSymbol* lrEdge; EdgeSymbol* tokenEdge; List* returnEdges; vint returnEdgeCount; vint Compare(const Entry& entry)const { if (lrEdge < entry.lrEdge) return -1; if (lrEdge > entry.lrEdge) return 1; if (tokenEdge < entry.tokenEdge) return -1; if (tokenEdge > entry.tokenEdge) return 1; return CompareEnumerable( From(*returnEdges).Take(returnEdgeCount), From(*entry.returnEdges).Take(returnEdgeCount) ); } bool operator< (const Entry& entry)const { return Compare(entry) < 0; } bool operator> (const Entry& entry)const { return Compare(entry) > 0; } bool operator==(const Entry& entry)const { return Compare(entry) == 0; } }; Group simpleUseRecords; // search for placeholder edges where their excluded return edges are all reuse edges for (vint recordIndex = 0; recordIndex < placeholderRecords.Count(); recordIndex++) { auto [placeholderIndex, lrEdge, tokenEdge] = placeholderRecords[recordIndex]; Entry entry{ lrEdge,tokenEdge,&returnEdgesArray[placeholderIndex],returnEdgeCount }; if(From(*entry.returnEdges) .Skip(returnEdgeCount) .All([](EdgeSymbol* edge) {return edge->input.ruleType == automaton::ReturnRuleType::Reuse; }) ) { simpleUseRecords.Add(entry, recordIndex); } } // for each group, if there are more than one placeholder edges // mark them as deleted except the first one SortedList recordsToRemove; for (vint recordGroup = 0; recordGroup < simpleUseRecords.Count(); recordGroup++) { auto&& records = simpleUseRecords.GetByIndex(recordGroup); if (records.Count() > 1) { CopyFrom(recordsToRemove, From(records).Skip(1)); } } // delete them in Group // this way is not recommended but the group is going to be discarded very soon for (vint i = recordsToRemove.Count() - 1; i >= 0; i--) { const_cast&>(placeholderRecords).RemoveAt(recordsToRemove[i]); } // convert reminaings for (auto [placeholderIndex, lrEdge, tokenEdge] : placeholderRecords) { auto placeholderEdge = placeholderEdges[placeholderIndex]; auto& endingStates = endingStatesArray[placeholderIndex]; auto& returnEdges = returnEdgesArray[placeholderIndex]; // search for all possible "LrPlaceholder {Ending} LeftRec Token" transitions // for each transition, compact edges and put injectEdge properly in returnEdges // here insBeforeInput has been ensured to be: // EndObject // LriStore // DelayFieldAssignment // placeholderEdge->insBeforeInput // LriFetch // loop {endingEdge->insBeforeInput returnEdge->insAfterInput} // --LeftRec--> ... // EndObject is for the ReopenObject in the use rule transition before // DelayFieldAssignment is for the ReopenObject in injectEdge->insAfterInput // injectEdge is the last returnEdge List instructionPrefix; // there is no instruction in injectEdge->insBeforeInput instructionPrefix.Add({ AstInsType::EndObject }); instructionPrefix.Add({ AstInsType::LriStore }); instructionPrefix.Add({ AstInsType::DelayFieldAssignment }); CopyFrom(instructionPrefix, placeholderEdge->insBeforeInput, true); instructionPrefix.Add({ AstInsType::LriFetch }); for (vint i = returnEdges.Count() - 1; i >= returnEdgeCount;i --) { auto endingState = endingStates[i]; auto returnEdge = returnEdges[i]; auto endingEdge = From(endingState->OutEdges()) .Where([](auto edge) { return edge->input.type == EdgeInputType::Ending; }) .First(); CopyFrom(instructionPrefix, endingEdge->insBeforeInput, true); CopyFrom(instructionPrefix, returnEdge->insAfterInput, true); } if (lrEdge) { auto newEdge = Ptr(new EdgeSymbol(injectEdge->From(), tokenEdge->To())); edges.Add(newEdge); newEdge->input = tokenEdge->input; newEdge->importancy = tokenEdge->importancy; CopyFrom(newEdge->returnEdges, From(returnEdges).Take(returnEdgeCount), true); CopyFrom(newEdge->returnEdges, tokenEdge->returnEdges, true); // newEdge consumes a token // lrEdge->insAfterInput happens before consuming this token // so it should be copied to newEdge->insBeforeInput CopyFrom(newEdge->insBeforeInput, instructionPrefix, true); CopyFrom(newEdge->insBeforeInput, lrEdge->insBeforeInput, true); CopyFrom(newEdge->insBeforeInput, lrEdge->insAfterInput, true); CopyFrom(newEdge->insBeforeInput, tokenEdge->insBeforeInput, true); CopyFrom(newEdge->insAfterInput, tokenEdge->insAfterInput, true); } else { auto newEdge = Ptr(new EdgeSymbol(injectEdge->From(), tokenEdge->To())); edges.Add(newEdge); newEdge->input = tokenEdge->input; newEdge->importancy = tokenEdge->importancy; CopyFrom(newEdge->returnEdges, From(returnEdges).Take(returnEdgeCount), true); CopyFrom(newEdge->returnEdges, tokenEdge->returnEdges, true); // newEdge consumes a token // lrEdge->insAfterInput happens before consuming this token // so it should be copied to newEdge->insBeforeInput CopyFrom(newEdge->insBeforeInput, instructionPrefix, true); CopyFrom(newEdge->insBeforeInput, tokenEdge->insBeforeInput, true); CopyFrom(newEdge->insAfterInput, tokenEdge->insAfterInput, true); } } } // report an error if nothing is created if (acceptableInputs.Count() == 0) { AddError( ParserErrorType::LeftRecursionInjectHasNoContinuation, {}, injectEdge->fromState->Rule()->Name(), lrpFlags[injectEdge->input.flags[0]], startState->Rule()->Name() ); } } /*********************************************************************** 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); } } // compact multiple shift (Rule) edges and an input (Token or LrPlaceholder) edge to one edge // when a cross-referenced edge is executed, for each Rule edge: // insBeforeInput instructions are executed // insAfterInput instructions are executed in its returnEdges 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); } } } } // convert LrInject to Token for (auto state : states) { vint index = orderedEdges.Keys().IndexOf(state); if (index != -1) { for (auto edge : orderedEdges.GetByIndex(index)) { if (edge->input.type == EdgeInputType::LrInject) { auto startState = edge->input.rule->startStates[0]; FixLeftRecursionInjectEdge(startState, edge); } } } } } } } }