mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-05-12 18:40:11 +08:00
17396 lines
631 KiB
C++
17396 lines
631 KiB
C++
/***********************************************************************
|
|
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<CppParserGenOutput> 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<AstClassSymbol*>& visitors, List<AstClassSymbol*>& concreteClasses)
|
|
{
|
|
for (auto name : file->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(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<WString> 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<WString> 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<CppAstGenOutput> output,
|
|
const WString& extraNss,
|
|
stream::StreamWriter& writer,
|
|
Func<void(const WString&)> 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<WString> 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<void(const WString&)> callback
|
|
)
|
|
{
|
|
WriteFileComment(file->Name(), writer);
|
|
writer.WriteLine(L"#include \"" + utilityHeaderFile + L"\"");
|
|
writer.WriteLine(L"");
|
|
{
|
|
List<WString> cppNss;
|
|
CopyFrom(cppNss, file->cppNss);
|
|
cppNss.Add(extraNss);
|
|
WString prefix = WriteNssBegin(cppNss, writer);
|
|
callback(prefix);
|
|
WriteNssEnd(cppNss, writer);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteParserUtilityHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteParserUtilityHeaderFile(
|
|
AstSymbolManager& manager,
|
|
Ptr<CppParserGenOutput> output,
|
|
const WString& guardPostfix,
|
|
stream::StreamWriter& writer,
|
|
Func<void(const WString&)> 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<void(const WString&)> 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<CppAstGenOutput> output, collections::Dictionary<WString, WString>& 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<CppParserGenOutput> output, collections::Dictionary<WString, WString>& 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<CppParserGenOutput> 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<AstClassSymbol*>(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<AstClassSymbol*>(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<vl::glr::ParsingAstBase> CreateAstNode(vl::vint32_t type) override;");
|
|
writer.WriteLine(prefix + L"\tvoid SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr<vl::glr::ParsingAstBase> 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<vl::glr::ParsingAstBase> ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& candidates) override;");
|
|
writer.WriteLine(prefix + L"};");
|
|
}
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteAstAssemblerCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteAstAssemblerCppFile(AstSymbolManager& manager, Ptr<CppParserGenOutput> 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<vl::glr::ParsingAstBase> " + 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<AstClassSymbol*>(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<vl::glr::ParsingAstBase> value)");
|
|
writer.WriteLine(prefix + L"{");
|
|
writer.WriteLine(prefix + L"\tauto cppFieldName = " + manager.Global().name + L"CppFieldName((" + manager.Global().name + L"Fields)field);");
|
|
|
|
List<AstClassPropSymbol*> props;
|
|
for (auto typeSymbol : manager.Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
for (auto [propSymbol, index] : indexed(classSymbol->Props().Values()))
|
|
{
|
|
if (propSymbol->propType != AstPropType::Token)
|
|
{
|
|
if (dynamic_cast<AstClassSymbol*>(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<AstClassPropSymbol*> props;
|
|
for (auto typeSymbol : manager.Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(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<AstClassPropSymbol*> props;
|
|
for (auto typeSymbol : manager.Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
for (auto [propSymbol, index] : indexed(classSymbol->Props().Values()))
|
|
{
|
|
if (propSymbol->propType == AstPropType::Type)
|
|
{
|
|
if (dynamic_cast<AstEnumSymbol*>(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<AstClassSymbol*> 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<AstClassSymbol*> 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<AstClassPropSymbol*> 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<AstClassPropSymbol*> 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<vl::glr::ParsingAstBase> " + manager.Global().name + L"AstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& candidates)");
|
|
writer.WriteLine(prefix + L"{");
|
|
writer.WriteLine(prefix + L"\tauto cppTypeName = " + manager.Global().name + L"CppTypeName((" + manager.Global().name + L"Classes)type);");
|
|
|
|
Dictionary<AstClassSymbol*, AstClassSymbol*> resolvables;
|
|
for (auto typeSymbol : manager.Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(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<AstClassSymbol*>(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<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(file, output, L"builder", writer, [&](const WString& prefix)
|
|
{
|
|
for(auto typeSymbol : file->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(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<AstEnumSymbol*>(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<CppAstGenOutput> 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<AstClassSymbol*>(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<AstEnumSymbol*>(propSymbol->propSymbol))
|
|
{
|
|
writer.WriteString(prefix + className + L"& " + className + L"::" + propSymbol->Name() + L"(");
|
|
PrintCppType(file, propSymbol->propSymbol, writer);
|
|
writer.WriteLine(L" value)");
|
|
}
|
|
if (dynamic_cast<AstClassSymbol*>(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<AstClassSymbol*>(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<WString>& 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<vl::Ptr<");
|
|
}
|
|
else if (purpose == PrintTypePurpose::Value && dynamic_cast<AstClassSymbol*>(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<AstClassSymbol*>(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<AstEnumSymbol*>(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<AstClassSymbol*>(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<IVisitor>");
|
|
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<AstEnumSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*>(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"/// <summary>Load all reflectable AST types, only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is off.</summary>");
|
|
writer.WriteString(prefix);
|
|
writer.WriteLine(L"/// <returns>Returns true if this operation succeeded.</returns>");
|
|
|
|
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<AstClassSymbol*>(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<AstEnumSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*>& visitors, List<AstClassSymbol*>& 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<AstClassSymbol*>(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<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(file, output, L"copy_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses);
|
|
|
|
writer.WriteLine(prefix + L"/// <summary>A copy visitor, overriding all abstract methods with AST copying code.</summary>");
|
|
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<AstClassSymbol*>(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<AstClassSymbol*>(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<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(file, output->copyH, L"copy_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses);
|
|
|
|
for (auto typeSymbol : file->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(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<AstClassSymbol*>(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<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(file, output, L"empty_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
for (auto name : file->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(file->Symbols()[name]))
|
|
{
|
|
if (classSymbol->derivedClasses.Count() > 0)
|
|
{
|
|
writer.WriteLine(prefix + L"/// <summary>An empty visitor, overriding all abstract methods with empty implementations.</summary>");
|
|
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<CppAstGenOutput> 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<AstClassSymbol*>(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<AstClassSymbol*>& visitors, List<AstClassSymbol*>& 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<AstEnumSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*> 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<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(file, output, L"json_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses);
|
|
|
|
writer.WriteLine(prefix + L"/// <summary>A JSON visitor, overriding all abstract methods with AST to JSON serialization code.</summary>");
|
|
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<AstClassSymbol*>(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<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(file, output->jsonH, L"json_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses);
|
|
|
|
for (auto typeSymbol : file->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(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<AstClassSymbol*>& visitors, List<AstClassSymbol*>& concreteClasses);
|
|
|
|
/***********************************************************************
|
|
WriteVisitFieldFunctionBody
|
|
***********************************************************************/
|
|
|
|
void WriteVisitFieldFunctionBody(AstDefFile* file, AstClassSymbol* fieldSymbol, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
writer.WriteLine(prefix + L"\tif (!node) return;");
|
|
List<AstClassSymbol*> order;
|
|
{
|
|
auto current = fieldSymbol;
|
|
while (current)
|
|
{
|
|
order.Add(current);
|
|
current = current->baseClass;
|
|
}
|
|
}
|
|
|
|
writer.WriteLine(prefix + L"\tTraverse(static_cast<vl::glr::ParsingAstBase*>(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<AstClassSymbol*>(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<vl::glr::ParsingAstBase*>(node));");
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteTraverseVisitorHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteTraverseVisitorHeaderFile(AstDefFile* file, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(file, output, L"traverse_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(file, visitors, concreteClasses);
|
|
|
|
writer.WriteLine(prefix + L"/// <summary>A traverse visitor, overriding all abstract methods with AST visiting code.</summary>");
|
|
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<AstClassSymbol*>(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<AstClassSymbol*>(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<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(file, output->traverseH, L"traverse_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> 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<AstClassSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*>(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<AstClassSymbol*>(symbols.Values()[index]);
|
|
if (!newBaseClass)
|
|
{
|
|
ownerFile->AddError(
|
|
ParserErrorType::BaseClassNotClass,
|
|
codeRange,
|
|
ownerFile->Name(),
|
|
name,
|
|
typeName
|
|
);
|
|
return false;
|
|
}
|
|
|
|
List<AstClassSymbol*> 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<typename T>
|
|
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<WString> 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<AstEnumSymbol>(symbolName, codeRange);
|
|
}
|
|
|
|
AstClassSymbol* AstDefFile::CreateClass(const WString& symbolName, ParsingTextRange codeRange)
|
|
{
|
|
return CreateSymbol<AstClassSymbol>(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<CppParserGenOutput> 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<CppParserGenOutput> 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<WString> 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<CppParserGenOutput> output, collections::Dictionary<WString, WString>& 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<char32_t> buffer(_regex.Length() + 1);
|
|
memset(&buffer[0], 0, sizeof(char32_t) * buffer.Count());
|
|
vint writing = 0;
|
|
|
|
List<regex_internal::Expression*> expanding;
|
|
expanding.Add(expr->expression.Obj());
|
|
while (expanding.Count() > 0)
|
|
{
|
|
auto current = expanding[expanding.Count() - 1];
|
|
if (auto charset = dynamic_cast<regex_internal::CharSetExpression*>(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<regex_internal::SequenceExpression*>(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<AstEnumSymbol*>(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<AstClassSymbol*>(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<GlrAstFile> 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<wchar_t> 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>discard/s)?/s*(<name>/$?[a-zA-Z_]/w*)/s*:(<regex>/.+))$");
|
|
Regex regexFragment(L"/{(<fragment>/$[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<WString, WString> 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<Ptr<RegexMatch>> 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<GlrSyntaxFile> syntaxFile);
|
|
extern void ValidateSwitchesAndConditions(VisitorContext& context, VisitorSwitchContext& sContext, Ptr<GlrSyntaxFile> syntaxFile);
|
|
extern void ValidatePartialRules(VisitorContext& context, Ptr<GlrSyntaxFile> syntaxFile);
|
|
extern void CalculateRuleAndClauseTypes(VisitorContext& context);
|
|
|
|
extern void CalculateFirstSet(VisitorContext& context, Ptr<GlrSyntaxFile> syntaxFile);
|
|
extern void ValidateTypes(VisitorContext& context, Ptr<GlrSyntaxFile> syntaxFile);
|
|
extern void ValidateStructure(VisitorContext& context, Ptr<GlrSyntaxFile> syntaxFile);
|
|
extern void ValidatePrefixMerge(VisitorContext& context, Ptr<GlrSyntaxFile> syntaxFile);
|
|
|
|
extern Ptr<GlrSyntaxFile> RewriteSyntax_Switch(VisitorContext& context, VisitorSwitchContext& sContext, SyntaxSymbolManager& syntaxManager, Ptr<GlrSyntaxFile> syntaxFile);
|
|
extern Ptr<GlrSyntaxFile> RewriteSyntax_PrefixMerge(VisitorContext& context, SyntaxSymbolManager& syntaxManager, Ptr<GlrSyntaxFile> syntaxFile);
|
|
extern void CompileSyntax(VisitorContext& context, Ptr<CppParserGenOutput> output, Ptr<GlrSyntaxFile> syntaxFile);
|
|
|
|
/***********************************************************************
|
|
CompileSyntax
|
|
***********************************************************************/
|
|
|
|
bool NeedRewritten_Switch(Ptr<GlrSyntaxFile> syntaxFile)
|
|
{
|
|
return syntaxFile->switches.Count() > 0;
|
|
}
|
|
|
|
bool NeedRewritten_PrefixMerge(Ptr<GlrSyntaxFile> syntaxFile)
|
|
{
|
|
return !From(syntaxFile->rules)
|
|
.SelectMany([](auto rule) { return From(rule->clauses); })
|
|
.FindType<GlrPrefixMergeClause>()
|
|
.IsEmpty();
|
|
}
|
|
|
|
void CreateSyntaxSymbols(LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, Ptr<GlrSyntaxFile> 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<GlrLeftRecursionPlaceholderClause>())
|
|
{
|
|
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<GlrSyntaxFile> 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<GlrSyntaxFile> 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<GlrSyntaxFile> CompileSyntax(AstSymbolManager& astManager, LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, Ptr<CppParserGenOutput> output, collections::List<Ptr<GlrSyntaxFile>>& 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<GlrClause> 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<GlrPushConditionSyntax*>(nodeSyntax);
|
|
if (pushSyntax) nodeSyntax = pushSyntax->syntax.Obj();
|
|
|
|
if (auto useSyntax = dynamic_cast<GlrUseSyntax*>(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<GlrSyntaxFile> 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<typename TClause>
|
|
void CalculateFirstSet_MoveFromDirectClauses(
|
|
SortedList<TClause*>& clauses,
|
|
Group<RuleSymbol*, TClause*>& indirectClauses,
|
|
Group<RuleSymbol*, TClause*>& 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<GlrLeftRecursionInjectClause*> lriClauses;
|
|
SortedList<GlrLeftRecursionPlaceholderClause*> lrpClauses;
|
|
SortedList<GlrPrefixMergeClause*> 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<GlrSyntaxFile> 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<GlrSyntaxFile> syntaxFile)
|
|
{
|
|
for (auto rule : syntaxFile->rules)
|
|
{
|
|
List<Ptr<GlrPartialClause>> partialClauses;
|
|
CopyFrom(partialClauses, From(rule->clauses).FindType<GlrPartialClause>());
|
|
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<RuleSymbol*>& 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<List<RuleSymbol*>> 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<RuleSymbol*> 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<RuleSymbol*> 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<GlrReuseClause>())
|
|
{
|
|
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<CppParserGenOutput> output;
|
|
AstClassSymbol* clauseType;
|
|
StatePair result;
|
|
|
|
StatePair Build(GlrSyntax* node)
|
|
{
|
|
node->Accept(this);
|
|
return result;
|
|
}
|
|
|
|
StatePair Build(const Ptr<GlrSyntax>& node)
|
|
{
|
|
node->Accept(this);
|
|
return result;
|
|
}
|
|
public:
|
|
CompileSyntaxVisitor(
|
|
VisitorContext& _context,
|
|
Ptr<CppParserGenOutput> _output,
|
|
RuleSymbol* _ruleSymbol
|
|
)
|
|
: automatonBuilder(_ruleSymbol)
|
|
, context(_context)
|
|
, output(_output)
|
|
{
|
|
}
|
|
|
|
void AssignClause(const Ptr<GlrClause>& 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<typename T>
|
|
void CollectElements(GlrSyntax* node, List<Func<StatePair()>>& elements)
|
|
{
|
|
if (auto pair = dynamic_cast<T*>(node))
|
|
{
|
|
CollectElements<T>(pair->first.Obj(), elements);
|
|
CollectElements<T>(pair->second.Obj(), elements);
|
|
}
|
|
else
|
|
{
|
|
elements.Add([this, node]() { return Build(node); });
|
|
}
|
|
}
|
|
|
|
void Visit(GlrSequenceSyntax* node) override
|
|
{
|
|
List<Func<StatePair()>> elements;
|
|
CollectElements<GlrSequenceSyntax>(node, elements);
|
|
result = automatonBuilder.BuildSequenceSyntax(elements);
|
|
}
|
|
|
|
void Visit(GlrAlternativeSyntax* node) override
|
|
{
|
|
List<Func<StatePair()>> elements;
|
|
CollectElements<GlrAlternativeSyntax>(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<Ptr<GlrAssignment>>& assignments)
|
|
{
|
|
for (auto node : assignments)
|
|
{
|
|
auto propSymbol = FindPropSymbol(clauseType, node->field.value);
|
|
auto enumSymbol = dynamic_cast<AstEnumSymbol*>(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<vint32_t>& flags, List<Ptr<GlrLeftRecursionPlaceholder>>& placeholders)
|
|
{
|
|
CopyFrom(
|
|
flags,
|
|
From(placeholders)
|
|
.Select([this](Ptr<GlrLeftRecursionPlaceholder> flag)
|
|
{
|
|
return (vint32_t)context.syntaxManager.lrpFlags.IndexOf(flag->flag.value);
|
|
})
|
|
.Distinct()
|
|
);
|
|
}
|
|
|
|
void Visit(GlrLeftRecursionPlaceholderClause* node) override
|
|
{
|
|
SortedList<vint32_t> flags;
|
|
CollectFlagsInOrder(flags, node->flags);
|
|
|
|
result = automatonBuilder.BuildClause([this, &flags]()
|
|
{
|
|
return automatonBuilder.BuildLrpClause(
|
|
flags,
|
|
{ this,&CompileSyntaxVisitor::FlagIndexToName }
|
|
);
|
|
});
|
|
}
|
|
|
|
using StateBuilder = Func<AutomatonBuilder::StatePair()>;
|
|
|
|
StateBuilder CompileLriTarget(SortedList<vint32_t>& 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<vint32_t> flags;
|
|
CollectFlagsInOrder(flags, cont->flags);
|
|
|
|
List<StateBuilder> 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<vint32_t> 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<CppParserGenOutput> output, Ptr<GlrSyntaxFile> 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<WString>& accessedSwitches;
|
|
RuleSymbol* ruleSymbol;
|
|
GlrReuseClause* reuseClause = nullptr;
|
|
|
|
public:
|
|
ResolveNameVisitor(
|
|
VisitorContext& _context,
|
|
VisitorSwitchContext& _sContext,
|
|
SortedList<WString>& _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<AstClassSymbol*>(context.astManager.Symbols().Values()[index]);
|
|
if (!classSymbol)
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::TypeNotClassInRule,
|
|
typeName.codeRange,
|
|
ruleSymbol->Name(),
|
|
typeName.value
|
|
);
|
|
}
|
|
return classSymbol;
|
|
}
|
|
|
|
void ResolveClause(Ptr<GlrClause> 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<regex::RegexToken> 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<Ptr<GlrSwitchItem>>& 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<GlrSyntaxFile> 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<WString> 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<GlrLeftRecursionPlaceholderClause>())
|
|
{
|
|
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<GlrClause*> unaffectedClauses; // clauses that are not affected by prefix extraction
|
|
SortedList<GlrClause*> prefixClauses; // simple use clauses that are prefix themselves
|
|
Group<GlrClause*, GlrClause*> 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<RuleSymbol*> pmRules; // all rules that need to be rewritten
|
|
Dictionary<RuleSymbol*, GlrRule*> originRules; // rewritten RuleSymbol -> GlrRule ends with _LRI_Original, which is the same GlrRule object before rewritten
|
|
Dictionary<RuleSymbol*, GlrRule*> lriRules; // rewritten RuleSymbol -> GlrRule containing left_recursion_inject clauses
|
|
Dictionary<RuleSymbol*, GlrRule*> fixedAstRules; // RuleSymbol -> GlrRule relationship after rewritten
|
|
|
|
Group<RuleSymbol*, PrefixRuleWithClause> extractPrefixClauses; // RuleSymbol -> {rule to be extracted, clause begins with rule}
|
|
Dictionary<Pair<RuleSymbol*, RuleSymbol*>, GlrRule*> extractedPrefixRules; // {rewritten RuleSymbol, prefix RuleSymbol} -> GlrRule ends with _LRI_Prefix
|
|
Dictionary<RuleSymbol*, Ptr<RewritingPrefixConflict>> extractedConflicts; // rewritten RuleSymbol -> all needed information if prefix extraction affects how it generates left_recursion_inject clauses
|
|
};
|
|
|
|
Ptr<RewritingPrefixConflict> 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<RewritingPrefixConflict> 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<List<RuleClausePath>&>(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<GlrSyntaxFile> 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<GlrSyntaxFile> 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<RewritingPrefixConflict> 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<GlrPrefixMergeClause*>(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<GlrSyntaxFile> 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<GlrPrefixMergeClause>;
|
|
|
|
struct PMInjectRecord
|
|
{
|
|
RuleSymbol* pmRule = nullptr;
|
|
RuleSymbol* injectIntoRule = nullptr;
|
|
};
|
|
|
|
void RewriteRules_AddPmClause(
|
|
const VisitorContext& vContext,
|
|
RuleSymbol* ruleSymbol,
|
|
GlrPrefixMergeClause* pmClause,
|
|
Group<WString, PMClauseRecord>& 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<RewritingPrefixConflict> RewriteRules_CollectUnaffectedIndirectPmClauses(
|
|
const VisitorContext& vContext,
|
|
const RewritingContext& rContext,
|
|
RuleSymbol* initiatedRuleSymbol,
|
|
RuleSymbol* ruleSymbol,
|
|
SortedList<RuleSymbol*>& visited,
|
|
Group<WString, PMClauseRecord>& 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<PMClauseRecord>& pmClauses,
|
|
Dictionary<WString, PMInjectRecord>& 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<Pair<RuleSymbol*, RuleSymbol*>, vint>& pathCounter
|
|
)
|
|
{
|
|
Pair<RuleSymbol*, RuleSymbol*> 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<GlrLeftRecursionInjectClause> 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<GlrLeftRecursionInjectContinuation> CreateLriContinuation(
|
|
const VisitorContext& vContext,
|
|
const RewritingContext& rContext,
|
|
RuleSymbol* ruleSymbol,
|
|
const PMInjectRecord& pmInjectRecord,
|
|
const WString& flag,
|
|
Dictionary<Pair<RuleSymbol*, RuleSymbol*>, 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<Pair<RuleSymbol*, RuleSymbol*>, vint>& pathCounter,
|
|
Group<WString, PMClauseRecord>& pmClauses,
|
|
SortedList<WString>& 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<WString, PMInjectRecord> 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<WString>& lripFlags,
|
|
GlrRule* lriRule,
|
|
Dictionary<Pair<RuleSymbol*, RuleSymbol*>, vint>& pathCounter,
|
|
SortedList<WString>& knownOptionalStartRules
|
|
)
|
|
{
|
|
Group<WString, PMClauseRecord> pmClauses;
|
|
{
|
|
SortedList<RuleSymbol*> 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<WString, PMInjectRecord> 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<RewritingPrefixConflict> conflict,
|
|
Dictionary<Pair<RuleSymbol*, RuleSymbol*>, vint>& pathCounter,
|
|
SortedList<WString>& 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<WString> 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<GlrLeftRecursionInjectClause> c1, Ptr<GlrLeftRecursionInjectClause> c2);
|
|
|
|
bool CompareLriTargest(List<Ptr<GlrLeftRecursionInjectClause>>& targets1, List<Ptr<GlrLeftRecursionInjectClause>>& 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<GlrLeftRecursionInjectClause> c1, Ptr<GlrLeftRecursionInjectClause> 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<Ptr<GlrLeftRecursionInjectClause>>& lriClauses)
|
|
{
|
|
for (auto lriClause : lriClauses)
|
|
{
|
|
if (lriClause->continuation)
|
|
{
|
|
OptimizeLri(lriClause->continuation->injectionTargets);
|
|
}
|
|
}
|
|
|
|
List<Ptr<GlrLeftRecursionInjectClause>> 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<Ptr<GlrLeftRecursionPlaceholder>> 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<Pair<RuleSymbol*, RuleSymbol*>, vint> pathCounter;
|
|
for (auto [ruleSymbol, originRule] : rContext.originRules)
|
|
{
|
|
auto lriRule = rContext.lriRules[ruleSymbol];
|
|
Ptr<RewritingPrefixConflict> conflict;
|
|
Group<WString, PMClauseRecord> pmClauses;
|
|
{
|
|
SortedList<RuleSymbol*> visited;
|
|
conflict = RewriteRules_CollectUnaffectedIndirectPmClauses(
|
|
vContext,
|
|
rContext,
|
|
ruleSymbol,
|
|
ruleSymbol,
|
|
visited,
|
|
pmClauses
|
|
);
|
|
}
|
|
|
|
SortedList<WString> knownOptionalStartRules;
|
|
RewriteRules_GenerateUnaffectedLRIClauses(
|
|
vContext,
|
|
rContext,
|
|
ruleSymbol,
|
|
lriRule,
|
|
pathCounter,
|
|
pmClauses,
|
|
knownOptionalStartRules
|
|
);
|
|
|
|
if (conflict)
|
|
{
|
|
RewriteRules_GenerateAffectedLRIClauses(
|
|
vContext,
|
|
rContext,
|
|
ruleSymbol,
|
|
lriRule,
|
|
conflict,
|
|
pathCounter,
|
|
knownOptionalStartRules
|
|
);
|
|
}
|
|
|
|
List<Ptr<GlrClause>> otherClauses;
|
|
List<Ptr<GlrLeftRecursionInjectClause>> lriClauses;
|
|
for (auto clause : lriRule->clauses)
|
|
{
|
|
if (auto lriClause = clause.Cast<GlrLeftRecursionInjectClause>())
|
|
{
|
|
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<GlrClause> {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<GlrPrefixMergeClause>())
|
|
{
|
|
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<GlrClause> 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<GlrReuseClause>())
|
|
{
|
|
if (auto pushSyntax = reuseClause->syntax.Cast<GlrPushConditionSyntax>())
|
|
{
|
|
reuseClause->syntax = pushSyntax->syntax;
|
|
}
|
|
}
|
|
visitor.FixClause(clause);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
RewriteSyntax
|
|
***********************************************************************/
|
|
|
|
Ptr<GlrSyntaxFile> RewriteSyntax_PrefixMerge(VisitorContext& context, SyntaxSymbolManager& syntaxManager, Ptr<GlrSyntaxFile> 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<Dictionary<WString, bool>> switchValues;
|
|
};
|
|
|
|
struct RewritingContext
|
|
{
|
|
Group<RuleSymbol*, Ptr<GeneratedRule>> generatedRules;
|
|
Group<RuleSymbol*, Ptr<GlrRule>> expandedCombinedRules;
|
|
Group<RuleSymbol*, Ptr<GlrRule>> expandedFirstLevelRules;
|
|
|
|
Dictionary<WString, Ptr<GlrRule>> combinedRulesByName;
|
|
Group<WString, GlrClause*> validCombinedClauses;
|
|
Group<WString, GlrClause*> 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<Dictionary<WString, bool>> ApplySwitches(Ptr<Dictionary<WString, bool>> currentValues, GlrPushConditionSyntax* node)
|
|
{
|
|
auto newValues = Ptr(new Dictionary<WString, bool>);
|
|
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<WString, bool>& 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<WString, bool>& _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<Dictionary<WString, bool>> workingSwitchValues = nullptr;
|
|
Ptr<GeneratedRule> generatedRule;
|
|
};
|
|
|
|
VisitorContext& vContext;
|
|
VisitorSwitchContext& sContext;
|
|
RewritingContext& rContext;
|
|
SortedList<RuleSymbol*> 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<WString>& affectedSwitches,
|
|
Ptr<Dictionary<WString, bool>> currentSwitchValues
|
|
)
|
|
{
|
|
// an affected rule respond to switch values
|
|
// collect switch values that the rule cares
|
|
auto workingSwitchValues = Ptr(new Dictionary<WString, bool>);
|
|
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<Dictionary<WString, bool>> 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<WString> 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<GlrSyntax> syntax, List<Ptr<GlrSyntax>>& items)
|
|
{
|
|
try
|
|
{
|
|
items.Add(CopyNode(syntax.Obj()));
|
|
}
|
|
catch (CancelBranch)
|
|
{
|
|
}
|
|
}
|
|
|
|
void BuildAlt(bool optional, List<Ptr<GlrSyntax>>& 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<GlrSyntax>();
|
|
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<GlrRefSyntax>()->literal);
|
|
}
|
|
}
|
|
|
|
void Visit(GlrUseSyntax* node) override
|
|
{
|
|
// only need to fix rule name for GlrUseSyntax
|
|
copy_visitor::RuleAstVisitor::Visit(node);
|
|
FixRuleName(result.Cast<GlrUseSyntax>()->name);
|
|
}
|
|
|
|
void Visit(GlrAlternativeSyntax* node) override
|
|
{
|
|
// alternative syntax converts to alternative syntax
|
|
List<Ptr<GlrSyntax>> 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<Ptr<GlrSyntax>> 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<Dictionary<WString, bool>> _workingSwitchValues
|
|
)
|
|
: vContext(_vContext)
|
|
, sContext(_sContext)
|
|
, workingSwitchValues(_workingSwitchValues)
|
|
{
|
|
}
|
|
|
|
Ptr<GlrClause> 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<GlrSyntax> CopyNodeSafe(Ptr<GlrSyntax> node)
|
|
{
|
|
if (node.Cast<EmptySyntax>())
|
|
{
|
|
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<EmptySyntax>())
|
|
{
|
|
// if the loop body is empty, it is empty
|
|
result = node->syntax;
|
|
}
|
|
else if (node->delimiter.Cast<EmptySyntax>())
|
|
{
|
|
node->delimiter = nullptr;
|
|
}
|
|
}
|
|
|
|
void Visit(GlrOptionalSyntax* node) override
|
|
{
|
|
node->syntax = CopyNodeSafe(node->syntax);
|
|
result = Ptr(node);
|
|
|
|
if (node->syntax.Cast<EmptySyntax>())
|
|
{
|
|
// 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<EmptySyntax>();
|
|
bool second = !node->second.Cast<EmptySyntax>();
|
|
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<EmptySyntax>();
|
|
bool second = !node->second.Cast<EmptySyntax>();
|
|
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<GlrSyntax>& syntax)
|
|
{
|
|
auto deducted = DeductEmptySyntaxVisitor().CopyNode(syntax.Obj());
|
|
if (deducted.Cast<EmptySyntax>())
|
|
{
|
|
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<GlrRule> rule, const wchar_t* tag, Dictionary<WString, bool>& switchValues)
|
|
{
|
|
auto ruleName = rule->name.value + tag;
|
|
for (auto [name, value] : switchValues)
|
|
{
|
|
ruleName += (value ? L"_1" : L"_0") + name;
|
|
}
|
|
|
|
return ruleName;
|
|
}
|
|
|
|
Ptr<GlrRule> CreateRule(RuleSymbol* ruleSymbol, Ptr<GlrRule> 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<GlrRule> CreateRule(RuleSymbol* ruleSymbol, Ptr<GlrRule> rule, const wchar_t* tag, Dictionary<WString, bool>& switchValues)
|
|
{
|
|
return CreateRule(ruleSymbol, rule, CreateRuleName(rule, tag, switchValues));
|
|
}
|
|
|
|
void AddRules(RuleSymbol* ruleSymbol, Ptr<GlrSyntaxFile> rewritten, Group<RuleSymbol*, Ptr<GlrRule>>& 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<RuleSymbol*, Ptr<GlrRule>>& 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<GlrSyntaxFile> RewriteSyntax_Switch(VisitorContext& context, VisitorSwitchContext& sContext, SyntaxSymbolManager& syntaxManager, Ptr<GlrSyntaxFile> 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<WString> 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<WString, bool>);
|
|
}
|
|
else
|
|
{
|
|
auto&& switches = sContext.clauseAffectedSwitches.GetByIndex(clauseIndex);
|
|
if (switches.Count() != generatedRule->switchValues->Count())
|
|
{
|
|
switchValues = Ptr(new Dictionary<WString, bool>);
|
|
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<GlrRule> 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<GlrClause> 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<const ParsingToken*, RuleSymbol*>;
|
|
|
|
VisitorContext& context;
|
|
RuleSymbol* ruleSymbol;
|
|
|
|
Ptr<List<NonSimpleUseDeduction>> result;
|
|
bool couldBeEmpty = false;
|
|
|
|
public:
|
|
ValidateDeducingPrefixMergeRuleVisitor(
|
|
VisitorContext& _context,
|
|
RuleSymbol* _ruleSymbol
|
|
)
|
|
: context(_context)
|
|
, ruleSymbol(_ruleSymbol)
|
|
{
|
|
}
|
|
|
|
void ValidateClause(Ptr<GlrClause> 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<NonSimpleUseDeduction>);
|
|
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<GlrUseSyntax*>(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<GlrSyntaxFile> 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<RuleSymbol*> visiting;
|
|
SortedList<RuleSymbol*> 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<GlrClause> 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<GlrClause> 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<WString, vint> 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<GlrSyntaxFile> 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<WString> pushedSwitches;
|
|
|
|
public:
|
|
CollectRuleAffectedSwitchesVisitorBase(
|
|
VisitorContext& _context,
|
|
VisitorSwitchContext& _sContext
|
|
)
|
|
: context(_context)
|
|
, sContext(_sContext)
|
|
{
|
|
}
|
|
|
|
void ValidateRule(Ptr<GlrRule> 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<WString> 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<GlrRule> 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<GlrSyntaxFile> 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<GlrClause> 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<AstClassSymbol*>(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<GlrReuseClause*>(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<AstEnumSymbol*>(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<GlrClause> 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<GlrLeftRecursionPlaceholderClause*> 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<GlrLeftRecursionInjectClause*, WString> lriEndings;
|
|
|
|
public:
|
|
LriPrefixTestingVisitor(
|
|
VisitorContext& _context,
|
|
RuleSymbol* _ruleSymbol
|
|
)
|
|
: context(_context)
|
|
, ruleSymbol(_ruleSymbol)
|
|
{
|
|
}
|
|
|
|
void ValidateClause(Ptr<GlrClause> clause)
|
|
{
|
|
clause->Accept(this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GlrClause::IVisitor
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void SearchLriEndings(List<GlrLeftRecursionInjectClause*>& 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<GlrLeftRecursionInjectClause*> visiting;
|
|
SearchLriEndings(visiting, node);
|
|
}
|
|
VerifyPrefix(node);
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
ValidateTypes
|
|
***********************************************************************/
|
|
|
|
void ValidateTypes(VisitorContext& context, Ptr<GlrSyntaxFile> 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<CppParserGenOutput> 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<WString>& 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<WString>& 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<vl::glr::parsergen::GlrRefCondition>(), 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<vl::glr::parsergen::GlrNotCondition>(), 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<vl::glr::parsergen::GlrAndCondition>(), 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<vl::glr::parsergen::GlrOrCondition>(), 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<vl::glr::parsergen::GlrSwitchItem>(), 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<vl::glr::parsergen::GlrRefSyntax>(), 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<vl::glr::parsergen::GlrUseSyntax>(), 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<vl::glr::parsergen::GlrLoopSyntax>(), 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<vl::glr::parsergen::GlrOptionalSyntax>(), 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<vl::glr::parsergen::GlrSequenceSyntax>(), 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<vl::glr::parsergen::GlrAlternativeSyntax>(), 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<vl::glr::parsergen::GlrPushConditionSyntax>(), 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<vl::glr::parsergen::GlrTestConditionBranch>(), 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<vl::glr::parsergen::GlrTestConditionSyntax>(), 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<vl::glr::parsergen::GlrAssignment>(), 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<vl::glr::parsergen::GlrCreateClause>(), 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<vl::glr::parsergen::GlrPartialClause>(), 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<vl::glr::parsergen::GlrReuseClause>(), 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<vl::glr::parsergen::GlrLeftRecursionPlaceholder>(), 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<vl::glr::parsergen::GlrLeftRecursionPlaceholderClause>(), 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<vl::glr::parsergen::GlrLeftRecursionInjectContinuation>(), 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<vl::glr::parsergen::GlrLeftRecursionInjectClause>(), 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<vl::glr::parsergen::GlrPrefixMergeClause>(), 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<vl::glr::parsergen::GlrRule>(), 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<vl::glr::parsergen::GlrSyntaxFile>(), 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<GlrSyntax>& value)
|
|
{
|
|
node->first = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeAlternativeSyntax& MakeAlternativeSyntax::second(const vl::Ptr<GlrSyntax>& value)
|
|
{
|
|
node->second = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeAndCondition
|
|
***********************************************************************/
|
|
|
|
MakeAndCondition& MakeAndCondition::first(const vl::Ptr<GlrCondition>& value)
|
|
{
|
|
node->first = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeAndCondition& MakeAndCondition::second(const vl::Ptr<GlrCondition>& 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<GlrAssignment>& value)
|
|
{
|
|
node->assignments.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
MakeCreateClause& MakeCreateClause::syntax(const vl::Ptr<GlrSyntax>& 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<GlrLeftRecursionInjectContinuation>& value)
|
|
{
|
|
node->continuation = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeLeftRecursionInjectClause& MakeLeftRecursionInjectClause::rule(const vl::Ptr<GlrRefSyntax>& value)
|
|
{
|
|
node->rule = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeLeftRecursionInjectContinuation
|
|
***********************************************************************/
|
|
|
|
MakeLeftRecursionInjectContinuation& MakeLeftRecursionInjectContinuation::configuration(GlrLeftRecursionConfiguration value)
|
|
{
|
|
node->configuration = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeLeftRecursionInjectContinuation& MakeLeftRecursionInjectContinuation::flags(const vl::Ptr<GlrLeftRecursionPlaceholder>& value)
|
|
{
|
|
node->flags.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
MakeLeftRecursionInjectContinuation& MakeLeftRecursionInjectContinuation::injectionTargets(const vl::Ptr<GlrLeftRecursionInjectClause>& 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<GlrLeftRecursionPlaceholder>& value)
|
|
{
|
|
node->flags.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeLoopSyntax
|
|
***********************************************************************/
|
|
|
|
MakeLoopSyntax& MakeLoopSyntax::delimiter(const vl::Ptr<GlrSyntax>& value)
|
|
{
|
|
node->delimiter = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeLoopSyntax& MakeLoopSyntax::syntax(const vl::Ptr<GlrSyntax>& value)
|
|
{
|
|
node->syntax = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeNotCondition
|
|
***********************************************************************/
|
|
|
|
MakeNotCondition& MakeNotCondition::condition(const vl::Ptr<GlrCondition>& value)
|
|
{
|
|
node->condition = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeOptionalSyntax
|
|
***********************************************************************/
|
|
|
|
MakeOptionalSyntax& MakeOptionalSyntax::priority(GlrOptionalPriority value)
|
|
{
|
|
node->priority = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeOptionalSyntax& MakeOptionalSyntax::syntax(const vl::Ptr<GlrSyntax>& value)
|
|
{
|
|
node->syntax = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeOrCondition
|
|
***********************************************************************/
|
|
|
|
MakeOrCondition& MakeOrCondition::first(const vl::Ptr<GlrCondition>& value)
|
|
{
|
|
node->first = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeOrCondition& MakeOrCondition::second(const vl::Ptr<GlrCondition>& value)
|
|
{
|
|
node->second = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakePartialClause
|
|
***********************************************************************/
|
|
|
|
MakePartialClause& MakePartialClause::assignments(const vl::Ptr<GlrAssignment>& value)
|
|
{
|
|
node->assignments.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
MakePartialClause& MakePartialClause::syntax(const vl::Ptr<GlrSyntax>& 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<GlrRefSyntax>& value)
|
|
{
|
|
node->rule = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakePushConditionSyntax
|
|
***********************************************************************/
|
|
|
|
MakePushConditionSyntax& MakePushConditionSyntax::switches(const vl::Ptr<GlrSwitchItem>& value)
|
|
{
|
|
node->switches.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
MakePushConditionSyntax& MakePushConditionSyntax::syntax(const vl::Ptr<GlrSyntax>& 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<GlrAssignment>& value)
|
|
{
|
|
node->assignments.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
MakeReuseClause& MakeReuseClause::syntax(const vl::Ptr<GlrSyntax>& value)
|
|
{
|
|
node->syntax = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeRule
|
|
***********************************************************************/
|
|
|
|
MakeRule& MakeRule::clauses(const vl::Ptr<GlrClause>& 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<GlrSyntax>& value)
|
|
{
|
|
node->first = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeSequenceSyntax& MakeSequenceSyntax::second(const vl::Ptr<GlrSyntax>& 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<GlrRule>& value)
|
|
{
|
|
node->rules.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
MakeSyntaxFile& MakeSyntaxFile::switches(const vl::Ptr<GlrSwitchItem>& value)
|
|
{
|
|
node->switches.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeTestConditionBranch
|
|
***********************************************************************/
|
|
|
|
MakeTestConditionBranch& MakeTestConditionBranch::condition(const vl::Ptr<GlrCondition>& value)
|
|
{
|
|
node->condition = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeTestConditionBranch& MakeTestConditionBranch::syntax(const vl::Ptr<GlrSyntax>& value)
|
|
{
|
|
node->syntax = value;
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeTestConditionSyntax
|
|
***********************************************************************/
|
|
|
|
MakeTestConditionSyntax& MakeTestConditionSyntax::branches(const vl::Ptr<GlrTestConditionBranch>& 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<GlrSyntax*>(from), static_cast<GlrSyntax*>(to));
|
|
to->first = CopyNode(from->first.Obj());
|
|
to->second = CopyNode(from->second.Obj());
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrAndCondition* from, GlrAndCondition* to)
|
|
{
|
|
CopyFields(static_cast<GlrCondition*>(from), static_cast<GlrCondition*>(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<GlrClause*>(from), static_cast<GlrClause*>(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<GlrClause*>(from), static_cast<GlrClause*>(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<GlrClause*>(from), static_cast<GlrClause*>(to));
|
|
for (auto&& listItem : from->flags)
|
|
{
|
|
to->flags.Add(CopyNode(listItem.Obj()));
|
|
}
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrLoopSyntax* from, GlrLoopSyntax* to)
|
|
{
|
|
CopyFields(static_cast<GlrSyntax*>(from), static_cast<GlrSyntax*>(to));
|
|
to->delimiter = CopyNode(from->delimiter.Obj());
|
|
to->syntax = CopyNode(from->syntax.Obj());
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrNotCondition* from, GlrNotCondition* to)
|
|
{
|
|
CopyFields(static_cast<GlrCondition*>(from), static_cast<GlrCondition*>(to));
|
|
to->condition = CopyNode(from->condition.Obj());
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrOptionalSyntax* from, GlrOptionalSyntax* to)
|
|
{
|
|
CopyFields(static_cast<GlrSyntax*>(from), static_cast<GlrSyntax*>(to));
|
|
to->priority = from->priority;
|
|
to->syntax = CopyNode(from->syntax.Obj());
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrOrCondition* from, GlrOrCondition* to)
|
|
{
|
|
CopyFields(static_cast<GlrCondition*>(from), static_cast<GlrCondition*>(to));
|
|
to->first = CopyNode(from->first.Obj());
|
|
to->second = CopyNode(from->second.Obj());
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrPartialClause* from, GlrPartialClause* to)
|
|
{
|
|
CopyFields(static_cast<GlrClause*>(from), static_cast<GlrClause*>(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<GlrClause*>(from), static_cast<GlrClause*>(to));
|
|
to->rule = CopyNode(from->rule.Obj());
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrPushConditionSyntax* from, GlrPushConditionSyntax* to)
|
|
{
|
|
CopyFields(static_cast<GlrSyntax*>(from), static_cast<GlrSyntax*>(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<GlrCondition*>(from), static_cast<GlrCondition*>(to));
|
|
to->name = from->name;
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrRefSyntax* from, GlrRefSyntax* to)
|
|
{
|
|
CopyFields(static_cast<GlrSyntax*>(from), static_cast<GlrSyntax*>(to));
|
|
to->field = from->field;
|
|
to->literal = from->literal;
|
|
to->refType = from->refType;
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrReuseClause* from, GlrReuseClause* to)
|
|
{
|
|
CopyFields(static_cast<GlrClause*>(from), static_cast<GlrClause*>(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<GlrSyntax*>(from), static_cast<GlrSyntax*>(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<GlrSyntax*>(from), static_cast<GlrSyntax*>(to));
|
|
for (auto&& listItem : from->branches)
|
|
{
|
|
to->branches.Add(CopyNode(listItem.Obj()));
|
|
}
|
|
}
|
|
|
|
void RuleAstVisitor::CopyFields(GlrUseSyntax* from, GlrUseSyntax* to)
|
|
{
|
|
CopyFields(static_cast<GlrSyntax*>(from), static_cast<GlrSyntax*>(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<GlrCondition> RuleAstVisitor::CopyNode(GlrCondition* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
node->Accept(static_cast<GlrCondition::IVisitor*>(this));
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrCondition>();
|
|
}
|
|
|
|
vl::Ptr<GlrSyntax> RuleAstVisitor::CopyNode(GlrSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
node->Accept(static_cast<GlrSyntax::IVisitor*>(this));
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrClause> RuleAstVisitor::CopyNode(GlrClause* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
node->Accept(static_cast<GlrClause::IVisitor*>(this));
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrClause>();
|
|
}
|
|
|
|
vl::Ptr<GlrSwitchItem> RuleAstVisitor::CopyNode(GlrSwitchItem* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrSwitchItem>();
|
|
}
|
|
|
|
vl::Ptr<GlrTestConditionBranch> RuleAstVisitor::CopyNode(GlrTestConditionBranch* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrTestConditionBranch>();
|
|
}
|
|
|
|
vl::Ptr<GlrAssignment> RuleAstVisitor::CopyNode(GlrAssignment* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrAssignment>();
|
|
}
|
|
|
|
vl::Ptr<GlrLeftRecursionPlaceholder> RuleAstVisitor::CopyNode(GlrLeftRecursionPlaceholder* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrLeftRecursionPlaceholder>();
|
|
}
|
|
|
|
vl::Ptr<GlrLeftRecursionInjectContinuation> RuleAstVisitor::CopyNode(GlrLeftRecursionInjectContinuation* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrLeftRecursionInjectContinuation>();
|
|
}
|
|
|
|
vl::Ptr<GlrRule> RuleAstVisitor::CopyNode(GlrRule* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrRule>();
|
|
}
|
|
|
|
vl::Ptr<GlrSyntaxFile> RuleAstVisitor::CopyNode(GlrSyntaxFile* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrSyntaxFile>();
|
|
}
|
|
|
|
vl::Ptr<GlrAlternativeSyntax> RuleAstVisitor::CopyNode(GlrAlternativeSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrAlternativeSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrAndCondition> RuleAstVisitor::CopyNode(GlrAndCondition* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrCondition*>(node)).Cast<GlrAndCondition>();
|
|
}
|
|
|
|
vl::Ptr<GlrCreateClause> RuleAstVisitor::CopyNode(GlrCreateClause* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrClause*>(node)).Cast<GlrCreateClause>();
|
|
}
|
|
|
|
vl::Ptr<GlrLeftRecursionInjectClause> RuleAstVisitor::CopyNode(GlrLeftRecursionInjectClause* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrClause*>(node)).Cast<GlrLeftRecursionInjectClause>();
|
|
}
|
|
|
|
vl::Ptr<GlrLeftRecursionPlaceholderClause> RuleAstVisitor::CopyNode(GlrLeftRecursionPlaceholderClause* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrClause*>(node)).Cast<GlrLeftRecursionPlaceholderClause>();
|
|
}
|
|
|
|
vl::Ptr<GlrLoopSyntax> RuleAstVisitor::CopyNode(GlrLoopSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrLoopSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrNotCondition> RuleAstVisitor::CopyNode(GlrNotCondition* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrCondition*>(node)).Cast<GlrNotCondition>();
|
|
}
|
|
|
|
vl::Ptr<GlrOptionalSyntax> RuleAstVisitor::CopyNode(GlrOptionalSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrOptionalSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrOrCondition> RuleAstVisitor::CopyNode(GlrOrCondition* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrCondition*>(node)).Cast<GlrOrCondition>();
|
|
}
|
|
|
|
vl::Ptr<GlrPartialClause> RuleAstVisitor::CopyNode(GlrPartialClause* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrClause*>(node)).Cast<GlrPartialClause>();
|
|
}
|
|
|
|
vl::Ptr<GlrPrefixMergeClause> RuleAstVisitor::CopyNode(GlrPrefixMergeClause* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrClause*>(node)).Cast<GlrPrefixMergeClause>();
|
|
}
|
|
|
|
vl::Ptr<GlrPushConditionSyntax> RuleAstVisitor::CopyNode(GlrPushConditionSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrPushConditionSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrRefCondition> RuleAstVisitor::CopyNode(GlrRefCondition* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrCondition*>(node)).Cast<GlrRefCondition>();
|
|
}
|
|
|
|
vl::Ptr<GlrRefSyntax> RuleAstVisitor::CopyNode(GlrRefSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrRefSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrReuseClause> RuleAstVisitor::CopyNode(GlrReuseClause* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrClause*>(node)).Cast<GlrReuseClause>();
|
|
}
|
|
|
|
vl::Ptr<GlrSequenceSyntax> RuleAstVisitor::CopyNode(GlrSequenceSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrSequenceSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrTestConditionSyntax> RuleAstVisitor::CopyNode(GlrTestConditionSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrTestConditionSyntax>();
|
|
}
|
|
|
|
vl::Ptr<GlrUseSyntax> RuleAstVisitor::CopyNode(GlrUseSyntax* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrSyntax*>(node)).Cast<GlrUseSyntax>();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\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<GlrCondition*>(node));
|
|
PrintFields(static_cast<GlrRefCondition*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrNotCondition* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"NotCondition", node);
|
|
PrintFields(static_cast<GlrCondition*>(node));
|
|
PrintFields(static_cast<GlrNotCondition*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrAndCondition* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"AndCondition", node);
|
|
PrintFields(static_cast<GlrCondition*>(node));
|
|
PrintFields(static_cast<GlrAndCondition*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrOrCondition* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"OrCondition", node);
|
|
PrintFields(static_cast<GlrCondition*>(node));
|
|
PrintFields(static_cast<GlrOrCondition*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrRefSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"RefSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrRefSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrUseSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"UseSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrUseSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrLoopSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"LoopSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrLoopSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrOptionalSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"OptionalSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrOptionalSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrSequenceSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"SequenceSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrSequenceSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrAlternativeSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"AlternativeSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrAlternativeSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrPushConditionSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"PushConditionSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrPushConditionSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrTestConditionSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"TestConditionSyntax", node);
|
|
PrintFields(static_cast<GlrSyntax*>(node));
|
|
PrintFields(static_cast<GlrTestConditionSyntax*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrCreateClause* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"CreateClause", node);
|
|
PrintFields(static_cast<GlrClause*>(node));
|
|
PrintFields(static_cast<GlrCreateClause*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrPartialClause* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"PartialClause", node);
|
|
PrintFields(static_cast<GlrClause*>(node));
|
|
PrintFields(static_cast<GlrPartialClause*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrReuseClause* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"ReuseClause", node);
|
|
PrintFields(static_cast<GlrClause*>(node));
|
|
PrintFields(static_cast<GlrReuseClause*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrLeftRecursionPlaceholderClause* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"LeftRecursionPlaceholderClause", node);
|
|
PrintFields(static_cast<GlrClause*>(node));
|
|
PrintFields(static_cast<GlrLeftRecursionPlaceholderClause*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrLeftRecursionInjectClause* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"LeftRecursionInjectClause", node);
|
|
PrintFields(static_cast<GlrClause*>(node));
|
|
PrintFields(static_cast<GlrLeftRecursionInjectClause*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrPrefixMergeClause* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"PrefixMergeClause", node);
|
|
PrintFields(static_cast<GlrClause*>(node));
|
|
PrintFields(static_cast<GlrPrefixMergeClause*>(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<GlrCondition::IVisitor*>(this));
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrSyntax* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
node->Accept(static_cast<GlrSyntax::IVisitor*>(this));
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrClause* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
node->Accept(static_cast<GlrClause::IVisitor*>(this));
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrSwitchItem* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"SwitchItem", node);
|
|
PrintFields(static_cast<GlrSwitchItem*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrTestConditionBranch* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"TestConditionBranch", node);
|
|
PrintFields(static_cast<GlrTestConditionBranch*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrAssignment* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"Assignment", node);
|
|
PrintFields(static_cast<GlrAssignment*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrLeftRecursionPlaceholder* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"LeftRecursionPlaceholder", node);
|
|
PrintFields(static_cast<GlrLeftRecursionPlaceholder*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrLeftRecursionInjectContinuation* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"LeftRecursionInjectContinuation", node);
|
|
PrintFields(static_cast<GlrLeftRecursionInjectContinuation*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrRule* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"Rule", node);
|
|
PrintFields(static_cast<GlrRule*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrSyntaxFile* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"SyntaxFile", node);
|
|
PrintFields(static_cast<GlrSyntaxFile*>(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<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrCondition*>(node));
|
|
Traverse(static_cast<GlrRefCondition*>(node));
|
|
Traverse(node->name);
|
|
Finishing(static_cast<GlrRefCondition*>(node));
|
|
Finishing(static_cast<GlrCondition*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrNotCondition* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrCondition*>(node));
|
|
Traverse(static_cast<GlrNotCondition*>(node));
|
|
InspectInto(node->condition.Obj());
|
|
Finishing(static_cast<GlrNotCondition*>(node));
|
|
Finishing(static_cast<GlrCondition*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrAndCondition* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrCondition*>(node));
|
|
Traverse(static_cast<GlrAndCondition*>(node));
|
|
InspectInto(node->first.Obj());
|
|
InspectInto(node->second.Obj());
|
|
Finishing(static_cast<GlrAndCondition*>(node));
|
|
Finishing(static_cast<GlrCondition*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrOrCondition* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrCondition*>(node));
|
|
Traverse(static_cast<GlrOrCondition*>(node));
|
|
InspectInto(node->first.Obj());
|
|
InspectInto(node->second.Obj());
|
|
Finishing(static_cast<GlrOrCondition*>(node));
|
|
Finishing(static_cast<GlrCondition*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrRefSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrRefSyntax*>(node));
|
|
Traverse(node->field);
|
|
Traverse(node->literal);
|
|
Finishing(static_cast<GlrRefSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrUseSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrUseSyntax*>(node));
|
|
Traverse(node->name);
|
|
Finishing(static_cast<GlrUseSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrLoopSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrLoopSyntax*>(node));
|
|
InspectInto(node->delimiter.Obj());
|
|
InspectInto(node->syntax.Obj());
|
|
Finishing(static_cast<GlrLoopSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrOptionalSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrOptionalSyntax*>(node));
|
|
InspectInto(node->syntax.Obj());
|
|
Finishing(static_cast<GlrOptionalSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrSequenceSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrSequenceSyntax*>(node));
|
|
InspectInto(node->first.Obj());
|
|
InspectInto(node->second.Obj());
|
|
Finishing(static_cast<GlrSequenceSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrAlternativeSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrAlternativeSyntax*>(node));
|
|
InspectInto(node->first.Obj());
|
|
InspectInto(node->second.Obj());
|
|
Finishing(static_cast<GlrAlternativeSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrPushConditionSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrPushConditionSyntax*>(node));
|
|
for (auto&& listItem : node->switches)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
InspectInto(node->syntax.Obj());
|
|
Finishing(static_cast<GlrPushConditionSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrTestConditionSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntax*>(node));
|
|
Traverse(static_cast<GlrTestConditionSyntax*>(node));
|
|
for (auto&& listItem : node->branches)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Finishing(static_cast<GlrTestConditionSyntax*>(node));
|
|
Finishing(static_cast<GlrSyntax*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrCreateClause* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrClause*>(node));
|
|
Traverse(static_cast<GlrCreateClause*>(node));
|
|
for (auto&& listItem : node->assignments)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
InspectInto(node->syntax.Obj());
|
|
Traverse(node->type);
|
|
Finishing(static_cast<GlrCreateClause*>(node));
|
|
Finishing(static_cast<GlrClause*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrPartialClause* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrClause*>(node));
|
|
Traverse(static_cast<GlrPartialClause*>(node));
|
|
for (auto&& listItem : node->assignments)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
InspectInto(node->syntax.Obj());
|
|
Traverse(node->type);
|
|
Finishing(static_cast<GlrPartialClause*>(node));
|
|
Finishing(static_cast<GlrClause*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrReuseClause* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrClause*>(node));
|
|
Traverse(static_cast<GlrReuseClause*>(node));
|
|
for (auto&& listItem : node->assignments)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
InspectInto(node->syntax.Obj());
|
|
Finishing(static_cast<GlrReuseClause*>(node));
|
|
Finishing(static_cast<GlrClause*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrLeftRecursionPlaceholderClause* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrClause*>(node));
|
|
Traverse(static_cast<GlrLeftRecursionPlaceholderClause*>(node));
|
|
for (auto&& listItem : node->flags)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Finishing(static_cast<GlrLeftRecursionPlaceholderClause*>(node));
|
|
Finishing(static_cast<GlrClause*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrLeftRecursionInjectClause* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrClause*>(node));
|
|
Traverse(static_cast<GlrLeftRecursionInjectClause*>(node));
|
|
InspectInto(node->continuation.Obj());
|
|
InspectInto(node->rule.Obj());
|
|
Finishing(static_cast<GlrLeftRecursionInjectClause*>(node));
|
|
Finishing(static_cast<GlrClause*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrPrefixMergeClause* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrClause*>(node));
|
|
Traverse(static_cast<GlrPrefixMergeClause*>(node));
|
|
InspectInto(node->rule.Obj());
|
|
Finishing(static_cast<GlrPrefixMergeClause*>(node));
|
|
Finishing(static_cast<GlrClause*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrCondition* node)
|
|
{
|
|
if (!node) return;
|
|
node->Accept(static_cast<GlrCondition::IVisitor*>(this));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrSyntax* node)
|
|
{
|
|
if (!node) return;
|
|
node->Accept(static_cast<GlrSyntax::IVisitor*>(this));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrClause* node)
|
|
{
|
|
if (!node) return;
|
|
node->Accept(static_cast<GlrClause::IVisitor*>(this));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrSwitchItem* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSwitchItem*>(node));
|
|
Traverse(node->name);
|
|
Finishing(static_cast<GlrSwitchItem*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrTestConditionBranch* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrTestConditionBranch*>(node));
|
|
InspectInto(node->condition.Obj());
|
|
InspectInto(node->syntax.Obj());
|
|
Finishing(static_cast<GlrTestConditionBranch*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrAssignment* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrAssignment*>(node));
|
|
Traverse(node->field);
|
|
Traverse(node->value);
|
|
Finishing(static_cast<GlrAssignment*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrLeftRecursionPlaceholder* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrLeftRecursionPlaceholder*>(node));
|
|
Traverse(node->flag);
|
|
Finishing(static_cast<GlrLeftRecursionPlaceholder*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrLeftRecursionInjectContinuation* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrLeftRecursionInjectContinuation*>(node));
|
|
for (auto&& listItem : node->flags)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
for (auto&& listItem : node->injectionTargets)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Finishing(static_cast<GlrLeftRecursionInjectContinuation*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrRule* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrRule*>(node));
|
|
for (auto&& listItem : node->clauses)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Traverse(node->name);
|
|
Traverse(node->type);
|
|
Finishing(static_cast<GlrRule*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void RuleAstVisitor::InspectInto(GlrSyntaxFile* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrSyntaxFile*>(node));
|
|
for (auto&& listItem : node->rules)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
for (auto&& listItem : node->switches)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Finishing(static_cast<GlrSyntaxFile*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(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 = 14429; // 198067 bytes before compressing
|
|
static const vl::vint dataBlock = 256;
|
|
static const vl::vint dataRemain = 93;
|
|
static const vl::vint dataSolidRows = 56;
|
|
static const vl::vint dataRows = 57;
|
|
static const char* compressed[] = {
|
|
"\xB3\x05\x03\x00\x55\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\x01\x10\xA3\x85\x8E\x74\x08\xCA\x7F\x29\x81\x7B\x74\x84\xE8\x7D\x82\xDB\x77\x05\xFF\x75\x6C\x67\x18\x5F\x81\x20\x24\x14\x50\x89\x0A\x92\x85\x2B\x93\x7E\x5E\x7C\x17\xB1\x84\x5A\x83\x09\xE8\x80\xE9\x71\x80\xFD\x6F\x12\x7E\x84\x52\x8A\x08\xF9\x7D\x2E\x9D\x85\x9C\x83\x16\x87\x7F\x60\x8F\x0C\xC3\x87\x07\x9F\x85\x4E\x84\x12\x88\x86\x07\x76\x10\x22\x86\xEF\x78\x86\x71\x85\x08\x94\x87\xCF\x66\x10\x44\x17\x33\x8A\x85\xDF\x84\x19\xA1\x87\x03\x89\xFD\x40\x83\xF6\x68\x7D\xE4\x83\x20\x16\x86\x09\x8C\x0A\xEA\x87\x18\x8C\x7D\x69\x16\xF5\x7C\x84\x6F\x80\x07\xFD\x85\x1D\x94\x84\xF8\x81\x49\x3A\x87\x73\x8B\x0C\xF5\x84\x40\x88\x7B\x12\x79\x1E\xA0\x83\x68\x89\x08\x8C\x7F\x06\x81\x7A\x1D\x83\x13\x9A\x82\x7F\x82\x0B\xA8\x75\x40\x9D\x12\x03\x8A\x21\x81\x08\x74\x84\x11\xC4\x84\x38\x97\x87\x08\x8D\x05",
|
|
"\x9A\x88\x00\x03\x0F\x8A\x82\x3D\x9F\x87\x29\x87\x22\x9B\x13\x8C\x8C\x06\x89\x08\x3F\x88\x89\x83\x87\x24\xA1\x7A\x95\x82\x26\x2C\x8B\xD5\x6E\x74\x24\x80\x1E\x9E\x61\xB1\x64\x13\xDC\x75\x44\x9C\x85\xAC\x10\x28\xB1\x6D\xA0\x8D\xFD\x28\x74\xAE\x19\x89\x02\x08\x6B\x3C\x85\xA3\x85\xFD\x0A\x0A\x52\x85\x8A\xFE\x66\x27\x99\x78\xEA\x14\x04\xEC\x86\x40\x1C\x81\xF9\x86\x07\xB1\x6C\xAC\x82\x10\xDA\x89\x55\x8A\x6A\x52\x8C\x05\xB5\x69\xF4\x78\xEA\x5C\x88\x46\x9E\x8A\xCF\x86\x2C\xAB\x88\xB4\x8D\x1C\x31\x83\x50\x0E\x8B\xD3\x81\x20\x2A\x8B\x9A\x8C\x16\xAD\x88\x0B\x61\x89\x3F\x81\x3B\x30\x8A\xF9\x6C\x88\x21\x8B\x53\x8D\x8B\x3C\x89\x24\x9E\x80\x9F\x03\x03\xCD\x0E\x64\x7F\x8A\x7A\x65\x30\x94\x0F\xBD\x60\x09\xC3\x0B\x0D\x94\x81\x2E\x7B\x24\x8C\x8A\xED\x70\xED\x06\x0B\x5F\x96\x8B\x03\x0B\x32\xAE\x87\xCA\x83\x10\x17\x8F\x4D\x89\x08\xBB\x87\x19\xA1\x8D\x91\x8D\x13\x80\x7D\xF4\x78\x8C\x02\x0B\x34\xA8\x8C\x5D\x81\xDB\x25\x8D\xF9\x6D\x7B\x23\x8C\x28\xB1\x8D\xA1\x81\x18\x0A\x8D\x76\x1B\x6B\x2F\x8E\x28\x3B\x8B\x9E\x0F\x18\x86\x8E\x42\x19",
|
|
"\x8D\x6F\x8B\xAC\x6A\x8D\xCF\x86\x10\x43\x8F\x8D\x78\x89\x4D\x8F\x34\x84\x8F\x76\x80\xF2\x6F\x85\xDA\x6F\x86\xB2\x8B\x35\x80\x01\xE8\x8B\x1C\x82\x08\x75\x9C\x0E\xBB\x8C\xEC\x46\x08\x5C\x80\x18\xC5\x7A\x67\x93\x7D\x2C\x84\x8F\x08\x8B\x80\x08\x48\x3C\x84\x47\x90\x89\x77\x86\x11\x9E\x88\xAB\x81\x10\x25\x88\x06\x9F\x88\xE8\x8D\x14\xA2\x87\x50\x85\x10\xC6\x84\x7C\x91\x84\x0C\x8A\x3D\xB1\x8A\x32\x82\x0C\xF5\x8D\x4C\x9A\x86\x12\x8F\x0D\xB1\x8F\x6C\x89\x02\xDB\x84\x02\x67\x8F\x15\x8A\x3F\xB4\x87\x14\x8F\x07\x99\x87\x42\x93\x88\x03\x93\x1D\x94\x85\x06\x9B\x1F\xC0\x8F\x35\x92\x89\xEB\x8B\x42\xB1\x6C\x04\x99\x21\xF6\x8C\x86\x9B\x8F\x8D\x8B\x3F\xAE\x8F\x24\x82\x1F\xEC\x8C\x00\x01\x91\x7C\x8D\x1B\xBE\x8F\xF4\x8F\xFB\x1B\x93\x8A\x85\x91\x94\x81\xEB\x68\x85\x11\x98\x09\x97\x91\x8C\x81\x90\x82\x84\x45\xB7\x8E\x07\x9F\x09\xCF\x86\x85\x8B\x90\xFF\x8E\x43\x94\x85\x57\x8C\x23\xA4\x8B\x8B\x84\x90\x85\x82\xF3\x66\x8F\x23\x92\x21\xA9\x80\x91\x9B\x8F\xDC\x8A\x3A\x86\x8F\x31\x8C\x21\xB6\x92\x90\x97\x92\x49\x96\x40\x8A\x08\x1A\x9D\x09",
|
|
"\x89\x93\x31\x98\x91\xAB\x80\x4B\xBA\x90\x13\x9A\x25\x89\x09\x95\x80\x92\x63\x96\x20\x85\x90\x4B\x80\x21\xDE\x93\x8E\x9B\x8F\x65\x92\x45\xB9\x8F\x62\x89\x25\xB1\x6E\x39\x83\x89\x67\x96\x24\xAA\x93\x20\x99\x24\xAE\x8E\x28\x76\x7E\xD5\x8D\x3D\x8C\x93\x8E\x8B\x1F\xFE\x92\x36\x60\x94\xC7\x8E\x25\x83\x95\x08\x90\x12\xE3\x8E\x48\x92\x8E\x79\x97\x3D\x9F\x90\x34\x90\x0C\xA3\x81\x72\x85\x81\xD2\x8C\x4B\x92\x86\x4A\x9D\x0C\xCC\x8C\x78\x81\x82\x09\x8A\x3A\xBF\x90\x3D\x92\x26\xB0\x91\x4A\x82\x8C\x2E\x93\x4E\xAF\x93\x14\x9E\x29\x9C\x80\xED\x6C\x93\x02\x96\x4D\x93\x95\x64\x8B\xF6\x17\x96\x4E\x81\x94\x04\x0B\x51\xB2\x95\x83\x8E\x28\x83\x8F\x1E\x63\x6B\x88\x1C\x17\x81\x97\x67\x8F\x1D\xAE\x95\x78\x91\x6D\xC5\x90\x22\x99\x78\xF1\x80\x15\xA4\x7D\xB2\x9D\x81\xCB\x95\xC3\x75\x84\x00\x0F\x2C\xD9\x89\xB4\x98\x81\x09\x0B\x58\x8D\x0F\xBC\x8D\xE0\x5C\x95\x75\x7E\x96\x4A\x6B\xAF\x44\x63\xBD\x6F\x24\xCE\x8D\x40\x0D\x26\xD8\x96\x20\x28\x96\xC8\x84\xD5\x20\x66\x16\x60\x97\x7A\x63\xAF\x4F\x27\x74\x93\x10\x51\x24\xBD\x82\x08\xEC\x1F\x5E\x81",
|
|
"\x09\x7C\x9C\x2E\x86\x08\x46\x1A\x97\x00\x03\x9A\x00\x98\x81\x9D\x2F\x83\x0A\xE0\x1E\x8D\xC9\x66\x5D\xAF\x8D\x84\x00\x49\x05\x9A\x1C\x5B\x70\x06\x0C\x79\x00\x98\x0A\x96\x2E\x80\x00\x1D\x2E\x98\x01\x09\x7B\x18\x98\x00\x01\x25\xB7\x8D\x1B\x90\x98\x03\x0E\xEF\x48\x98\x83\x02\x32\x8B\x8D\x45\x00\x99\x02\x0D\x76\x1B\x99\x3B\x96\x32\x89\x08\xCB\x9E\x98\x09\x0A\x8A\x00\x98\x99\x9B\x31\xB3\x73\x6B\x76\x99\x88\x6C\x26\xBB\x6A\x9D\x9F\x10\x28\x9B\x46\x9E\x99\x00\x07\x8E\x00\x99\x59\x23\x34\xC0\x98\xD1\x9B\x98\x47\x9D\x39\x1A\x02\xF0\x5D\xFE\x4D\x9A\x86\x63\x0F\xF4\x0E\x4F\x08\x60\xF0\x5C\x2D\xCF\x99\xED\x51\x9A\x09\x0C\x5B\x9A\x9B\x1C\x8C\x35\xFF\x0E\x42\x14\x9A\x5F\x98\x6B\x97\x9B\xAC\x9A\x10\x43\x82\x41\x1C\x96\x66\x9B\x20\x28\x9A\xB1\x9E\xC3\x50\x98\xD9\x89\x08\x53\x9C\x6D\x97\x8B\xB0\x9F\x36\x86\x09\xF8\x61\x7F\xEF\x7F\xFD\x7B\x6A\x4C\x10\x1A\x8A\x0B\x75\x9B\x9B\x0A\x0E\x38\x97\x8E\xCD\x81\x10\x00\x9D\xDF\x89\x08\x7F\x9A\x21\x3C\x9B\xE2\x8E\x37\x8A\x0A\xE1\x8C\x9C\x88\x9E\x71\x8A\x9D\xC0\x9D\x38\x89\x0B\xE3\x83\x15",
|
|
"\x95\x9E\x20\x17\x9D\xD4\x89\x39\x83\x0B\xE6\x8C\x8D\x91\x9E\x65\x92\x9D\x84\x0B\x38\x98\x9D\xE8\x85\x87\xA3\x9E\x20\x25\x9C\xCE\x97\x3A\x83\x0B\xCB\x80\x00\xBD\x79\x6E\xB5\x9B\x4F\x70\x37\xF4\x9B\xD9\x8C\x6A\x0A\x0A\x76\xB7\x9C\xDD\x5D\x39\xEE\x5D\xEF\x97\x15\x44\x73\x55\x01\x9F\x81\x07\x1D\xDF\x61\xF1\x9F\x9D\x09\x60\x79\x86\x9F\xE1\x96\x1D\x8D\x08\xF3\x81\x08\xD7\x8F\x75\x8B\x9E\xD1\x9D\x17\xD4\x9C\xEA\x96\x9E\x6B\x86\x0B\x83\x08\x41\x6B\x3D\x9F\x98\xE9\x94\x9C\xAD\x98\x0B\x93\x9D\xC3\x92\x3C\xD5\x9E\x41\x08\x87\xAB\x98\x74\xA5\x9F\xF3\x93\x3E\x90\x9F\xFA\x86\x82\xED\x9E\x74\xAF\x9E\xF1\x9F\x3D\xE4\x9C\xF1\x9E\x9E\xAA\x98\x7C\xB3\x9F\x9F\x95\x3F\xEE\x9F\xFD\x86\x93\xF1\x9C\x75\xBB\x9E\x00\x0F\x3A\xE8\x9E\xFE\x9F\x9F\xD7\x9C\x7D\xBD\x9E\xF9\x98\x40\xAE\x9D\xCF\x8B\x84\x09\x0B\xC6\x71\x9C\xDB\x9A\x36\xCC\x71\xE3\x73\x9B\x6E\x9B\x77\xBE\x5C\xDC\x95\x3B\x99\xA1\x05\xBE\x75\x2A\x79\x77\x94\xA0\x81\x0C\x2D\xF5\x6B\x04\xBE\xA0\x24\xA0\x39\xB4\x9D\xBB\x88\x42\x81\x08\xB7\x9E\x86\xE9\x98\x00\x02\x9D\xDF\x81\x40\xEA",
|
|
"\x9D\x03\xA2\x08\x84\x99\x57\x8B\xA0\x01\xA7\x43\xF4\x8F\x0E\xB6\xA1\xCD\x9A\x51\xBF\xA0\x19\xA8\x3C\xB0\xA3\x01\xA1\xA2\x72\x91\x7F\xB6\x9E\x24\xAA\x0C\xC3\xA3\x0C\xA2\xA2\x4A\xA6\x7F\x8C\xA3\x61\x14\x43\xCE\xA0\xF2\x8F\x9D\x46\xA3\x89\x90\x9E\xE7\x99\x10\x5F\x8D\x0C\xAF\xA2\x96\x8D\x86\x84\xA3\xF0\x90\x3C\xDD\xA2\x18\xA0\xA3\x9D\x8F\x8C\x88\x9E\x2F\xA7\x44\xDB\xA2\x19\xB6\xA2\x64\xA4\x5A\xAA\xA3\x38\xAC\x46\xDA\xA3\x74\x8E\x8A\x73\xA3\x80\xAF\x9D\x3A\xA2\x45\xEE\xA1\x02\xA9\xA3\x70\xA2\x8F\x8A\x09\x92\x91\x10\x5F\xA0\xF2\x84\xA4\x00\x06\x90\xB1\xA3\x1C\xA8\x48\x8A\xA7\x00\xAD\xA4\x6D\xA7\x8E\x89\x08\x48\xA6\x47\xD7\x8C\x25\xBD\xA3\x92\xA4\x64\xB9\xA3\x1E\xA0\x00\x17\xA4\x03\xB3\xA2\x01\x0E\x93\xBC\xA0\x50\xA4\x40\x83\xA7\x26\xA4\xA5\xAF\x9A\x94\x80\xA2\x3F\xAE\x40\xF1\xA3\xE0\x88\x9E\xD7\x89\x96\xB0\xA5\x2B\xA4\x4B\xF1\xA3\xEB\x86\x6E\x00\x00\x97\xB9\xA0\x5C\xAC\x4B\xC4\x65\xC2\x9F\xA5\xC4\x68\x7B\x9A\x44\x2E\xA1\x4C\xFF\xA3\x28\xAC\xA5\xC7\xA1\x93\x99\x8D\x48\xA7\x1D\xE8\xA1\x32\xAD\xA6\xC8\x9E\x99\xAB\xA4",
|
|
"\x65\xAF\x4C\xC4\xA7\x27\xA8\xA6\x01\x0F\x75\x92\xA7\x52\xA9\x10\x07\x98\x29\xBE\xA6\xD8\xA0\x00\x39\xA0\x70\xA4\x4D\x81\x08\x39\xB7\x8E\xE7\xA3\x22\x08\x9F\x74\xAD\x4D\xEB\xA5\x2D\xA6\x08\xEC\xA6\x98\xA6\xA7\x77\xA3\x10\x0E\xA4\x27\xB6\xA7\xA4\xA1\x87\xB8\xA7\x70\xAB\x4F\xE5\xA5\x22\xAC\xA6\xA7\xA4\x9F\x80\xA9\x40\xA7\x4F\x83\xAA\x3C\xBF\xA7\x95\xA6\x9A\x82\x09\x7E\xA1\x3D\x8A\x0A\xB6\x82\x08\x0F\xA9\x20\x39\x70\x86\xA6\xF9\x04\xA8\x29\xB7\x63\x51\xA7\x9A\xBE\xA7\x89\xA6\x50\xCB\xA5\xBB\x96\xA8\xE1\xA1\x87\x98\xA9\x7A\xAD\x51\xB8\xA3\x8F\x64\xA9\x09\xAF\xA3\x99\xA9\x6A\xA9\x10\x23\xAB\x42\xA5\xA9\x12\xA9\xA0\xBE\xA6\x7D\x74\x51\xAD\xAA\x4C\xB7\x8E\x1C\xA9\xA5\x88\x81\x95\xA3\x4D\xD7\x8E\x4B\xA5\xA4\x30\xA8\x00\x3F\xA8\x84\xA8\x49\xB8\xAB\x4D\xB5\xA8\x3C\xAB\x8C\x83\xA1\x9C\xA5\x54\xC8\xA8\x4A\xAD\xAA\x36\xA8\xA4\x9B\xA9\xA3\xAA\x52\xCF\xAA\x46\xBE\xA9\x54\xAD\xA4\x59\xAB\x56\xAB\x53\xD6\xA8\x4B\xA7\xA8\x43\xAD\xA6\x87\xA8\xA6\xA7\x55\x8A\xA9\x8F\x9E\xAA\x3D\xAE\xAC\x82\xAB\xAD\xA4\x45\x9C\x72\x54\xAD\xA8\x55",
|
|
"\xAF\xA5\xBA\xA8\xAE\xA3\x10\x61\xA9\x50\xAF\x9D\x35\x7A\x65\x8B\x1E\x85\x02\x31\x86\x08\x55\x86\x08\x1A\x9B\xAF\x89\x09\xBF\xA3\x10\x01\xAC\xBE\x87\x20\xFE\x59\x21\x1E\x76\x4C\x91\x10\x0F\x6F\x40\x14\x99\x03\x0F\x62\x85\xAC\x5B\x4A\x10\x42\x9A\x41\x0C\x96\x03\x0D\x3C\x86\x08\xCD\xA3\x10\x02\x7F\x40\x0D\x98\x9F\xA9\xF0\x4A\x08\xC2\xA2\x10\x06\xAD\x40\x04\xAD\x19\x9A\x21\x0A\x6F\xD2\xAA\x5A\x94\xAD\x42\x1E\xAC\x02\x0F\x97\x43\x09\xA4\x92\x10\x34\xAF\x69\xAE\xAD\x06\x0E\xB6\x80\x00\xD4\xA0\x00\x26\xAC\x00\x0B\x97\x46\x74\xAD\xA7\x96\xA7\xA2\x57\xD0\xAA\xBA\x87\x64\x6F\xAA\x21\x00\xAF\x0F\x72\x5C\xE2\xA6\x72\xA4\xAE\x40\xAB\xAE\xA6\xA9\x84\x0B\x5C\x81\x0A\x5D\xB2\xAE\x65\xA7\xB8\xAE\xAB\xA4\xAB\x4D\xD5\xAD\x25\x89\xAE\xD4\xA8\xB9\x9C\xAE\xE4\x9E\x5D\xE4\xAB\x57\xA3\x08\xDE\xAC\xA6\x81\xAA\xEF\xA7\x5D\xC6\xAC\x7A\xA7\xA9\xC5\xAD\xAC\xA1\xAF\xB8\xA1\x5D\xEE\xAE\x40\x0C\xAF\xCD\xA8\xBF\xA0\xAE\xED\xAD\x55\xF1\xAF\x79\xB7\xAF\xF0\xAD\xBE\xB2\xAE\xFE\xAF\x5E\xF3\xAE\x56\xBB\xAF\x05\xB5\xBF\x82\xB1\xFF\xA3\x5C\xD1\xAB",
|
|
"\x78\xB1\xA3\xE5\xA9\xBF\x90\xAE\xA2\xA3\x60\x89\xB1\x5D\xB2\xB0\x06\xB1\xB8\x88\xB1\xB6\xA4\x60\xB1\x7B\x86\xB9\xA6\xCF\xAE\xC1\xA8\xAA\xA5\xAC\x49\xAF\x9D\x84\xBF\xB0\xDC\xA5\xC3\xA7\xAA\xFF\xA9\x56\xC2\xA5\x83\xA6\x08\xED\xAD\xC2\x9C\xB0\x0B\xBC\x5C\xA8\xB2\x89\xB3\xB0\x62\xAC\xAE\x80\xB0\x11\xBC\x62\xA4\xB0\x2A\xAA\x08\xF3\x96\x20\x36\x96\x83\x04\x30\x83\x09\x35\x29\x08\xB9\x6E\x20\x1C\x27\xA6\x91\x10\x4C\x98\x93\xA1\x08\xAE\x01\x2F\x9D\x44\xF0\x59\x36\xED\x7C\xF8\x4F\x05\x52\xB2\x84\x91\xA1\x27\xB0\x88\x05\x11\x27\x48\x87\x41\x08\x7C\x70\x05\x2C\xBF\x64\xB9\xA1\x98\xAA\x08\xB1\x04\xCC\x8C\xB2\xE3\x8C\x65\x80\x02\x2C\x0A\xB3\x03\x0D\x13\x79\x79\x36\xB3\x0B\x70\xB1\x0A\xAF\x73\x6D\xB1\x21\x34\x04\x3B\xBE\x42\xEB\x6D\x9E\xA9\x08\xB5\x04\xCF\xBE\xA6\x7E\x9F\x67\x81\x0A\x2D\x02\xB4\xC6\x8B\xB5\x0F\xB2\x22\x61\x14\x31\xA0\x69\x2B\xB4\x0A\x0F\x16\x02\xB5\xBD\x6B\x56\x10\xB5\x42\x18\x05\x82\xB5\xCA\x81\x09\x9F\x2F\x64\xBC\x67\x71\x0F\x7F\x41\x2D\xD3\x85\x10\xF0\x50\x59\x85\xB5\x2E\x02\xB4\x31\xA3\xB1\x85\xB4\x00",
|
|
"\x0A\x0B\x02\xB4\xB7\x89\xB2\xAB\xB3\x17\x2E\xB4\xDC\x6B\x6A\x82\x08\x2F\x02\xB4\xD7\x8F\xC8\xB5\xB5\x5E\x09\x69\x8A\x0A\x37\x22\xB5\x75\x12\xD3\x80\x01\x71\x20\x6C\x86\x46\x42\x07\x27\xB5\xB0\x00\x3E\x04\x41\xB1\xFE\x05\x29\xB2\xBF\x05\xB8\xB2\x21\x1E\x29\x64\xB0\x0C\x51\xB5\x42\x1B\x29\xC9\xB1\x18\x16\xB6\x83\x0A\x54\x16\xB6\x41\x02\x06\x93\xB2\x21\x1B\x2B\x64\xB3\x0C\x28\xB6\x42\x09\x2C\xC9\xB4\x18\x02\xB5\x1C\xA2\x5D\x45\xB6\x93\x17\x8E\x81\x31\xD9\x85\x07\x6D\xB3\x10\x06\x35\xB2\xA6\x06\xF4\xB2\x20\x09\x35\x64\xB7\x0C\x02\xB5\xCE\x7A\x2F\xC9\xB0\x19\x3E\xB6\x85\x05\x60\x49\xB5\x32\x02\xB4\x1D\x98\x00\x07\x31\x64\xBA\x0C\x02\xB4\x3A\x83\x38\xEE\xB4\x46\x1C\x9E\x81\x0E\x6D\x11\xB8\x8E\x1F\x62\x0C\x31\xD9\x8B\x06\x41\xBF\xC5\x11\x31\xB2\xAC\x06\x82\xB7\x75\x86\x33\x64\xBD\x0C\x21\xB9\x4E\x09\xB6\x00\x06\x19\x26\xB9\x84\x0A\x67\x49\xB7\x33\x0B\xB9\x06\x0D\xE5\xB5\xB4\x68\x00\x73\x83\x08\xA9\x29\xB6\xD1\x05\xE6\x82\x09\x9B\xB5\x6B\xD2\x04\xC7\xAA\x08\xCF\x31\xD9\x93\x07\x9F\xB9\x10\x53\x35\xB2\xB4\x06\x82\xB2",
|
|
"\xF2\x58\x37\x64\xB5\x0D\x03\xB9\x42\x1B\x39\xC9\xB3\x3B\x12\x7C\x6E\x39\x6C\xD6\x06\xC3\xAA\x08\xF9\x36\xE2\xBF\x13\x9C\x73\x72\x49\xB7\x35\x08\xB8\x0A\x09\xE7\x09\xB6\x6C\x02\x68\xBD\x7F\xD2\x29\xB6\xD9\x02\xD0\xB1\x60\xAB\x3A\x75\xDB\x0F\x8C\x78\x3A\xC9\xB2\x1B\x02\xB5\xB7\xB8\x72\xDB\x07\xDC\xAA\x08\x5A\x39\xD9\x9C\x07\xBB\xB9\x10\x79\xB9\xAD\xBD\x06\x82\xB3\x16\x36\x8D\xF5\x7E\x1D\x6D\xB2\xA7\xBC\x16\x41\x0B\x2E\x86\xBC\x6D\x21\x14\x70\x95\x72\x09\xBC\x7E\x10\x7C\x4A\xBC\x2D\xB6\x37\x85\x11\x50\x11\x61\x87\xB9\x38\x01\x0A\xAB\x9D\x36\x83\x11\x50\x02\xB6\x99\xBD\x38\x3D\x8C\x0C\xAA\x41\xCE\x11\x50\x01\x7F\x9D\x47\xFD\x7B\x81\xC8\xBD\x3C\x0D\xB6\x36\x35\x9A\x96\xB9\x92\xA1\xBC\x7F\x18\x79\xB1\xBD\x1C\xB3\xBD\x0F\x1A\xD8\xB9\x7B\x36\xB5\x45\x77\x9A\xED\xA6\x08\x39\xA6\xF1\x81\x0E\xB0\x99\x10\x61\x7F\xE4\xAF\xB2\x39\x7A\xF8\x85\x0F\xF0\x7C\x2D\xCC\xBF\xEF\xBF\x6E\x72\x9F\x6A\x14\xBC\x8D\xAC\x2D\xEF\x7C\xE1\xA7\x0E\x41\x08\x97\x87\xBE\xDE\x7E\x27\x2A\xBF\xF3\xB0\xA8\xD3\xBC\x46\x1F\x63\xD4\xB1\x7D\xFF\x11\x50",
|
|
"\x1A\x77\xC5\x7C\x85\x8E\x87\x38\xB2\x46\xD7\xBF\xE3\xBC\xAB\xCD\x1B\xE2\x81\x09\x4E\x41\x43\xDB\xBD\xD3\x9C\xAD\xB8\xB9\x28\x28\x86\xFA\xB5\x7E\xDB\x0D\x50\x1E\xAD\x9D\x44\xD0\xA4\xBD\x81\x09\x70\x9D\x46\x71\x9B\x6B\xFE\xBE\xC9\x43\x1D\xD8\x1B\x4D\x89\xC2\x62\xA5\xBF\x92\xAF\x61\xB5\x13\xEB\x81\x43\x8E\xC0\x4D\x39\xA1\x08\xC5\xF0\x95\xAC\x6D\x29\x43\xD7\x8E\x05\xC3\x08\x98\xAF\xCE\x87\x66\xA8\x37\x50\xEE\xBE\xE6\xAA\x08\xB2\xAA\x20\x0C\xB5\xC8\x83\x80\xB3\xB1\x0B\xD8\x11\x41\x09\xC8\x83\x09\x15\xC0\x42\xF2\x8A\x5A\xAA\xBE\xD0\x09\x28\x3A\xB5\x19\xCE\x6B\xE1\xBE\xF4\xBD\xA0\x94\x65\xF8\x9F\xBF\x80\x04\x6C\xEA\xBE\x93\x1A\xBE\xCF\x98\x00\x36\xBF\xF6\x78\x6C\xC6\xC0\x8D\x11\xA8\x4A\xC1\x09\xF8\xC1\xEA\x01\x14\x4E\xB6\x13\xC1\x08\x0F\x28\x08\xDA\x84\x2D\xC3\x0E\xA1\xA1\x9D\x01\x0A\x2B\x2C\x04\xCE\x13\x9C\x72\x7F\xE6\xBE\x42\x18\xB6\xA5\xBA\x20\x03\x2A\x31\xC2\x10\x65\xC3\x58\x98\xBE\xA3\x20\x1D\x94\x99\x1C\xCA\x10\x46\x28\x1B\xD8\x11\xE8\x85\x0C\xDF\xC0\x81\x08\x54\x33\x9E\x40\x11\x2A\x77\xC4\x63\x8A\x08\x13\xC5",
|
|
"\x1C\x41\x0B\x54\x3E\xC3\x38\x15\xE6\x60\x5F\x84\xBB\x84\xE3\x7F\x5B\x28\xC4\x7F\x14\xB7\x8B\xC5\xFE\xBA\x81\x89\x0B\xA3\xA9\xC3\x01\x0D\xB5\x17\xC2\x00\x0F\x2F\xE3\x9B\x06\xB0\xA0\x9E\xBA\x21\x33\x2C\x2E\xC2\x40\x75\x69\xB5\x87\xC1\x09\x08\xB7\x0B\xC1\xE4\x15\xD7\x38\xA7\x1E\xD2\x54\xBB\x2E\x07\xFF\x13\xEF\x88\x48\xAF\xC7\x9F\x15\x2E\xA4\xC7\x4F\x08\xA5\x51\x94\x85\xAD\x57\x08\xA2\x20\xB8\xA4\x17\xED\xB2\x80\xBE\x89\xC9\x1C\x39\xB7\x76\x70\xC5\x95\x39\x71\xA1\xA6\x8B\xD5\x21\x8E\x67\xC5\x85\xC2\x21\x03\x31\x40\xC4\xD8\x1D\x45\x8E\x6E\xC5\x95\xC6\x20\x05\xB9\x55\xC2\x10\x0B\xBB\x26\xCE\xAC\x12\xC2\xC1\xB2\xA3\x2F\xCA\x10\x19\xB8\x37\xD8\x11\xA5\xB3\xFE\x93\xB0\x6C\xC9\x8C\x86\x0A\x83\x35\x23\x1E\xBB\x13\xD1\xC0\x75\xCC\x63\x81\x08\x14\xCD\xC6\x5A\x25\xE6\x72\x91\x76\xC7\x51\x35\x78\x33\xD9\xC6\x17\x2A\xAF\x82\x08\xDE\xA8\x8F\x90\x20\x6F\xAC\x2A\xE4\xC1\x21\x15\x30\x48\xCB\x1D\x16\xAF\x07\xBE\xAB\xA3\xAB\x08\xC0\x01\x1A\x3C\x90\xDE\x0C\x68\xA2\x08\x31\x64\xB7\x99\xC3\x50\xC9\x10\x5C\x31\x45\xC7\x0E\x32\xC2\x04",
|
|
"\xC3\x08\xDE\xAE\x5D\xB6\xC6\x9D\x3F\xC8\xC9\x08\xD6\xA2\xC9\x81\xCA\x10\x65\x25\x42\xC6\x08\xFB\xB0\x13\xFF\x13\x22\xCF\x90\xA3\xC8\x0A\xD2\xC8\x3C\xBD\x26\xF4\x10\x2B\xCA\x93\xB7\xAD\x42\x0B\xB2\x1C\xCE\x20\x2D\x34\x99\xCB\x1D\x61\xC2\x4C\xDC\xAD\xE1\x27\x25\xC3\x08\x5C\x38\x92\xC1\x0D\xA8\xA7\xCA\x0A\x0C\xB3\xB4\x11\xA0\x05\x6C\x10\xC6\xD1\xBB\xC4\xDD\xB6\x20\x19\xC8\xD1\xAA\x94\x82\x0B\xD2\xB2\xC9\xE0\x33\x13\xE3\xB6\xAD\xC1\x91\x89\x09\x08\xD0\xC1\x0A\x08\xDD\x10\xC5\x84\x3B\x89\xE8\xB4\x59\xC9\x08\xBE\xAD\xAF\xA6\xBD\x51\x22\x80\xA9\xAD\x57\xC5\x29\x9D\xC3\x20\x04\xC4\x3A\xC9\x10\x19\x3A\xD7\x95\x13\x8A\xB2\x26\xF9\xCB\x17\xC6\x86\x89\x09\xCF\x2F\xCB\x03\x15\xB6\x10\xC5\xC1\xCD\x67\xF7\xC8\x00\x09\x3A\x7F\xCE\x20\x2C\xBB\x4D\xCD\x6E\xB2\xCA\xAA\xA7\x63\x8E\xCE\xEF\xAC\xBE\xCE\x14\xD8\x36\x72\x2D\xDC\x3A\x81\xC3\x3B\x20\xC7\x80\x08\x90\xC1\xCB\x40\x1F\x3A\xB9\xC3\x3B\x2D\x2F\x5C\xC3\x9A\xBB\xAE\x44\xC3\x3B\xA9\xCE\x3B\x04\xC6\x1E\xC9\x10\x2D\xCF\x46\xD3\xCB\x09\x0F\xEC\x31\xCD\xE3\x03\x8D\xDF\xC5\x88\xA6",
|
|
"\xCD\x02\x0E\xEE\x3B\xCD\xE4\x0E\x8D\x9D\xBF\x40\x0D\xCD\x2E\xC8\x38\xC1\x08\xBD\x33\x9C\xC1\x0E\x39\xC6\xCE\x02\x0D\x35\xFE\x95\x5E\xCD\x4A\x2D\xCD\x0A\xC8\xCB\x09\x0E\xEF\x0D\xCF\xE2\x01\x8F\xD0\xCD\x63\xAA\x08\x40\xC8\x37\xC6\x09\xC1\x3B\x9D\xD0\x0F\x42\xDE\xCD\x09\x09\x29\xCA\xCE\x00\x07\x78\x65\xCD\x75\x05\x31\xAC\xC9\x2A\xD2\xC9\xC5\x39\x8B\x8F\x3D\x2E\xD4\xC8\xC5\xC1\x3A\xDC\xCB\xF5\xCA\x79\x39\xC4\xEA\x39\xC5\x54\x35\x85\x89\x6D\x3D\x22\x91\xAC\x3D\x2E\xD1\x3D\xB9\xC6\xCD\x02\xD1\x74\xC3\xA0\x8E\xCD\x15\x33\xC7\x00\x02\x2A\xD8\xCF\x01\x15\x7B\x6E\xCD\x50\x10\xD0\xB0\xAB\x42\xCE\x13\xDC\x36\xA1\x99\x08\x81\xCE\xD0\xDE\x08\xF9\x1D\xD0\xB3\xCB\x81\x8E\xCC\xF3\x23\xD1\x03\x12\x42\xC1\x9A\x89\xC0\x7D\x28\xD2\x93\x19\xD0\x2B\xD6\x31\xD5\x3E\x17\xD4\x23\x17\xC8\x69\xD2\xC8\xD9\x39\x34\xD6\xC9\xB2\xCB\x9E\xDB\x3D\x20\xD2\xB9\x9B\xCE\x20\x36\xD0\x00\x07\x9B\xD3\xCA\x42\x1D\x3E\x3A\xD7\x38\x03\xD3\x92\xC0\x90\x82\x0B\xF7\x29\xD2\xC9\x0B\x48\xC9\xCE\xF1\xC3\x10\x61\x3C\x94\xC1\x0E\x43\xD7\x3A\xC5\xCC\x83\x00\x7F",
|
|
"\x57\xD1\x71\x03\xD2\xE1\xCE\x48\xC9\x08\xFA\x3E\xA5\xD0\x0F\x90\xCA\xCF\x54\xD2\x20\x36\x3F\x32\xD5\x1D\x43\xD2\x8A\xD6\xC5\x01\x45\x8E\x03\x41\x5C\xC1\x6F\xE7\xC4\x00\x03\xD2\x30\xD6\x16\xC7\x41\x3A\x29\x80\x39\xC6\xBD\xB6\xD3\x43\xD7\x2C\xDB\xD3\x81\x0E\x80\x75\x20\x04\x59\xC5\x31\xC9\x48\xC3\x08\x2D\xDA\x5B\x85\xC9\x72\x14\x40\x34\xD1\x20\x3A\xAD\xD5\xAA\xA1\x82\x08\x08\x4C\xD3\x41\x0E\xBB\x83\xB3\x34\xD5\x52\x5E\xAC\x34\xDC\xCB\x06\x0E\x05\x41\xC4\x47\x35\x47\x5E\xAC\x3B\xCF\xBF\x09\x08\x06\x75\x23\x1D\x49\x8B\x92\x35\x1D\x21\xC9\x3F\xC3\x3D\xD4\x43\x40\xC7\x69\x2F\xD6\x2F\xAB\xCF\x63\x45\x8E\x25\x43\x5C\xC9\x93\xE1\xC5\xBD\x8A\x08\xA5\xCC\x53\xF4\xC7\x9E\xCF\x27\x26\x36\x4C\xDB\xD4\x2C\xCE\x31\xC3\x45\xA6\xC5\x1C\x31\x35\x64\xDF\xD5\x09\x0D\x48\xD5\xD5\xF6\x8F\x87\x53\xC1\x50\x1C\x35\x90\xC0\x59\xEF\xB0\x61\xDC\x00\x55\xD5\x81\x01\xBA\xC7\xD5\x25\xD2\xC9\x48\x4C\xAC\xD0\x0F\x57\xC4\xD6\xDA\xD0\x00\x1A\xD2\x5B\xC4\x01\x5E\xD5\x9D\x01\xCB\xE8\xD0\x3C\xD2\xC8\x4C\x45\xAE\xD5\x0D\xD6\xA1\xD7\xE9\xCA\x22\xDF",
|
|
"\x45\x7A\xD1\x14\x7E\xC8\xBE\xDB\xAC\x12\xC8\x04\x2E\xD6\xBF\xAF\x87\x08\x60\xD4\xA8\xCC\xD0\xD4\x91\x12\xC8\x5D\x40\x89\xE9\x45\x2E\xC7\x3A\xCF\xD2\x20\x29\xD6\x41\xD6\x8B\xF5\x44\x24\xD0\x48\xB9\xC4\xEA\x11\xD9\x80\x05\x64\xC9\x6E\x44\xC0\x49\x98\xD2\x21\x3B\xC0\x81\x0D\xB1\xD3\xD7\x5E\x2A\xC9\x01\x08\x56\xC3\xD4\x8D\x28\xB2\x80\x01\xBA\xCE\xD4\x1D\x21\x4C\xFE\xC9\xF5\xC3\x2E\x28\xCE\x9D\xDF\xB5\x23\xC3\x3D\xE5\x48\x01\xD0\x4E\x3C\xD2\xB0\xC3\x17\x61\x3D\x8E\x34\xC8\x8F\xDE\x98\xBA\x48\xCF\xD3\x16\x53\xD2\x20\x3B\xCA\xEA\xC4\x64\xEC\x59\x9D\x10\xCD\x08\xDA\x20\x09\xDA\x1B\xCE\x98\xF7\x4B\xC6\xDF\x13\x78\x3F\x6A\xD3\xDA\x00\x06\xAD\xDC\xB3\x65\x57\xDA\xBE\x49\x17\xE4\xCF\xA8\xD1\x10\x4D\xC3\x40\x0B\x28\x20\xD0\x82\x26\xDA\x81\x08\x4F\x69\xDB\x09\x2D\xDB\x95\xBE\x31\xC8\x4F\xAB\xDB\x1D\x0D\x3F\xD5\xD0\xDB\xDE\xCB\x65\xC1\x08\xF6\x44\xB7\xDE\x0F\x7F\xC4\xDB\x00\x00\x6F\xEB\xC8\x93\xD1\xA1\x57\xDA\x90\x59\xC5\xB3\x3F\x6A\xFC\xC8\x81\x08\xB6\xB4\xDA\x16\x2B\xDC\x01\x0A\x70\xE6\xD9\x2A\x2D\xB8\x83\x08\xA5\xDA\xDB",
|
|
"\x00\x04\x4A\x61\xD9\x68\xD0\xAC\x92\xC9\x98\x5C\xD7\x0A\x0A\x44\xF2\xC8\x69\xDE\x9A\x8E\xCE\x9E\x40\xDD\x09\x0D\x45\xC0\xDC\xD2\xD4\xBA\xB6\xC7\xA4\x48\xDD\x06\x0E\x47\xE3\xDD\xDF\xC2\xAC\xA8\x54\xEC\xC3\x08\x5D\xD3\x76\xC9\x09\xAD\xD6\x8B\xBD\x57\xED\xC2\x08\x73\xD2\x77\xC6\x09\x75\xDD\xA4\x81\x0A\xB6\x5F\xDD\x01\x0C\x01\x50\xC4\xD2\xD2\xB3\x98\xDF\xBB\x48\xDE\x00\x00\x52\xC2\xDF\x81\x08\xA6\xE2\xD2\x41\x0F\x58\xD0\xDA\x55\xD3\xDF\x43\x22\x91\xA2\x58\x24\xC3\x5A\xB9\xC1\x57\xEB\xDD\xFD\xC2\xAC\xCE\x58\x24\xC6\x04\x05\xD9\x77\x8E\xDA\x83\x04\xBA\x94\xD9\xF1\xC0\x00\x5F\x58\x12\xCC\x05\xF4\xD5\x7C\xEB\xDF\x40\x13\xB6\x06\x0D\xA7\x2E\xDB\x0E\x28\xBF\x83\x0A\x51\xDF\xD9\x5A\x27\x7F\xC2\x09\x60\xD6\xBD\x83\x09\xD9\x50\xDE\xDD\xD0\x12\xC2\xE1\x99\xD2\xAC\x92\x07\xC0\xCE\x17\xF6\xDA\x20\x0B\xE0\x22\xD2\x91\x96\x07\x03\xF4\x11\x95\x42\x81\xF4\xDD\x02\xE2\x10\x1A\x07\x05\xF8\x11\x19\x07\x83\xC0\x01\x09\xEC\xBB\xEF\xDE\x27\x02\xE1\xDB\x0D\x03\x22\xE1\x09\xE4\xBC\xFC\xC6\x40\x02\x05\x28\xE6\x3B\x21\x01\x15\xE2\xAF\x8E",
|
|
"\xCC\xDE\x50\xDE\xB7\x42\x83\xF9\xD6\xC7\xC0\xB8\x50\xDF\x37\x5A\xE1\x00\xDE\x31\xDF\x5C\x48\xC1\xBB\x39\xC7\x3D\x57\xDA\x13\xE1\x4F\xEF\xDE\x5A\x02\xC2\xB8\x04\xFD\xC2\xD2\x11\xE1\x20\x13\xE0\xF7\xDE\xC2\x81\x0A\x2E\x02\xE1\xBE\x07\x89\xC3\x08\xA4\x40\xB6\x8A\x0A\xFE\xCE\xDC\x10\x27\x8B\xD6\xDC\x89\xC0\x0C\x5A\x4C\xA7\xB9\xD9\xC2\xD1\x18\x39\x5A\x7F\x1F\x94\xE3\xE2\x63\xC4\x06\xDA\x4D\x8D\xEA\xC2\x89\xC5\x45\x6B\xC2\x41\x16\xC3\x60\xE1\x39\x05\x06\x2D\xE4\x23\x78\xE2\x1B\xEB\xCF\xC7\x02\x3B\x7D\xC2\x34\xEC\xC1\x81\x08\x32\x1A\x4E\x59\xCB\x20\x03\xE4\x00\xE0\x41\x04\xE3\x8D\xCE\xCC\xC9\x01\x86\xC7\x0E\xB4\x40\x89\x8E\xE5\xE9\xCB\xCF\xCD\x02\x92\xC9\x0F\xC0\x47\xB5\x96\xE5\xEB\xCF\xDF\xD1\x02\x93\xC1\x0E\xD3\x45\xC9\x9B\xE2\xC9\xD5\x06\xA2\xE5\x38\x01\x4F\x52\xEB\xBB\x92\xC9\x36\x09\xE5\xDD\x4A\x84\xD6\xE5\x16\xE8\xAA\x86\x09\x37\x10\xE5\xD5\x08\x3F\x6C\xE4\x25\xB2\x91\xE1\x04\x2E\xE1\x0A\x1B\x53\x97\xD4\xDE\x89\xC5\x0E\x3F\xE7\xB9\xB2\xE5\xF2\xCE\x31\xE9\x06\x11\xED\x0E\x7C\xE1\x40\x03\x53\x9D\xE4\x7C\xC5\xE4",
|
|
"\x00\x0F\x0E\x22\xE3\x3C\x0E\xE6\x00\x01\x51\x51\xE6\x12\xDE\x98\xF5\x06\x08\xF9\x07\xD8\xE2\x54\x57\xDB\xA7\x26\x10\x16\xE6\x2D\xDB\x07\xD8\xE3\x3B\x3E\xDC\x3B\xD4\xCE\xB6\xCA\x63\xDD\x07\xE9\xE6\x3B\x05\x57\x5C\xCD\xCE\xA5\x4C\x1D\xF1\xE7\xBC\xC8\x1E\x75\xE7\x6D\xD3\xCD\x81\x01\xFE\x4D\xC4\x00\x07\x78\xEC\xE6\x71\xDE\x98\x83\x03\x3F\xE5\x10\xDC\x55\x8E\x3B\xE6\x75\xD2\x91\x85\x03\x41\xF5\x13\xDF\x52\xA1\xF5\xE1\xF5\xC7\x00\x0F\xEB\x80\x09\x57\x12\xEB\x87\xEB\xCF\x04\x06\xD1\xCE\x13\xF3\xC3\xE8\x09\x0F\x4D\xEF\xDF\x05\x0D\xD1\xB8\xA1\x49\xE1\x08\xF8\x54\x9E\xD2\xE6\x93\xDF\x00\x27\xEB\xF2\x6E\xE9\x0B\x5A\xA5\xDC\xE7\xF5\xC3\x01\x2E\xE9\x05\x0E\xE9\x14\x59\x17\xC7\xC5\x72\xE2\x91\x97\x01\xFE\x59\xBF\x0A\x09\x63\x75\x23\x9D\xEE\xCE\xEB\xCC\x06\x1F\xE9\x05\x16\x7B\xDB\xC4\xA2\xE6\xCF\x8E\xCD\x06\x08\xEA\x75\x15\x66\x43\xEA\x53\xE8\xB9\x9A\x00\x54\xE3\x10\x41\x5B\xAA\xED\xE4\xC7\xCB\x01\x57\xEA\x93\x00\xDF\x76\xD4\xA9\xF7\x64\x7D\xDE\xD5\xB4\x11\xD1\x5A\xEA\xBC\xE6\x31\xDD\x01\xB2\xE8\x23\x66\xDD\x58\xEA\x08\xD5",
|
|
"\xDE\x64\xDE\x00\xB6\xEF\x27\x54\x58\x5A\xF9\xAC\x12\xCF\x03\x34\xEA\x10\x0E\xD2\xD6\x5A\x4E\xEB\xE9\x98\xDA\x04\x34\xEB\x11\x0E\xD2\xE8\xDF\x5F\xF3\xE9\xC2\xD5\x04\x34\xEA\x13\x0E\xD2\xF1\xDE\x58\xCA\x08\x80\xC3\x3D\xE8\x00\xBA\xE3\x2E\x63\xCB\x40\x02\xEB\x98\xD9\x05\x39\x5E\x6E\x9D\x02\x14\xEE\x77\x15\xB4\x06\x09\xB2\xC2\xD6\x17\x0E\xD9\xD1\x14\x68\xF7\xEC\x12\xCF\x05\x1B\xEC\xD5\xA5\xDA\xC9\x0D\x5B\x3C\xE9\x8E\xCC\x06\x39\x5E\x1A\xC6\x10\x0A\x04\x36\xEF\xED\x45\xEA\x58\xF7\x01\xD9\xE5\x20\x73\xDE\x80\xD8\xED\x4D\xEB\x3D\xFA\x00\xDE\xE5\x27\x0F\x07\x6D\xF4\xEA\xB6\xC5\x07\x04\xEF\x01\x17\xB6\x39\xC4\x70\xE1\x08\x25\xE5\x8A\xC0\x00\x20\x0B\xDC\xCE\x13\x24\x07\xEE\xBE\x62\x22\xC3\x03\xEA\xE4\x23\x15\x04\x76\xE9\xEB\xEB\xCE\x08\x1C\xEE\x1C\x17\x09\x5F\xEF\x30\xEE\xCC\x49\x03\xBC\xFF\x12\xB7\x5E\xDC\xC9\xE7\x7A\xCC\x02\xEA\xEF\x09\x2E\xE9\x4D\x03\x8A\x4F\xEC\x00\x0A\xE2\xD2\xE9\x0A\x2A\xEE\x2A\x0E\xD2\xA7\xE3\x6F\xFF\xD0\xEB\xCE\x0A\x2A\xEF\x2C\x0E\xD2\xA1\x07\x28\x5D\x2B\x09\x0E\x9C\xEF\xDF\x2D\x0E\xD2\xDB\x0C",
|
|
"\x29\x18\xE6\x08\xF0\x22\xCE\xCD\x2E\x0D\xE0\xDE\x0F\x0D\xF9\xCF\x01\x09\xC2\xC3\x09\x4F\xE2\xDD\xDF\x01\x85\xE7\x0E\x7E\x59\x17\xDA\xF1\x1D\xBB\x9E\xE1\x03\x87\xE9\x0E\x84\x5A\xC4\xC4\xE9\xF5\xC3\x06\x27\xF1\x70\x12\x5C\x2A\xF1\xBB\xCE\xCD\x32\x0E\xE2\xC5\x0D\xE8\x51\xF1\xE0\xEA\x58\xE7\x03\x1A\xF0\x1D\x2A\x5C\x8E\xE7\xEF\xEB\xC9\x0D\x3C\xF1\xEA\x02\x78\xBF\xF0\xF7\xCE\xCC\x6B\x06\xA5\xED\x02\x97\xE5\x0B\x07\xF0\x60\xF6\xC5\x6F\x06\xA5\xF1\x02\x97\xEE\xC4\x82\xD3\x88\xE1\x08\x54\xE5\x96\xC3\x09\x39\x0E\xD2\xF5\x02\x4B\xFB\x05\xA3\x46\x2D\xC3\x09\x47\xCB\x9E\xF7\x01\x6B\xF8\x16\x62\xF3\x49\x52\xC8\x3C\x0B\xDA\x89\x08\x1F\x07\xF3\xC5\x0D\xB2\x09\x09\x2B\xF8\xB9\xA3\x2E\x42\x04\xF3\xC2\xD5\x0F\x30\xF2\x7F\x17\x89\x83\x0A\x9C\xEB\xCF\x7E\x05\xCD\xC6\x08\x41\x0B\xE7\xD5\x0E\x69\x30\xED\xEB\xCB\x10\x02\xF4\x27\x19\xC5\x82\xD3\xA1\xF9\xED\xD3\xE7\x10\x0B\xF4\x1A\x1A\xC6\x90\xC7\xA3\xE1\xEE\xC2\xD3\x11\x13\xF4\x1C\x1B\xC7\x8E\xF4\x72\xEF\xDF\x8F\x03\xD3\xFF\x13\x43\xEE\xE9\xDB\xEB\x7A\xD3\x04\xA2\xF3\x3B\x0B\x07\x51",
|
|
"\x47\xE9\xE3\xEA\x63\xD7\x04\xA9\xF6\x3B\x0E\x06\x56\xF3\xD1\xC2\xD7\x26\x11\xF5\xC7\x09\x94\xE5\xF4\x83\x01\xD7\x98\xDF\x27\x18\xF5\xC9\x0C\x1A\x34\xF5\x90\xE2\x91\xA3\x06\xA8\xE7\x05\x2E\xEF\x1A\x22\xE1\x56\xF7\xDF\x92\xC9\x2A\x02\xF5\xAD\x06\xA5\xDB\x07\x65\xF0\xE0\xC2\xD7\x2B\x02\xF5\xB3\x06\xA5\xDF\x06\x11\xE1\x98\x83\x09\x6A\x2E\xCC\xB5\x03\xC8\xCC\x12\x4D\xC3\x10\x23\xC5\x1E\xFD\x20\xE4\xF2\x20\x0A\xCD\x73\xFA\x44\x66\xF7\x40\x11\x2D\x8E\xCF\x16\x22\xF7\x02\x1B\xEE\xEF\xF6\x44\xD9\x05\xF3\xF5\x4E\x2A\xC5\x81\x0C\x5B\x0E\xCF\x2E\x14\xEB\xBC\x01\xDF\xC6\x09\x7E\xF6\x10\x6E\xF7\x34\xE3\x17\xE3\x00\x1E\x44\xF9\x81\x05\xEF\x87\xFB\xB4\x04\x07\xF0\x45\x32\xC3\x08\x5C\xCC\xEE\xD0\x0E\x2F\x02\xF8\x13\xFA\x21\x3A\x2C\xC7\xC0\x0C\x05\xF4\x93\x06\x2F\x88\xF1\x8D\xF9\x5F\xDD\xBA\x10\x45\xE4\x24\xC0\xF9\x03\x0A\xC1\xD2\xEE\x63\x03\xF2\x85\x13\x32\xE7\xF9\x9D\xDE\x31\xCB\x07\x96\xF5\x27\x4D\xE4\xCC\xE3\xAC\x12\xC8\x1A\x34\xF9\x01\x11\x0F\x51\xE0\x00\x08\xF9\xC9\xD3\x3D\xD5\x07\x9D\xFE\x24\x76\x06\xCF\xE0\xFA\x0C\xE3",
|
|
"\x9A\xDA\x06\xA2\xF4\x23\x68\xE7\xD5\xC8\xFA\x14\xE6\x31\xDF\x06\xA6\xF0\x83\xA2\xF4\xD4\xFC\xF0\x5A\xF2\x20\x24\x06\xAA\xFF\x27\x04\x02\xD5\xEA\x08\x58\xF8\x15\xDC\xD2\xAE\xFB\x1D\x08\x03\xD7\xF9\xB0\xD3\xE6\x1D\x24\xFA\xEF\x0C\x00\x67\xFA\x8A\xB8\xDC\xF3\x03\xED\xC7\x0E\x08\x0E\xF6\xB4\xB2\xC9\xD8\x07\x72\xF9\x39\x14\x01\xBA\xF2\xB5\x92\xC9\x3F\x19\xFB\xC1\x0F\xA8\xF7\xF8\x83\x01\xDD\xD9\xFA\x5C\x9D\x5E\x24\xFD\x9B\xBC\xFA\xE8\xE2\x91\x87\x00\xE2\xE5\x10\x7C\xEB\xF0\xCB\xD4\x89\xCC\x00\x0F\xFD\x9D\x04\x01\x8B\xFC\xA1\xCE\xCD\x08\x06\xF9\x83\x13\x64\xF2\xFC\xB1\xAA\x22\xD6\x01\xCE\xFE\x24\x2C\x01\xE6\xE1\x30\x5C\xED\x7B\x40\xEB\x3A\x10\xF5\xBD\xCE\xB0\xDC\x00\xAA\xFA\x6B\x10\xFB\xE6\xD6\x8B\x9D\x00\xE9\xF4\x11\x30\x01\xF3\xF4\xFD\xF7\xD2\x02\x37\xFC\x8E\x12\xED\xA0\xF9\x20\x3B\xFC\xE9\xE7\x02\x3E\xFF\x9F\x18\x01\x99\xFD\xD7\xD5\xD8\xE3\xFB\x1D\x3C\x01\xF2\xF2\xC8\x31\x04\xF9\xDE\x0E\xEA\xE1\xFC\x80\x02\xF2\xEF\xDF\x36\x02\xFA\xC7\x0E\x22\x09\xF9\xE7\xCE\xB0\xDB\x01\xB1\xFC\x73\x10\xFA\x91\xE2\xDD\xBC\x02\xF1",
|
|
"\xE1\x02\xDD\x58\x81\x48\x02\xAE\xF3\xFE\xDA\xEE\xF1\xE8\x02\xE9\xFD\x0E\xEC\xFE\xF7\xE2\xAC\xCA\x02\xF1\xEF\x02\xF1\xF9\x21\x12\x03\xF9\xFF\x5A\x92\xC9\x14\x06\xFE\x56\x01\xFE\x76\x10\x17\x01\xFC\x7E\xC2\x6E\x98\x58\x01\xC6\x7D\x17\x02\x00\x83\x04\x5C\x01\x01\x8D\x59\x52\x64\x5F\x02\xF1\x74\x06\x0B\x80\x02\x06\x89\x7F\xF4\x55\x7B\xD3\x72\x19\x06\xFC\x6B\x01\x14\x81\x40\x06\x06\x0E\x80\x02\x05\x96\x72\xF6\x43\x04\x6D\x02\xF1\x72\x07\x1D\x80\x00\x01\x92\x77\x01\x88\x76\xD3\x70\x1D\x06\xFC\x79\x01\x28\x80\x1C\x0C\xF5\x6B\x66\x06\x07\xAC\x1E\x98\x7B\x01\xE1\x7E\x41\x0C\x07\x28\x80\x5E\x79\x1D\x16\x5F\x09\x04\xE9\x16\x63\x6E\x07\x39\x80\xC9\x0F\x6C\x62\x10\x3F\x80\x15\x7D\x11\x1F\x5F\x30\x2A\x74\x72\x16\x18\xFA\x46\x04\x4B\x81\x12\x83\x37\x2E\x7E\x02\x06\x0D\x8B\x9E\x7F\x01\x44\x82\x40\x00\x08\x28\x80\x76\x00\x5D\x7B\x8D\x67\x1B\x12\x66\x20\x09\x05\xB8\x08\x66\x79\x1D\x1F\x05\xAA\x2D\x12\x67\x20\x03\x06\xBF\x09\x6C\x7A\x80\x67\x06\x81\x04\xD8\x6B\x7A\x64\x08\x2B\x81\xDB\x07\x1E\x0A\xDE\x45\x67\x02\x05\x10\x8B\x9E",
|
|
"\x45\x02\x74\x83\xB4\x0A\x60\x09\x04\xAB\x1A\x63\x66\x08\x2B\x81\x87\x00\x0A\x81\xE8\x75\x11\xCF\x66\x40\x03\x61\x3B\x6F\xE8\x2A\x42\x0F\x8E\x52\x81\x5A\x0F\x23\x86\xC0\x52\x64\x89\x03\x1A\x8A\x08\x28\x80\x7F\x00\x5D\x7D\x9D\x4A\x82\x4D\x80\x04\x1B\x09\x81\x04\x92\x82\xC3\x70\x41\x0B\x82\x06\x06\x1E\x82\xAC\x4C\x02\x7D\x81\xB4\x0E\xFD\x42\x04\x7F\x80\x24\x8C\x39\x17\x18\x09\x04\x7C\x6E\x0A\x86\x04\x8D\x00\x0A\x8B\x1D\x32\x82\x03\x06\x29\x83\xCD\x4F\x02\xA9\x80\xB7\x08\x0B\x82\x04\x33\x18\x23\x8C\x45\x01\x83\x3A\x81\x27\x87\x42\x04\x83\xFC\x7A\x44\x60\x09\x2B\x81\x91\x00\x0A\x80\x08\x34\x75\xF8\x65\x32\x8E\x98\x53\x02\x6B\x80\x25\x08\x02\x81\x02\x74\x76\x8F\x10\x04\x95\x70\xBD\x80\xB6\x03\x72\x45\x83\xC2\x81\x11\x1F\x0D\x83\x04\xD1\x82\x28\x87\x42\x01\x68\xD7\x6E\x31\x8D\x41\x1E\x64\x06\x05\x9A\x11\x0E\x94\x65\xB6\x82\x77\x0E\x0E\xA5\x82\x12\x65\x26\x0D\x0D\xAB\x0B\xF3\x83\x40\x0A\xA0\x73\x82\xC9\x0F\x3E\x83\x10\x27\x64\xFC\x83\xED\x0E\x0F\x82\x04\x0B\x7F\x34\x7A\x09\x2B\x81\x9B\x00\x0A\x84\xE8\x75\x11\x71\x19",
|
|
"\x42\x05\x10\xA6\x6C\x9D\x03\x1A\x8E\x09\x28\x80\x8A\x79\x1D\x10\x10\xB9\x82\x12\x64\x28\x07\x0F\xBE\x0B\x40\x6A\x40\x07\x11\xA6\x83\x1D\x11\x47\x81\x10\x0D\x84\x01\x86\x00\x15\xA7\x43\x04\xE8\x80\x23\x77\x42\x3F\x69\x03\x04\x3B\x8A\x12\x9D\x10\x89\x69\x1E\x82\x91\x61\x02\x1B\x87\xC3\x01\x13\x81\x04\xA4\x69\x49\x81\x41\x39\x84\x03\x05\xAD\x6A\x13\xA3\x0B\x3C\x84\x41\x82\x91\x62\x02\x6B\x83\x28\x08\x02\x84\x02\x74\x76\xAB\x63\xF0\x52\x64\xA5\x03\x1A\x86\x0A\x28\x80\x85\x00\x5D\x7E\x13\x98\x84\x8E\x64\x2A\x05\x13\x8C\x09\xBD\x69\x40\x03\x15\xA0\x84\x4A\x11\x56\x80\x00\x0A\x85\x2F\x86\x12\x16\xAC\x53\x82\x8E\x65\x2A\x0B\x06\xAA\x02\xF1\x83\x71\x01\x08\xB4\x82\x12\x64\x2B\x07\x15\x85\x08\x43\x67\x40\x06\x05\x82\x6B\xAD\x03\x1A\x8E\x0A\x29\x85\xC9\x07\x5C\x82\x10\x0E\x6B\xEB\x64\x2C\x0D\xBD\x34\x76\x4E\x09\xAD\x16\x10\x3A\x1A\xEF\x82\xD6\x02\x18\x83\x04\x71\x81\x58\x8C\x45\x04\x86\x06\x04\x53\x6B\x9E\x73\x02\x78\x84\xB6\x09\x18\x82\x04\x8E\x86\xB0\x65\x0B\x11\x86\xEB\x09\xB0\x13\x18\xAA\x83\xEB\x0A\x21\x04\xD7\x5A",
|
|
"\x86\x88\x84\x67\x8E\x2F\x12\x7A\x75\x11\xB3\x10\x08\x92\x64\xB7\x03\x1A\x88\x0B\x28\x80\x88\x00\x5D\x70\xAE\x43\x04\xD5\x19\x61\x8C\x39\x2F\x86\x1D\x72\x68\x85\x44\x11\x1B\xA7\x85\x66\x6B\x06\xBB\x02\x28\x81\x22\x04\xD7\x57\x65\xB0\x86\x6D\x83\x37\x00\x87\xB5\x86\x6C\x81\x3B\x31\x86\x06\x06\xBF\x62\xAC\x7D\x02\x6F\x85\x42\x0A\x08\x34\x75\xC8\x86\x5C\x8F\x9A\x68\x80\xC0\x00\x0A\x8A\xE9\x79\x62\xE7\x6A\x40\x05\x95\x7F\x84\xD3\x09\x76\x81\x10\x1A\x1B\xC6\x85\xF2\x00\x1E\x89\x87\x12\x66\x30\x0D\x1C\xB4\x82\x74\x77\x78\x82\x1D\x8E\x66\xC3\x00\x0A\x85\x0C\x28\x80\x8E\x02\x4B\x74\x75\x46\x04\xDB\x86\x62\x85\x44\x33\x87\x03\x06\x7A\x8C\x15\x9C\x11\x15\x5E\x41\x06\x1A\x9C\x87\xD1\x08\xBC\x62\x10\x2A\x65\x80\x73\x79\x8E\x24\x02\x88\x01\x04\x63\x82\xAC\x48\x03\x06\x8B\x5E\x85\xE0\x4A\x04\x93\x86\xC9\x69\x0C\x0D\x88\x01\x06\x24\x0E\xD2\x44\x88\x03\x06\x82\x8B\x1F\x8F\x0C\x94\x03\x85\x80\x21\x82\x87\x05\x0A\x25\x0E\xD2\x6F\x1B\x09\x06\xB8\x1E\x98\x4A\x03\x7F\x86\xD6\x07\xAF\x43\x04\x24\x88\x80\x8C\x2D\x10\x5C\x06\x06\x89",
|
|
"\x88\xC9\x69\x88\x9C\x0C\x5B\x63\x10\x0A\x87\xD3\x70\x34\x04\x21\xBF\x09\x36\x89\x15\x82\x91\x51\x03\x28\x83\x34\x08\x02\x98\x02\x74\x74\x8E\x81\x10\x3A\x85\xA7\x73\x1A\x86\x0D\x28\x80\x99\x00\x5D\x7D\x75\x46\x04\x18\x8B\x34\x78\x0D\x3B\x88\x9A\x02\x93\x8A\x10\x1A\x88\x26\x6D\x36\x0B\x23\xB7\x7A\x02\x6B\x93\x81\x1A\x8E\x66\xDA\x03\x8E\x8E\x09\x2A\x77\x2F\x1D\x42\x07\x71\x0E\x66\xDB\x03\x8E\x8B\x1D\x22\x5D\x06\x05\x99\x8E\x22\x98\x0B\x07\x6F\x40\x07\x26\xAB\x67\xDC\x00\x66\x8E\x2F\x07\x66\x03\x06\xD0\x16\xA2\x6B\x81\xDF\x02\x9D\x85\x1D\x3A\x89\x06\x05\xD1\x11\x1E\xB7\x0E\x80\x8B\x40\x0D\x74\x03\x8A\x02\x11\xA1\x82\x10\x10\x66\x6F\x8B\xBA\x02\x28\x86\x04\x10\x6E\x4E\x81\x0E\x3E\x89\x41\x05\xA4\x86\x28\xA0\x88\x9C\x0E\xA5\x8B\x28\x98\x8A\xB1\x0C\xA3\x89\xF2\x52\x64\xE3\x02\xF6\x79\x1C\x21\x02\x5C\x7E\xA7\x83\xC0\x52\x64\xE8\x02\xA8\x81\x1C\x26\x02\xA5\x89\xCC\x7B\x9E\x6D\x03\xAA\x89\x71\x0B\x0A\x2D\x8A\x38\x7E\x63\x62\x0F\x31\x8A\xD0\x04\x2C\x09\xBF\x02\x5B\xA6\x89\xD2\x76\xB2\x77\x03\xB8\x89\x75\x06\x0B\x3B\x8A",
|
|
"\x0A\x05\xAF\x87\xC9\x42\x6B\xFC\x01\xB0\x81\x14\x01\x7C\x09\x04\xAF\x80\xF6\x52\x64\x01\x01\x5E\x49\xF8\x5F\x5B\xB4\x88\xFB\x62\x91\x46\x00\xD2\x89\x81\x07\x0C\x15\x8B\x1B\x7A\x44\x6B\x00\x19\x8B\x75\x08\x33\x0C\x2D\xA4\x78\xC2\x68\x04\x00\x2E\x83\x08\xD1\x03\xB8\x8C\xCF\x66\x6C\x15\x03\xB9\x8E\x24\x16\x03\xEA\x8B\x6F\x52\x91\x5A\x00\xEE\x88\x8D\x0B\x0D\x31\x8B\x85\x7F\x08\x8D\xD9\x35\x8B\x38\x08\x38\x08\x2F\x92\x64\x24\x00\xBF\x8F\x27\x25\x03\xFF\x8A\x63\x69\x02\x02\x8C\xDB\x06\x3A\x01\x2F\xB4\x72\xFA\x89\x40\x0E\x02\x08\x8C\xDE\x07\x3B\x0B\x30\x92\x64\x33\x00\xC4\x87\x1C\x34\x03\x13\x8E\x63\x68\x03\x16\x8C\xC9\x05\x3E\x01\x2F\x8F\x81\xC2\x69\x0F\x02\x68\x5B\x07\xFE\x00\x5D\x76\x2C\x94\x81\x26\x6E\x0F\x03\x32\x92\x08\x26\x8D\xAD\x73\xCD\x7F\x00\x1C\x8E\xE6\x56\xFC\x46\x8B\xC3\x7E\xE1\x70\x00\x04\x01\x31\x8D\x71\x05\x00\x33\x8C\x2E\x8E\xC9\x69\x04\x39\x8C\xD0\x06\x02\x0C\x33\x9A\x74\xC2\x6A\x13\x00\x34\x95\x07\x0F\x03\xD0\x8C\xEB\x52\x64\x53\x03\xD1\x81\x14\x14\x00\x4A\x8C\x90\x72\xAC\x58\x01\x4E\x8E\x53\x41",
|
|
"\x35\x82\x04\xAB\x82\xC9\x6D\x05\x2B\x8C\xC7\x06\x07\x0B\x06\x86\x8B\xE4\x7E\xCD\x8E\x05\x02\x8C\x63\x01\x5E\x48\xF5\x1D\x2F\xCE\x88\xB1\x73\xE3\x42\x8C\x6A\x02\xD9\x86\x8B\x28\x8D\xC5\x88\xFD\x73\xCD\x6C\x01\x02\x8D\x1C\x0E\x36\xB5\x66\x70\x8D\x42\x06\x2C\xB8\x77\x36\x8F\x1C\x02\x30\xB8\x01\x77\x8C\x23\x19\x37\x86\x04\x7B\x8E\x44\x6A\x07\x02\x8C\x7F\x01\xE0\x8B\xC5\x43\x8E\x03\x05\xE1\x8E\x98\x41\x02\x02\x8E\x21\x0A\x38\x82\x04\x3D\x00\xE3\x8B\x29\xAC\x80\x26\x6C\x22\x02\x30\x8D\x02\x93\x8D\x40\x03\x04\x16\x8E\x01\x06\xB1\x82\x02\x91\x63\x09\x07\x23\x02\x30\x94\x02\x9D\x8C\x00\x09\x04\x20\x8E\x8F\x64\x06\x86\xB2\x56\x02\x02\x8F\x26\x09\x3A\xB8\x7F\xCD\x8A\x42\x07\x76\x46\x04\x87\x89\xA3\x8E\x2F\x37\x8E\x8D\x8C\xA7\x89\x3C\x39\x8E\x03\x04\xD0\x1E\x98\x5D\x02\x5C\x8C\xB7\x0F\x74\x07\x58\xEB\x66\x27\x05\x3C\x81\x07\x55\x03\x1A\x87\x3C\xB9\x89\x12\x67\x27\x09\x3A\xA1\x02\xA9\x8D\x00\x85\x47\x13\x66\xD0\x8E\x63\x63\x0A\x02\x5A\xA4\x01\xEA\x87\x05\x2B\x81\x70\x5E\x41\x0A\xB1\x6B\x67\xA6\x03\xF2\x8B\x2E\x21\x8F\xD9",
|
|
"\x8F\x7A\x67\x0A\x02\x5A\xA8\x01\xEA\x88\x00\xB5\x11\x9A\x66\x40\x03\x3E\x82\x6B\xAA\x02\xF9\x8E\x2F\x31\x8F\x01\x06\xA2\x86\xB2\x6B\x02\x82\x58\x2B\x09\x3A\x99\x01\xBB\x84\x97\x5E\x7F\x72\x2F\x90\x5C\x97\x58\xC0\x28\x5C\xBE\x6A\xD3\x4B\x78\x67\x0C\xB8\x5F\x3F\x03\x7A\x49\x90\xC3\x6A\x9D\x64\xCB\x36\x46\x54\x6D\x6A\x03\x17\x5C\x43\x8A\x69\xDE\x64\xCB\x37\x30\x05\x92\xB7\x59\x1E\x06\x31\x4E\x58\x25\x6C\x14\x13\x61\xFF\x00\xEC\x55\x7E\x74\x32\xDC\x48\x56\x0B\x7B\x5F\x3F\x31\x32\x0A\x9D\x66\x6D\x90\x97\x5D\x9B\x52\x6C\x62\x05\x33\x92\x54\x02\x6C\x58\x05\x37\x93\xE7\x5D\x66\x4B\x6D\x00\x03\xD2\x6F\x0F\x21\x3F\x58\x04\x10\x97\x7A\x7B\x90\x6D\x5A\x7B\x46\x24\x65\x2F\xDE\x5F\x96\x45\x44\xBE\x09\x00\x01\x06\x6C\x14\x0E\x91\x19\x3C\x2D\x3B\xD7\x12\x91\x65\x4D\x50\x0B\xD7\x37\x90\x57\x92\x15\x95\x45\xA9\x4E\x03\x04\x16\x9B\x45\x96\x4E\xBF\x61\xE1\x41\x46\x8D\x91\xE5\x5C\x19\x90\x89\x66\x91\x71\x6C\x18\x92\x84\x5C\x91\x4A\x6E\x16\x9B\x46\xAA\x91\x69\x92\xE6\x42\x8B\x68\x91\x79\x6C\x1D\x94\x98\x76\x91\x15\x92\x1C\x99\x8B",
|
|
"\x78\x91\x00\x01\x0B\x91\xFF\x2C\x91\xED\x3F\x1F\x90\x47\xB2\x43\x6E\x92\x41\x0F\xFE\x3C\x91\x87\x91\x05\x65\x15\x0A\x92\x49\x05\x0C\x54\xCB\x0E\x92\xAE\x5C\x97\x53\x25\x55\x05\x93\x91\x52\x06\x1C\x74\x32\x97\x91\x50\x09\x49\x91\x52\x58\x06\x07\x65\x15\x1E\x92\x49\x07\x75\x48\x15\x39\x50\x62\x04\x29\x92\x15\x26\x59\x41\x05\x0E\x54\xCB\x2F\x4E\x62\x04\x2B\x92\x15\x2F\x4E\x58\x04\x2C\x91\x14\x32\x92\x1C\x51\x6A\x03\x87\x7D\x04\xBD\x3D\x0B\x99\x4B\x81\x05\xBB\x91\x2D\x93\x10\x3A\x92\x5D\x4F\x05\x5D\x98\x42\x93\x5C\x6C\x2F\x95\x46\xBD\x3E\x4C\x4C\x32\x96\x4C\x82\x68\xB0\x4F\x18\x9A\x4C\xBE\x92\x2A\x63\x32\x96\xA7\x4D\x93\x75\x10\x35\x93\x4D\xBD\x3E\xB4\x30\x36\x92\x4D\x99\x90\x5E\x63\x35\x9D\x66\x7D\x3E\x58\x04\x38\x9B\x4D\x8D\x4D\xE2\x90\x34\x9D\xFE\x1A\x93\xE6\x93\xF8\x37\x42\x44\x93\x07\x93\x3A\x9C\x7D\x7B\x91\xEE\x92\x17\x3E\x18\x2F\x61\x46\x07\x17\x38\x15\x1B\x43\xFC\x45\xF5\x23\x67\x41\x05\x7A\x61\x55\x0D\x4F\x89\x05\x65\x60\x56\x05\x86\x74\x32\x91\x48\x34\x45\xBD\x20\x59\xFA\x5D\x9B\x58\x50\xB8\x4F\x4C\x5B",
|
|
"\x42\x90\x40\x5C\x59\x0E\x96\x02\x5F\x64\x51\x94\x04\x62\x63\x09\x70\x72\x2F\x05\x63\xD3\x8C\x44\x99\x94\x0F\x53\x93\x58\x22\x40\x05\x1F\x95\x4F\x02\xF9\x34\x32\x23\x95\x50\x05\x52\xAC\x60\x11\x90\xF4\x5C\x65\x78\x4C\x4C\x04\x4B\x96\x14\x33\x38\x58\x04\x4C\x91\x14\x32\x94\x16\x53\x93\x54\x53\x9B\x59\x5C\x59\x4F\x44\x13\x7F\x03\x75\x34\x56\x0D\x53\x81\x05\x3F\x94\x97\x50",
|
|
};
|
|
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<ParserGenTokens, RuleParserStates, ParserGenAstInsReceiver>(&ParserGenTokenDeleter, &ParserGenLexerData, &ParserGenRuleParserData)
|
|
{
|
|
};
|
|
|
|
vl::vint32_t RuleParser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const
|
|
{
|
|
return -1;
|
|
};
|
|
|
|
vl::Ptr<vl::glr::parsergen::GlrSyntaxFile> RuleParser::ParseFile(const vl::WString& input, vl::vint codeIndex) const
|
|
{
|
|
return ParseWithString<vl::glr::parsergen::GlrSyntaxFile, RuleParserStates::File>(input, this, codeIndex);
|
|
};
|
|
|
|
vl::Ptr<vl::glr::parsergen::GlrSyntaxFile> RuleParser::ParseFile(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex) const
|
|
{
|
|
return ParseWithTokens<vl::glr::parsergen::GlrSyntaxFile, RuleParserStates::File>(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<vl::glr::parsergen::GlrEnumItem>(), 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<vl::glr::parsergen::GlrEnum>(), 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<vl::glr::parsergen::GlrClassProp>(), 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<vl::glr::parsergen::GlrClass>(), 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<vl::glr::parsergen::GlrAstFile>(), 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<GlrType>& 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<GlrClassProp>& 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<GlrEnumItem>& 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<GlrType*>(from), static_cast<GlrType*>(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<GlrType*>(from), static_cast<GlrType*>(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<GlrType> TypeAstVisitor::CopyNode(GlrType* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
node->Accept(static_cast<GlrType::IVisitor*>(this));
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrType>();
|
|
}
|
|
|
|
vl::Ptr<GlrEnumItem> TypeAstVisitor::CopyNode(GlrEnumItem* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrEnumItem>();
|
|
}
|
|
|
|
vl::Ptr<GlrClassProp> TypeAstVisitor::CopyNode(GlrClassProp* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrClassProp>();
|
|
}
|
|
|
|
vl::Ptr<GlrAstFile> TypeAstVisitor::CopyNode(GlrAstFile* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
Visit(node);
|
|
this->result->codeRange = node->codeRange;
|
|
return this->result.Cast<GlrAstFile>();
|
|
}
|
|
|
|
vl::Ptr<GlrClass> TypeAstVisitor::CopyNode(GlrClass* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrType*>(node)).Cast<GlrClass>();
|
|
}
|
|
|
|
vl::Ptr<GlrEnum> TypeAstVisitor::CopyNode(GlrEnum* node)
|
|
{
|
|
if (!node) return nullptr;
|
|
return CopyNode(static_cast<GlrType*>(node)).Cast<GlrEnum>();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\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<GlrType*>(node));
|
|
PrintFields(static_cast<GlrEnum*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void TypeAstVisitor::Visit(GlrClass* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"Class", node);
|
|
PrintFields(static_cast<GlrType*>(node));
|
|
PrintFields(static_cast<GlrClass*>(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<GlrType::IVisitor*>(this));
|
|
}
|
|
|
|
void TypeAstVisitor::Print(GlrEnumItem* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"EnumItem", node);
|
|
PrintFields(static_cast<GlrEnumItem*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void TypeAstVisitor::Print(GlrClassProp* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"ClassProp", node);
|
|
PrintFields(static_cast<GlrClassProp*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void TypeAstVisitor::Print(GlrAstFile* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(L"AstFile", node);
|
|
PrintFields(static_cast<GlrAstFile*>(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<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrType*>(node));
|
|
Traverse(static_cast<GlrEnum*>(node));
|
|
for (auto&& listItem : node->items)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Traverse(node->name);
|
|
Finishing(static_cast<GlrEnum*>(node));
|
|
Finishing(static_cast<GlrType*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void TypeAstVisitor::Visit(GlrClass* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrType*>(node));
|
|
Traverse(static_cast<GlrClass*>(node));
|
|
Traverse(node->baseClass);
|
|
for (auto&& listItem : node->props)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Traverse(node->name);
|
|
Finishing(static_cast<GlrClass*>(node));
|
|
Finishing(static_cast<GlrType*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void TypeAstVisitor::InspectInto(GlrType* node)
|
|
{
|
|
if (!node) return;
|
|
node->Accept(static_cast<GlrType::IVisitor*>(this));
|
|
}
|
|
|
|
void TypeAstVisitor::InspectInto(GlrEnumItem* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrEnumItem*>(node));
|
|
Traverse(node->name);
|
|
Finishing(static_cast<GlrEnumItem*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void TypeAstVisitor::InspectInto(GlrClassProp* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrClassProp*>(node));
|
|
Traverse(node->name);
|
|
Traverse(node->propTypeName);
|
|
Finishing(static_cast<GlrClassProp*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
}
|
|
|
|
void TypeAstVisitor::InspectInto(GlrAstFile* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrAstFile*>(node));
|
|
for (auto&& listItem : node->types)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Finishing(static_cast<GlrAstFile*>(node));
|
|
Finishing(static_cast<vl::glr::ParsingAstBase*>(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<ParserGenTokens, TypeParserStates, ParserGenAstInsReceiver>(&ParserGenTokenDeleter, &ParserGenLexerData, &ParserGenTypeParserData)
|
|
{
|
|
};
|
|
|
|
vl::vint32_t TypeParser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const
|
|
{
|
|
return -1;
|
|
};
|
|
|
|
vl::Ptr<vl::glr::parsergen::GlrAstFile> TypeParser::ParseFile(const vl::WString& input, vl::vint codeIndex) const
|
|
{
|
|
return ParseWithString<vl::glr::parsergen::GlrAstFile, TypeParserStates::File>(input, this, codeIndex);
|
|
};
|
|
|
|
vl::Ptr<vl::glr::parsergen::GlrAstFile> TypeParser::ParseFile(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex) const
|
|
{
|
|
return ParseWithTokens<vl::glr::parsergen::GlrAstFile, TypeParserStates::File>(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<vl::glr::ParsingAstBase> 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<vl::glr::ParsingAstBase> 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<vl::glr::ParsingAstBase> ParserGenAstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& 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<CppSyntaxGenOutput> GenerateSyntaxFileNames(SyntaxSymbolManager& manager, Ptr<CppParserGenOutput> 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<CppParserGenOutput> 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<vl::regex::RegexToken>& 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<CppParserGenOutput> 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<AstClassSymbol*> 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<vl::regex::RegexToken>& 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<CppParserGenOutput> output, collections::Dictionary<WString, WString>& 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<StateSymbol*>& 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<StateSymbol*>& order)
|
|
{
|
|
Group<RuleSymbol*, StateSymbol*> groupedStates;
|
|
{
|
|
List<StateSymbol*> 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<WString> 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<StateBuilder>& elements)
|
|
{
|
|
/*
|
|
* S --(a)--> ? --(b)--> E
|
|
*/
|
|
CHECK_ERROR(elements.Count() > 0, L"vl::glr::parsergen::AutomatonBuilder::BuildSequenceSyntax(List<StateBuilder>&)#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<StateBuilder>& elements)
|
|
{
|
|
/*
|
|
* +--(a)--+
|
|
* | V
|
|
* S --+--(b)--+--> E
|
|
*/
|
|
|
|
CHECK_ERROR(elements.Count() > 0, L"vl::glr::parsergen::AutomatonBuilder::BuildAlternativeSyntax(List<StateBuilder>&)#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<vint32_t>& flags, const Func<WString(vint32_t)>& 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<vint32_t>& flags, RuleSymbol* rule, const Func<WString(vint32_t)>& 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:<skip>";
|
|
endPoses.Add(pair.end, clauseDisplayText.Length());
|
|
return pair;
|
|
}
|
|
|
|
AutomatonBuilder::StatePair AutomatonBuilder::BuildLriClauseSyntax(StateBuilder useOrLriSyntax, bool optional, collections::List<StateBuilder>&& 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<StateBuilder> 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<RuleSymbol*> 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<StateSymbol*> 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<EdgeSymbol*> edgesInOrder;
|
|
List<EdgeSymbol*> returnEdgesInOrder;
|
|
List<vint32_t> returnIndicesInOrder;
|
|
List<AstIns> 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<StateSymbol*> EmptyStates;
|
|
|
|
Ptr<SortedList<StateSymbol*>> 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<StateSymbol*>);
|
|
states->Add(state);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
const SortedList<StateSymbol*>& 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<StateSymbol*> StateSymbolSet::EmptyStates;
|
|
|
|
/***********************************************************************
|
|
CompactSyntaxBuilder
|
|
***********************************************************************/
|
|
|
|
class CompactSyntaxBuilder
|
|
{
|
|
using StateList = collections::List<Ptr<StateSymbol>>;
|
|
using EdgeList = collections::List<Ptr<EdgeSymbol>>;
|
|
protected:
|
|
RuleSymbol* rule;
|
|
StateList& newStates;
|
|
EdgeList& newEdges;
|
|
Dictionary<StateSymbol*, StateSymbol*> oldToNew;
|
|
Dictionary<StateSymbol*, StateSymbol*> newToOld;
|
|
|
|
void BuildEpsilonEliminatedEdgesInternal(
|
|
StateSymbol* walkingOldState,
|
|
StateSymbol* newState,
|
|
StateSymbol* endState,
|
|
List<StateSymbol*>& visited,
|
|
List<EdgeSymbol*>& 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"<BuildCompactNFAInternal>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<StateSymbol*>& visited)
|
|
{
|
|
List<EdgeSymbol*> 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<EdgeSymbol*> 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<RuleSymbol*, EdgeSymbol*> prefixEdges;
|
|
List<EdgeSymbol*> 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"<EliminateSingleRulePrefix>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<RuleSymbol*> 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<AstIns> 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<StateSymbol*> 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<StateSymbol*, EdgeSymbol*>& orderedEdges, collections::List<EdgeSymbol*>& 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"<BuildCrossReferencedNFAInternal>LrInject is impossible from a start state");
|
|
break;
|
|
default:
|
|
CHECK_FAIL(L"<BuildCrossReferencedNFAInternal>Unhandled!");
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::FixLeftRecursionInjectEdge
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::FixLeftRecursionInjectEdge(StateSymbol* startState, EdgeSymbol* injectEdge)
|
|
{
|
|
// search for all qualified placeholder edge starts from inject targets
|
|
List<EdgeSymbol*> 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<List<StateSymbol*>> endingStatesArray(placeholderEdges.Count());
|
|
Array<List<EdgeSymbol*>> 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<vint32_t, vint>;
|
|
using InputValue = Tuple<vint, EdgeSymbol*, EdgeSymbol*>;
|
|
Group<InputKey, InputValue> 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<EdgeSymbol*>* 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<Entry, vint> 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<vint> 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<List<InputValue>&>(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<AstIns> 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<StateSymbol*> states;
|
|
GetStatesInStableOrder(states);
|
|
|
|
Group<StateSymbol*, EdgeSymbol*> orderedEdges;
|
|
for (auto state : states)
|
|
{
|
|
List<EdgeSymbol*> 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<EdgeSymbol*> 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|