mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-02-06 20:11:41 +08:00
15942 lines
558 KiB
C++
15942 lines
558 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)
|
|
{
|
|
auto globalName = manager.Global().name;
|
|
for (auto group : manager.FileGroups().Values())
|
|
{
|
|
auto astOutput = Ptr(new CppAstGenOutput);
|
|
astOutput->astH = globalName + group->Name() + L".h";
|
|
astOutput->astCpp = globalName + group->Name() + L".cpp";
|
|
astOutput->builderH = globalName + group->Name() + L"_Builder.h";
|
|
astOutput->builderCpp = globalName + group->Name() + L"_Builder.cpp";
|
|
astOutput->emptyH = globalName + group->Name() + L"_Empty.h";
|
|
astOutput->emptyCpp = globalName + group->Name() + L"_Empty.cpp";
|
|
astOutput->copyH = globalName + group->Name() + L"_Copy.h";
|
|
astOutput->copyCpp = globalName + group->Name() + L"_Copy.cpp";
|
|
astOutput->traverseH = globalName + group->Name() + L"_Traverse.h";
|
|
astOutput->traverseCpp = globalName + group->Name() + L"_Traverse.cpp";
|
|
astOutput->jsonH = globalName + group->Name() + L"_Json.h";
|
|
astOutput->jsonCpp = globalName + group->Name() + L"_Json.cpp";
|
|
parserOutput->astOutputs.Add(group, astOutput);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
Utility
|
|
***********************************************************************/
|
|
|
|
void CollectVisitorsAndConcreteClasses(AstDefFileGroup* group, List<AstClassSymbol*>& visitors, List<AstClassSymbol*>& concreteClasses)
|
|
{
|
|
for (auto name : group->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(group->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(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer);
|
|
extern void WriteTypeDefinitions(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer);
|
|
extern void WriteVisitorImpl(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer);
|
|
extern void WriteTypeReflectionDeclaration(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer);
|
|
extern void WriteTypeReflectionImplementation(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer);
|
|
|
|
/***********************************************************************
|
|
WriteAstHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteAstHeaderFile(AstDefFileGroup* group, stream::StreamWriter& writer)
|
|
{
|
|
WriteFileComment(group->Name(), writer);
|
|
auto&& headerGuard = group->Owner()->Global().headerGuard;
|
|
if (headerGuard != L"")
|
|
{
|
|
writer.WriteString(L"#ifndef ");
|
|
writer.WriteLine(headerGuard + L"_" + wupper(group->Name()) + L"_AST");
|
|
writer.WriteString(L"#define ");
|
|
writer.WriteLine(headerGuard + L"_" + wupper(group->Name()) + L"_AST");
|
|
}
|
|
else
|
|
{
|
|
writer.WriteLine(L"#pragma once");
|
|
}
|
|
writer.WriteLine(L"");
|
|
for (auto include : group->Owner()->Global().astIncludes)
|
|
{
|
|
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(group->cppNss, writer);
|
|
WriteTypeForwardDefinitions(group, prefix, writer);
|
|
WriteTypeDefinitions(group, prefix, writer);
|
|
WriteNssEnd(group->cppNss, writer);
|
|
}
|
|
{
|
|
List<WString> refNss;
|
|
refNss.Add(L"vl");
|
|
refNss.Add(L"reflection");
|
|
refNss.Add(L"description");
|
|
WString prefix = WriteNssBegin(refNss, writer);
|
|
WriteTypeReflectionDeclaration(group, prefix, writer);
|
|
WriteNssEnd(refNss, writer);
|
|
}
|
|
|
|
if (headerGuard != L"")
|
|
{
|
|
writer.WriteString(L"#endif");
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteAstCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteAstCppFile(AstDefFileGroup* group, const WString& astHeaderName, stream::StreamWriter& writer)
|
|
{
|
|
WriteFileComment(group->Name(), writer);
|
|
writer.WriteLine(L"#include \"" + astHeaderName + L"\"");
|
|
writer.WriteLine(L"");
|
|
{
|
|
WString prefix = WriteNssBegin(group->cppNss, writer);
|
|
writer.WriteLine(L"/***********************************************************************");
|
|
writer.WriteLine(L"Visitor Pattern Implementation");
|
|
writer.WriteLine(L"***********************************************************************/");
|
|
WriteVisitorImpl(group, prefix, writer);
|
|
WriteNssEnd(group->cppNss, writer);
|
|
}
|
|
{
|
|
List<WString> refNss;
|
|
refNss.Add(L"vl");
|
|
refNss.Add(L"reflection");
|
|
refNss.Add(L"description");
|
|
WString prefix = WriteNssBegin(refNss, writer);
|
|
WriteTypeReflectionImplementation(group, prefix, writer);
|
|
WriteNssEnd(refNss, writer);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteAstUtilityHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteAstUtilityHeaderFile(
|
|
AstDefFileGroup* group,
|
|
Ptr<CppAstGenOutput> output,
|
|
const WString& extraNss,
|
|
stream::StreamWriter& writer,
|
|
Func<void(const WString&)> callback
|
|
)
|
|
{
|
|
WriteFileComment(group->Name(), writer);
|
|
auto&& headerGuard = group->Owner()->Global().headerGuard;
|
|
if (headerGuard != L"")
|
|
{
|
|
writer.WriteString(L"#ifndef ");
|
|
writer.WriteLine(headerGuard + L"_" + wupper(group->Name()) + L"_AST_" + wupper(extraNss));
|
|
writer.WriteString(L"#define ");
|
|
writer.WriteLine(headerGuard + L"_" + wupper(group->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, group->cppNss);
|
|
cppNss.Add(extraNss);
|
|
WString prefix = WriteNssBegin(cppNss, writer);
|
|
callback(prefix);
|
|
WriteNssEnd(cppNss, writer);
|
|
}
|
|
if (headerGuard != L"")
|
|
{
|
|
writer.WriteString(L"#endif");
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteAstUtilityCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteAstUtilityCppFile(
|
|
AstDefFileGroup* group,
|
|
const WString& utilityHeaderFile,
|
|
const WString& extraNss,
|
|
stream::StreamWriter& writer,
|
|
Func<void(const WString&)> callback
|
|
)
|
|
{
|
|
WriteFileComment(group->Name(), writer);
|
|
writer.WriteLine(L"#include \"" + utilityHeaderFile + L"\"");
|
|
writer.WriteLine(L"");
|
|
{
|
|
List<WString> cppNss;
|
|
CopyFrom(cppNss, group->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 group : manager.FileGroups().Values())
|
|
{
|
|
writer.WriteLine(L"#include \"" + output->astOutputs[group]->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(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, collections::Dictionary<WString, WString>& files)
|
|
{
|
|
{
|
|
WString fileH = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteAstHeaderFile(group, writer);
|
|
});
|
|
|
|
WString fileCpp = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteAstCppFile(group, output->astH, writer);
|
|
});
|
|
|
|
files.Add(output->astH, fileH);
|
|
files.Add(output->astCpp, fileCpp);
|
|
}
|
|
|
|
{
|
|
WString fileH = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteAstBuilderHeaderFile(group, output, writer);
|
|
});
|
|
|
|
WString fileCpp = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteAstBuilderCppFile(group, output, writer);
|
|
});
|
|
|
|
files.Add(output->builderH, fileH);
|
|
files.Add(output->builderCpp, fileCpp);
|
|
}
|
|
|
|
{
|
|
WString fileH = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteEmptyVisitorHeaderFile(group, output, writer);
|
|
});
|
|
|
|
WString fileCpp = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteEmptyVisitorCppFile(group, output, writer);
|
|
});
|
|
|
|
files.Add(output->emptyH, fileH);
|
|
files.Add(output->emptyCpp, fileCpp);
|
|
}
|
|
|
|
{
|
|
WString fileH = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteCopyVisitorHeaderFile(group, output, writer);
|
|
});
|
|
|
|
WString fileCpp = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteCopyVisitorCppFile(group, output, writer);
|
|
});
|
|
|
|
files.Add(output->copyH, fileH);
|
|
files.Add(output->copyCpp, fileCpp);
|
|
}
|
|
|
|
{
|
|
WString fileH = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteTraverseVisitorHeaderFile(group, output, writer);
|
|
});
|
|
|
|
WString fileCpp = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteTraverseVisitorCppFile(group, output, writer);
|
|
});
|
|
|
|
files.Add(output->traverseH, fileH);
|
|
files.Add(output->traverseCpp, fileCpp);
|
|
}
|
|
|
|
{
|
|
WString fileH = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteJsonVisitorHeaderFile(group, output, writer);
|
|
});
|
|
|
|
WString fileCpp = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteJsonVisitorCppFile(group, 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 group : manager.FileGroups().Values())
|
|
{
|
|
WriteAstFiles(group, output->astOutputs[group], 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(AstDefFileGroup* fileGroupContext, AstSymbol* propSymbol, stream::StreamWriter& writer);
|
|
|
|
LazyList<AstSymbol*> GetAllSymbols(AstSymbolManager& manager)
|
|
{
|
|
return Range<vint>(0, manager.Symbols().Count())
|
|
.SelectMany([&manager](vint index) { return From(manager.Symbols().GetByIndex(index)); })
|
|
;
|
|
}
|
|
|
|
/***********************************************************************
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
auto current = classSymbol;
|
|
while (current)
|
|
{
|
|
if (current->derivedClass_ToResolve)
|
|
{
|
|
resolvables.Add(classSymbol, current->derivedClass_ToResolve);
|
|
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 : GetAllSymbols(manager))
|
|
{
|
|
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(AstDefFileGroup* fileGroupContext, AstSymbol* propSymbol, stream::StreamWriter& writer);
|
|
|
|
/***********************************************************************
|
|
WriteAstBuilderHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteAstBuilderHeaderFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(group, output, L"builder", writer, [&](const WString& prefix)
|
|
{
|
|
for(auto typeSymbol : group->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(group, 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(group, 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(group, propSymbol->propSymbol, writer);
|
|
writer.WriteLine(L">& value);");
|
|
break;
|
|
}
|
|
}
|
|
currentClass = currentClass->baseClass;
|
|
}
|
|
writer.WriteLine(prefix + L"};");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteAstBuilderCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteAstBuilderCppFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(group, output->builderH, L"builder", writer, [&](const WString& prefix)
|
|
{
|
|
for (auto typeSymbol : group->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(group, 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(group, 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(group, 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(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
for (auto [name, index] : indexed(group->Symbols().Keys()))
|
|
{
|
|
if (dynamic_cast<AstClassSymbol*>(group->Symbols().Values()[index]))
|
|
{
|
|
writer.WriteString(prefix);
|
|
writer.WriteString(L"class ");
|
|
writer.WriteString(group->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(AstDefFileGroup* fileGroupContext, 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 group = propSymbol->Owner()->Owner();
|
|
if (purpose == PrintTypePurpose::ReflectionName)
|
|
{
|
|
PrintNss(group->refNss, writer);
|
|
}
|
|
else
|
|
{
|
|
if (fileGroupContext != group)
|
|
{
|
|
PrintNss(group->cppNss, writer);
|
|
}
|
|
}
|
|
writer.WriteString(group->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(AstDefFileGroup* fileGroupContext, AstPropType propType, AstSymbol* propSymbol, stream::StreamWriter& writer)
|
|
{
|
|
PrintAstType(fileGroupContext, propType, propSymbol, PrintTypePurpose::Value, writer);
|
|
}
|
|
|
|
void PrintCppType(AstDefFileGroup* fileGroupContext, AstSymbol* propSymbol, stream::StreamWriter& writer)
|
|
{
|
|
PrintAstType(fileGroupContext, AstPropType::Type, propSymbol, PrintTypePurpose::TypeName, writer);
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteTypeDefinitions
|
|
***********************************************************************/
|
|
|
|
void WriteTypeDefinitions(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
for (auto name : group->SymbolOrder())
|
|
{
|
|
auto typeSymbol = group->Symbols()[name];
|
|
if (auto enumSymbol = dynamic_cast<AstEnumSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteLine(L"");
|
|
writer.WriteString(prefix);
|
|
writer.WriteString(L"enum class ");
|
|
writer.WriteString(group->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 : group->SymbolOrder())
|
|
{
|
|
auto typeSymbol = group->Symbols()[name];
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteLine(L"");
|
|
writer.WriteString(prefix);
|
|
writer.WriteString(L"class ");
|
|
writer.WriteString(group->classPrefix);
|
|
writer.WriteString(name);
|
|
if (classSymbol->derivedClasses.Count() > 0)
|
|
{
|
|
writer.WriteString(L" abstract");
|
|
}
|
|
writer.WriteString(L" : public ");
|
|
if (classSymbol->baseClass)
|
|
{
|
|
PrintCppType(group, classSymbol->baseClass, writer);
|
|
}
|
|
else
|
|
{
|
|
writer.WriteString(L"vl::glr::ParsingAstBase");
|
|
}
|
|
writer.WriteString(L", vl::reflection::Description<");
|
|
writer.WriteString(group->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(group, 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(group, 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(group, propSymbol->propType, propSymbol->propSymbol, writer);
|
|
writer.WriteString(L" ");
|
|
writer.WriteString(propName);
|
|
if (dynamic_cast<AstEnumSymbol*>(propSymbol->propSymbol))
|
|
{
|
|
writer.WriteString(L" = ");
|
|
PrintCppType(group, 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(group, classSymbol->baseClass, writer);
|
|
writer.WriteLine(L"::IVisitor* visitor) override;");
|
|
}
|
|
|
|
writer.WriteString(prefix);
|
|
writer.WriteLine(L"};");
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteVisitorImpl
|
|
***********************************************************************/
|
|
|
|
void WriteVisitorImpl(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
for (auto name : group->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(group->Symbols()[name]))
|
|
{
|
|
if (classSymbol->baseClass)
|
|
{
|
|
writer.WriteLine(L"");
|
|
writer.WriteString(prefix);
|
|
writer.WriteString(L"void ");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteString(L"::Accept(");
|
|
PrintCppType(group, 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(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
writer.WriteLine(L"#ifndef VCZH_DEBUG_NO_REFLECTION");
|
|
|
|
for (auto&& name : group->SymbolOrder())
|
|
{
|
|
auto typeSymbol = group->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 : group->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(group->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(group->Owner()->Global().name);
|
|
writer.WriteString(group->Name());
|
|
writer.WriteLine(L"LoadTypes();");
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteTypeReflectionImplementation
|
|
***********************************************************************/
|
|
|
|
void WriteTypeReflectionImplementation(AstDefFileGroup* group, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
writer.WriteLine(L"#ifndef VCZH_DEBUG_NO_REFLECTION");
|
|
|
|
writer.WriteLine(L"");
|
|
|
|
for (auto&& name : group->SymbolOrder())
|
|
{
|
|
auto typeSymbol = group->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 : group->SymbolOrder())
|
|
{
|
|
auto typeSymbol = group->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 : group->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(group->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(group->Owner()->Global().name);
|
|
writer.WriteString(group->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 : group->SymbolOrder())
|
|
{
|
|
auto typeSymbol = group->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(group->Owner()->Global().name);
|
|
writer.WriteString(group->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(group->Owner()->Global().name);
|
|
writer.WriteString(group->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(AstDefFileGroup* fileGroupContext, AstSymbol* propSymbol, stream::StreamWriter& writer);
|
|
extern void CollectVisitorsAndConcreteClasses(AstDefFileGroup* group, List<AstClassSymbol*>& visitors, List<AstClassSymbol*>& concreteClasses);
|
|
|
|
/***********************************************************************
|
|
WriteCopyFieldFunctionBody
|
|
***********************************************************************/
|
|
|
|
void WriteCopyFieldFunctionBody(AstDefFileGroup* group, AstClassSymbol* fieldSymbol, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
if (fieldSymbol->baseClass)
|
|
{
|
|
writer.WriteString(prefix + L"\tCopyFields(static_cast<");
|
|
PrintCppType(group, fieldSymbol->baseClass, writer);
|
|
writer.WriteString(L"*>(from), static_cast<");
|
|
PrintCppType(group, 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(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(group, output, L"copy_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(group, visitors, concreteClasses);
|
|
|
|
writer.WriteLine(prefix + L"/// <summary>A copy visitor, overriding all abstract methods with AST copying code.</summary>");
|
|
writer.WriteLine(prefix + L"class " + group->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(group, visitorSymbol, writer);
|
|
writer.WriteLine(L"::IVisitor");
|
|
}
|
|
writer.WriteLine(prefix + L"{");
|
|
|
|
writer.WriteLine(prefix + L"protected:");
|
|
for (auto typeSymbol : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"\tvoid CopyFields(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteString(L"* from, ");
|
|
PrintCppType(group, 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(group, 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(group, 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(group, classSymbol, writer);
|
|
writer.WriteString(L"> CopyNode(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node);");
|
|
}
|
|
|
|
writer.WriteLine(L"");
|
|
for (auto classSymbol :
|
|
From(group->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(group, classSymbol, writer);
|
|
writer.WriteString(L"> CopyNode(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node);");
|
|
}
|
|
writer.WriteLine(prefix + L"};");
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteCopyVisitorCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteCopyVisitorCppFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(group, output->copyH, L"copy_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(group, visitors, concreteClasses);
|
|
|
|
for (auto typeSymbol : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::CopyFields(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteString(L"* from, ");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* to)");
|
|
writer.WriteLine(prefix + L"{");
|
|
WriteCopyFieldFunctionBody(group, classSymbol, prefix, writer);
|
|
writer.WriteLine(prefix + L"}");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
for (auto classSymbol : concreteClasses)
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::Visit(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node)");
|
|
writer.WriteLine(prefix + L"{");
|
|
writer.WriteString(prefix + L"\tauto newNode = vl::Ptr(new ");
|
|
PrintCppType(group, 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 " + group->Name() + L"Visitor::Visit(");
|
|
PrintCppType(group, 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(group, 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(group, 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(group, classSymbol, writer);
|
|
writer.WriteString(L"> " + group->Name() + L"Visitor::CopyNode(");
|
|
PrintCppType(group, 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(group, 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(group, classSymbol, writer);
|
|
writer.WriteLine(L">();");
|
|
writer.WriteLine(prefix + L"}");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
for (auto classSymbol : concreteClasses)
|
|
{
|
|
writer.WriteString(prefix + L"vl::Ptr<");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteString(L"> " + group->Name() + L"Visitor::CopyNode(");
|
|
PrintCppType(group, 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(group, classSymbol, writer);
|
|
writer.WriteLine(L">();");
|
|
writer.WriteLine(prefix + L"}");
|
|
writer.WriteLine(L"");
|
|
}
|
|
|
|
for (auto classSymbol :
|
|
From(group->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(group, classSymbol, writer);
|
|
writer.WriteString(L"> " + group->Name() + L"Visitor::CopyNode(");
|
|
PrintCppType(group, 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(group, rootBaseClass, writer);
|
|
writer.WriteString(L"*>(node)).Cast<");
|
|
PrintCppType(group, 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(AstDefFileGroup* fileGroupContext, AstSymbol* propSymbol, stream::StreamWriter& writer);
|
|
|
|
/***********************************************************************
|
|
WriteEmptyVisitorHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteEmptyVisitorHeaderFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(group, output, L"empty_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
for (auto name : group->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(group->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(group, 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(group, 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(group, childSymbol, writer);
|
|
writer.WriteLine(L"* node) override;");
|
|
}
|
|
|
|
writer.WriteLine(prefix + L"};");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteEmptyVisitorCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteEmptyVisitorCppFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(group, output->emptyH, L"empty_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
for (auto name : group->SymbolOrder())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(group->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(group, 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(AstDefFileGroup* fileGroupContext, AstSymbol* propSymbol, stream::StreamWriter& writer);
|
|
extern void CollectVisitorsAndConcreteClasses(AstDefFileGroup* group, List<AstClassSymbol*>& visitors, List<AstClassSymbol*>& concreteClasses);
|
|
|
|
/***********************************************************************
|
|
WriteVisitFieldFunctionBody
|
|
***********************************************************************/
|
|
|
|
void WritePrintFieldsFunctionBody(AstDefFileGroup* group, AstClassSymbol* fieldSymbol, const WString& prefix, stream::StreamWriter& writer)
|
|
{
|
|
for (auto propSymbol : fieldSymbol->Props().Values())
|
|
{
|
|
writer.WriteLine(prefix + L"\tBeginField(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(AstDefFileGroup* group, 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(vl::WString::Unmanaged(L\"" + fieldSymbol->Name() + L"\"), node);");
|
|
for (auto classSymbol : From(order).Reverse())
|
|
{
|
|
writer.WriteString(prefix + L"\tPrintFields(static_cast<");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"*>(node));");
|
|
}
|
|
writer.WriteLine(prefix + L"\tEndObject();");
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteJsonVisitorHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteJsonVisitorHeaderFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(group, output, L"json_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(group, 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 " + group->Name() + L"Visitor");
|
|
writer.WriteLine(prefix + L"\t: public vl::glr::JsonVisitorBase");
|
|
for (auto visitorSymbol : visitors)
|
|
{
|
|
writer.WriteString(prefix + L"\t, protected virtual ");
|
|
PrintCppType(group, visitorSymbol, writer);
|
|
writer.WriteLine(L"::IVisitor");
|
|
}
|
|
writer.WriteLine(prefix + L"{");
|
|
|
|
writer.WriteLine(prefix + L"protected:");
|
|
for (auto typeSymbol : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"\tvirtual void PrintFields(");
|
|
PrintCppType(group, 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(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node) override;");
|
|
}
|
|
writer.WriteLine(L"");
|
|
}
|
|
|
|
writer.WriteLine(prefix + L"public:");
|
|
writer.WriteLine(prefix + L"\t" + group->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(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node);");
|
|
}
|
|
writer.WriteLine(prefix + L"};");
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteJsonVisitorCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteJsonVisitorCppFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(group, output->jsonH, L"json_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(group, visitors, concreteClasses);
|
|
|
|
for (auto typeSymbol : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::PrintFields(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node)");
|
|
writer.WriteLine(prefix + L"{");
|
|
WritePrintFieldsFunctionBody(group, classSymbol, prefix, writer);
|
|
writer.WriteLine(prefix + L"}");
|
|
}
|
|
}
|
|
writer.WriteLine(L"");
|
|
|
|
for (auto visitorSymbol : visitors)
|
|
{
|
|
for (auto classSymbol : visitorSymbol->derivedClasses)
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::Visit(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node)");
|
|
writer.WriteLine(prefix + L"{");
|
|
if (classSymbol->derivedClasses.Count() == 0)
|
|
{
|
|
WriteVisitFunctionBody(group, classSymbol, prefix, writer);
|
|
}
|
|
else
|
|
{
|
|
writer.WriteString(prefix + L"\tnode->Accept(static_cast<");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"::IVisitor*>(this));");
|
|
}
|
|
writer.WriteLine(prefix + L"}");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
writer.WriteLine(prefix + group->Name() + L"Visitor::" + group->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 " + group->Name() + L"Visitor::Print(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node)");
|
|
writer.WriteLine(prefix + L"{");
|
|
WriteNullAndReturn(prefix, writer);
|
|
writer.WriteString(prefix + L"\tnode->Accept(static_cast<");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"::IVisitor*>(this));");
|
|
writer.WriteLine(prefix + L"}");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
for (auto classSymbol : concreteClasses)
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::Print(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node)");
|
|
writer.WriteLine(prefix + L"{");
|
|
WriteVisitFunctionBody(group, 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(AstDefFileGroup* fileGroupContext, AstSymbol* propSymbol, stream::StreamWriter& writer);
|
|
extern void CollectVisitorsAndConcreteClasses(AstDefFileGroup* group, List<AstClassSymbol*>& visitors, List<AstClassSymbol*>& concreteClasses);
|
|
|
|
/***********************************************************************
|
|
WriteVisitFieldFunctionBody
|
|
***********************************************************************/
|
|
|
|
void WriteVisitFieldFunctionBody(AstDefFileGroup* group, 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(group, 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(group, classSymbol, writer);
|
|
writer.WriteLine(L"*>(node));");
|
|
}
|
|
writer.WriteLine(prefix + L"\tFinishing(static_cast<vl::glr::ParsingAstBase*>(node));");
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteTraverseVisitorHeaderFile
|
|
***********************************************************************/
|
|
|
|
void WriteTraverseVisitorHeaderFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityHeaderFile(group, output, L"traverse_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(group, visitors, concreteClasses);
|
|
|
|
writer.WriteLine(prefix + L"/// <summary>A traverse visitor, overriding all abstract methods with AST visiting code.</summary>");
|
|
writer.WriteLine(prefix + L"class " + group->Name() + L"Visitor");
|
|
writer.WriteLine(prefix + L"\t: public vl::Object");
|
|
for (auto visitorSymbol : visitors)
|
|
{
|
|
writer.WriteString(prefix + L"\t, protected virtual ");
|
|
PrintCppType(group, 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 : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"\tvirtual void Traverse(");
|
|
PrintCppType(group, 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 : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"\tvirtual void Finishing(");
|
|
PrintCppType(group, 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(group, 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(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node);");
|
|
}
|
|
writer.WriteLine(prefix + L"};");
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
WriteTraverseVisitorCppFile
|
|
***********************************************************************/
|
|
|
|
void WriteTraverseVisitorCppFile(AstDefFileGroup* group, Ptr<CppAstGenOutput> output, stream::StreamWriter& writer)
|
|
{
|
|
WriteAstUtilityCppFile(group, output->traverseH, L"traverse_visitor", writer, [&](const WString& prefix)
|
|
{
|
|
List<AstClassSymbol*> visitors, concreteClasses;
|
|
CollectVisitorsAndConcreteClasses(group, visitors, concreteClasses);
|
|
|
|
writer.WriteLine(prefix + L"void " + group->Name() + L"Visitor::Traverse(vl::glr::ParsingToken& token) {}");
|
|
writer.WriteLine(prefix + L"void " + group->Name() + L"Visitor::Traverse(vl::glr::ParsingAstBase* node) {}");
|
|
for (auto typeSymbol : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::Traverse(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node) {}");
|
|
}
|
|
}
|
|
writer.WriteLine(L"");
|
|
|
|
writer.WriteLine(prefix + L"void " + group->Name() + L"Visitor::Finishing(vl::glr::ParsingAstBase* node) {}");
|
|
for (auto typeSymbol : group->Symbols().Values())
|
|
{
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(typeSymbol))
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::Finishing(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node) {}");
|
|
}
|
|
}
|
|
writer.WriteLine(L"");
|
|
|
|
for (auto visitorSymbol : visitors)
|
|
{
|
|
for (auto classSymbol : visitorSymbol->derivedClasses)
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::Visit(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node)");
|
|
writer.WriteLine(prefix + L"{");
|
|
if (classSymbol->derivedClasses.Count() == 0)
|
|
{
|
|
WriteVisitFieldFunctionBody(group, classSymbol, prefix, writer);
|
|
}
|
|
else
|
|
{
|
|
writer.WriteString(prefix + L"\tnode->Accept(static_cast<");
|
|
PrintCppType(group, 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 " + group->Name() + L"Visitor::InspectInto(");
|
|
PrintCppType(group, 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(group, classSymbol, writer);
|
|
writer.WriteLine(L"::IVisitor*>(this));");
|
|
writer.WriteLine(prefix + L"}");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
for (auto classSymbol : concreteClasses)
|
|
{
|
|
writer.WriteString(prefix + L"void " + group->Name() + L"Visitor::InspectInto(");
|
|
PrintCppType(group, classSymbol, writer);
|
|
writer.WriteLine(L"* node)");
|
|
writer.WriteLine(prefix + L"{");
|
|
WriteVisitFieldFunctionBody(group, 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()->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 (parent->Owner() != propSymbol->Owner() && !propSymbol->isPublic)
|
|
{
|
|
ownerFile->AddError(
|
|
ParserErrorType::FieldTypeNotPublic,
|
|
codeRange,
|
|
ownerFile->Name(),
|
|
parent->Name(),
|
|
name
|
|
);
|
|
return false;
|
|
}
|
|
|
|
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->Owner()->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;
|
|
}
|
|
else if (ownerFile != newBaseClass->Owner() && !newBaseClass->isPublic)
|
|
{
|
|
ownerFile->AddError(
|
|
ParserErrorType::BaseClassNotPublic,
|
|
codeRange,
|
|
ownerFile->Name(),
|
|
name,
|
|
typeName
|
|
);
|
|
return false;
|
|
}
|
|
|
|
if (newBaseClass->derivedClass_Common)
|
|
{
|
|
newBaseClass = newBaseClass->derivedClass_Common;
|
|
}
|
|
|
|
List<AstClassSymbol*> visited;
|
|
visited.Add(newBaseClass);
|
|
// TODO: (enumerable) foreach:alterable
|
|
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::CreateDerivedClass_ToResolve(ParsingTextRange codeRange)
|
|
{
|
|
if (!derivedClass_ToResolve)
|
|
{
|
|
auto derived = ownerFile->CreateClass(name + L"ToResolve", false, codeRange);
|
|
derived->classType = AstClassType::Generated_ToResolve;
|
|
derived->baseClass = this;
|
|
derivedClasses.Add(derived);
|
|
|
|
auto prop = derived->CreateProp(L"candidates", codeRange);
|
|
prop->propType = AstPropType::Array;
|
|
prop->propSymbol = this;
|
|
|
|
derivedClass_ToResolve = derived;
|
|
}
|
|
return derivedClass_ToResolve;
|
|
}
|
|
|
|
AstClassSymbol* AstClassSymbol::CreateDerivedClass_Common(ParsingTextRange codeRange)
|
|
{
|
|
if (!derivedClass_Common)
|
|
{
|
|
auto derived = ownerFile->CreateClass(name + L"Common", isPublic, codeRange);
|
|
derived->classType = AstClassType::Generated_Common;
|
|
derived->baseClass = this;
|
|
derivedClasses.Add(derived);
|
|
|
|
derivedClass_Common = derived;
|
|
}
|
|
return derivedClass_Common;
|
|
}
|
|
|
|
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::DuplicatedSymbolInFile,
|
|
codeRange,
|
|
name,
|
|
symbolName
|
|
);
|
|
}
|
|
else if (ownerGroup->symbolMap.Keys().Contains(symbolName))
|
|
{
|
|
AddError(
|
|
ParserErrorType::DuplicatedSymbolInFileGroup,
|
|
codeRange,
|
|
name,
|
|
symbolName,
|
|
ownerGroup->symbolMap[symbolName]->Owner()->name
|
|
);
|
|
}
|
|
else
|
|
{
|
|
ownerGroup->symbolMap.Add(symbolName, symbol);
|
|
ownerGroup->ownerManager->symbolGroup.Add(symbolName, symbol);
|
|
}
|
|
|
|
return symbol;
|
|
}
|
|
|
|
AstDefFile::AstDefFile(AstDefFileGroup* _ownerGroup, const WString& _name)
|
|
: ownerGroup(_ownerGroup)
|
|
, name(_name)
|
|
{
|
|
}
|
|
|
|
AstEnumSymbol* AstDefFile::CreateEnum(const WString& symbolName, bool isPublic, ParsingTextRange codeRange)
|
|
{
|
|
auto symbol = CreateSymbol<AstEnumSymbol>(symbolName, codeRange);
|
|
symbol->isPublic = isPublic;
|
|
return symbol;
|
|
}
|
|
|
|
AstClassSymbol* AstDefFile::CreateClass(const WString& symbolName, bool isPublic, ParsingTextRange codeRange)
|
|
{
|
|
auto symbol = CreateSymbol<AstClassSymbol>(symbolName, codeRange);
|
|
symbol->isPublic = isPublic;
|
|
return symbol;
|
|
}
|
|
|
|
/***********************************************************************
|
|
AstDefFileGroup
|
|
***********************************************************************/
|
|
|
|
AstDefFileGroup::AstDefFileGroup(AstSymbolManager* _ownerManager, const WString& _name)
|
|
: ownerManager(_ownerManager)
|
|
, name(_name)
|
|
{
|
|
}
|
|
|
|
bool AstDefFileGroup::AddDependency(const WString& dependency, ParsingTextRange codeRange)
|
|
{
|
|
if (dependencies.Contains(dependency)) return true;
|
|
if (!ownerManager->FileGroups().Keys().Contains(dependency))
|
|
{
|
|
AddError(
|
|
ParserErrorType::FileGroupDependencyNotExists,
|
|
codeRange,
|
|
name,
|
|
dependency
|
|
);
|
|
return false;
|
|
}
|
|
|
|
List<WString> visited;
|
|
visited.Add(dependency);
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < visited.Count(); i++)
|
|
{
|
|
auto currentName = visited[i];
|
|
if (currentName == name)
|
|
{
|
|
AddError(
|
|
ParserErrorType::FileGroupCyclicDependency,
|
|
codeRange,
|
|
name,
|
|
dependency
|
|
);
|
|
return false;
|
|
}
|
|
auto current = ownerManager->FileGroups()[currentName];
|
|
// TODO: (enumerable) foreach
|
|
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;
|
|
}
|
|
|
|
AstDefFile* AstDefFileGroup::CreateFile(const WString& name)
|
|
{
|
|
auto file = new AstDefFile(this, name);
|
|
if (!files.Add(name, file))
|
|
{
|
|
AddError(
|
|
ParserErrorType::DuplicatedFile,
|
|
{},
|
|
name
|
|
);
|
|
}
|
|
return file;
|
|
}
|
|
|
|
/***********************************************************************
|
|
AstSymbolManager
|
|
***********************************************************************/
|
|
|
|
AstSymbolManager::AstSymbolManager(ParserSymbolManager& _global)
|
|
: global(_global)
|
|
{
|
|
}
|
|
|
|
AstDefFileGroup* AstSymbolManager::CreateFileGroup(const WString& name)
|
|
{
|
|
auto fileGroup = new AstDefFileGroup(this, name);
|
|
if (!fileGroups.Add(name, fileGroup))
|
|
{
|
|
global.AddError(
|
|
ParserErrorType::DuplicatedFileGroup,
|
|
{ ParserDefFileType::AstGroup,name },
|
|
name
|
|
);
|
|
}
|
|
return fileGroup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\AST\ASTSYMBOL_CREATEPARSERGENRULEAST.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
CreateParserGenRuleAst
|
|
***********************************************************************/
|
|
|
|
AstDefFile* CreateParserGenRuleAst(AstSymbolManager& manager)
|
|
{
|
|
auto _group = manager.CreateFileGroup(L"RuleAst");
|
|
auto _ast = _group->CreateFile(L"Ast");
|
|
Fill(_group->cppNss, L"vl", L"glr", L"parsergen");
|
|
Fill(_group->refNss, L"glr", L"parsergen");
|
|
_group->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");
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// Rule
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
auto _Rule = _ast->CreateClass(L"Rule");
|
|
_Rule->CreateProp(L"attPublic")->SetPropType(AstPropType::Token);
|
|
_Rule->CreateProp(L"attParser")->SetPropType(AstPropType::Token);
|
|
_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 _group = manager.CreateFileGroup(L"TypeAst");
|
|
auto _ast = _group->CreateFile(L"Ast");
|
|
Fill(_group->cppNss, L"vl", L"glr", L"parsergen");
|
|
Fill(_group->refNss, L"glr", L"parsergen");
|
|
_group->classPrefix = L"Glr";
|
|
|
|
auto _type = _ast->CreateClass(L"Type");
|
|
_type->CreateProp(L"attPublic")->SetPropType(AstPropType::Token);
|
|
_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 _class = _ast->CreateClass(L"Class");
|
|
_class->SetBaseClass(L"Type");
|
|
_class->CreateProp(L"attAmbiguous")->SetPropType(AstPropType::Token);
|
|
_class->CreateProp(L"baseClass")->SetPropType(AstPropType::Token);
|
|
_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().astIncludes)
|
|
{
|
|
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"ATT_AMBIGUOUS", L"@ambiguous");
|
|
manager.CreateToken(L"ATT_PUBLIC", L"@public");
|
|
manager.CreateToken(L"ATT_PARSER", L"@parser");
|
|
|
|
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"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
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
CompileAst
|
|
***********************************************************************/
|
|
|
|
class CreateAstSymbolVisitor :public Object, public virtual GlrType::IVisitor
|
|
{
|
|
protected:
|
|
AstDefFile* astDefFile;
|
|
public:
|
|
CreateAstSymbolVisitor(AstDefFile* _astDefFile)
|
|
: astDefFile(_astDefFile)
|
|
{
|
|
}
|
|
|
|
void Visit(GlrEnum* node) override
|
|
{
|
|
auto symbol = astDefFile->CreateEnum(node->name.value, node->attPublic, node->name.codeRange);
|
|
symbol->isPublic = node->attPublic;
|
|
}
|
|
|
|
void Visit(GlrClass* node) override
|
|
{
|
|
auto symbol = astDefFile->CreateClass(node->name.value, node->attPublic, node->name.codeRange);
|
|
symbol->isPublic = node->attPublic;
|
|
|
|
if (node->attAmbiguous)
|
|
{
|
|
symbol->CreateDerivedClass_ToResolve(node->name.codeRange);
|
|
if (node->props.Count() > 0)
|
|
{
|
|
symbol->CreateDerivedClass_Common(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 FillClassSymbolBaseClass(GlrClass* node, AstClassSymbol* classSymbol)
|
|
{
|
|
if (node->baseClass)
|
|
{
|
|
classSymbol->SetBaseClass(node->baseClass.value, node->baseClass.codeRange);
|
|
}
|
|
}
|
|
|
|
void FillClassSymbolProps(GlrClass* node, AstClassSymbol* classSymbol)
|
|
{
|
|
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 Visit(GlrClass* node) override
|
|
{
|
|
auto classSymbol = dynamic_cast<AstClassSymbol*>(astDefFile->Symbols()[node->name.value]);
|
|
FillClassSymbolBaseClass(node, classSymbol);
|
|
|
|
if (node->attAmbiguous && classSymbol->derivedClass_Common)
|
|
{
|
|
classSymbol = classSymbol->derivedClass_Common;
|
|
}
|
|
FillClassSymbolProps(node, classSymbol);
|
|
}
|
|
};
|
|
|
|
void CompileAst(AstSymbolManager& astManager, collections::List<collections::Pair<AstDefFile*, Ptr<GlrAstFile>>>& files)
|
|
{
|
|
for (auto [astDefFile, file] : files)
|
|
{
|
|
CreateAstSymbolVisitor visitor(astDefFile);
|
|
for (auto type : file->types)
|
|
{
|
|
type->Accept(&visitor);
|
|
}
|
|
}
|
|
if (astManager.Global().Errors().Count() == 0)
|
|
{
|
|
for (auto [astDefFile, file] : files)
|
|
{
|
|
FillAstSymbolVisitor visitor(astDefFile);
|
|
for (auto type : file->types)
|
|
{
|
|
type->Accept(&visitor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CompileAst(AstSymbolManager& astManager, AstDefFile* astDefFile, Ptr<GlrAstFile> file)
|
|
{
|
|
List<Pair<AstDefFile*, Ptr<GlrAstFile>>> files;
|
|
files.Add({ astDefFile,file });
|
|
CompileAst(astManager, files);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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 Ptr<GlrSyntaxFile> RewriteSyntax_Switch(VisitorContext& context, VisitorSwitchContext& sContext, 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;
|
|
}
|
|
|
|
void CreateSyntaxSymbols(LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, vint fileIndex, 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,
|
|
fileIndex,
|
|
rule->attPublic,
|
|
rule->attParser,
|
|
rule->codeRange
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
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_UntilCompile(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;
|
|
|
|
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, index] : indexed(files))
|
|
{
|
|
CopyFrom(syntaxFile->switches, file->switches, true);
|
|
CopyFrom(syntaxFile->rules, file->rules, true);
|
|
CreateSyntaxSymbols(lexerManager, syntaxManager, index, file);
|
|
}
|
|
|
|
auto rawSyntaxFile = 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;
|
|
}
|
|
|
|
{
|
|
VisitorContext context(astManager, lexerManager, syntaxManager);
|
|
VisitorSwitchContext sContext;
|
|
if (!VerifySyntax_UntilSwitch(context, sContext, syntaxFile)) goto FINISHED_COMPILING;
|
|
if (!VerifySyntax_UntilCompile(context, syntaxFile)) goto FINISHED_COMPILING;
|
|
CompileSyntax(context, output, syntaxFile);
|
|
}
|
|
FINISHED_COMPILING:
|
|
return rawSyntaxFile == syntaxFile ? nullptr : syntaxFile;
|
|
}
|
|
|
|
Ptr<GlrSyntaxFile> CompileSyntax(AstSymbolManager& astManager, LexerSymbolManager& lexerManager, SyntaxSymbolManager& syntaxManager, Ptr<CppParserGenOutput> output, Ptr<GlrSyntaxFile> file)
|
|
{
|
|
List<Ptr<GlrSyntaxFile>> files;
|
|
files.Add(file);
|
|
return CompileSyntax(astManager, lexerManager, syntaxManager, output, files);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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];
|
|
}
|
|
|
|
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
|
|
{
|
|
couldBeEmpty = false;
|
|
}
|
|
|
|
void Visit(GlrUseSyntax* node) override
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
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(VisitorContext& context, Ptr<GlrSyntaxFile> syntaxFile)
|
|
{
|
|
CalculateFirstSet_DirectStartRules(context, syntaxFile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
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)
|
|
{
|
|
auto astRule = context.astRules[rule];
|
|
List<Func<StatePair()>> elements;
|
|
for (auto clause : astRule->clauses)
|
|
{
|
|
auto partialClause = clause.Cast<GlrPartialClause>();
|
|
elements.Add([this, partialClause]()
|
|
{
|
|
return BuildAssignments(Build(partialClause->syntax), partialClause->assignments);
|
|
});
|
|
}
|
|
result = automatonBuilder.BuildAlternativeSyntax(elements);
|
|
}
|
|
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
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
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
|
|
{
|
|
// Content of partial clauses are embedded in the caller side
|
|
}
|
|
|
|
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); }
|
|
);
|
|
});
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
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&& resolvedSymbols = context.astManager.Symbols().GetByIndex(index);
|
|
if (resolvedSymbols.Count() > 1)
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::TypeNotUniqueInRule,
|
|
typeName.codeRange,
|
|
ruleSymbol->Name(),
|
|
typeName.value
|
|
);
|
|
return nullptr;
|
|
}
|
|
|
|
auto classSymbol = dynamic_cast<AstClassSymbol*>(resolvedSymbols[0]);
|
|
if (!classSymbol)
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::TypeNotClassInRule,
|
|
typeName.codeRange,
|
|
ruleSymbol->Name(),
|
|
typeName.value
|
|
);
|
|
return nullptr;
|
|
}
|
|
|
|
if (classSymbol->derivedClass_Common)
|
|
{
|
|
classSymbol = classSymbol->derivedClass_Common;
|
|
}
|
|
return classSymbol;
|
|
}
|
|
|
|
void ResolveClause(Ptr<GlrClause> clause)
|
|
{
|
|
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
|
|
);
|
|
}
|
|
else if (ruleIndex != -1)
|
|
{
|
|
auto refRuleSymbol = context.syntaxManager.Rules().Values()[ruleIndex];
|
|
if (ruleSymbol->fileIndex != refRuleSymbol->fileIndex && !refRuleSymbol->isPublic)
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::ReferencedRuleNotPublicInRuleOfDifferentFile,
|
|
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 (ruleSymbol->fileIndex != usedRuleSymbol->fileIndex && !usedRuleSymbol->isPublic)
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::ReferencedRuleNotPublicInRuleOfDifferentFile,
|
|
name.codeRange,
|
|
ruleSymbol->Name(),
|
|
name.value
|
|
);
|
|
}
|
|
|
|
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.clauseTypes.Add(node, classSymbol);
|
|
}
|
|
node->syntax->Accept(this);
|
|
}
|
|
|
|
void Visit(GlrPartialClause* node) override
|
|
{
|
|
if (auto classSymbol = GetRuleClass(node->type))
|
|
{
|
|
context.clauseTypes.Add(node, classSymbol);
|
|
}
|
|
node->syntax->Accept(this);
|
|
}
|
|
|
|
void Visit(GlrReuseClause* node) override
|
|
{
|
|
reuseClause = node;
|
|
node->syntax->Accept(this);
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
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
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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)
|
|
{
|
|
vint index = workingSwitchValues->Keys().IndexOf(switchName);
|
|
auto value = index == -1 ? sContext.switches[switchName].key : workingSwitchValues->Values()[index];
|
|
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];
|
|
// TODO: (enumerable) Linq:Skip
|
|
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->priority = GlrOptionalPriority::Equal;
|
|
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(GlrLoopSyntax* node) override
|
|
{
|
|
Ptr<GlrSyntax> syntax, delimiter;
|
|
|
|
try
|
|
{
|
|
syntax = CopyNode(node->syntax.Obj());
|
|
}
|
|
catch (CancelBranch)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
delimiter = CopyNode(node->delimiter.Obj());
|
|
}
|
|
catch (CancelBranch)
|
|
{
|
|
}
|
|
|
|
if (syntax && delimiter)
|
|
{
|
|
auto loop = Ptr(new GlrLoopSyntax);
|
|
loop->codeRange = node->codeRange;
|
|
loop->syntax = syntax;
|
|
loop->delimiter = delimiter;
|
|
result = loop;
|
|
}
|
|
else if (syntax)
|
|
{
|
|
auto loop = Ptr(new GlrLoopSyntax);
|
|
loop->codeRange = syntax->codeRange;
|
|
loop->syntax = syntax;
|
|
result = loop;
|
|
}
|
|
else if (delimiter)
|
|
{
|
|
auto loop = Ptr(new GlrLoopSyntax);
|
|
loop->codeRange = delimiter->codeRange;
|
|
loop->syntax = delimiter;
|
|
result = loop;
|
|
}
|
|
else
|
|
{
|
|
result = Ptr(new EmptySyntax);
|
|
}
|
|
}
|
|
|
|
void Visit(GlrOptionalSyntax* node) override
|
|
{
|
|
try
|
|
{
|
|
copy_visitor::RuleAstVisitor::Visit(node);
|
|
}
|
|
catch (CancelBranch)
|
|
{
|
|
result = Ptr(new EmptySyntax);
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
bool syntax = !node->syntax.Cast<EmptySyntax>();
|
|
bool delimiter = !node->delimiter.Cast<EmptySyntax>();
|
|
if (syntax && delimiter)
|
|
{
|
|
// if both are not empty, nothing need to worry
|
|
}
|
|
else if (syntax)
|
|
{
|
|
// if only syntax is not empty, it is {syntax}
|
|
node->delimiter = nullptr;
|
|
}
|
|
else if (delimiter)
|
|
{
|
|
// if only delimiter is empty, it is {delimiter}
|
|
node->syntax = node->delimiter;
|
|
node->delimiter = nullptr;
|
|
}
|
|
else
|
|
{
|
|
// if both are empty, it is empty
|
|
result = node->syntax;
|
|
}
|
|
}
|
|
|
|
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->priority = GlrOptionalPriority::Equal;
|
|
opt->syntax = node->first;
|
|
result = opt;
|
|
}
|
|
else if (second)
|
|
{
|
|
// if only second is not empty, it is [second]
|
|
auto opt = Ptr(new GlrOptionalSyntax);
|
|
opt->priority = GlrOptionalPriority::Equal;
|
|
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);
|
|
}
|
|
|
|
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, bool applyAttributes)
|
|
{
|
|
auto newRule = Ptr(new GlrRule);
|
|
newRule->codeRange = rule->codeRange;
|
|
if (applyAttributes)
|
|
{
|
|
newRule->attPublic = rule->attPublic;
|
|
newRule->attParser = rule->attParser;
|
|
}
|
|
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), true);
|
|
}
|
|
|
|
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))
|
|
.OrderByKey([](auto&& a) { return a->name.value; })
|
|
)
|
|
{
|
|
rewritten->rules.Add(expandedRule);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CreateRuleSymbols(SyntaxSymbolManager& syntaxManager, Group<RuleSymbol*, Ptr<GlrRule>>& expandedRules)
|
|
{
|
|
// TODO: (enumerable) foreach on group, sort pairs instead of calling Get
|
|
for (auto ruleSymbol : From(expandedRules.Keys())
|
|
.OrderByKey([](auto&& a) { return a->Name(); })
|
|
)
|
|
{
|
|
for (auto rule : expandedRules[ruleSymbol])
|
|
{
|
|
auto newRuleSymbol = syntaxManager.CreateRule(
|
|
rule->name.value,
|
|
ruleSymbol->fileIndex,
|
|
ruleSymbol->isPublic,
|
|
ruleSymbol->isParser,
|
|
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())
|
|
{
|
|
CHECK_FAIL(L"vl::glr::parsergen::RewriteSyntax_Switch(...)#Internal error: This function should not be called when there is no switch used in any rule.");
|
|
}
|
|
|
|
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->attPublic = rule->attPublic;
|
|
newRule->attParser = rule->attParser;
|
|
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, false);
|
|
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_VALIDATESTRUCTURE.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
using namespace collections;
|
|
using namespace compile_syntax;
|
|
|
|
/***********************************************************************
|
|
ValidateStructureCountingVisitor
|
|
***********************************************************************/
|
|
|
|
class ValidateStructureCountingVisitor
|
|
: public Object
|
|
, protected virtual GlrSyntax::IVisitor
|
|
, protected virtual GlrClause::IVisitor
|
|
{
|
|
protected:
|
|
VisitorContext& context;
|
|
RuleSymbol* ruleSymbol;
|
|
GlrClause* clause = nullptr;
|
|
|
|
vint optionalCounter = 0;
|
|
vint loopCounter = 0;
|
|
bool lastSyntaxPiece = true;
|
|
bool prioritySyntaxOccurred = false;
|
|
|
|
vint syntaxMinLength = 0;
|
|
vint syntaxMinUseRuleCount = 0;
|
|
vint syntaxMaxUseRuleCount = 0;
|
|
|
|
public:
|
|
ValidateStructureCountingVisitor(
|
|
VisitorContext& _context,
|
|
RuleSymbol* _ruleSymbol
|
|
)
|
|
: context(_context)
|
|
, ruleSymbol(_ruleSymbol)
|
|
{
|
|
}
|
|
|
|
void ValidateClause(Ptr<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);
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
ValidateStructureRelationshipVisitor
|
|
***********************************************************************/
|
|
|
|
class ValidateStructureRelationshipVisitor
|
|
: public Object
|
|
, protected virtual GlrSyntax::IVisitor
|
|
, protected virtual GlrClause::IVisitor
|
|
{
|
|
protected:
|
|
VisitorContext& context;
|
|
RuleSymbol* ruleSymbol;
|
|
GlrClause* clause = nullptr;
|
|
Dictionary<WString, vint> fieldCounters;
|
|
|
|
public:
|
|
ValidateStructureRelationshipVisitor(
|
|
VisitorContext& _context,
|
|
RuleSymbol* _ruleSymbol
|
|
)
|
|
: context(_context)
|
|
, ruleSymbol(_ruleSymbol)
|
|
{
|
|
}
|
|
|
|
void ValidateClause(Ptr<GlrClause> clause)
|
|
{
|
|
clause->Accept(this);
|
|
}
|
|
|
|
protected:
|
|
|
|
void AddFieldCounter(const WString& name, vint counter)
|
|
{
|
|
vint index = fieldCounters.Keys().IndexOf(name);
|
|
if (index == -1)
|
|
{
|
|
fieldCounters.Add(name, counter);
|
|
}
|
|
else
|
|
{
|
|
const_cast<List<vint>&>(fieldCounters.Values())[index] += counter;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GlrSyntax::IVisitor
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(GlrRefSyntax* node) override
|
|
{
|
|
if (node->field)
|
|
{
|
|
AddFieldCounter(node->field.value, 1);
|
|
}
|
|
|
|
if (ruleSymbol->isPartial && node->refType == GlrRefType::Id)
|
|
{
|
|
vint ruleIndex = context.syntaxManager.Rules().Keys().IndexOf(node->literal.value);
|
|
if (ruleIndex != -1)
|
|
{
|
|
auto refRuleSymbol = context.syntaxManager.Rules().Values()[ruleIndex];
|
|
if (refRuleSymbol->isPartial && !context.partialRuleDependencies.Contains(ruleSymbol, refRuleSymbol))
|
|
{
|
|
context.partialRuleDependencies.Add(ruleSymbol, refRuleSymbol);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
{
|
|
Dictionary<WString, vint> currentCounters(std::move(fieldCounters));
|
|
|
|
node->first->Accept(this);
|
|
Dictionary<WString, vint> firstCounters(std::move(fieldCounters));
|
|
|
|
node->second->Accept(this);
|
|
Dictionary<WString, vint> secondCounters(std::move(fieldCounters));
|
|
|
|
vint firstIndex = 0;
|
|
vint secondIndex = 0;
|
|
fieldCounters = std::move(currentCounters);
|
|
while (true)
|
|
{
|
|
bool firstAvailable = firstIndex < firstCounters.Count();
|
|
bool secondAvailable = secondIndex < secondCounters.Count();
|
|
|
|
if (firstAvailable && secondAvailable)
|
|
{
|
|
auto firstKey = firstCounters.Keys()[firstIndex];
|
|
auto secondKey = secondCounters.Keys()[secondIndex];
|
|
auto compare = firstKey <=> secondKey;
|
|
|
|
if (compare == std::strong_ordering::less)
|
|
{
|
|
secondAvailable = false;
|
|
}
|
|
else if (compare == std::strong_ordering::greater)
|
|
{
|
|
firstAvailable = false;
|
|
}
|
|
}
|
|
|
|
if (firstAvailable && secondAvailable)
|
|
{
|
|
vint firstValue = firstCounters.Values()[firstIndex];
|
|
vint secondValue = secondCounters.Values()[secondIndex];
|
|
AddFieldCounter(firstCounters.Keys()[firstIndex], (firstValue > secondValue ? firstValue : secondValue));
|
|
firstIndex++;
|
|
secondIndex++;
|
|
}
|
|
else if (firstAvailable)
|
|
{
|
|
AddFieldCounter(firstCounters.Keys()[firstIndex], firstCounters.Values()[firstIndex]);
|
|
firstIndex++;
|
|
}
|
|
else if (secondAvailable)
|
|
{
|
|
AddFieldCounter(secondCounters.Keys()[secondIndex], secondCounters.Values()[secondIndex]);
|
|
secondIndex++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
auto clauseType = context.clauseTypes[clause];
|
|
for (auto [key, value] : fieldCounters)
|
|
{
|
|
auto prop = FindPropSymbol(clauseType, key);
|
|
if (prop->propType != AstPropType::Array && value > 1)
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::FieldAssignedMoreThanOnce,
|
|
node->codeRange,
|
|
ruleSymbol->Name(),
|
|
clauseType->Name(),
|
|
prop->Name()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(GlrCreateClause* node) override
|
|
{
|
|
clause = node;
|
|
node->syntax->Accept(this);
|
|
CheckAfterClause(node);
|
|
}
|
|
|
|
void Visit(GlrPartialClause* node) override
|
|
{
|
|
clause = node;
|
|
node->syntax->Accept(this);
|
|
CheckAfterClause(node);
|
|
}
|
|
|
|
void Visit(GlrReuseClause* node) override
|
|
{
|
|
clause = node;
|
|
node->syntax->Accept(this);
|
|
CheckAfterClause(node);
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
ValidateStructure
|
|
***********************************************************************/
|
|
|
|
void ValidateStructure(VisitorContext& context, 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);
|
|
}
|
|
}
|
|
|
|
PartialOrderingProcessor pop;
|
|
List<RuleSymbol*> partialRules;
|
|
CopyFrom(partialRules,
|
|
From(context.syntaxManager.Rules().Values())
|
|
.Where([&](RuleSymbol* rule) { return rule->isPartial; })
|
|
);
|
|
pop.InitWithGroup(partialRules, context.partialRuleDependencies);
|
|
pop.Sort();
|
|
|
|
for (vint i = 0; i < context.partialRuleDependencies.Count(); i++)
|
|
{
|
|
auto partialRule = context.partialRuleDependencies.Keys()[i];
|
|
if (context.partialRuleDependencies.GetByIndex(i).Contains(partialRule))
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::PartialRuleIsRecursive,
|
|
context.astRules[partialRule]->codeRange,
|
|
partialRule->Name()
|
|
);
|
|
}
|
|
}
|
|
|
|
for (auto&& component : pop.components)
|
|
{
|
|
if (component.nodeCount > 1)
|
|
{
|
|
for (auto partialRule : From(FromPointer(component.firstNode, component.firstNode + component.nodeCount))
|
|
.Select([&](vint index) { return partialRules[index]; })
|
|
.OrderByKey([](auto partialRule) { return partialRule->Name(); }))
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::PartialRuleIsRecursive,
|
|
context.astRules[partialRule]->codeRange,
|
|
partialRule->Name()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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)
|
|
{
|
|
// TODO: (enumerable) operate on GetByIndex returned list object directly
|
|
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
|
|
);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
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);
|
|
}
|
|
|
|
if (sContext.ruleAffectedSwitches.Count() == context.syntaxManager.Rules().Count())
|
|
{
|
|
context.syntaxManager.AddError(
|
|
ParserErrorType::SwitchUnaffectedRuleNotExist,
|
|
syntaxFile->codeRange
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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());
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\PARSERGEN_GLOBAL\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"");
|
|
}
|
|
|
|
void WriteNssName(const collections::List<WString>& cppNss, stream::StreamWriter& writer)
|
|
{
|
|
for (auto [ns, index] : indexed(cppNss))
|
|
{
|
|
if (index != 0) writer.WriteString(L"::");
|
|
writer.WriteString(ns);
|
|
}
|
|
}
|
|
|
|
WString WriteNssBegin(const collections::List<WString>& cppNss, stream::StreamWriter& writer)
|
|
{
|
|
if (cppNss.Count() == 0)
|
|
{
|
|
return WString::Empty;
|
|
}
|
|
|
|
writer.WriteString(L"namespace ");
|
|
WriteNssName(cppNss, writer);
|
|
writer.WriteLine(WString::Empty);
|
|
writer.WriteLine(L"{");
|
|
return WString::Unmanaged(L"\t");
|
|
}
|
|
|
|
void WriteNssEnd(const collections::List<WString>& cppNss, stream::StreamWriter& writer)
|
|
{
|
|
if (cppNss.Count() == 0)
|
|
{
|
|
return;
|
|
}
|
|
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_GLOBAL\PARSERSYMBOL.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
|
|
/***********************************************************************
|
|
Utility
|
|
***********************************************************************/
|
|
|
|
void InitializeParserSymbolManager(ParserSymbolManager& manager)
|
|
{
|
|
manager.name = L"ParserGen";
|
|
Fill(manager.astIncludes, L"../AstBase.h");
|
|
Fill(manager.syntaxIncludes, 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::glr::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);
|
|
}
|
|
}
|
|
namespace vl::reflection::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::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::GlrRule)
|
|
CLASS_MEMBER_BASE(vl::glr::ParsingAstBase)
|
|
|
|
CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::parsergen::GlrRule>(), NO_PARAMETER)
|
|
|
|
CLASS_MEMBER_FIELD(attPublic)
|
|
CLASS_MEMBER_FIELD(attParser)
|
|
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))
|
|
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::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::glr::parsergen::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;
|
|
}
|
|
|
|
/***********************************************************************
|
|
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;
|
|
}
|
|
|
|
/***********************************************************************
|
|
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::attParser(const vl::WString& value)
|
|
{
|
|
node->attParser.value = value;
|
|
return *this;
|
|
}
|
|
|
|
MakeRule& MakeRule::attPublic(const vl::WString& value)
|
|
{
|
|
node->attPublic.value = value;
|
|
return *this;
|
|
}
|
|
|
|
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::glr::parsergen::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(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(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)
|
|
{
|
|
to->attParser = from->attParser;
|
|
to->attPublic = from->attPublic;
|
|
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(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;
|
|
}
|
|
|
|
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<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<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<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::glr::parsergen::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)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\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::glr::parsergen::json_visitor
|
|
{
|
|
void RuleAstVisitor::PrintFields(GlrAlternativeSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"first"));
|
|
Print(node->first.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"second"));
|
|
Print(node->second.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrAndCondition* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"first"));
|
|
Print(node->first.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"second"));
|
|
Print(node->second.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrAssignment* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"field"));
|
|
WriteToken(node->field);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"type"));
|
|
switch (node->type)
|
|
{
|
|
case vl::glr::parsergen::GlrAssignmentType::Strong:
|
|
WriteString(vl::WString::Unmanaged(L"Strong"));
|
|
break;
|
|
case vl::glr::parsergen::GlrAssignmentType::Weak:
|
|
WriteString(vl::WString::Unmanaged(L"Weak"));
|
|
break;
|
|
default:
|
|
WriteNull();
|
|
}
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"value"));
|
|
WriteToken(node->value);
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrClause* node)
|
|
{
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrCondition* node)
|
|
{
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrCreateClause* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"assignments"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->assignments)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"syntax"));
|
|
Print(node->syntax.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"type"));
|
|
WriteToken(node->type);
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrLoopSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"delimiter"));
|
|
Print(node->delimiter.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"syntax"));
|
|
Print(node->syntax.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrNotCondition* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"condition"));
|
|
Print(node->condition.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrOptionalSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"priority"));
|
|
switch (node->priority)
|
|
{
|
|
case vl::glr::parsergen::GlrOptionalPriority::Equal:
|
|
WriteString(vl::WString::Unmanaged(L"Equal"));
|
|
break;
|
|
case vl::glr::parsergen::GlrOptionalPriority::PreferSkip:
|
|
WriteString(vl::WString::Unmanaged(L"PreferSkip"));
|
|
break;
|
|
case vl::glr::parsergen::GlrOptionalPriority::PreferTake:
|
|
WriteString(vl::WString::Unmanaged(L"PreferTake"));
|
|
break;
|
|
default:
|
|
WriteNull();
|
|
}
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"syntax"));
|
|
Print(node->syntax.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrOrCondition* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"first"));
|
|
Print(node->first.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"second"));
|
|
Print(node->second.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrPartialClause* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"assignments"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->assignments)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"syntax"));
|
|
Print(node->syntax.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"type"));
|
|
WriteToken(node->type);
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrPushConditionSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"switches"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->switches)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"syntax"));
|
|
Print(node->syntax.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrRefCondition* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"name"));
|
|
WriteToken(node->name);
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrRefSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"field"));
|
|
WriteToken(node->field);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"literal"));
|
|
WriteToken(node->literal);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"refType"));
|
|
switch (node->refType)
|
|
{
|
|
case vl::glr::parsergen::GlrRefType::ConditionalLiteral:
|
|
WriteString(vl::WString::Unmanaged(L"ConditionalLiteral"));
|
|
break;
|
|
case vl::glr::parsergen::GlrRefType::Id:
|
|
WriteString(vl::WString::Unmanaged(L"Id"));
|
|
break;
|
|
case vl::glr::parsergen::GlrRefType::Literal:
|
|
WriteString(vl::WString::Unmanaged(L"Literal"));
|
|
break;
|
|
default:
|
|
WriteNull();
|
|
}
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrReuseClause* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"assignments"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->assignments)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"syntax"));
|
|
Print(node->syntax.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrRule* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"attParser"));
|
|
WriteToken(node->attParser);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"attPublic"));
|
|
WriteToken(node->attPublic);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"clauses"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->clauses)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"name"));
|
|
WriteToken(node->name);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"type"));
|
|
WriteToken(node->type);
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrSequenceSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"first"));
|
|
Print(node->first.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"second"));
|
|
Print(node->second.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrSwitchItem* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"name"));
|
|
WriteToken(node->name);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"value"));
|
|
switch (node->value)
|
|
{
|
|
case vl::glr::parsergen::GlrSwitchValue::False:
|
|
WriteString(vl::WString::Unmanaged(L"False"));
|
|
break;
|
|
case vl::glr::parsergen::GlrSwitchValue::True:
|
|
WriteString(vl::WString::Unmanaged(L"True"));
|
|
break;
|
|
default:
|
|
WriteNull();
|
|
}
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrSyntax* node)
|
|
{
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrSyntaxFile* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"rules"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->rules)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"switches"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->switches)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrTestConditionBranch* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"condition"));
|
|
Print(node->condition.Obj());
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"syntax"));
|
|
Print(node->syntax.Obj());
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrTestConditionSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"branches"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->branches)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
}
|
|
void RuleAstVisitor::PrintFields(GlrUseSyntax* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"name"));
|
|
WriteToken(node->name);
|
|
EndField();
|
|
}
|
|
|
|
void RuleAstVisitor::Visit(GlrRefCondition* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(L"ReuseClause"), node);
|
|
PrintFields(static_cast<GlrClause*>(node));
|
|
PrintFields(static_cast<GlrReuseClause*>(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(vl::WString::Unmanaged(L"SwitchItem"), node);
|
|
PrintFields(static_cast<GlrSwitchItem*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrTestConditionBranch* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(L"TestConditionBranch"), node);
|
|
PrintFields(static_cast<GlrTestConditionBranch*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrAssignment* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(L"Assignment"), node);
|
|
PrintFields(static_cast<GlrAssignment*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrRule* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(L"Rule"), node);
|
|
PrintFields(static_cast<GlrRule*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void RuleAstVisitor::Print(GlrSyntaxFile* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(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::glr::parsergen::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(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(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(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(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::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(GlrRule* node)
|
|
{
|
|
if (!node) return;
|
|
Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
|
|
Traverse(static_cast<GlrRule*>(node));
|
|
Traverse(node->attParser);
|
|
Traverse(node->attPublic);
|
|
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::glr::parsergen
|
|
{
|
|
void ParserGenRuleParserData(vl::stream::IStream& outputStream)
|
|
{
|
|
static const vl::vint dataLength = 10130; // 132882 bytes before compressing
|
|
static const vl::vint dataBlock = 256;
|
|
static const vl::vint dataRemain = 146;
|
|
static const vl::vint dataSolidRows = 39;
|
|
static const vl::vint dataRows = 40;
|
|
static const char* compressed[] = {
|
|
"\x12\x07\x02\x00\x8A\x27\x00\x00\x23\x00\x01\x82\x80\x0E\x03\x82\x81\x82\x06\x89\x82\x88\x0A\x80\x86\x82\x0A\x0A\x97\x0A\x9C\x0A\x82\x12\x85\x24\x0A\xCE\x0A\x94\x2A\x87\x2A\x85\x2E\x0A\xF0\x0A\x9A\x3A\x82\x66\x09\x84\xFF\x29\xAA\x89\x9A\x80\x03\x95\x95\x2D\xAF\xAA\x91\x92\x9F\x7C\x9A\x99\x37\xAF\xB9\x90\x9A\x85\x9A\x9B\x9E\x35\xBB\xB3\x80\xA8\x9C\xA2\x9D\x96\x0A\x81\x06\xBC\x98\x91\xA3\xA5\xA1\x4D\xC5\x91\xA7\xA3\xAC\xA6\x82\x9F\x42\xAC\x8F\xBA\xA5\xA8\xAB\xAA\xA7\x5D\xDC\x9F\xB2\xA3\xB4\xAA\x82\xA5\x09\xE8\xA5\xB6\xA3\x80\xAF\xAD\x9F\x61\xF0\x86\x82\x09\xA7\xB5\xAC\xB9\x6D\xE0\xAB\xBE\xA9\xBC\xB1\xBE\xB3\x7F\xEC\x82\x8E\xB1\xBF\xBA\xC2\xBB\x88\x85\xC9\xDB\xB2\xB1\xC0\xBF\xC1\x7A\x8E\xCD\xD0\xCE\xBC\xC8\xC0\xCB\x82\x81\x84\xCC\xC8\xB8\xCF\xC6\xCD\x91\x9E\xD3\xC0\xD5\xCC\xD3\xCA\xD3\x99\xAE\xA1\xC8\xDF\xCA\xD5\xD2\xD7\xA7\xB0\xE9\xDB\xC2\xCD\xCC\xD7\xD1\xB2\xAD\xF4\xC2\xD6\xD9\xDC\xDD\xDD\xB7\xBD\xC0\xFE\xD2\xE3\xD4\xE3\xC3\x8A\xC9\xDC\xC8\xE6\x83\x01\xBA\xE5\xB5\xCC\xD1\xEB\xC3\xE8\xE8\xDE\xE9\xD7\xD4\xD9\xF6",
|
|
"\xE1\xE5\x94\x03\xE7\xCB\xDA\xDD\xE2\xF0\x05\x00\xF1\xEA\xE1\xDC\xC7\xEA\x86\x07\xF3\xED\xF4\xF0\xE8\xF2\xEF\xF3\xFB\xF2\xF5\xE1\xF8\xC6\xF9\xEF\xDB\xF9\xD9\xFF\xD9\xFA\x41\x8C\x7E\x80\xFE\x44\x80\x83\x80\x08\x85\x89\x83\x81\x0A\x8D\x8C\x83\x83\xBA\x46\x77\x02\x7B\xF6\x71\x74\x7F\x85\x15\xB5\x7B\x7B\x7D\x06\x91\x8B\x82\x87\x0E\xA0\x80\x87\x6F\x1D\xA4\x8F\x86\x89\x21\xA8\x83\x89\x71\x27\xAC\x89\x8A\x8B\x2B\x98\x79\x84\x86\x1B\x96\x83\x8D\x40\x0C\x69\x54\x7B\x7F\x22\xBD\x8A\x8A\x8F\x30\x80\x92\x8D\x8D\x1A\xBC\x8F\x8F\x91\x41\x88\x93\x92\x91\x49\x8D\x9B\x91\x89\x4E\xBB\x80\x97\x93\x2D\x94\x9F\x8A\x95\x31\x92\x95\x96\x96\x57\x9C\x99\x96\x7A\x09\x14\x84\x90\x8D\x4C\x98\x92\x92\x97\x67\x9C\x8B\x96\x9A\x5D\xAC\x9F\x96\x8D\x63\xB7\x81\x9F\x9C\x65\xA8\x9A\x92\x9D\x51\xAE\x99\x9A\x41\x0A\x22\x95\x9E\x9E\x77\x80\xA9\x9C\x9C\x7F\x84\xA3\x96\x42\x0B\x3E\x97\xA2\xA0\x2D\x4C\x0A\xA3\x9A\x86\x90\xA5\x93\xA2\x91\xAD\x95\xA7\x9B\x93\xAF\x6D\x03\xA3\x96\x99\xAD\xA4\x99\x94\x9E\xA8\xA4\xA8\x92\x87\x4C\xA7\xA8\x72\x83\x7F\x03\xA9",
|
|
"\x7B\xA2\xAD\xA8\xA9\x9F\xA9\xA1\xA8\xAC\xA8\xB4\x93\xAE\xAC\xA5\xB8\xA1\xAE\xAD\xB9\xBC\xAB\xAD\xA1\xAE\x81\xA7\xA7\xAB\xBA\xB5\xA0\xB0\xAD\xC4\xBE\xA6\xB3\xAD\xCA\x89\xB0\x04\xAB\xC2\x81\xB3\xA2\xB4\x66\x91\xB8\xB2\xB5\x72\x91\x00\xB7\xB4\xD7\xBD\x67\x4A\x8E\x8C\xB8\x9D\x4B\x04\x62\x90\x40\xBB\xB0\xD8\x8D\xB9\xBB\xB1\xC5\x89\xBC\xBA\xBA\xDC\xAD\xBB\xB8\xB3\xEF\xB5\xB4\xBF\xBD\xBD\xB6\xB9\xBC\xBE\xBF\xBC\xBB\xB3\xBE\x00\xFD\xB1\xC3\xBF\xBB\x95\x0B\xB5\xB5\xF1\xB0\xB8\xC3\xC2\xE2\x8D\xC1\xB9\x42\x16\x22\x92\x47\xB9\xD4\x8E\xC8\xB9\xC2\xFA\x82\xCA\xC4\xC1\x1C\xEE\xBE\xBE\xC7\x03\xE0\xCB\xC6\xC8\x1D\xF3\xB1\xCA\xC9\x23\xE8\xC5\xC9\xC2\x18\x07\xC6\xC5\xC5\x0F\xD7\xCC\xC1\xCC\x1A\x99\x0E\xC8\xCD\x34\x9A\x07\xCE\xCC\x2F\xDD\xB3\xCC\xCF\x38\xF2\xB8\xC7\xC7\x2A\xE4\xC6\xD1\xD1\x48\xC3\xD7\xCA\xD2\x29\xCC\xDB\xCB\xCF\x30\xC0\xD2\xD5\xD4\x54\xC2\x4B\x07\xCE\x55\xC2\xD0\xD6\xCF\x3D\xDA\xD4\x78\x45\x14\xDC\xD1\xD0\x00\x1D\x18\xD2\xD8\x9C\x1E\x22\x9F\x06\xD9\x5E\xE3\xD9\xC7\xD3\x5D\xCA\xC1\xDF\xDB\x47\xCE\xD5\xDF\xD6\x6D",
|
|
"\xD3\xD7\xD9\xD6\x72\xEE\xD4\xD2\xDD\x49\xF8\xDD\xDE\xDE\x79\xFC\xD0\x08\xDB\x83\xFC\xD4\xDD\xE0\x73\xFF\xDD\x49\x08\x62\x96\x41\xD9\xE1\x7B\xD5\xE4\xE7\xE5\x89\xD6\xE9\xE4\xE6\x8B\xC0\xEE\xE6\xE0\x9D\xE0\xEE\xE1\xE3\x4B\xE2\xE5\xE9\xDC\x00\x53\xEB\xE7\xEA\xA1\xE4\xED\xD2\xE0\x24\x08\xED\xE9\x42\x25\x32\xE3\xEA\xDF\xA7\xF8\xEF\xEA\xEB\x70\xFA\xED\xEC\xE1\xAC\xF7\xE0\xF3\xEC\xC3\xC2\xF3\x42\x09\xB6\xF9\xE5\xF2\xF2\x8A\xC6\xFA\xE4\xF1\xCD\xCC\xFF\xF2\xF3\x9C\xD4\xF1\xF2\xF4\xD5\xD8\xF7\xF7\xEE\xBE\xF7\xDC\xEE\xF7\xDD\xE9\xB7\x09\xF2\xDC\xC6\x48\x08\xF9\xBF\xD1\xF5\xFA\xFA\xE9\xD3\xFA\xF4\xF4\xEE\xEB\xF1\xFD\xFB\xD9\xF2\xF5\xFC\xFD\xDB\xF8\xF0\xFF\xFD\xE0\xCB\xF6\xFD\xFE\xFD\x6C\x7D\x00\xF3\x7D\x35\x14\x28\x7B\x80\x01\x2A\x07\x01\x8C\x71\x7D\xCF\x5F\x7C\x81\xFE\x7A\x7E\xF5\x7B\x70\x80\x08\x82\x86\x82\x34\x4B\x07\x02\x8E\x8D\x80\xD3\x7F\x7C\x82\x20\x93\x82\x08\xEF\x73\x85\x0F\xA5\x82\x82\x24\x89\x87\xFF\x2C\x0B\x82\x0F\xA8\x86\x84\x2A\x89\x35\x0B\x2D\x81\x6E\x17\x34\x85\x83\x0F\x9C\x81\x04\x88\x85\x82\x1D\x97\x86",
|
|
"\x87\x04\x98\x80\xFF\x42\x8D\x86\x17\xAD\x37\x05\x37\x9B\x84\x11\xA1\x81\x86\x1E\x8C\x88\x86\x50\x8F\x86\x14\xCE\x8C\x58\x18\x09\x8F\x87\x46\x8B\x8B\x09\xD4\x8D\x88\x2D\x9D\x88\x88\x43\x80\x8D\x11\xB9\x89\x8A\x31\x8F\x89\x35\x31\x08\x72\x0C\x08\x73\x06\xC4\x74\x02\x4C\x35\x17\x8A\xE6\x36\x02\x8F\x80\x37\x05\x8E\x00\x18\x06\x98\x39\x02\x4C\x1D\x22\x4B\x07\x62\x5C\x04\x1E\xE7\x8C\x8B\x28\x85\x93\x8A\x5E\x86\x91\xBA\x3D\x03\x91\x2D\x89\x90\x91\x66\x8E\x91\x24\xDF\x83\x48\x1F\x08\x77\x07\x88\x60\x08\xE2\x41\x02\x4C\x21\x0D\x94\x92\xE4\x23\x08\x1E\xC4\x02\x4D\x22\x22\x4E\x08\x62\x47\x0A\x98\x48\x0F\x92\x45\x93\x96\x95\x65\x91\x94\x19\xB3\x98\x87\x5A\x8A\x8F\x95\x90\x92\x96\x2D\xD8\x84\x97\x5B\xBA\x96\x97\xBD\x9C\x97\x2E\x9A\x78\x22\xD5\x44\x90\x37\x4A\x0D\x95\x2E\xC1\x91\x88\x5C\x87\x97\x99\x8F\x90\x9A\x33\xD1\x94\x9B\x69\x96\x9F\x97\xC2\x80\x9B\x30\xE1\x88\x9A\x81\x0B\x08\x8F\x4C\x0A\x99\xB2\x4D\x02\x9D\x6A\x9D\x9C\x9B\xCC\x88\x9F\x36\xE3\x8B\x9D\x63\xBD\x32\x23\xC6\x92\x91\x4B\x4F\x05\x9D\x6B\xA9\x9C\x9D\xDA\x90",
|
|
"\x4C\x14\x08\x71\x0A\xC4\x52\x08\x71\x53\x02\x4C\x47\x71\x90\x95\x75\x95\x08\x8F\x56\x02\x4E\x47\x2A\x78\x0A\x31\x59\x0A\x4C\x5A\x18\x8F\x16\x75\x97\x9C\x7C\x99\x9F\xA2\xCD\x95\xA2\x3B\x9A\xA2\x9F\x7B\x9B\xA6\xA3\x1D\xAB\x9C\x17\x14\xA0\xA5\x82\xB9\x98\xA3\xEA\x87\xA5\x46\xA5\xA0\x96\x96\x8B\x9D\x9D\xD6\x60\x24\x41\xB1\x3E\x0A\x92\xB0\xA6\xA4\x28\xB6\xA3\x4A\xB7\xAB\x57\x2F\x08\x70\x0C\x88\x61\x0C\xE2\x62\x02\x4D\x31\x36\xA2\xA5\x72\x44\x0C\x1E\xE5\x02\x4C\x33\x22\x4F\x0C\x62\x48\x0E\x98\x69\x08\x8E\x35\x07\xA9\xA7\x1F\xBC\xA7\x4B\xC8\xAA\xA7\x94\x98\xA9\xA4\x5C\xB9\xA9\x58\xE0\xAF\xAB\xD7\x2B\x0F\xAA\x3B\xA3\xAC\x4E\xE9\xA5\xAD\x96\x9A\xAA\x9A\x1C\xBD\x54\x1B\x68\xAE\xAA\xB6\xB6\xAD\xAE\x78\xBD\xAA\x5E\xE2\xAD\xAC\xFC\x6D\x08\x71\x6E\x08\x73\x1B\x08\x72\x24\xD5\x71\x0C\xAE\x7B\xA6\x3A\x1C\x78\x83\x0E\x31\x74\x0A\x4C\x75\x02\x4E\x1D\x62\x47\x0E\x3C\xB8\x08\xB1\x7C\xB7\xAD\x62\xEB\xA9\xAF\xCC\x9D\xB4\xAC\x9A\xBE\xB3\x66\xEE\xAA\xAD\xFF\x79\x08\xB3\xA0\xBF\xB0\x67\xA3\xBB\xAB\xBE\xB0\xAE\xA5\xAF\xA9\x20\x49\x33",
|
|
"\xAD\xB5\xD0\xA9\xB4\xB5\xB1\xA5\xB5\x6D\xAA\xB4\xB4\xBE\x7B\x08\xB5\xAB\xA2\xB4\x05\xFC\x00\xB9\xD8\x3D\x0D\xB8\xBB\xB8\xB6\x39\xF7\x9E\x0E\xE4\xB9\xB6\xB5\xE9\x5F\x0E\x73\xCB\xBF\xAC\xEA\xBA\xB7\xB9\x34\x40\x13\x74\xF6\x95\xBA\xEE\x86\x21\x10\xDB\xAD\x26\x20\x61\xB0\xB6\xEB\x90\xBA\x8C\x83\x04\xBD\x77\xF1\xA1\x36\x42\x2A\xBF\xBA\x44\x85\x13\x7B\xE7\xBC\xBD\xE4\x82\xBF\xB6\xF7\xA1\xB8\x7E\xFB\xBA\xBF\xFE\xB1\x36\x10\x88\x67\x10\xE2\x08\x18\x71\x44\x22\x4A\x11\xF3\xBA\xB3\x22\x78\x8C\x10\x31\x4D\x12\x4C\x8E\x02\x4F\x23\x62\x40\x12\x3C\x91\x11\xC1\xBC\xB6\xBC\x7F\xBD\xB6\xB6\xFF\x9A\xC6\xC3\xD8\xB9\xC1\x88\xCA\xB2\x8C\x49\x18\xC4\xC4\xF5\xA3\xC5\x7E\x9C\xC2\xC4\xF3\x9A\xB3\x12\x88\x74\x10\xE2\x15\x18\x70\x4B\x22\x4F\x12\x27\xD4\x80\x26\x78\x89\x12\x31\x5A\x12\x4C\x9B\x02\x4C\x27\x62\x4D\x13\x1C\xDB\xC7\xC3\x2C\xDA\xAE\x27\x46\xCD\x57\x4F\x0C\xC9\xC9\x2B\xC8\xCA\x94\xA3\xC0\x14\xC4\x61\x10\x71\xA2\x08\x73\x28\x62\x44\x15\x27\xF8\x7D\x14\x78\x86\x16\x98\x27\x12\x4C\x54\x22\x49\x15\x62\x4A\x16\x97\xAA\xC7\xC8\x36",
|
|
"\xDA\x7B\x15\x6B\xCE\xC5\x8B\xDE\xB4\xBE\x85\x2C\x11\xCE\x74\xDD\xC0\x94\xED\xC2\xCE\x14\xE5\xB9\xCF\x98\x6D\x14\x9E\xA9\xCD\xCF\x28\xEE\xCB\x57\xAE\x03\xD3\x9F\x84\xDD\x37\x57\x0A\xD3\xBD\x8B\xD1\xD0\xA4\xEA\x30\x17\x47\xF0\xB8\xD0\x7E\xD3\xD3\xA5\x8C\xDC\xD2\x49\xDB\xD6\xD3\x1A\x51\x17\x89\xB2\x16\xD3\x3A\xDA\xD6\xD4\x9F\xC7\xD6\x9E\xD3\xCD\xCF\x59\x25\xD3\xD5\x87\xCC\xD4\xA6\xEF\x54\x17\x57\xF3\xCD\xD3\x09\x35\x16\xAD\x99\xD9\xD5\x5E\xE8\xD7\xD7\xB0\xC5\xD0\x9F\xB3\xD3\xD8\x5C\xC6\x26\x16\xBB\xC6\xD2\xB0\xA0\xCB\xD9\x3D\xCC\xDC\xD8\xBD\x57\x14\xE2\x38\x18\x71\x5C\x08\x72\x17\x62\x5B\x15\xB2\xCC\x5C\x16\x3C\xBD\x12\x4C\xBE\x02\x4F\x2F\x62\x40\x18\x31\x41\x1B\xDB\xCF\xC6\xDB\x40\x42\x18\x71\x61\x08\x74\x18\x88\x65\x1A\x98\x46\x18\xDD\x5D\x47\x18\x8F\xC8\x02\x4D\x32\x62\x4A\x18\x31\x4B\x1A\x4C\xCC\x15\xDE\xAC\xEA\xD1\xD8\x68\xCE\xDF\xE0\x03\xE0\xD5\xC1\x84\xE7\xD6\xF2\x0D\x18\x71\xCE\x08\x73\x33\x08\x70\x1A\x31\x51\x1A\xE0\xC9\x52\x18\x1E\xD3\x12\x4C\x6A\x22\x4D\x1A\x62\x56\x1A\x98\x57\x18\x8E\x6C\x22\x49\x1B",
|
|
"\x18\xED\xD9\xC2\xAA\xDD\xE0\x96\xFC\xD0\xD8\x72\x5A\x1A\x98\x5B\x19\xE4\x83\xEB\xE6\xD7\x0B\xEA\xE1\xCB\xB8\xEB\xE6\x98\xEF\xE4\x46\xDC\x08\x71\x37\x08\x7E\x1A\xC4\x5F\x1A\x4C\xE0\x15\xE7\x90\x61\x18\x8E\x71\x22\x4B\x1C\x62\x44\x1E\x98\x65\x12\x4C\x73\x0A\xEA\xE7\x3F\xFD\xE5\xCE\xAE\xEA\xD8\x9B\xF1\xD7\xEB\x2A\xE0\xED\x6F\x67\x18\x70\x74\x08\x71\x1D\x88\x6A\x1E\x98\x6B\x17\xEA\xF5\x2C\x18\x8F\xED\x02\x4E\x3B\x62\x4F\x1C\x31\x70\x1A\x4C\xF1\x18\x8E\x3C\x62\x43\x1F\xB6\xFC\xE1\xEB\x80\xFD\xE8\xC3\x81\xF5\xD8\xAC\xC2\xF6\xF0\x85\xFC\xEA\xF5\x74\x1E\xEE\x9F\xF5\x1A\x4C\xF6\x0D\xF3\xD6\xFF\xE7\xF0\xC5\xE9\xD8\xF1\x97\xF6\xF0\xC2\xC9\x57\x1E\xC4\x78\x18\x71\xF9\x08\x72\x3E\x62\x4B\x1E\xC9\xF2\x4C\x1F\x78\x9D\x1E\x98\x7E\x1E\x4E\x31\x40\x02\x2D\x02\x30\xF5\xEC\xB2\xFF\xF4\xCC\xDB\xF1\xEC\xB8\xFE\xE9\xEE\x83\xF5\xF2\xCA\xC6\x3A\x00\xB4\xF4\xF4\xE1\x99\xFE\xF6\xE2\xFE\xE5\xF7\xC7\xE9\xF1\xF1\xB7\xFA\xF7\xE6\xFC\xF2\xF9\xC9\xFD\x57\x00\x41\xF6\xF7\x9B\xD1\xFC\xF9\xCF\xE6\xFB\xE4\xD7\xF6\xFB\xED\xDE\xFA\xEB\xE0\xE3\xF8",
|
|
"\xF6\xD5\xF3\xC4\x02\x14\xFE\xE5\x05\x07\xFF\xF2\xDD\xF1\xFC\xE4\xDF\xFA\xFC\xEC\xF0\xFE\xD8\xD9\xF3\xFC\xCD\xF1\xFE\xFD\xED\xE6\x3A\x01\x6A\xFC\xFB\xF9\xE4\xFB\xF7\xFF\x7E\x7C\x01\x8D\x12\x07\x0C\x7F\x0B\x16\x80\xF9\x7A\x7D\x09\x85\x7F\x70\x29\x00\x08\x83\x27\x0A\x0F\x80\xC3\x1B\x00\x12\x86\x1C\x0C\x0F\x80\x0D\x05\x81\x0A\x8B\x3A\x0E\x0A\x81\xBB\x2F\x00\x0F\x80\x01\x0F\x81\x01\x0F\x82\x01\x0F\x83\x01\x1E\x87\x7F\xD0\x7F\x7E\xF8\x72\x7F\x00\x86\x7F\xFE\x70\x83\x2F\x8B\x7E\x31\x84\x83\x33\x8D\x7F\x44\x44\x01\x29\x83\x62\x15\x0B\x83\x37\x8C\x82\x2B\x82\x27\x16\x0E\x83\x02\x82\x83\x45\x86\x83\x47\x88\x83\x49\x80\x84\xAF\x17\x01\x44\x84\x7F\x2A\x8B\x5A\x18\x0F\x84\x03\x85\x85\x46\x80\x85\x35\x8A\x84\x58\x89\x2E\x19\x04\x85\xEB\x4A\x01\x5E\x88\x84\x5B\x8B\x84\x0B\x81\x85\x0C\x8A\x85\x56\x82\x86\x69\x8E\x73\x1B\x01\x86\x39\x5C\x01\x6E\x8C\x84\x67\x8F\x7E\x1D\x01\x87\x65\x89\x85\x72\x89\x1A\x1E\x06\x87\x2E\x84\x86\x7D\x83\x86\x80\x8B\x86\x79\x8C\x43\x1F\x0C\x87\x2D\x87\x88\xD6\x30\x02\x86\x81\x84\x7F\x82\x88\x77\x8F",
|
|
"\x83\x8F\x8E\x87\xEF\x21\x02\x8B\x8A\x3D\x22\x05\x89\x73\x81\x89\x81\x87\x85\x8E\x8D\x88\x9C\x8F\x89\x6A\x80\x8A\x7C\x33\x02\x98\x88\x3F\x24\x05\x8A\x78\x8A\x89\x9D\x88\x88\x1B\x8D\x82\x25\x08\x8A\x90\x8E\x89\x5C\x56\x02\xB0\x82\x89\x8C\x8C\x8A\x99\x82\x8B\x68\x82\x8A\x02\x17\x02\xB5\x82\x38\x28\x0F\x8B\xAB\x87\x8B\xC4\x8D\x8A\xC5\x89\x8B\xB8\x86\x86\xCA\x89\x8A\x73\x29\x02\xC2\x83\x36\x2A\x0F\x8C\xA1\x83\x8D\xBB\x84\x8D\x9A\x5B\x02\xD2\x85\x8D\xDA\x83\x88\x7D\x6C\x02\xD9\x8A\x39\x2D\x0F\x8D\xAA\x83\x36\x2E\x02\x8E\x7A\x5F\x02\xE6\x89\x8C\xCC\x8A\x8E\xB1\x83\x1C\x30\x0F\x80\x31\x09\x8E\xC7\x8B\x8C\xED\x83\x8F\xCC\x82\x03\xF2\x86\x8C\xFA\x88\x8C\xF6\x85\x8F\xFB\x84\x8F\xB6\x8A\x3D\x33\x09\x8F\xFC\x8F\x8F\xEB\x8D\x8F\x7E\x84\x03\x04\x90\x90\x9B\x86\x8D\xE3\x8E\x90\xBA\x8A\x59\x35\x0B\x90\x07\x96\x90\xFE\x85\x90\xB9\x86\x03\x0F\x87\x03\x0F\x88\x03\x14\x97\x91\x0C\x93\x8C\x16\x91\x90\x18\x91\x92\x2E\x79\x03\x1F\x94\x92\x26\x90\x91\xEC\x8E\x87\x3A\x0F\x80\x3B\x09\x92\x0D\x9B\x8D\x0F\x94\x93\x00\x0C\x03\x7C\x8D\x03",
|
|
"\x7C\x8E\x03\x7C\x8F\x03\x0F\x80\x04\x32\x98\x75\x41\x06\x8E\x42\x0F\x80\x43\x0F\x80\x44\x0F\x80\x45\x0F\x80\x46\x01\x94\xBC\x85\x93\xDC\x8A\x92\x23\x67\x04\x0F\x88\x04\x4E\x9C\x92\xD6\x39\x04\x57\x96\x93\x2D\x93\x93\x51\x9E\x95\x50\x91\x96\x00\x0A\x04\x0F\x8B\x04\x5B\x92\x10\x4C\x07\x96\x62\x9D\x95\x22\x99\x64\x4D\x0A\x96\x11\x9B\x96\x08\x90\x96\x71\x95\x97\x6C\x9F\x94\x76\x93\x97\x6D\x99\x5C\x4E\x06\x8E\x4F\x00\x97\xC3\x10\x05\x80\x9A\x97\x78\x97\x97\x58\x93\x92\x2D\x11\x05\x83\x9F\x1A\x52\x0B\x98\x49\x63\x05\x0F\x84\x05\x8E\x9B\x92\x5C\x94\x98\x87\x9B\x2B\x55\x03\x99\xAD\x16\x05\xE6\x87\x05\x0F\x88\x05\x9A\x90\x92\x15\x95\x92\xA3\x99\x5C\x59\x01\x9A\xBD\x1A\x05\xE6\x8B\x05\x0F\x8C\x05\xA8\x94\x97\x86\x95\x99\x88\x94\x1E\x5D\x0F\x9A\x7B\x95\x9A\xB8\x92\x9A\xE9\x2E\x05\x7C\x8F\x05\xB6\x95\x98\xD6\x3C\x01\xCE\x13\x17\x6F\x1F\x2E\x74\x11\x17\xC6\x95\x9C\xCC\x27\x9C\x9C\x19\x9C\xC8\x9B\x9C\xCA\x9D\x2B\xDF\x19\x10\x8E\x21\x17\xE6\x19\x10\x06\x3A\x3A\x13\x2F\x9C\x32\x13\x9D\x06\x1A\x2D\xD6\x9A\x10\x6B\x38\x14\x06",
|
|
"\x1B\x9D\xCD\x95\x13\xE6\x95\x1B\x4C\x2C\x9C\x03\x1C\x9E\xBC\x1E\x9C\xE7\x9D\x2B\xEE\x91\x1C\xF0\x9A\x9E\xD0\x9C\x9D\xBB\x23\x9F\xC4\x15\x9F\xEF\x97\x9F\xF1\x99\x9F\xD1\x9B\x2B\xDE\x93\x10\xC2\x7E\x13\xD7\x94\x9C\xE4\x93\x10\x07\xA3\x10\xC3\x98\xA0\xE5\x91\xA0\x2B\x13\xA0\xB1\x7F\x16\x0B\xA2\x10\xFA\x9D\x12\x15\xA1\x10\x0D\xAD\x9E\x0A\x19\x9E\xFD\x92\x13\xFA\x9E\x13\x3E\x1B\xA1\x34\x27\x17\xC2\x7E\xA1\xF4\x98\x9E\x10\xAA\x12\x21\xA2\xA2\x32\x14\xA2\x72\x2D\xA2\x2E\xA5\x2B\x32\xA3\xA3\xE9\x25\xA3\x36\xA3\x24\x38\xA3\xA3\x3A\xAB\xA2\x37\xAE\xA3\x09\x32\xA1\x01\x1E\x10\xB5\x19\xA1\x00\x0D\x32\x09\xA2\x10\x46\xA6\x33\x09\x1A\x9F\x28\xAB\x9F\x35\x12\xA4\x04\x14\xA1\x0A\x18\xA4\x49\xA5\x1E\x0A\x1C\xA4\x0E\xA3\x10\x4F\xA6\xA3\x2B\x1B\xA3\x2E\xA0\xA3\x73\x26\xA2\x1D\xA0\xA4\x5D\xAE\xA5\x29\x10\xA6\x22\xA2\xA6\xC3\x1A\xA6\xFC\x99\xA2\xF2\x90\xA4\x43\x27\xA6\x68\xAE\xA6\xFE\x96\x9F\xBD\x24\xA6\xAA\x3D\x12\xFA\x92\xA5\x11\x31\x9E\x09\x1C\x42\xAA\x36\xA4\x33\x4D\xA4\x65\xA8\x9F\x2B\x12\x7C\x8A\xAA\x10\x7E\xA4\xA5\x81\xA7",
|
|
"\xA5\x01\x14\xA8\x62\x24\xA7\x5E\xA6\xA7\x71\xA8\xA8\xC9\x26\xA9\x02\xA9\xA5\x8E\xA6\x10\x56\x40\xA9\x46\xA9\x46\x86\xA9\x10\x94\xA6\xA3\x52\xAA\xA5\x45\xAA\x10\x9F\xA7\xA5\xA1\xAA\x10\x4E\xA0\xA4\x9A\xA4\xA3\x72\xA4\x1E\xB1\xA9\xA9\xB3\xAA\x1E\xB5\xA9\x2E\x77\x12\xA6\xB9\xA9\x30\xBD\xAD\xA3\x98\xAF\xA3\xC1\xAE\xAB\xB7\xAC\x19\xFA\x9F\xAB\x6F\x12\xA5\x7A\xAB\xA5\x1F\xA0\xA0\xC3\xA0\xAC\xFF\x92\xAB\xCF\xA4\xAB\xC5\xAA\x21\xC8\xA8\xAB\xD5\xA4\x23\xD7\xA0\x27\xDB\xA6\xAD\xD9\xA1\x1C\xC7\xAF\xAD\xC4\x1A\xAC\x6F\x12\x7C\x52\xA0\x36\x9C\x16\xA4\x71\x4A\x9D\xE2\xA3\xA2\xAE\xAD\xAE\xBF\x70\xAF\xAF\x1D\xAD\xDA\xA2\xAF\xB1\x14\xAF\x31\xA6\xAF\xA9\x18\xAF\x73\x2C\xAF\x6D\xAA\xAF\xAD\x1E\xAF\xF1\xA3\xAD\xD8\xA4\xB0\xDC\xA0\xB0\xB8\x12\xB0\x20\xAF\xAE\x06\xB5\x1B\x52\xA2\xA5\xCF\x20\xA8\x06\x15\x36\x83\xAA\x10\x69\x39\x10\x52\xA5\xAA\x3C\xAD\xA9\x49\xAE\x13\x17\xAF\x16\xBC\xA8\xB0\xBD\x1A\xB0\xF7\xA2\xB2\x7C\xA6\xB2\x0C\xB1\xAD\xB6\xAD\xB0\xF5\xAC\xB2\xF9\xAE\xB2\xFD\xA8\xB2\xA3\xAA\xB2\x48\x21\xAE\x30\xBE\x13\x52\xAB\xA8",
|
|
"\x18\xBC\xA8\x0A\x1B\x29\x12\xB3\x10\x13\x3C\xAC\x91\xAA\x10\x7F\xA6\x10\x19\xB2\xB2\x62\xAB\xAC\x1C\xA7\xB3\x03\xB4\xB3\xC4\xAC\xB4\xF3\xA2\xB3\x42\xB0\xA5\x97\xAE\xB4\xD0\xA8\xA7\xCE\xA6\xB5\xD4\xA0\xB5\x25\xBC\xB5\x5F\xA9\xB2\x58\xBB\x22\x39\xB0\xB6\x02\x1F\xB0\x3D\xBC\xB1\x02\x11\xB4\x4B\xB6\x10\x46\xA5\xB4\x03\x17\xB4\x5E\xBA\x12\x49\xB5\xAE\x64\xB0\xA7\x59\xB1\xB6\x2B\xBA\xB5\xEA\x17\x17\xE4\xA1\x17\x36\xBA\xB7\x07\xB1\xB7\x09\xB2\xB5\x1D\xB1\xA5\x90\xA4\x1C\x7D\xAA\x10\x3A\x3F\xB3\x02\x1B\x46\x15\xB9\x10\x8E\xBD\x1C\x87\xAE\xB4\x24\xBB\xAF\x84\xB6\xA1\x97\xB1\x10\x95\xB1\xB0\x99\xB0\x00\x9B\xB3\xB8\x82\xB3\xB2\x9D\xBF\xB9\xA2\xB1\xBA\x7F\xB8\xB7\x48\x23\xB6\x90\xA2\xA6\x52\xAE\xB3\xE9\xA1\x11\x62\x2D\xB6\x0A\x12\xA6\x1A\xBE\xA2\x77\x17\xBA\xCD\xA2\xAD\x80\xBE\xAD\xA1\xB7\xB2\xBD\xB5\xB7\x54\xB7\xB7\xB9\xB9\xB7\xA8\xBF\xB4\xBB\xBD\xB2\xC7\xBF\xB2\xC9\xB8\xB8\xC0\xB8\xA6\xA9\xB7\xB8\x38\xB0\xBD\x35\x18\xBB\x76\xBA\xBB\xC5\xB7\xB5\xC3\xB2\xAC\xCB\xBF\xAF\xBF\xB3\xB3\xD7\xBB\xB5\xDB\xBD\xB4\xDF\xB5\xB0\xE1",
|
|
"\xB1\xB5\xA6\xBD\xBC\xCE\xBC\xB7\xD2\xBD\x9D\x3C\xB9\x10\x89\x2C\xB8\x01\x16\x2E\x67\x1A\x10\x46\xA4\x2E\x09\x14\xBB\x40\xA2\x7C\x2D\x16\xAE\x0A\x1F\x2D\xAF\xB9\x10\x90\x30\xAA\x15\x11\xBB\x0A\x11\xC0\x53\xB6\xA4\x92\x32\xB9\x09\x16\xA4\x06\xCF\xB6\xF4\xB3\xC0\x0B\xCF\xC0\x09\x17\x38\xA4\xA3\xB9\xC5\xBA\xBF\xAE\x7F\x16\xED\x1A\x3A\xC2\x7C\xBA\xFD\xB8\xB6\x01\x1D\xC0\x09\xA8\xC0\x04\xC0\xC0\xC0\xB4\xC2\xF7\xB2\xC1\x06\x12\xC2\x01\x12\xA5\x28\xCC\xB6\x2A\xC3\x10\x14\xCF\xA0\x15\xC3\xAC\x3A\xBA\xC0\x57\xAE\x13\x1B\xC9\xC3\x2A\xAB\xB3\x09\x1E\xBF\xA9\xA6\xC2\x02\xC9\x10\x09\xC4\xA0\x31\xC2\x10\x2C\xCE\xB9\x47\xC1\x10\x45\xC2\x10\x62\xAC\xC0\xED\xB0\xC3\x44\xCB\xC4\x58\xA3\xC1\x16\xC2\x10\xB5\xB2\xA2\xC2\x7A\x9F\x46\xA2\xA5\x40\xCC\x1B\x50\xC3\xC4\x06\x1D\xC4\x01\x12\x7C\x61\xC7\xC0\x10\xC8\xC3\x0A\xA5\xC0\x51\xCB\xC6\x53\xC1\xC1\x70\xC6\x10\x33\xCC\xA5\x57\xC5\xBD\x2A\x1B\xC5\x54\xC7\x17\x3B\xC4\xC7\xE7\xBE\xBD\xD9\xB6\xBC\xE3\xB1\xB8\xE5\xBD\xB5\x83\xC6\xB9\xDD\xB3\xB5\xCE\xB0\xC8\x7F\xC8\xBD\x76\xCA\xBD\x81\xCC",
|
|
"\xBB\x85\xCC\xA2\xE8\xB8\xA6\xEA\xBE\xC7\x8D\xCA\xC8\x97\xCC\xC8\xC1\xB6\xBD\x8B\xC0\xBE\x8F\xC8\xBC\x9F\xCA\xBC\xA1\xC1\xB3\x87\xCB\xB6\xA3\xCC\xBD\x91\xC9\xA6\x93\xCE\xA5\x95\xC8\xC8\xE9\xBE\xC9\x9D\xC4\xBE\xA7\xC2\xBE\xB1\xC2\xC8\xB3\xC6\xBE\xA9\xC5\xBA\xB9\xCE\xBB\xBB\xCB\xCA\x39\xA0\xCB\x99\xCF\x16\xD4\xBB\xC9\x40\x26\xB6\xD8\x90\xC2\x00\x0A\x40\x62\xC3\x10\x1A\x4C\xAE\xC3\xA2\xA5\xD9\x9F\xBF\x06\x1A\xCC\xAC\xAA\x10\xCD\xC3\xBF\x35\xC4\xB9\x40\xAC\xA6\x12\x26\xA6\xB0\xAB\xCD\xC0\xC4\xCC\x8E\xC5\xCB\x90\xC7\xCB\x84\xC6\xCE\x86\xCD\xCB\x96\xC2\xCE\x98\xCC\xCE\x9A\xC9\xC8\xEF\xCF\xCA\xB2\xC4\xCE\xBC\x13\xCC\xF0\xC9\xAC\xBE\xCB\xB1\xF3\xC1\xCC\xFB\xCE\xCE\xE1\xC7\xCF\xFD\xC0\xD0\xB6\xC4\xCF\xA2\xC4\xD0\xA4\xCA\xCE\xAE\xC4\xC9\xFF\xC2\xCF\xC6\xA9\xCF\xB6\xB8\xCF\x3E\xCC\xC3\x32\x16\xA4\x87\xB5\xC5\xD8\xC3\xB5\x59\xC1\xBD\x90\xA6\xA0\x15\xD4\xC5\x78\xC9\xCD\xC5\xBD\xAB\xDC\xCF\x1A\x4A\xB8\xC5\xDE\xC3\xAC\x22\xDB\xD0\x0A\xD1\xD0\x0C\xD5\xCE\x06\xD8\xCA\xE8\xCC\xB9\xA5\xC8\xB9\x33\xDA\xB9\xA3\xB7\xD3\x35\xDA\xC4",
|
|
"\x7D\xC9\xD0\xAC\xC0\xD1\x34\xCA\xCD\x39\xD8\xC1\xEB\xC7\x17\x5D\xCE\xD0\xFF\x05\xD4\xCB\xCA\xA4\x27\xC4\xC5\x2E\xCC\x1E\x54\xC9\xD1\x35\x17\xC3\x0E\xCB\xD1\x35\x14\xD1\x74\xB4\xD5\x2F\xA6\xD4\x6F\xAE\xCF\x2C\xDB\xD2\x03\xDC\xCF\x5F\xDC\xD5\x61\xD2\xD0\x2E\xD0\xD6\x65\xD2\xD6\x67\xD4\xD6\xA0\xCF\xD2\xD3\xBA\xD5\x50\x2D\xB7\x9C\x1E\xC1\x09\x1B\x2A\xF0\xB0\x00\x57\x39\xD4\x01\x18\xAE\x0C\xA4\xC5\x8B\xB2\xC5\x3F\xD1\xD3\x29\x10\xD7\xB5\x1F\xA4\xA4\xBC\xCB\x80\xDD\x1B\x52\xA4\xD7\xD2\xC3\x10\x77\xD5\xCD\x09\x1A\xD7\x4E\xCC\xD7\x4F\xD2\xB2\x4F\xAA\xC7\x6D\xCB\x10\xC8\xCA\xD8\x49\xA6\xA4\x11\xB8\xC6\x09\x14\xA4\x65\xB5\xC7\x68\xDC\x1B\x73\xB1\x17\x7B\xC4\xD3\x08\xD6\xCA\x6C\xDF\x1A\x52\xA9\x23\x8B\xD2\x10\x9A\xD3\xC2\x0A\x1D\xD9\xAA\xD3\xB4\x9F\xD7\xD9\x01\x10\xD5\x2D\x27\xDA\xE4\x9C\xD1\x58\xDF\x12\x52\xA5\xD8\x6E\xD2\x9D\x0A\x16\xBF\xAF\xD1\x10\xB1\x38\xD7\x00\x09\x3A\x18\xD2\xB2\x82\xD4\xDA\xEB\xBF\x12\x1F\xBE\xB7\xB8\xD0\x00\xC6\xD1\xC4\x06\x19\xDC\x8E\xD6\x10\xCC\xD5\xDB\x00\x0A\xDB\x2F\x22\xD4\x9C\x1F\xD1\xA9",
|
|
"\xD8\xDA\x87\xD4\xDE\x87\xD3\xDD\xE3\xD1\xDD\x5F\xBF\xDB\xED\xD2\xD1\x2F\x15\xDA\x9C\x15\xD9\xC8\xCD\xCA\x85\xB2\x13\xF4\xD5\xD7\xC2\xDB\xCE\x6A\xD5\xD0\x66\xDB\xD6\xFF\xDE\xDF\xA3\xD2\xE0\xFD\xD7\xD0\x87\xD6\xD8\xAB\xD7\xCE\x09\xE9\xCE\xE9\xD3\xDC\x2F\x2F\xDC\xC1\x19\xDF\xC7\xD0\x00\x52\xA2\xBF\xD8\xD7\x3C\x87\xB6\xA4\xB5\x3F\xB8\xE6\x3B\xD4\x09\x16\x40\x11\xDE\xC6\x06\x13\x3E\x09\x1C\xDB\xDF\xDF\xCD\x39\xD4\xBA\xE8\xDB\xE0\x32\xD9\xCB\xEA\xD5\x1B\x21\xB9\xE2\x38\xD5\xDE\x36\xD2\xE3\x36\xE9\xCB\x2B\xE1\xE0\xCC\xB1\xE2\x02\x16\xA5\x17\xE2\x10\x48\x4C\xE1\x03\x16\x43\x3C\xE6\xDB\x06\x14\xE4\x7E\xDC\xC7\x40\xD4\xE3\x3A\xD8\xE3\x0E\xEB\x22\x89\xB9\x10\x3E\xE0\xC6\x0A\x11\xE4\x17\xD2\xE2\x43\xE5\xDD\x46\xA8\xE4\x58\xE6\xD2\x28\xD3\xE3\xE7\xDF\xE4\x40\x2F\xE2\xF5\xCC\xDE\x72\xB3\xBB\x57\xDC\xD3\x36\xAD\xAB\x29\xD4\xDD\x29\xCE\xE6\x6A\xE3\xA3\x23\xD1\x1B\x73\xEF\xDE\xDE\xD9\xC8\x75\xE7\xC7\x68\xE1\x17\x1D\xCE\xD3\x77\xEE\xBC\x6D\xED\xD0\x6F\xE2\xE8\x6A\xCC\x1B\x7D\xE1\x17\x62\xA9\xE7\x29\x17\xE8\xEB\xD3\xE8\x30\xEB",
|
|
"\xE7\x8D\xE5\xE8\xE0\xA2\xE6\x29\x1A\xE8\xBD\x16\xE9\x46\xA8\xE9\x90\xEE\xB0\x9B\xEC\x1B\x52\xA6\xE9\xFA\x90\xEA\x9D\xE1\x1C\x26\xE1\xE8\x9C\xEE\xE8\x86\xE3\xEA\xC4\x1C\xE8\xA7\xE2\xE9\xC4\x19\xE9\xC8\xCE\x07\x64\xED\xD1\x39\xE0\x00\x72\xD7\xE5\xE6\xD1\xD9\x45\xE5\x7B\xEB\xC7\xEB\x53\xD6\xB4\x5A\xE4\xC5\xB0\xEB\xEB\xBE\xEA\xEB\xC0\xE5\xE2\xD5\xD6\xE2\x52\xAA\xEC\xC0\xB5\xEC\x35\xEE\xEA\xC1\xDA\xEA\x70\xB3\xB5\xCE\xE7\xE2\xBD\xE5\xDD\x84\xD2\xED\x0A\x1E\xDA\x03\x11\x26\x09\x1C\xED\x02\x1E\xED\x06\x10\xEE\x01\x12\xEE\x03\x14\xEE\x00\x06\xEE\x98\xD9\x10\xEA\xE8\x23\x0A\x1D\xEE\x00\x08\xEE\xF0\xE2\xEF\xDB\xEF\xEE\xF5\xEC\xEE\xF7\xE6\x10\xF0\xED\x27\x09\x1C\xEF\x06\x1F\xBE\xFF\xEA\x10\xD5\x96\x10\xAE\xB3\x10\xA0\xD5\xEE\x02\xF7\xB6\xB7\xD8\xEF\xD4\x9A\xF0\x06\x17\xF0\xE9\xE9\xF0\x09\x15\xF0\xA6\x2C\xF0\x06\x13\xF0\x03\x14\xF1\x43\xA6\xEF\x0D\xF3\xF1\x0D\x1C\xF1\x17\xFE\xF0\x06\xF0\xF2\x03\x18\xF1\x02\x1A\xF1\x53\xA6\xF1\x25\xF2\xF2\x15\xFA\xEF\x12\xF4\xF0\x1F\xFA\xF2\x02\x16\xF2\x01\x18\xF2\x10\xF0\xEF\xB1\xD5\xF3",
|
|
"\x31\xFE\xF2\x73\xDC\xF2\x1B\xF2\xF3\x01\x19\xF3\x00\x06\xF3\x24\xF0\xDB\x3E\xF9\xF2\x3C\xF6\x10\x42\xF4\xF4\x40\xF0\x00\x4B\xFB\xF3\xDD\xEA\x10\x4F\xFB\xF0\x49\xF3\x10\x53\xFF\xF0\x45\xF1\xF4\x47\xF7\xF3\x52\xFB\xF5\x59\xFE\xF4\x5E\xFD\xF4\xB4\xD7\xF2\x50\xF1\xEE\xB3\xD1\xF6\x55\xF2\x10\x63\xFA\xF3\x54\xF1\xF5\x09\x1B\xF6\x43\xF5\xF6\x08\xFF\xF6\x68\xFE\xF6\x06\x10\xF7\x4C\xF9\xF6\x01\x18\xF7\x72\xF1\xF1\x74\xFE\xF1\x6D\xF6\xF6\x7F\xF0\xF3\x81\xF3\xF7\x77\xF5\xF7\x82\xF7\xF8\x80\xF8\xF5\x4D\xF0\x9E\x7F\xD9\xEB\x1A\xA5\xDD\x8E\xFA\xE4\xDE\xD5\xED\x93\xFE\xE5\xD4\xE5\xDD\x5F\xC9\xDB\xCD\xEA\xF9\xA2\xD1\xEA\x9E\xF0\xD2\x90\xF6\xEB\xD5\xD7\xDD\x64\xF5\xF8\x7E\xF6\x10\xA6\xFC\xF6\x8C\xFA\xF7\xD6\xD8\xF8\x86\xF3\x10\xAB\xF1\xF7\xA8\xF0\xEF\xB3\xF9\xF7\x76\xF2\xFB\xB0\xF9\xFA\xBA\xFB\xF8\x23\xFD\xF4\xB7\xFD\xF7\xB6\xFB\xFB\xC3\xFE\xFB\x2D\xF9\xFB\x02\x11\xFC\xB5\xFA\x10\x16\xE7\xFA\xAD\xF8\xFC\xF1\xB4\xFC\xCC\xF2\xFD\x09\x1D\xFC\xAC\xFF\xFB\xAE\xF6\xFD\xB4\xFF\xFC\x89\xF3\x10\xDA\xF8\xFB\xDD\xF2\x10\xDF\xF2\xFC\xD3",
|
|
"\xF6\xFC\x3F\xF9\xFD\xD4\xFF\x10\xE9\xFE\xFD\xEB\xF2\x10\xD1\xC9\xF1\xE4\xF7\xCC\xE6\xF8\xF4\xD0\xF0\x00\xEF\xFE\xFC\xD8\xF5\xFF\xF7\xF7\xFD\xC7\xF1\xFE\x01\x1B\xFF\xDB\x79\xFF\x7E\x7E\xFB\x7D\xFE\x7F\x7D\x01\x84\x80\xF3\x7C\xEB\x72\x7E\xC2\x7C\xFD\x31\x7E\xFB\x67\x80\x00\x80\xFC\x4E\x81\x80\x0E\xB6\x78\x7D\xFF\x73\x80\x00\x05\x02\xBC\x7F\xF3\x75\xFF\x1A\x81\x00\x97\x80\xBC\x7A\x20\x1E\x80\x09\x81\x02\x94\x83\x01\x83\x81\xF1\x7E\x20\x28\x81\xE5\x70\x31\x27\x82\x0B\x89\x80\x5F\x7B\x05\x8D\x81\x12\x84\x03\xF0\x76\x0D\x9F\x7A\x37\x85\xE9\x79\x80\xD7\x7A\xB6\x69\x58\xEC\x49\x08\x3D\x81\x20\x01\x82\x00\x03\x04\xC5\x83\x0F\x86\x08\x46\x84\x05\xB3\x80\x78\x7A\x00\xCB\x81\x0A\x82\x80\x18\x85\x09\x90\x82\x1A\x82\x05\xA0\x80\x13\x9F\x7A\x53\x70\x03\x99\x82\x1A\x8B\x05\xF0\x75\x17\x95\x52\x58\x81\x0C\x8D\x7B\x2F\x82\xE5\x62\x82\xEB\x64\x83\x0C\x83\x0A\xB0\x76\x12\x8B\x06\xCF\x82\x05\x9C\x80\x03\x84\x0D\x87\x80\x39\x80\x03\xCD\x78\x1D\x89\x83\x56\x87\x00\xA8\x55\x37\x84\xFF\x03\x83\x1E\x9B\x80\x7D\x80\x03\xBF\x83\x0F\x80",
|
|
"\x07\x82\x86\x1E\x87\x84\x75\x86\xF5\x43\x85\x3B\x83\x10\x0B\x86\x1B\x81\x08\x8E\x82\x09\x8D\x84\x44\x88\x07\x85\x84\x0D\x9D\x6B\x8C\x6B\x22\x0A\x08\x8A\x56\x10\x17\x5A\x41\x03\x4F\x72\x64\x53\x49\x85\xFA\x73\xC7\x02\x09\x24\x8E\x82\x56\x61\x21\x27\x84\x35\x8A\x10\x25\x84\x24\x87\x80\xAE\x80\x00\x2B\x85\x3C\x89\x0A\x86\x0B\x2C\x96\x84\xF0\x71\x16\xB7\x85\x40\x84\x03\xBA\x84\x2C\x82\x85\x95\x84\x17\xB9\x84\x60\x80\xFF\x12\x86\x40\x1E\x85\xA3\x83\x00\x89\x63\x65\x89\xC6\x03\x08\x19\x6B\x6E\x0A\x0D\xBB\x42\x08\xED\x63\x10\x54\x87\x34\x8A\x08\x1B\x76\x20\x19\x87\x81\x0B\x0D\x82\x08\xF2\x09\x08\xDF\x86\x20\x21\x87\x24\x54\xE2\x57\x52\xA5\x75\x68\xF4\x03\x3E\x6C\x74\x81\x06\xE2\x43\x0F\x39\x80\x5E\x1E\x86\x1D\x8A\x09\x7A\x0A\x0E\xE2\x13\xEC\x72\x87\x09\x0E\x1E\x35\x86\x48\x58\xF2\x78\x86\x41\x17\x07\xFB\x87\x4A\x40\x78\x0D\x1D\x12\x78\x05\x40\x86\x62\x09\x0F\xF2\x72\x13\x96\x09\x0F\x07\x8A\xB1\x63\x08\x49\x63\x38\x2D\x08\x7D\x03\x9F\x2F\x55\x42\x1E\x84\x04\x8A\x21\x3C\x06\x87\x81\x10\x26\x70\x39\x2A\x0F\x62\x55\x1F",
|
|
"\x1C\x88\x0A\x76\xCD\x64\x0D\x4B\x1E\x07\x23\x8A\x4A\x57\x67\x8C\x88\x12\x23\x88\xBC\x74\x66\x2C\x88\xD5\x7C\x75\x71\x7A\x10\x09\x28\x48\x89\x0A\x30\x57\x44\x4A\x09\x80\x27\x13\xCD\x51\x4E\x9F\x7A\x5C\x75\x44\x73\x5D\x9F\x8D\xF4\x11\x5D\x4C\x8F\x5B\x44\x89\xC9\x42\x09\x75\x50\x27\x18\x51\x52\x9D\x72\x76\x26\x24\xAC\x0F\xA7\x83\x00\x80\x27\xDE\x5D\x50\x54\x88\x03\x8C\x25\xAB\x8F\xED\x59\x88\x0D\x98\x24\x5C\x8A\xDF\x5E\x8A\x78\x7A\x4A\x3D\x88\x9C\x06\x71\xE1\x21\x2C\x83\x08\x05\x0E\x15\xCF\x51\x3F\x2A\x8B\x02\x0B\x01\x23\x8A\x85\x03\x58\x70\x89\x40\x0C\x00\x30\x52\x3F\x7E\x77\x81\x0A\x54\x76\x88\x41\x1E\x8A\x7B\x8A\x20\x3D\x8B\xA6\x82\xF5\x00\x8E\x42\x14\x2A\x7E\x88\x02\x06\x8D\x84\x08\x18\x84\x8D\x42\x8B\x8C\x06\x0F\xAF\x3E\x8A\x09\x00\x19\x83\x0A\x64\x8E\x8C\xAA\x7E\x2B\x83\x88\x81\x07\x59\x7E\x88\x05\x1E\x8A\x34\x78\x00\x12\x2E\xBF\x85\x01\x79\x89\x75\x60\x2F\x7E\x8F\x02\x1E\x8A\x29\x58\x1A\x98\x8F\x40\x18\x00\xA0\x8A\x21\x23\x8C\xD7\x86\x0A\xB1\x8D\x42\x1A\x2E\x7E\x8A\x03\x36\x8C\x83\x08\x1B\xB4\x8D\x40\x1B",
|
|
"\x00\x5E\x88\x0C\x22\x6E\xCC\x7C\x37\x08\x73\x42\x86\x6A\x9A\x62\x4D\x55\x68\x29\x5F\x2E\x51\x75\x3F\x79\x62\x43\x15\xD4\x47\x5D\x5A\x7A\x1C\xE4\x0C\xBA\x7A\x4F\x52\x6B\xF4\x4C\x8E\x66\x11\x18\xCF\x76\x77\x6B\x87\x65\x61\x6E\x21\x8D\x77\x8B\xEB\x05\x50\xB3\x02\x7A\xE4\x8A\x29\xA1\x8F\xB1\x1B\xF9\x33\x8A\x86\x06\x71\x46\x57\x5D\x33\x7C\xF3\x8F\x1A\x4F\x50\x74\x84\x0F\xDA\x78\xF4\x7B\x75\x6C\x73\x36\x1E\x82\x45\x87\x76\x8F\x7D\x85\x71\x1B\x2D\x8A\x9F\x1B\x8E\x80\x9F\x76\xA2\x6F\x5D\x18\x85\xD1\x72\xF4\x42\x3F\x75\x91\x1B\x90\x6E\x3B\xAA\x7A\x31\x18\xEE\x5B\x8D\xAF\x18\x88\xA3\x7A\x21\xAE\x8E\x81\x0D\x1D\xD6\x74\xF0\x11\x85\xFA\x4D\x3D\x82\x3F\x0E\x95\x1D\xEA\x0F\x33\x9A\x4F\xF3\x8A\x21\x1D\x90\x0B\x9B\x2B\x56\x86\x84\x91\x7E\xAA\x1E\x40\xB4\x81\x77\x13\x0E\xA1\x6E\x7A\x12\x91\xA1\x8F\x5D\x30\x88\x76\x84\x1E\x21\x8D\x87\x8F\x17\xAB\x50\x21\xB0\x12\x94\x70\xEF\x6F\x16\xA8\x58\x75\x72\x10\xE5\x79\x90\x66\x16\x14\x8F\x88\x8D\x10\x78\xF7\x8A\x3D\x0C\x8A\xEF\x60\x00\xFA\x4C\xC4\x65\x91\x70\x17\x8E\x2B\x67\x21\x86\x25",
|
|
"\xD5\x6F\xBB\x1C\x23\xEB\x63\x10\xBA\x4E\xB8\x71\x25\xF0\x12\x55\x93\x5A\x8D\x6E\xBB\x70\x7A\x2C\x9A\x21\x5B\x8B\xD4\x5C\x84\x6A\x96\x4B\x8C\x16\xB0\x83\xB5\x20\x86\x77\x7A\x90\x42\x7F\x5D\x1C\x25\x5D\x73\x1C\x1A\x91\x7B\x8F\x17\xA6\x20\xD9\x6A\x0F\xF6\x80\xF7\x6F\x17\x37\x34\x2D\xAD\x0B\xF6\x79\x92\x66\x19\x16\xC8\x93\x9C\x13\x7D\x7F\x94\x59\x1F\x88\x57\x73\x1C\x5A\x7D\x99\x9A\x10\xFB\x23\x9D\x49\x62\x31\x59\x1F\xF1\x1B\x3F\x2B\x67\x2E\x94\xF4\x55\x7E\x39\x9D\x2B\x03\x2B\xD4\x45\x87\x7B\x6D\x05\x8B\x80\xBE\x16\x13\x8E\x97\x70\x03\x82\x83\x87\x5D\x0B\x29\x38\x78\x1B\x43\x81\x9A\x9A\x1C\x0F\x2C\xBF\x46\x0F\x41\x8B\x20\x98\x1F\x44\x28\x94\xB8\x0D\x57\x87\x53\xB8\x13\x52\x71\x62\x86\x17\x95\x01\x0B\x0B\xAF\x16\xA1\x26\x2C\xB4\x11\x84\x9E\x90\x7C\x1E\xA9\x2B\x67\x1D\x97\x20\x86\x0B\xB3\x8C\x93\x34\x12\xAA\x2B\x67\xA0\x85\x2D\x83\x0B\xB3\x8C\x91\xB5\x16\xAA\x2B\x67\x26\x9D\x2D\x82\x08\x86\x81\x08\x70\x92\x73\x33\x2A\x3E\x96\x1C\x76\x92\x40\x09\x97\x98\x1D\xB0\x00\x90\x0D\x11\x0B\xAC\x27\xD8\x0F\x2C\xEB\x64\x8E\x2B",
|
|
"\x67\x58\x80\x26\xC0\x1F\x64\x2B\x67\x7A\x23\x5F\x8A\x08\x41\x23\x36\x1D\x8F\xD4\x5E\x23\x02\x98\x1C\xB1\x1B\xD9\x23\xB5\x04\x9B\xD4\x51\x85\x6F\x23\x6C\x04\x2F\x75\x66\x49\x09\x9B\x27\x91\x1B\xCD\x28\x58\xBD\x0D\x58\x81\x2A\xEF\x17\x6C\x9E\x6E\x9A\x26\x62\x83\x08\x2B\x7C\x37\x2D\x8E\x77\x7E\x24\x22\x9A\x20\x2D\x23\xB1\x19\x5E\x6B\x64\x29\x29\x99\x01\x0B\x4F\x80\x1E\xF9\x2B\xCE\x28\x24\xCC\x80\x00\x28\x98\x78\x02\x31\x75\x66\x2F\x8F\x9A\x42\x01\x94\xC0\x1E\xC0\x2B\x67\x64\x2A\x29\xAD\x85\xDC\x0B\x30\x1A\x9D\x25\x0F\x87\x9E\x9C\x37\x0D\x32\xAE\x8F\x0D\xCF\x85\x5F\xBC\x1B\x08\x3F\x34\xB1\x0F\x33\x8E\x98\x7C\x1D\xC2\x15\x9B\xD4\x0F\x0C\xB5\x90\xE6\x06\x31\x5B\x9D\x35\x0F\x87\x88\x90\x3C\x32\x31\xD8\x98\x0D\xCF\x85\x63\x8C\x16\x1B\x37\x36\xBD\x0F\x33\x84\x99\x9A\x1B\xC7\x2D\x9A\xA5\x9A\x10\x2B\x98\xF0\x1F\x31\x73\x9D\x19\x82\x08\x99\x9C\x37\x43\x31\xDE\x8F\x63\x06\x09\x67\xBC\x1B\x25\x3F\x37\xE3\x63\xCF\x91\x1B\x55\x35\x70\x95\x86\x6C\x81\x37\x59\x31\xD2\x8C\x9C\x09\x0A\x1A\x98\x1D\x2D\x32\x13\xF3\x12\xD7\x80\x00",
|
|
"\xE7\x1B\x6C\x22\x33\xC7\x9A\x30\xAA\x85\xDC\x04\x33\xEB\x65\x51\x82\x92\x0C\x79\x10\x48\x97\xEA\x08\x33\xEB\x63\x52\xA3\x9D\x5E\x44\x0C\x9A\x1C\x9C\x2B\x67\xF0\x26\x51\xA8\x94\xAB\x11\x37\x02\x37\x3A\x74\x27\xAA\x19\x73\x86\x08\xA6\x9A\x39\x0E\x37\x3A\x79\x94\xF3\x92\x20\x3A\x9D\x81\x02\x35\x9A\x1E\xA8\x2B\x67\xA6\x97\xD7\x43\x09\xE1\x92\x10\x58\x9A\xE6\x0E\x35\xEB\x65\xA1\x3B\x74\xE6\x91\x10\x17\x9F\xBB\x1A\x35\xEB\x65\x58\x81\x9F\x80\x04\x3D\x80\x00\xD9\x9C\x1B\xD2\x33\x9D\x40\x2B\xE9\x9A\x10\x6A\x99\xAF\x16\x36\xEB\x63\x30\x8A\x9E\xE1\x95\xE5\x71\x1A\xB6\x2B\x67\xDA\x93\x7B\x98\x9D\xBA\x91\x37\x5F\x37\x3A\x6B\x97\xF2\x9D\x7B\xBC\x9A\xCD\x13\x6E\x6B\x66\xBC\x8B\x9F\xDC\x9A\x21\x02\x9C\xCD\x17\x6E\x6B\x64\xBE\x99\x9F\x87\x9B\x6C\x2E\x37\x75\x66\x30\x80\xA0\x00\x00\x71\xDC\x69\x6E\x32\x36\x76\x9F\x1A\x54\x97\x03\xB1\x1B\xFB\x34\x73\x86\x09\x95\x8C\x3A\xE3\x19\xBF\x3A\xA0\xCC\x62\x21\x1D\x9F\x77\x1F\x6F\x20\xA2\x40\x02\x54\xBB\x99\x6E\x01\x39\x75\x63\x31\xF2\x9C\x0A\xA4\x9E\x71\x19\xE2\x2B\x67\xDE\x8E\x40\xAF",
|
|
"\xA1\xF3\x91\x1B\x15\x3B\x9D\x6E\x2F\x5D\x76\x43\xD5\x9D\xDC\x1A\x38\xEB\x64\xC0\x3C\xA0\x85\x0F\x3D\x9A\x1E\xC7\x2B\x67\x4E\x9E\x85\xA5\x9F\xB8\x12\x72\x6B\x66\xD6\x8A\xA2\x09\x08\x6E\x98\x1C\x93\x3B\xCE\x66\x98\x14\xA6\x08\x76\x9C\x6F\x32\x39\x75\x62\x37\xD7\xA3\x40\x1B\x9F\x98\x19\xE8\x2B\x66\xBF\x9E\x45\x82\x0B\x00\xB8\x1C\x45\x3B\x9D\x49\x9D\x32\xA1\x10\x40\x98\xDF\x09\x3A\xEB\x65\xCB\x3B\x75\x42\x51\x41\xE3\x1A\xD3\x2D\x96\x72\x14\x5B\x80\x00\x3A\xAC\x37\x64\x3A\x09\xA1\x08\x52\xA0\x00\x3D\xA1\xD5\x16\x76\x7F\xA0\x00\x01\x92\x02\x0C\x77\x98\x1C\xB4\x3B\xCE\x66\x33\xAE\x68\xA4\x01\x0D\x78\x98\x1C\xB6\x3B\xCE\x77\x33\x23\xA3\x98\x71\x19\xEE\x2B\x67\x4A\x37\x49\x9D\x9C\xF0\x15\x3B\xEB\x65\xD6\x1D\xA4\x83\x05\x44\x98\x1D\xDE\x2B\x67\xD4\x33\x94\x8B\x9D\xB1\x1D\x77\x6B\x65\xB7\x2A\xA5\x40\x71\x6E\x0F\x3D\x75\x65\x6E\x30\xA5\x40\x19\xA2\x9A\x1D\xF3\x2B\x66\x78\x36\x4B\x80\x00\x18\xAB\x1D\xA1\x3B\x9D\x79\x37\x5E\xA7\x46\xAB\x1D\xE9\x2B\x67\x2B\xA2\x7E\x90\xA4\x00\x0E\x46\x9A\x1E\xEA\x2B\x67\x39\xA2\x7E\x87\x93",
|
|
"\x81\x02\x39\xAC\x1C\x15\x63\x0E\xE4\x90\x00\x13\xA6\xCD\x16\x7E\x06\xA4\x2E\xA1\x08\xCB\xA7\x5D\x29\x3E\x43\xA5\x4A\xD0\x96\xE6\x1B\x3F\xEB\x67\x88\xAA\x8E\xEF\x98\x1C\xD6\x8C\xED\x3A\x4F\x28\x38\x8F\xAC\xA6\x0A\xAB\x2B\x11\x43\x3A\x69\xA3\xEB\xA3\x4A\x82\x09\x80\x90\x3C\x17\x42\x21\xBA\xA7\x01\x0A\x5F\x80\x1F\x0C\x46\x48\x82\xA8\xE5\x7A\x1C\x1D\x43\x9D\x50\x3A\x79\xA6\x50\xA3\x7F\xBB\x02\x41\xEB\x65\x90\xAB\xA7\x86\xA5\x2E\x98\x1E\x09\x4B\x67\x9A\xA3\x9D\x9A\x92\x83\x0C\x4F\xFC\x1A\x0E\x46\xA4\x1B\xAB\x20\x14\xA9\xD5\x1D\x83\x06\xA5\x47\xA2\x08\xD5\xA7\x5D\x03\x42\x7A\xA9\x1A\x12\xA4\x00\x0A\xA4\xAB\x18\x0C\x6B\x67\xBD\x3B\xEB\x2E\xAA\x4B\xAF\x17\x70\x43\x9D\x51\x3D\x9A\xA8\x49\xE3\x1B\x1E\x4B\x67\xA3\x3C\xA7\x9E\xA4\xC3\x1F\x4E\x8A\x08\xEB\x22\xAA\xA4\xA1\x6E\x17\x45\x75\x60\x7C\x48\xAB\x2A\xA0\x1E\xA7\x43\x9D\x68\xA6\xF9\x9E\x52\x81\xA4\x8D\x85\xAA\xFD\x74\xF6\x12\x52\x97\xAF\x4D\xAB\x1D\x30\x4B\x67\x09\xAC\xAA\x8A\x09\x5F\xAA\x23\xD8\xAA\x41\x17\xA8\x62\xA9\x21\x05\xA7\x77\x1E\x8D\x6B\x67\x4A\xA9\xAB\x06",
|
|
"\x0D\x99\x98\x1D\x72\x4B\xCE\x32\xAA\xFC\x88\x98\x75\xA0\x78\x2F\x46\x79\xA3\x1C\x67\x93\x40\x18\xAB\x7C\x1B\x22\x46\xA4\xE7\x91\x10\x30\xAB\xBB\x1A\x48\xEB\x67\xA7\xB2\x9E\xC2\xA0\x00\x37\xA8\xB3\x1E\x48\xEB\x63\xA9\x8B\xAD\x9E\xA0\x3C\x2F\x4B\x3A\x74\x45\xBB\x74\xB1\x96\x9E\x66\x18\x93\x53\x96\x56\xB4\xAC\x03\x0D\x9C\xAF\x16\x9E\x4B\x2D\x9F\xAD\x42\x0C\xAC\xE6\x9B\x57\x00\x4B\x71\x96\x5A\x86\x08\x63\xB6\xAA\xCC\x15\x28\x79\x97\xD6\xA3\x10\x0C\xAD\x57\xAF\x17\x49\x4B\x9D\x56\xAD\xC9\xA9\x10\x64\xA8\xB3\x0D\x4A\x14\x9C\xB6\xB7\xA0\xB5\xA1\x37\x56\x4B\x3A\x72\xAD\xBC\xA9\xAE\xB1\x1A\xB2\x45\x33\xC2\xAD\x40\x0E\x93\x03\x09\x64\x80\x1F\xB4\x46\x48\xD0\xAE\x40\x15\x98\xC0\x1F\x2D\x46\xA4\xEC\xA3\x10\x06\xAC\xB3\x1D\x4B\x43\x9E\xB9\x80\x00\xEE\xA2\x10\x0E\xAD\xAF\x02\x4C\xB0\x9A\xBC\xA4\xAF\x80\x0C\x58\xEF\x15\x63\x4B\x67\xEF\xAA\x7E\xAB\xAE\x00\x0B\x59\xA5\x96\x59\xA3\x08\x9C\x4B\xD7\x73\xAE\xD1\xAC\x2C\x79\xAF\xD4\x4A\x4D\xFA\xAB\x89\xA3\x1A\xD0\x4B\xCE\x3C\x4D\x80\xB1\xA2\x71\x18\xC0\x93\x5A\x31\x0A\x5E\xF4\x9F",
|
|
"\xD8\x0E\x4D\xEB\x66\x0C\x0D\xB1\xDE\xA1\x37\x06\xB3\xD4\x4A\x03\x13\xB1\x70\xB1\x1A\xE1\x8B\xCE\x6E\x01\x86\xA3\x08\x72\xAB\x75\x0C\xB1\x75\x62\x07\x62\xAC\x9D\x91\xAE\x71\x1C\x0C\x3C\x42\xE9\xA4\x4D\xF1\x19\x19\x02\xAF\xC3\x0F\x97\xA9\xA8\x66\x19\x06\x34\x3F\x8F\x86\x0E\xBF\xA2\x94\x23\x1B\x39\x07\x5F\xB4\x11\x31\xB3\xB1\xBD\x15\x0E\x36\xB0\xF2\x05\x4C\xBA\xB0\xF0\x1F\x03\x3D\xB2\x4E\x06\xB3\x81\x0F\x32\xC0\x1D\x20\x1C\x43\x4D\xB5\xC5\xA3\x1A\x41\x04\x7B\x45\x92\x71\x01\xB1\x40\xB3\x57\x0B\x05\x21\xBA\x1E\x21\xB3\x92\xBA\x1C\x95\x01\xC9\xB3\x12\x9B\x99\x57\xFC\x1B\x25\x1C\x43\x65\x8E\x20\x24\xB2\xBE\x18\x09\x7C\x40\x4C\xBE\xAE\xBD\x11\x13\x22\xB2\x3B\x02\x5E\xB0\xAA\x79\xBB\x15\x9B\x02\xCC\xBA\x03\x3A\xB0\x5A\x9A\x1D\x27\x02\xB3\x7E\x04\xCF\x83\xAA\xCD\x1F\x09\x62\xB0\x95\xBB\x75\x30\xAC\xBF\xBD\x15\x50\x02\x66\x86\x06\xA0\xB9\x6E\x71\x1B\x14\x22\xB2\x45\x0F\x68\xA3\x99\xDC\x05\x05\x62\xB6\x11\x15\xB4\x95\x9F\x39\xE2\xB2\x24\x1B\xB4\x31\x99\x6E\x29\x04\x31\xB6\x09\x20\xB4\xCE\x91\x1B\xAB\x02\xCC\x9A\x04\x53",
|
|
"\xB1\x62\xEF\x15\x2B\x02\xB3\x9E\x02\xBC\x85\x27\x14\xA3\x36\x2F\x06\x98\xA2\x05\x0F\x43\xD6\xB0\xA1\xB1\x11\x0B\x62\xB2\xA4\xAA\x1D\xBA\xB3\xB8\x80\x1F\x59\x02\x66\xA4\x05\xAE\xAA\x08\xF5\xAB\x57\x35\x04\x31\xB8\x69\xC0\xB4\x11\xB1\x1B\xB7\x02\xCC\xA6\x05\x63\xB9\x10\x29\xAD\xAD\x19\x05\x62\xB7\x14\x14\xB6\x83\x00\x5B\xBD\x17\x2E\x02\xB3\xA8\x03\xDB\x83\x09\xDB\xAC\x2C\x3D\x06\x98\xA3\xB5\xCE\xB4\xC2\xA3\x1B\x5F\x02\x66\xAA\x06\xB8\xA6\xA3\x71\x19\x18\x22\xB3\x54\xB9\x6E\xCA\xAE\x02\xA2\xB3\xAC\x05\x2C\x4A\x08\x38\xBB\x2B\x45\x06\x98\xAF\xB5\xAA\x1F\x50\x86\x09\x3B\xB5\x2B\x47\x06\x98\xAE\x05\xFA\xB7\xB4\x98\xA0\x31\xB6\x6B\x81\xB8\xB2\xB1\x1B\xCB\x02\xCC\xB0\x05\x84\xB9\x54\xE3\x19\x33\x02\xB3\xBD\xB6\xE1\x95\xB7\xB8\x1F\x0C\x62\xB2\x2C\x14\xB8\x96\xB3\x6C\x11\x06\x31\xB4\x6C\x9A\xB8\x16\xB1\x1B\xD3\x02\xCC\xB4\x04\x90\xBB\x37\xF1\x19\x35\x02\xB3\xCB\xB6\xE4\x83\x09\xB5\xAC\x2C\x57\x06\x98\xB6\x05\x2C\xBD\x8D\xB1\x1B\x6C\x02\x66\xD1\xB6\xEA\x02\x9D\x02\x0C\x68\x80\x1F\x6D\x00\x63\xC6\x0C\xD0\xA1\x08\x02\xBC",
|
|
"\x6F\x1F\x06\xDA\x3D\x0E\xC6\x0E\xEA\x81\xBA\x71\x1D\x1C\x3C\x43\xA7\xB8\x74\xF1\x1A\x39\x14\x3D\xE9\x8B\x20\x31\x9D\xEE\xA1\x37\x69\x06\x98\xB8\x05\x62\xB3\xEB\xA5\xAF\xB8\x1B\x0E\x62\xB2\x2E\x01\xBB\x7D\xB0\x73\x2D\x06\x31\xBC\x0B\x68\xBB\xA0\xB8\x1C\xEF\x02\xCC\xBE\x04\xB7\xB5\x71\xC0\x1D\x3C\x02\xB3\xC0\x04\xEE\x8F\xAA\xBE\x13\x0F\x62\xB2\x30\x1A\xBB\xB1\xA3\x6C\x35\x06\x31\xB4\x0C\x00\xBF\x2D\xB1\x1B\xF7\x02\xCC\x86\x06\xC3\xBE\x4B\xF1\x19\x3E\x02\xB3\xC8\x04\xF1\xB4\xB9\x5E\x1B\x0F\x62\xB2\x32\x0C\xBC\xAD\xB4\x59\x3D\x06\x31\xBC\x0C\x62\xB0\xF0\x9C\xBA\x6E\x1A\xCC\x8E\x06\xCF\xBA\x10\x04\xB9\xB2\x01\x00\x15\x8A\x21\x10\x06\xD2\xBA\x70\xE3\x1B\x00\x09\xBD\x09\x0A\x1A\x2C\xBC\x71\x81\x37\x05\x00\xEC\xA6\x08\xD4\x03\xF6\xA1\xAD\xB8\x17\x00\x37\xBF\x40\x16\x06\xBA\xBF\x1A\xA3\x1B\x04\x0E\x7B\x82\x08\x36\x01\xBE\x80\xA1\x6E\x0B\x01\xE2\xB1\x10\x5A\x04\xF2\xA0\x00\xE4\xB5\x57\x0D\x00\xE6\xB0\x00\x5C\x07\xF3\xBE\xAD\xBD\x17\x01\x14\xBE\x6F\x0F\x7C\x93\xBF\xAE\x11\x00\xD4\xB8\x1C\x0F\xBF\xCC\xBD\x2B\x13\x00\xF5",
|
|
"\xA2\x07\x62\xB7\x2D\x86\x08\xDC\x90\x3C\x15\x03\x7C\x40\x97\xAD\x0A\xFD\x83\x09\x4F\x90\x3C\x19\x03\x7C\x4D\xBA\x8C\x4A\x21\x1F\xBC\xCD\x1F\x01\x23\x8B\x70\x1C\x89\xEB\xB9\x6E\x20\x00\xFF\xB6\x1C\x00\xC3\xFC\xB1\x1B\x21\x03\x3E\x59\xBA\x81\x09\x3C\x89\xA5\xDC\x04\x01\xD4\xBC\x1C\x18\xBB\x8D\x05\x7A\xF1\x1A\x09\x14\xBE\xE7\x03\x02\xC9\x09\x06\xCC\x5E\xF1\x18\x0A\x14\xBE\xEA\x02\x03\xC6\x08\x0E\xC4\x5F\xF1\x1A\x0A\x14\xBE\x6B\xBD\x72\xA4\xC0\x45\xBB\x2B\x2C\x00\xF5\xB0\x07\x22\xC3\x20\x24\xC0\x6B\xB9\x2C\x2E\x00\xF5\xBD\xBB\x2A\xC5\x7D\xA3\x1A\x18\x04\x7D\xF6\x05\x0C\xCC\xC0\x0E\xB0\x78\x32\x00\xEA\xBF\x78\xB9\xC2\xBA\xA0\x1E\x34\x04\xFA\xBC\x07\x1F\xC1\x10\x24\xC2\xF7\xB5\x15\x36\x04\xFA\xBF\x06\x26\xC0\x00\x24\xC0\xF9\xBB\x15\x38\x04\xFA\x82\x00\x05\xC5\x13\x8A\x0B\x41\x23\x1B\x3A\x04\x00\xEF\x0D\x59\x93\x10\x5A\x9C\xDF\x1B\x01\x52\xC6\x38\x39\x94\x83\x01\x51\x63\x19\x0F\x09\xC3\xAF\x0D\x0D\xC6\x08\xE9\x90\x3C\x3F\x03\xFD\xA4\x0F\xBF\x94\x0D\xF1\x1B\x22\x00\x87\xB1\x0E\x19\xC2\x08\x6B\xC4\x6F\x07\x02\x31\xCE",
|
|
"\x87\x8A\x09\x1E\xDC\x1B\x48\x04\x10\xE9\x0C\x99\x24\x6B\xC0\x1D\x12\x14\xBE\xB6\xBB\xD7\x4C\xC5\x5D\xB0\x3C\x4B\x00\xF5\xA4\xBE\x92\xC1\xED\xAB\x1D\x26\x04\x7D\xD3\xBD\x26\xCF\xBB\xAB\x1F\x09\x14\xBE\xF0\xBF\x89\xF5\xB8\xDF\x11\x02\xD4\xBE\xFD\xA5\xC5\xBD\xBA\x39\x53\x00\xF5\xB6\xBF\xAB\xC1\xF0\x80\x1F\x2A\x04\x7D\x9D\x03\xFB\xBF\x08\x41\xC4\x6F\x17\x02\xEA\xB9\x80\xB1\xC5\xA8\xA3\x1B\x59\x04\xFA\xA5\x01\x5B\xC9\x10\x13\xC4\xBC\xA3\x1B\x5B\x04\xFA\xA9\x00\x62\xC6\x10\x46\xC6\xCE\xA3\x1B\x5D\x04\xFA\xAD\x00\x66\xC3\x10\x3E\x29\x42\x03\x9F\xC0\x1F\x0B\x0A\xC5\xD6\x08\x8D\x83\x09\x4D\x23\x1B\x60\x03\x3E\x71\x8E\xE3\x0D\x8D\x82\x08\xB3\x80\x1E\x65\x03\x1B\xF8\x0D\x73\xC3\x10\x46\x2B\xD8\x06\x03\xEA\xC5\x37\x2C\xC6\x81\x0F\x87\x98\x1F\x19\x14\xBE\x31\x03\x24\x84\x2B\x84\x05\x8F\xAB\x1D\x1A\x14\xBE\x43\xC2\x75\x2E\xC6\x83\x0F\x8D\xC0\x1F\x1A\x02\xC7\xE4\x0A\x7D\x82\x09\x81\xCC\x37\x70\x01\x3C\xCD\x09\x0A\xC9\x20\x3B\xC6\xE0\x11\x07\x0F\xCA\x42\x0C\x2A\x09\x0D\x20\xFC\x1A\x39\x08\x90\xEA\x0C\x46\xC6\x08\xD2\x90\x78",
|
|
"\x37\x02\x8B\xC9\x10\x21\xCB\x40\x11\x9F\x7C\x18\x0F\x24\xC8\x90\xCA\x10\x7D\xC7\xBB\x19\x03\xD4\xBB\x06\x23\x88\xA8\x2C\x8F\xF1\x1B\x1E\x14\xBE\x49\xC2\x75\x28\xC8\x81\x0A\x91\x9A\x1D\x1F\x1D\xC8\x70\x15\x31\xA7\xC9\xB8\x12\x08\x2B\xCB\x40\x02\xCA\x02\x0C\x26\xC0\x1F\x41\x06\x94\x82\x0A\xB8\x86\x08\xF8\x9C\x6F\x04\x05\xA6\xC1\x10\x4F\xC9\x19\xD1\x1B\x85\x04\xFA\xB5\x01\x91\x87\x56\x35\xCB\xD8\x07\x04\xD4\xB9\x0A\xEA\x1D\xA8\xCC\x93\xF1\x19\x22\x14\xC6\x34\x17\x32\x83\x08\xB2\xC8\x39\x0D\x04\x55\xC0\x00\x6A\xCA\x20\x1D\xCA\xE0\x1E\x08\x6F\xC9\x60\x29\x08\xD6\xC0\x78\x0F\x04\xBB\xC7\x91\xF1\x18\x24\x0F\xCB\x75\x8C\x20\xF1\x1B\x48\x08\x96\xF2\x11\x60\xC3\x08\x77\xC8\x78\x15\x04\xC0\xCA\x10\x56\xCA\xE6\x16\x04\x6F\xCF\x7F\x82\x09\xC5\x23\x36\x17\x05\x1F\xC9\x0D\x92\xC9\x20\x0D\x2D\xB1\x19\x09\x17\xCD\x6B\x19\xCC\x00\x07\x80\xBC\x1B\x4D\x0E\x99\xB8\x0C\x65\xC6\x08\x9B\xC8\x78\x1D\x05\xB7\xC7\x9A\x83\x0A\x68\xDA\x1C\x9E\x07\x2D\xE9\xCC\xD7\xC1\x37\x1F\x07\x5B\xCF\xCD\x01\x09\xB2\x23\x1A\x50\x07\x9B\x8A\x0B\x69\x23",
|
|
"\x1B\xA1\x05\x37\xC9\x09\xCA\x23\x36\x22\x07\x5B\xDA\xCD\x06\x0F\x5F\x80\x1F\x51\x0F\x96\xCA\xCF\x40\x1F\xCD\xC0\x1C\x14\x0D\xCE\x85\x04\x9C\xC0\x1D\x29\x0F\xCB\xD5\xC8\xF4\x80\x1E\x53\x04\x7D\xB7\x00\x50\xC3\x08\xD9\xCB\xEC\xA3\x1A\x54\x04\x7D\xBC\x03\x77\xC2\x08\xE1\xCD\x03\xE3\x1A\x55\x04\x7D\xC1\x03\x79\xC1\x08\xE9\xCD\x04\xE3\x1A\x56\x04\x7D\xC6\x03\x7B\xC0\x00\xF1\xCC\x05\xF5\x14\x57\x04\x7D\x96\xC6\x3C\xB1\xCF\x34\xC1\x5D\x30\x04\xEA\xB0\x05\x77\xCD\x7C\xDD\xB6\xBB\x12\x16\x14\xBE\x5A\xCF\x9F\xB9\xC6\xE6\x14\x05\xD4\xBA\x0B\x06\xD1\xB1\xA1\x37\x36\x04\xF5\xBA\xC6\x0D\xD4\xB8\xA3\x1A\x5C\x04\x7D\xE4\x03\x84\xC9\x08\x57\xC5\x56\x3A\x04\xEA\xBF\x8F\xF2\xA5\x03\xA2\x08\xD0\xCC\x6F\x3C\x05\xB7\xC7\xA2\xF0\xCD\xFD\x8F\xCB\x29\xD2\x20\x07\x2D\xB1\x1E\x0B\x73\x4F\xA5\x82\x08\x0C\x9B\x20\x2D\xCC\xCD\x15\x0C\x54\xBE\x1B\x03\x89\x39\xD2\x20\x33\xCC\xCD\x17\x0C\x54\xBF\x1B\x00\xD2\x0A\x0D\x85\xBC\x1B\x64\x05\x9A\xBD\x0D\x90\xC1\x08\xB8\xCB\x75\x0B\x06\xEA\xBE\x90\xAA\x1E\x92\xC2\x08\x19\x98\x78\x0D\x07\xB7\xC7\xA5",
|
|
"\xAF\x87\xD8\x0E\x06\xD4\xBD\x22\xD6\xD2\x85\x06\x3A\xEF\x14\x34\x14\xBE\x1C\xCA\x75\x07\x2E\xCF\x93\x36\x52\x04\xF5\xB3\x03\x23\x8B\x4D\xC6\x09\x32\xDC\x2C\x54\x04\xF5\xB4\x03\x23\x89\x4B\xFA\xD0\x26\xA4\x7D\xF5\x01\x9E\xCA\x08\x43\xD3\x8A\x94\xBE\x3B\x0F\xA7\x89\x09\x94\xCF\x17\xDA\x04\xFA\xA3\xC8\xD5\x1F\x31\x82\x0B\x6F\x23\x1B\xDC\x07\x3E\xC3\x0F\x46\xD1\x10\x3B\xD0\xE6\x01\x07\xD4\xBA\x25\xCC\xD4\x40\xD1\x37\x63\x04\xF5\xB0\xC9\x9B\xD6\x50\xD1\xBA\xEA\xBA\x07\x23\x88\x0D\xAE\xD4\x71\x1F\x1C\x12\xD4\xE3\x07\xAA\x95\xD5\xDC\x0C\x07\xD4\xBF\x26\xEA\x1D\x56\xD0\x00\x01\xD7\xEA\x0E\x07\xD4\xBC\x0F\x26\xD4\x85\x07\xA8\xCC\x14\x3C\x14\xBE\x3F\xCA\x75\x26\x98\x81\x02\xA7\xFC\x1A\x3C\x0F\xCB\xC3\xD1\x20\x3A\xD2\xCD\x13\x0F\x6F\xCB\x78\x3D\x68\x28\x08\x5A\xD2\xD6\x5A\x7B\xBF\x3D\x0A\xFE\x57\xD6\xD5\xD0\x78\x4D\x73\xB6\x07\xA1\x5D\xD6\x71\x91\x7C\xAA\x77\x1F\x09\x5A\x65\x5C\x1C\xE4\xD6\x77\x18\x50\xE8\xD0\x25\x14\x69\x75\xD9\xAE\x82\x96\xBB\xCD\x0B\x26\x70\x00\x31\xD7\x79\xDD\x12\x74\xD6\x53\x77\xD7\xEF\xD3\x20\x36",
|
|
"\xD7\x7C\xDC\x23\xF8\xD6\x41\x1B\xD7\xFF\xD5\x5E\xC2\xD8\x7F\xDA\xAF\x83\xD8\xBF\xDD\x88\x06\xD9\x60\xC4\xD9\x7E\xD7\xB0\xF2\xD5\xC2\xC5\xD8\x0B\xD8\x61\xD1\xD8\x87\xD3\xB1\x95\x6D\x97\x56\xD8\x04\x45\x25\x28\x77\x78\x7D\x13\x1B\xDA\xC7\xDA\xD8\x2D\x08\xDE\x73\x90\x91\xDD\x21\x80\x03\x8F\x85\xD9\x28\xDD\x25\x25\xD8\x19\x90\x00\x32\x93\x3F\x0C\xD9\x30\xDD\x25\x31\xD8\x44\x12\xB3\xB5\xD8\xCD\xD7\xD9\xEE\x5E\x66\xF9\xD8\x9C\xD1\xF0\x3C\xDB\x40\x0C\xD9\xA1\x88\x00\x39\x91\xA0\xD4\xB4\x8D\x16\xD1\xCF\x79\x21\x78\x69\xC5\x87\xF9\x7F\x0F\x28\x78\x21\x80\x84\x4F\xD9\x6A\xCE\xDB\x96\x00",
|
|
};
|
|
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"TestBranch",
|
|
L"Syntax0",
|
|
L"Syntax1",
|
|
L"Syntax2",
|
|
L"Syntax",
|
|
L"Assignment",
|
|
L"Clause",
|
|
L"Rule",
|
|
L"File",
|
|
};
|
|
return results[index];
|
|
}
|
|
|
|
const wchar_t* RuleParserStateLabel(vl::vint index)
|
|
{
|
|
static const wchar_t* results[] = {
|
|
L"[0][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][TestBranch] BEGIN ",
|
|
L"[29][TestBranch] END [ENDING]",
|
|
L"[30][TestBranch]< Cond \":\" ( Syntax1 @ | \";\" ) >",
|
|
L"[31][TestBranch]< Cond \":\" ( Syntax1 | \";\" @ ) >",
|
|
L"[32][TestBranch]< Cond \":\" @ ( Syntax1 | \";\" ) >",
|
|
L"[33][TestBranch]< Cond @ \":\" ( Syntax1 | \";\" ) >",
|
|
L"[34][Syntax0] BEGIN ",
|
|
L"[35][Syntax0] END [ENDING]",
|
|
L"[36][Syntax0]< \"!\" @ ID >",
|
|
L"[37][Syntax0]< \"!\" ID @ >",
|
|
L"[38][Syntax0]< \"!(\" @ { SwitchItem ; \",\" } \";\" Syntax \")\" >",
|
|
L"[39][Syntax0]< \"!(\" { SwitchItem ; \",\" @ } \";\" Syntax \")\" >",
|
|
L"[40][Syntax0]< \"!(\" { SwitchItem ; \",\" } \";\" @ Syntax \")\" >",
|
|
L"[41][Syntax0]< \"!(\" { SwitchItem ; \",\" } \";\" Syntax \")\" @ >",
|
|
L"[42][Syntax0]< \"!(\" { SwitchItem ; \",\" } \";\" Syntax @ \")\" >",
|
|
L"[43][Syntax0]< \"!(\" { SwitchItem @ ; \",\" } \";\" Syntax \")\" >",
|
|
L"[44][Syntax0]< \"+\" \"[\" @ Syntax \"]\" >",
|
|
L"[45][Syntax0]< \"+\" \"[\" Syntax \"]\" @ >",
|
|
L"[46][Syntax0]< \"+\" \"[\" Syntax @ \"]\" >",
|
|
L"[47][Syntax0]< \"+\" @ \"[\" Syntax \"]\" >",
|
|
L"[48][Syntax0]< \"-\" \"[\" @ Syntax \"]\" >",
|
|
L"[49][Syntax0]< \"-\" \"[\" Syntax \"]\" @ >",
|
|
L"[50][Syntax0]< \"-\" \"[\" Syntax @ \"]\" >",
|
|
L"[51][Syntax0]< \"-\" @ \"[\" Syntax \"]\" >",
|
|
L"[52][Syntax0]< \"?(\" @ TestBranch { \"|\" TestBranch } \")\" >",
|
|
L"[53][Syntax0]< \"?(\" TestBranch @ { \"|\" TestBranch } \")\" >",
|
|
L"[54][Syntax0]< \"?(\" TestBranch { \"|\" @ TestBranch } \")\" >",
|
|
L"[55][Syntax0]< \"?(\" TestBranch { \"|\" TestBranch @ } \")\" >",
|
|
L"[56][Syntax0]< \"?(\" TestBranch { \"|\" TestBranch } \")\" @ >",
|
|
L"[57][Syntax0]< \"[\" @ Syntax \"]\" >",
|
|
L"[58][Syntax0]< \"[\" Syntax \"]\" @ >",
|
|
L"[59][Syntax0]< \"[\" Syntax @ \"]\" >",
|
|
L"[60][Syntax0]< \"{\" @ Syntax [ \";\" Syntax ] \"}\" >",
|
|
L"[61][Syntax0]< \"{\" Syntax @ [ \";\" Syntax ] \"}\" >",
|
|
L"[62][Syntax0]< \"{\" Syntax [ \";\" @ Syntax ] \"}\" >",
|
|
L"[63][Syntax0]< \"{\" Syntax [ \";\" Syntax @ ] \"}\" >",
|
|
L"[64][Syntax0]< \"{\" Syntax [ \";\" Syntax ] \"}\" @ >",
|
|
L"[65][Syntax0]< ( ID @ | STRING | CONDITIONAL_LITERAL ) [ \":\" ID ] >",
|
|
L"[66][Syntax0]< ( ID | STRING @ | CONDITIONAL_LITERAL ) [ \":\" ID ] >",
|
|
L"[67][Syntax0]< ( ID | STRING | CONDITIONAL_LITERAL ) [ \":\" @ ID ] >",
|
|
L"[68][Syntax0]< ( ID | STRING | CONDITIONAL_LITERAL ) [ \":\" ID @ ] >",
|
|
L"[69][Syntax0]< ( ID | STRING | CONDITIONAL_LITERAL @ ) [ \":\" ID ] >",
|
|
L"[70][Syntax0]<! \"(\" !Syntax \")\" @ !>",
|
|
L"[71][Syntax0]<! \"(\" !Syntax @ \")\" !>",
|
|
L"[72][Syntax0]<! \"(\" @ !Syntax \")\" !>",
|
|
L"[73][Syntax1] BEGIN ",
|
|
L"[74][Syntax1] END [ENDING]",
|
|
L"[75][Syntax1]< Syntax1 @ Syntax0 >",
|
|
L"[76][Syntax1]< Syntax1 Syntax0 @ >",
|
|
L"[77][Syntax1]<! !Syntax0 @ !>",
|
|
L"[78][Syntax2] BEGIN ",
|
|
L"[79][Syntax2] END [ENDING]",
|
|
L"[80][Syntax2]< Syntax2 \"|\" @ Syntax1 >",
|
|
L"[81][Syntax2]< Syntax2 \"|\" Syntax1 @ >",
|
|
L"[82][Syntax2]< Syntax2 @ \"|\" Syntax1 >",
|
|
L"[83][Syntax2]<! !Syntax1 @ !>",
|
|
L"[84][Syntax] BEGIN ",
|
|
L"[85][Syntax] END [ENDING]",
|
|
L"[86][Syntax]<! !Syntax2 @ !>",
|
|
L"[87][Assignment] BEGIN ",
|
|
L"[88][Assignment] END [ENDING]",
|
|
L"[89][Assignment]< ID ( \"=\" @ | \"?=\" ) ID >",
|
|
L"[90][Assignment]< ID ( \"=\" | \"?=\" ) ID @ >",
|
|
L"[91][Assignment]< ID ( \"=\" | \"?=\" @ ) ID >",
|
|
L"[92][Assignment]< ID @ ( \"=\" | \"?=\" ) ID >",
|
|
L"[93][Clause] BEGIN ",
|
|
L"[94][Clause] END [ENDING]",
|
|
L"[95][Clause]< Syntax \"as\" \"partial\" @ ID [ \"{\" { Assignment ; \",\" } \"}\" ] >",
|
|
L"[96][Clause]< Syntax \"as\" \"partial\" ID @ [ \"{\" { Assignment ; \",\" } \"}\" ] >",
|
|
L"[97][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" @ { Assignment ; \",\" } \"}\" ] >",
|
|
L"[98][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" @ } \"}\" ] >",
|
|
L"[99][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" @ ] >",
|
|
L"[100][Clause]< Syntax \"as\" \"partial\" ID [ \"{\" { Assignment @ ; \",\" } \"}\" ] >",
|
|
L"[101][Clause]< Syntax \"as\" ID @ [ \"{\" { Assignment ; \",\" } \"}\" ] >",
|
|
L"[102][Clause]< Syntax \"as\" ID [ \"{\" @ { Assignment ; \",\" } \"}\" ] >",
|
|
L"[103][Clause]< Syntax \"as\" ID [ \"{\" { Assignment ; \",\" @ } \"}\" ] >",
|
|
L"[104][Clause]< Syntax \"as\" ID [ \"{\" { Assignment ; \",\" } \"}\" @ ] >",
|
|
L"[105][Clause]< Syntax \"as\" ID [ \"{\" { Assignment @ ; \",\" } \"}\" ] >",
|
|
L"[106][Clause]< Syntax [ \"{\" @ { Assignment ; \",\" } \"}\" ] >",
|
|
L"[107][Clause]< Syntax [ \"{\" { Assignment ; \",\" @ } \"}\" ] >",
|
|
L"[108][Clause]< Syntax [ \"{\" { Assignment ; \",\" } \"}\" @ ] >",
|
|
L"[109][Clause]< Syntax [ \"{\" { Assignment @ ; \",\" } \"}\" ] >",
|
|
L"[110][Clause]{{< Syntax \"as\" @ \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] > ; < Syntax \"as\" @ ID [ \"{\" { Assignment ; \",\" } \"}\" ] >}}",
|
|
L"[111][Clause]{{< Syntax @ \"as\" \"partial\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] > ; < Syntax @ \"as\" ID [ \"{\" { Assignment ; \",\" } \"}\" ] > ; < Syntax @ [ \"{\" { Assignment ; \",\" } \"}\" ] >}}",
|
|
L"[112][Rule] BEGIN ",
|
|
L"[113][Rule] END [ENDING]",
|
|
L"[114][Rule]< [ \"@public\" @ ] [ \"@parser\" ] ID [ \":\" ID ] { \"::=\" Clause } \";\" >",
|
|
L"[115][Rule]< [ \"@public\" ] [ \"@parser\" @ ] ID [ \":\" ID ] { \"::=\" Clause } \";\" >",
|
|
L"[116][Rule]< [ \"@public\" ] [ \"@parser\" ] ID @ [ \":\" ID ] { \"::=\" Clause } \";\" >",
|
|
L"[117][Rule]< [ \"@public\" ] [ \"@parser\" ] ID [ \":\" @ ID ] { \"::=\" Clause } \";\" >",
|
|
L"[118][Rule]< [ \"@public\" ] [ \"@parser\" ] ID [ \":\" ID @ ] { \"::=\" Clause } \";\" >",
|
|
L"[119][Rule]< [ \"@public\" ] [ \"@parser\" ] ID [ \":\" ID ] { \"::=\" @ Clause } \";\" >",
|
|
L"[120][Rule]< [ \"@public\" ] [ \"@parser\" ] ID [ \":\" ID ] { \"::=\" Clause @ } \";\" >",
|
|
L"[121][Rule]< [ \"@public\" ] [ \"@parser\" ] ID [ \":\" ID ] { \"::=\" Clause } \";\" @ >",
|
|
L"[122][File] BEGIN ",
|
|
L"[123][File] END [ENDING]",
|
|
L"[124][File]< [ \"switch\" @ { SwitchItem ; \",\" } \";\" ] Rule { Rule } >",
|
|
L"[125][File]< [ \"switch\" { SwitchItem ; \",\" @ } \";\" ] Rule { Rule } >",
|
|
L"[126][File]< [ \"switch\" { SwitchItem ; \",\" } \";\" @ ] Rule { Rule } >",
|
|
L"[127][File]< [ \"switch\" { SwitchItem ; \",\" } \";\" ] Rule @ { Rule } >",
|
|
L"[128][File]< [ \"switch\" { SwitchItem ; \",\" } \";\" ] Rule { Rule @ } >",
|
|
L"[129][File]< [ \"switch\" { SwitchItem @ ; \",\" } \";\" ] Rule { Rule } >",
|
|
};
|
|
return results[index];
|
|
}
|
|
|
|
RuleParser::RuleParser()
|
|
: vl::glr::ParserBase<ParserGenTokens, RuleParserStates, ParserGenAstInsReceiver>(&ParserGenTokenDeleter, &ParserGenLexerData, &ParserGenRuleParserData)
|
|
{
|
|
}
|
|
|
|
vl::WString RuleParser::GetClassName(vl::vint32_t classIndex) const
|
|
{
|
|
return vl::WString::Unmanaged(ParserGenTypeName((ParserGenClasses)classIndex));
|
|
}
|
|
|
|
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::glr::parsergen
|
|
{
|
|
/***********************************************************************
|
|
Visitor Pattern Implementation
|
|
***********************************************************************/
|
|
|
|
void GlrEnum::Accept(GlrType::IVisitor* visitor)
|
|
{
|
|
visitor->Visit(this);
|
|
}
|
|
|
|
void GlrClass::Accept(GlrType::IVisitor* visitor)
|
|
{
|
|
visitor->Visit(this);
|
|
}
|
|
}
|
|
namespace vl::reflection::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::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(attPublic)
|
|
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_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(attAmbiguous)
|
|
CLASS_MEMBER_FIELD(baseClass)
|
|
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::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::glr::parsergen::builder
|
|
{
|
|
|
|
/***********************************************************************
|
|
MakeAstFile
|
|
***********************************************************************/
|
|
|
|
MakeAstFile& MakeAstFile::types(const vl::Ptr<GlrType>& value)
|
|
{
|
|
node->types.Add(value);
|
|
return *this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MakeClass
|
|
***********************************************************************/
|
|
|
|
MakeClass& MakeClass::attAmbiguous(const vl::WString& value)
|
|
{
|
|
node->attAmbiguous.value = 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::attPublic(const vl::WString& value)
|
|
{
|
|
node->attPublic.value = 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::attPublic(const vl::WString& value)
|
|
{
|
|
node->attPublic.value = 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::attPublic(const vl::WString& value)
|
|
{
|
|
node->attPublic.value = value;
|
|
return *this;
|
|
}
|
|
|
|
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::glr::parsergen::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->attAmbiguous = from->attAmbiguous;
|
|
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->attPublic = from->attPublic;
|
|
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::glr::parsergen::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::glr::parsergen::json_visitor
|
|
{
|
|
void TypeAstVisitor::PrintFields(GlrAstFile* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"types"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->types)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
}
|
|
void TypeAstVisitor::PrintFields(GlrClass* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"attAmbiguous"));
|
|
WriteToken(node->attAmbiguous);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"baseClass"));
|
|
WriteToken(node->baseClass);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"props"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->props)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
}
|
|
void TypeAstVisitor::PrintFields(GlrClassProp* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"name"));
|
|
WriteToken(node->name);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"propType"));
|
|
switch (node->propType)
|
|
{
|
|
case vl::glr::parsergen::GlrPropType::Array:
|
|
WriteString(vl::WString::Unmanaged(L"Array"));
|
|
break;
|
|
case vl::glr::parsergen::GlrPropType::Token:
|
|
WriteString(vl::WString::Unmanaged(L"Token"));
|
|
break;
|
|
case vl::glr::parsergen::GlrPropType::Type:
|
|
WriteString(vl::WString::Unmanaged(L"Type"));
|
|
break;
|
|
default:
|
|
WriteNull();
|
|
}
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"propTypeName"));
|
|
WriteToken(node->propTypeName);
|
|
EndField();
|
|
}
|
|
void TypeAstVisitor::PrintFields(GlrEnum* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"items"));
|
|
BeginArray();
|
|
for (auto&& listItem : node->items)
|
|
{
|
|
BeginArrayItem();
|
|
Print(listItem.Obj());
|
|
EndArrayItem();
|
|
}
|
|
EndArray();
|
|
EndField();
|
|
}
|
|
void TypeAstVisitor::PrintFields(GlrEnumItem* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"name"));
|
|
WriteToken(node->name);
|
|
EndField();
|
|
}
|
|
void TypeAstVisitor::PrintFields(GlrType* node)
|
|
{
|
|
BeginField(vl::WString::Unmanaged(L"attPublic"));
|
|
WriteToken(node->attPublic);
|
|
EndField();
|
|
BeginField(vl::WString::Unmanaged(L"name"));
|
|
WriteToken(node->name);
|
|
EndField();
|
|
}
|
|
|
|
void TypeAstVisitor::Visit(GlrEnum* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(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(vl::WString::Unmanaged(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(vl::WString::Unmanaged(L"EnumItem"), node);
|
|
PrintFields(static_cast<GlrEnumItem*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void TypeAstVisitor::Print(GlrClassProp* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(L"ClassProp"), node);
|
|
PrintFields(static_cast<GlrClassProp*>(node));
|
|
EndObject();
|
|
}
|
|
|
|
void TypeAstVisitor::Print(GlrAstFile* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
WriteNull();
|
|
return;
|
|
}
|
|
BeginObject();
|
|
WriteType(vl::WString::Unmanaged(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::glr::parsergen::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->attPublic);
|
|
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->attAmbiguous);
|
|
Traverse(node->baseClass);
|
|
for (auto&& listItem : node->props)
|
|
{
|
|
InspectInto(listItem.Obj());
|
|
}
|
|
Traverse(node->attPublic);
|
|
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::glr::parsergen
|
|
{
|
|
void ParserGenTypeParserData(vl::stream::IStream& outputStream)
|
|
{
|
|
static const vl::vint dataLength = 2480; // 34610 bytes before compressing
|
|
static const vl::vint dataBlock = 256;
|
|
static const vl::vint dataRemain = 176;
|
|
static const vl::vint dataSolidRows = 9;
|
|
static const vl::vint dataRows = 10;
|
|
static const char* compressed[] = {
|
|
"\x32\x87\x00\x00\xA8\x09\x00\x00\x23\x00\x01\x82\x80\x06\x03\x82\x81\x82\x06\x89\x82\x84\x0A\x84\x06\x85\x0B\x0A\xA2\x0A\x86\x1A\x82\x08\x85\x81\xFF\x19\x9A\x99\x8A\x80\x03\x8D\x8D\x1D\x9F\x9A\x81\x92\x97\x7C\x92\x91\x27\x9F\xA9\x80\x9A\x85\x92\x93\x96\x25\xAB\xA3\x90\x98\x94\x9A\x94\x9B\x2C\x89\xAE\x92\x9C\x88\x9F\x98\x9D\x31\xBE\xBD\x80\xA5\x9C\xA3\x9A\xA3\x39\x86\xBB\x82\xAF\x90\xA7\x9E\xA5\x41\xCE\x83\xB0\xA5\xA4\xAB\xA2\xAB\x49\x98\x91\xB8\xAF\xA2\xAD\xAB\x8E\x03\x81\x0C\xBC\x9D\xA4\xAF\xA8\xAF\x57\xE8\x99\xA2\x8B\xA2\xA9\xB2\xB5\x5D\xEC\x9B\xB0\xB7\xB2\xBB\xAE\xBB\x69\xF8\xAB\xA1\x8D\xB6\xB3\xB6\xBD\x71\xFC\xB3\xA0\xC5\xBA\xC3\xBA\xC3\x79\x88\xFB\xBE\x83\xC2\xC5\xC0\xC6\x87\x90\xC9\xD2\xCB\xC5\xBC\xBB\xBF\x8E\x85\xD4\xCF\xC6\xCC\xC0\xCD\xCD\x9A\x9D\xD9\xDF\xC2\xD0\xD0\xD3\xC6\xA6\xE4\xAA\xCA\x82\xB1\x85\xD6\xBF\xAB\xEE\xB1\xD0\xD3\xB5\xDA\xD8\xDB\xB4\xB7\xFA\xD9\xDC\xDF\xCB\xD8\xDF\xB8\xC0\xFB\xC2\xED\xDE\xCF\xDE\xE3\xC1\xC8\xC3\xEA\xE5\xE3\xD3\xE2\xE7\xC9\xD0\xCB\xF2\xED\xE1\xD5\xE8\xEB\xD3\xD8\xD5\xE5",
|
|
"\xDC\xE8\xD5\xEF\xC8\xDF\x93\xE1\xF5\xCE\xED\xF0\xF0\xF3\x93\x82\x2C\xD7\xE3\xF4\xCC\xF4\xF2\xE7\xF1\xE2\xEF\xFE\xF2\xF8\xF9\xF9\xF6\xF5\xF8\xF3\xC3\x03\xF5\xED\xD2\x0C\x6E\x6C\x78\x7D\xA1\x44\x87\x69\x7E\x05\x88\x87\x83\x7E\xF7\x4D\x8A\x7E\x83\x09\x8C\x8F\x83\x84\x11\x90\x8B\x82\x85\xCF\x5A\x74\x73\x86\xCC\x5C\x84\x76\x87\x1A\x9D\x82\x8B\x87\x23\xA1\x84\x8B\x89\x26\xA9\x8D\x79\x85\x14\x97\x8D\x89\x86\x2B\xAE\x8C\x8B\x8C\x32\xB5\x80\x8E\x81\x37\x8A\x89\x8E\x84\x34\xBB\x88\x87\x80\x3A\x80\x93\x65\x01\xFE\x5B\x78\x8E\x90\x3F\xBF\x77\x92\x92\x41\x8C\x9C\x8E\x8D\x48\xAF\x81\x95\x8F\x53\x90\x9E\x91\x92\x46\x8D\x99\x97\x93\x3E\x92\x97\x96\x97\x5B\x98\x90\x89\x8C\x5D\x94\x9F\x96\x99\x61\xA0\x93\x9B\x92\x69\xA8\x90\x8B\x45\x61\x55\x95\x9A\x95\x6D\xB4\x9B\x9A\x96\x77\x9C\x92\x9F\x9E\x67\xB6\x92\x43\x01\x45\xB9\x92\x99\x89\x64\xBC\x95\x9F\x9C\x88\x8A\x48\x01\xA0\x84\xAC\x92\xA2\x9A\x8D\xB8\x91\xA6\x9E\x7D\x89\xA5\xA6\xA1\x20\x89\x0C\xA0\x8A\x85\x97\xAE\xA7\xA1\x98\x93\xA3\xA1\x40\x0A\x1B\xAA\x8A\xA3\x25\x8B\x06\xA9\xA7",
|
|
"\xA0\x9F\xAF\xA2\x9B\xA2\x90\xAC\xA4\xAA\xB3\x92\xA5\xAC\xA5\xAD\xB9\xAF\xAA\x9F\xB7\xA3\xA7\xAA\xAD\xBF\xB8\xAB\xAE\xA5\xBA\xB1\xA0\xAD\xAF\xB2\x81\xBE\xAE\x43\x02\xAE\xA6\xB0\xAF\xCA\x89\xBC\xAB\xB0\xA1\x88\xB7\xB1\xB4\xD7\x93\xBF\xB0\xB1\x20\x8D\x0B\xA8\xAD\xD8\x90\xBA\xB6\xB5\xE2\xA0\xB3\xB9\xB8\xDC\x9B\xB5\xB4\xBA\xEB\xA7\xBE\xBA\xB9\xF0\x80\xBF\xBA\xBC\xF1\x82\xBA\xBA\xB3\xE4\xA9\xB9\xBD\xBB\xF5\xBE\xA3\xBE\xBD\xFB\xB8\xBC\xBA\xC0\xFF\xBE\xBD\xBE\xB4\x07\xD9\xB9\xC1\xB9\xF4\x8D\xC0\xC3\xC0\xC5\x81\x4E\x03\xB7\x0E\xC6\xC5\xC4\xC2\x17\xCA\xC9\xC4\xC3\x0F\xC5\xC8\xC5\xC7\x0B\xD9\x8F\x00\xC5\x20\xDB\xCA\xBC\xC4\xD4\x84\xC1\xC8\xBF\x26\xEC\xC5\xCB\xCB\x16\xF0\xCF\xC5\xCC\x8B\x50\x04\xC8\xCD\x33\xF9\xCA\xC6\xCC\xD7\x91\x07\xCE\xCE\x1C\xF8\xCB\xCE\xD0\x41\xC0\xD7\xCA\xC7\x43\xC6\xDE\xC8\xD1\x47\xEB\xCA\xC9\xCB\x4F\xFC\xC5\xD1\xD2\x54\xD3\xD6\xD5\xD3\x50\xD5\x72\x07\xCF\x55\xD8\xD2\xD6\xD7\x4C\xCB\xDA\xD1\xD4\x61\xE4\xD9\xB3\x04\x5C\xD7\xD2\xD9\xD7\x6B\xEA\xD6\xD8\xDB\x6F\xEE\xD1\xC4\xCA\xF7\xB3\xD8\xD0\xB4\x14",
|
|
"\x29\xD0\xDB\xD8\x76\xCE\xDD\xDD\xD6\x29\xFF\xDF\xD5\xDB\x7B\xF0\xD6\x41\x05\x7A\xC4\xEA\xE1\xDC\x85\xF2\xD1\xE3\xE3\x75\xE0\x86\x06\x42\xEA\x4C\xEB\xE2\xE0\x65\xD8\xEC\xDC\xE4\x01\xDA\xE6\xE0\xE7\x00\x18\x09\xE2\xE5\xA4\xDE\xEE\xE1\xE4\x25\x99\x06\xAA\x06\xA3\xC6\x4B\x05\xEB\xA0\xF7\xDD\xE3\xEC\x97\xF1\xEE\xDE\xED\x80\xE8\xED\xE4\xEE\x83\xE5\xEC\xED\xE6\xBF\xDB\xEA\xEC\xDD\xBB\xC3\xF2\xED\xED\xC6\xF7\xE9\xF0\xB0\x1C\x30\xE5\x89\x07\xCE\xC5\xF2\xF4\xF1\xD4\xC7\xFE\xEF\xF2\xBD\xE6\xE4\xEF\xF5\xD3\xD6\xF3\xDE\x07\xD1\xD5\xFA\xF1\xF7\xE3\xE2\xF9\xEC\xF9\xE7\xE6\xF9\xF5\xF0\x9F\xD8\xF0\xF2\xFB\xC2\xE8\xFB\xF8\xFC\xED\xF2\xFF\xFA\xFD\xF1\xD4\xFF\x05\xF8\xDE\xEC\xF7\xE8\xFE\xF5\x6A\x7F\xFD\x29\x40\x04\xFE\x65\x7F\x5C\x21\x06\x81\xFA\x7D\x74\x7F\xFF\x42\x81\x7F\x0C\x80\x82\x03\x91\x8F\x81\x00\x94\x87\x82\x07\x85\x7E\x44\x4D\x5A\x7A\xE4\x52\x83\x7B\x1D\x9C\x78\xF5\x00\x2C\x82\xFF\x60\x86\x84\x1E\x95\x83\x04\x99\x8B\x80\x16\x93\x34\x04\x0A\x93\x7F\x07\xEB\x55\x05\x18\x83\x80\x83\x2D\x99\x86\x0C\xAA\x87\x85\x06\x99\x44",
|
|
"\x22\x25\x9E\x85\x0A\x94\x87\x04\x1B\x90\x86\x85\x37\x88\x8B\x11\xE9\x78\x04\x23\x96\x82\x89\x4F\x9A\x85\x12\xD2\x8B\x89\x1D\xB8\x86\x8A\x50\x8B\x85\x64\x29\x06\x54\x15\x14\x77\x3A\x2C\x06\x55\x0B\x4E\x8A\x8A\x2C\x94\x89\x8A\x66\x89\x8F\x14\xEA\x85\x8B\x35\xAE\x8D\x8D\x70\x88\x8F\x1B\xF2\x81\x8F\x32\xB3\x8E\x8E\x75\x87\x66\x0B\x64\x8D\x87\x19\xA2\x87\x8A\x77\x9D\x8C\x0F\xC3\x89\x8A\x41\xA7\x5F\x05\x7C\x84\x93\x19\xF8\x84\x8F\x46\x8C\x97\x91\x86\x85\x92\x22\xEC\x8A\x32\x18\x26\x51\x06\x5F\x99\x3B\x0C\x26\x54\x07\x44\xBF\x8A\x92\x9F\x8B\x91\x24\xA2\x93\x93\x40\xA5\x91\x8F\xA7\x8E\x93\x28\x94\x90\x93\x54\xAD\x91\x94\x3B\x95\x05\xF8\x36\x06\x55\x1B\x19\x95\x3A\x39\x06\x56\x0E\x1E\x91\x85\x5E\xA8\x80\x96\xA6\x80\x98\x2A\xC2\x97\x5B\x1D\x21\x7C\x07\xA6\x5D\x07\x2D\xA0\x4F\x06\x53\x40\x0C\x97\xBF\x9E\x96\x10\xC4\x9F\x94\x69\xBE\x8E\x9A\x83\x89\x22\x21\x4B\x9E\x33\x73\x41\x46\x20\xA5\x4E\x2C\x91\x09\x2B\x6A\xB0\x06\x20\x50\x6E\x31\x47\x6B\x03\x25\x72\xBF\x27\x5D\x9D\x97\x2A\x9E\x39\xFE\x2B\x9D\x79\xAE\x20\x9E\xF6\x85",
|
|
"\x27\x38\x86\x28\x9F\xD1\x27\x5C\x2C\xFB\x8C\x9C\x53\x5E\x9A\x20\x4D\x62\x9A\x21\x9B\x93\x9E\x40\x01\xA2\x21\x4E\x89\x25\x9F\x00\x0C\xA1\x40\x3E\x69\x21\x6F\x83\x20\x9D\xEE\x86\x41\x7F\x0F\xA3\xA0\x70\x64\x2D\x9E\x01\x20\xA4\x58\x16\xA9\x9E\x91\x2A\x51\x88\x21\xAA\x20\x9C\x25\xAF\x23\x93\x86\x24\xA4\x01\x32\xA2\x69\x32\xAE\xA5\x38\x49\x22\xA6\xCC\x4F\xA6\x42\x32\xAE\x5B\x9B\xBB\xA5\x21\x2A\xBF\xA5\x42\x3D\xA7\x9C\xA1\x86\x21\xA7\x03\x21\x9D\x51\xE9\x95\x24\x91\x90\xA2\xA9\x0A\xAE\x25\x4D\xAC\xAB\x22\x83\x8A\xA6\x34\x8B\x57\xAA\x69\x1B\xA7\xAA\x97\x32\xA4\x2C\x18\xB1\xA9\x49\x10\xA0\xA2\x97\x32\x9C\xA3\x4C\xA0\x59\x59\xE6\xAA\x40\x88\x9F\xA2\xAB\xA6\x2E\xAC\x53\x72\xAE\x2C\xAE\xA2\xAA\x24\x2B\xA6\x9E\x4B\x30\xA0\x2C\xAF\xB0\xAE\x25\x79\xA0\x03\x5A\xEC\xAE\x56\xB2\x19\xAC\x9F\x1D\xA0\x5A\x61\x8A\x2C\xAE\xBE\xBE\xA9\x21\x09\xB7\xAA\x4C\x87\xB6\xA6\x83\x32\xA6\xA1\x06\x36\xAF\x42\x85\xA6\xA9\x81\x32\xA0\xAA\x7F\x4A\x21\x58\xDD\x93\xAD\xC4\x8F\x4E\xA9\xA6\xBE\x57\x60\x84\xB7\x5B\xD5\xAC\xB4\x2C\x64\xA9\xB5\x8B\x22",
|
|
"\xA3\xB4\x7F\xA5\x25\xB6\xA6\x37\x9E\x6C\xB4\x48\xB5\xB4\x8F\x66\xB5\x84\xB9\x40\x70\xEC\xA0\xB6\x6E\xB6\xB2\x41\x22\xBC\xAE\x66\xA3\x32\xA6\xDC\x9D\x25\xB9\xA6\x58\xB4\x6B\x9B\x23\xB8\xB3\xAF\xA8\xAD\x19\xAA\xAF\x6E\xD0\x55\xBB\x18\x71\xB6\xB7\x16\x49\xBA\x42\x4B\xB3\xA6\xD1\xB0\xA8\xBA\x28\xA0\x02\x74\xD3\xB9\x23\xEE\x86\x45\xB7\xD9\xBF\xB7\x76\xC2\xB3\xBF\xB9\x86\xB9\xB7\xEF\xA3\xBC\x53\x4A\xBB\xBE\xFD\xAE\x28\xB7\xE4\xAE\x24\x6E\xEE\xB2\x24\x02\xDF\x26\xC0\x1B\x21\xC0\x6A\x0A\xC2\x24\x91\x8C\xC7\x23\x22\xA5\x8A\x56\xF0\xB3\x20\xF2\xBC\xAA\xA6\x8D\xBD\xB3\x41\x0C\xB1\xA8\x9F\x89\x21\xB0\x7C\xA0\xC5\x87\x96\xB6\xBD\x8A\xA5\xC4\xC4\x09\x38\xB4\x5F\xAA\xC7\xC4\xCF\x8A\x54\xC3\x09\x34\xB3\x66\xB1\xC0\xC6\x83\x32\xC1\x20\x7C\xB7\xC5\x44\xF0\xA6\xAA\x85\xBD\xC5\x44\x1D\x3C\x0E\xA9\x1D\x2F\xC6\x14\x5D\x25\x0F\xA6\x50\xA1\x01\xD9\x3D\x22\x3F\x09\xCA\x21\x4B\xD5\x39\x47\x7F\x06\x54\xF2\xB5\x81\x3B\xE4\xA0\x12\xA9\x22\xA0\x86\x2C\xCA\x21\x10\xA6\x5C\xAD\x13\xCC\xCA\x20\x41\x37\xBC\xAF\x5C\x84\xCD\x42\x04\x11\xCC\x85",
|
|
"\x29\xCA\xCA\x0A\x25\x12\xA9\x41\x00\xAF\x07\xC5\xB7\xBE\xA5\x30\xA2\x48\xEF\x9E\xBF\xEA\x24\xBD\xBA\x19\x52\xA7\x9E\xA8\x31\xC5\x75\x41\xB0\xD0\x35\xD7\xA3\xBA\x3A\xC8\xD1\x0F\xED\xC3\x78\xA0\xA9\xA5\x76\x38\xB3\xAB\xE9\x55\xD0\x00\x83\xD1\x32\x8E\x91\xD4\x7A\xA4\x82\x21\xD3\x93\x3A\xC6\x9D\xC9\x54\xA8\x81\x93\xC4\xB3\x09\x3C\xD3\xB9\x23\x69\xBD\xD2\x05\xC8\x00\xA3\xD7\x5A\xCD\x58\xB5\xB3\x5A\xC2\x24\xD3\x32\xA7\x5D\x39\xA8\xC5\x3B\x4B\xFA\xC7\x5C\x10\x2D\xD4\x6A\x1E\xD2\x63\x75\x62\x74\xD6\x25\x53\x61\x42\x13\x72\x60\xD6\x42\xD9\x32\xAC\xC6\x20\x45\xF3\x6F\x74\x64\xE8\x43\xD6\xD2\xCB\x5C\xF4\x56\xD9\x45\x69\xC3\x25\xD4\xC3\x7B\x7C\x8D\xD9\x3B\xD7\x81\x1E\xDB\x78\x12\xC8\xB1\x76\x68\x64\x9D\x75\x6F\xCE\xD6\x28\x59\x6D\x42\x6C\xD3\x6E\x2F\x8F\xDB\x32\x88\x69\x21\xB4\xA0\x7B\x05\xF0\x79\xDE\x20\xD8\xC0\x75\x18\xF7\xDB\x31\x7F\xC3\x22\xDE\x73\x63\x8C\xC1\x8F\x3C\xD9\xC3\x6B\x5B\x8F\x0B\xFA\x31\xB0\x86\x2E\xD9\xB9\x48\x94\xDB\xA5\x33\xE3\x40\x2A\x72\x60\x4C\x98\xE0\x35\x1A\xE2\x21\xB5\xF3\x61\xB2\x53\xD5\x3C\xE3",
|
|
"\x14\xEB\x5E\x2C\x91\xEF\x32\x94\xC3\x23\xE4\xA0\x74\x94\xCB\x9D\x25\xE3\x97\xEB\x5E\x96\x33\xEA\x20\xCC\x82\x2D\x78\x81\x78\x01\x7C\x3D\xE6\x22\xB8\xF3\x69\x97\x9C\xC9\x21\xE8\x03\x3B\xDB\xDC\x3B\x96\xE8\x83\x0A\xEB\x20\xE0\x62\x62\x31\xCD\xE0\xEA\x85\x03\xE8\x74\xC8\x94\xEA\x40\x57\xE2\x20\x65\xF3\x6A\x99\xDC\xDA\xCE\xD5\x8A\x29\x80\x81\x4D\x9A\xEB\x01\x31\xCB\x40\x5E\xE0\x75\x67\x9C\xDC\xBC\x22\xAA\xEE\x40\x65\xE3\x6E\x21\x21\x7C\xEE\x03\x27\xDB\xDC\x43\x0F\xD0\x14\x5B\x81\xE5\x02\x6A\x0B\x99\xA6\x5F\xEF\x81\x01\xB7\x5C\x4C\x17\xBE\xA0\x91\x2A\x20\x97\xC3\x7E\x09\xF7\xA1\xB2\x48\x85\xF2\xE5\x75\x50\x0F\xBE\xB8\xB3\xF1\xDF\xD4\x72\x0B\xFB\xBA\xC4\xCB\x0A\x24\x87\xDC\x54\x01\x7D\x2B\xC6\x22\xF4\xA0\x75\x09\xF8\x40\x80\xF1\xB9\x56\x0F\xBE\xAF\xD0\xA0\xEB\x86\xFB\x5C\x2C\x37\xBF\xD2\xB2\xED\xF3\xBA\x5A\x07\xBE\x70\xC1\x21\xF7\x09\x3B\xE7\xF4\x5C\x07\xBF\x7D\xC2\x20\xF8\x4B\xB3\x6E\x17\x77\xB7\xDD\xDF\xCA\x23\xCC\x06\x29\xDC\xE8\x60\x09\xD1\x12\x50\xFB\x20\x35\xE3\x78\x19\x77\xB4\xDE\x93\xC3\x27\xFA\x1B\xC2\x62",
|
|
"\x19\x77\xB6\xE1\xE3\xCF\xFA\xF7\x02\x68\x0F\x7D\xA1\xEE\xF9\x84\x20\xF9\x20\xC2\xF4\x7A\x1A\x77\xBE\xF1\xF6\xC6\x27\xFD\xEA\xAB\x5C\x1B\x77\xB1\xFE\x88\xAF\xDA\x20\xD2\x73\x3C\x6E\x05\x7D\x28\x2F\x7F\x01\x19\x7D\xD3\x32\x07\xF7\x5F\x74\xE6\x79\x10\x06\x84\x10\xEB\x24\x07\xF7\x5C\x75\xF6\x73\x10\x0F\x85\x7F\xD4\x36\x07\xF7\x58\x77\x0D\x86\x10\x0F\x81\x7F\xE7\x28\x07\xF7\x58\x7A\x1D\x86\x81\x9B\x77\x2E\x7A\x07\x5F\xA6\x7E\x7D\x02\x16\x6F\x70\x5D\x12\x2F\x82\x69\xAD\x62\x52\x98\x6D\x11\x34\x87\x83\x36\x8D\x11\x6E\x55\x56\x3B\x8A\x83\x3E\x87\x5F\x82\x5F\x83\xDC\x61\x84\x7D\x69\x59\x2D\x14\x5E\xB0\x6D\x11\x48\x8B\x84\x4A\x8D\x84\x45\x85\x61\x1D\x1C\x57\x00\x0E\x58\x52\x82\x85\x5F\x59\x6B\x57\x8F\x82",
|
|
};
|
|
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"classProp",
|
|
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]< [ \"@public\" @ ] \"enum\" ID \"{\" { EnumItem } \"}\" >",
|
|
L"[7][Enum]< [ \"@public\" ] \"enum\" @ ID \"{\" { EnumItem } \"}\" >",
|
|
L"[8][Enum]< [ \"@public\" ] \"enum\" ID \"{\" @ { EnumItem } \"}\" >",
|
|
L"[9][Enum]< [ \"@public\" ] \"enum\" ID \"{\" { EnumItem @ } \"}\" >",
|
|
L"[10][Enum]< [ \"@public\" ] \"enum\" ID \"{\" { EnumItem } \"}\" @ >",
|
|
L"[11][Enum]< [ \"@public\" ] \"enum\" ID @ \"{\" { EnumItem } \"}\" >",
|
|
L"[12][classProp] BEGIN ",
|
|
L"[13][classProp] END [ENDING]",
|
|
L"[14][classProp]< \"var\" @ ID \":\" ( \"token\" | ID | ID \"[\" \"]\" ) \";\" >",
|
|
L"[15][classProp]< \"var\" ID \":\" ( \"token\" @ | ID | ID \"[\" \"]\" ) \";\" >",
|
|
L"[16][classProp]< \"var\" ID \":\" ( \"token\" | ID @ | ID \"[\" \"]\" ) \";\" >",
|
|
L"[17][classProp]< \"var\" ID \":\" ( \"token\" | ID | ID \"[\" \"]\" ) \";\" @ >",
|
|
L"[18][classProp]< \"var\" ID \":\" ( \"token\" | ID | ID \"[\" \"]\" @ ) \";\" >",
|
|
L"[19][classProp]< \"var\" ID \":\" ( \"token\" | ID | ID \"[\" @ \"]\" ) \";\" >",
|
|
L"[20][classProp]< \"var\" ID \":\" ( \"token\" | ID | ID @ \"[\" \"]\" ) \";\" >",
|
|
L"[21][classProp]< \"var\" ID \":\" @ ( \"token\" | ID | ID \"[\" \"]\" ) \";\" >",
|
|
L"[22][classProp]< \"var\" ID @ \":\" ( \"token\" | ID | ID \"[\" \"]\" ) \";\" >",
|
|
L"[23][Class] BEGIN ",
|
|
L"[24][Class] END [ENDING]",
|
|
L"[25][Class]< [ \"@public\" @ ] [ \"@ambiguous\" ] \"class\" ID [ \":\" ID ] \"{\" { classProp } \"}\" >",
|
|
L"[26][Class]< [ \"@public\" ] [ \"@ambiguous\" @ ] \"class\" ID [ \":\" ID ] \"{\" { classProp } \"}\" >",
|
|
L"[27][Class]< [ \"@public\" ] [ \"@ambiguous\" ] \"class\" @ ID [ \":\" ID ] \"{\" { classProp } \"}\" >",
|
|
L"[28][Class]< [ \"@public\" ] [ \"@ambiguous\" ] \"class\" ID @ [ \":\" ID ] \"{\" { classProp } \"}\" >",
|
|
L"[29][Class]< [ \"@public\" ] [ \"@ambiguous\" ] \"class\" ID [ \":\" @ ID ] \"{\" { classProp } \"}\" >",
|
|
L"[30][Class]< [ \"@public\" ] [ \"@ambiguous\" ] \"class\" ID [ \":\" ID @ ] \"{\" { classProp } \"}\" >",
|
|
L"[31][Class]< [ \"@public\" ] [ \"@ambiguous\" ] \"class\" ID [ \":\" ID ] \"{\" @ { classProp } \"}\" >",
|
|
L"[32][Class]< [ \"@public\" ] [ \"@ambiguous\" ] \"class\" ID [ \":\" ID ] \"{\" { classProp @ } \"}\" >",
|
|
L"[33][Class]< [ \"@public\" ] [ \"@ambiguous\" ] \"class\" ID [ \":\" ID ] \"{\" { classProp } \"}\" @ >",
|
|
L"[34][Type] BEGIN ",
|
|
L"[35][Type] END [ENDING]",
|
|
L"[36][Type]<! ( !Enum @ | !Class ) !>",
|
|
L"[37][Type]<! ( !Enum | !Class @ ) !>",
|
|
L"[38][File] BEGIN ",
|
|
L"[39][File] END [ENDING]",
|
|
L"[40][File]< Type @ { Type } >",
|
|
L"[41][File]< Type { Type @ } >",
|
|
};
|
|
return results[index];
|
|
}
|
|
|
|
TypeParser::TypeParser()
|
|
: vl::glr::ParserBase<ParserGenTokens, TypeParserStates, ParserGenAstInsReceiver>(&ParserGenTokenDeleter, &ParserGenLexerData, &ParserGenTypeParserData)
|
|
{
|
|
}
|
|
|
|
vl::WString TypeParser::GetClassName(vl::vint32_t classIndex) const
|
|
{
|
|
return vl::WString::Unmanaged(ParserGenTypeName((ParserGenClasses)classIndex));
|
|
}
|
|
|
|
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::glr::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::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::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::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::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_attAmbiguous:
|
|
return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrClass::attAmbiguous, 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::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_attParser:
|
|
return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRule::attParser, object, field, token, tokenIndex, cppFieldName);
|
|
case ParserGenFields::Rule_attPublic:
|
|
return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrRule::attPublic, 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_attPublic:
|
|
return vl::glr::AssemblerSetTokenField(&vl::glr::parsergen::GlrType::attPublic, 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::ClassProp_propType:
|
|
return vl::glr::AssemblerSetEnumField(&vl::glr::parsergen::GlrClassProp::propType, 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"LoopSyntax",
|
|
L"NotCondition",
|
|
L"OptionalSyntax",
|
|
L"OrCondition",
|
|
L"PartialClause",
|
|
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 < 29 ? 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::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::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 < 29 ? 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::attAmbiguous",
|
|
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"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"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::attParser",
|
|
L"Rule::attPublic",
|
|
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::attPublic",
|
|
L"Type::name",
|
|
L"UseSyntax::name",
|
|
};
|
|
vl::vint index = (vl::vint)field;
|
|
return 0 <= index && index < 54 ? 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::attAmbiguous",
|
|
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::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::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::attParser",
|
|
L"vl::glr::parsergen::GlrRule::attPublic",
|
|
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::attPublic",
|
|
L"vl::glr::parsergen::GlrType::name",
|
|
L"vl::glr::parsergen::GlrUseSyntax::name",
|
|
};
|
|
vl::vint index = (vl::vint)field;
|
|
return 0 <= index && index < 54 ? 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::glr::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"ATT_AMBIGUOUS",
|
|
L"ATT_PUBLIC",
|
|
L"ATT_PARSER",
|
|
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"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"@public",
|
|
L"@parser",
|
|
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"-",
|
|
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"@public",
|
|
L"@parser",
|
|
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"[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 = 1801; // 25496 bytes before compressing
|
|
static const vl::vint dataBlock = 256;
|
|
static const vl::vint dataRemain = 9;
|
|
static const vl::vint dataSolidRows = 7;
|
|
static const vl::vint dataRows = 8;
|
|
static const char* compressed[] = {
|
|
"\x98\x63\x00\x00\x01\x07\x00\x00\x60\x00\x01\x80\x21\x84\x81\x83\x1E\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\x87\x86\x84\x83\x80\x81\x04\xC1\x04\x9A\x24\x83\x2D\xB2\x82\x5C\x68\x84\x9D\x2B\xB4\x82\x2E\xB7\x04\xDF\x31\xA4\x80\x81\x81\xBA\x00\x61\x04\xB9\xA1\x82\x34\x81\xBF\x80\x63\x04\x81\xC1\x84\x34\x81\xC3\x80\x65\x04\x89\xC1\x86\x34\x81\xC7\x80\x67\x04\x91\xC1\x88\x34\x81\xCB\x80\x69\x04\x99\xC1\x8A\x34\x81\xCF\x80\x6B\x04\xA1\xC1\x8C\x34\x81\xD3\x80\x6D\x04\xA9\xC1\x8E\x34\x81\xD7\x80\x6F\x04\xB1\xC1\x80\x3C\x81\xDB\x80\x71\x04\xB9\xC1\x82\x3C\x81\xDF\x80\x73\x04\x81\xE1\x84\x3C\x81\xE3\x80\x75\x04\x89\xE1\x86\x3C\x81\xE7\x80\x77\x04\x91\xE1\x88\x3C\x82\x3C\x82\x7B\x58\xC4\x9C",
|
|
"\x3B\xEC\x81\x3E\xEF\x04\xFE\x04\x9F\x7F\x78\x08\x00\xF2\xE4\x9C\x04\x8A\xF1\x80\xF7\x7E\xF6\xE7\xE8\xF0\xEF\x04\x82\x0F\xF0\xF4\x11\x04\x9B\x0E\x81\x80\x89\xF6\xF4\x17\x04\x43\x04\x41\x18\x37\x74\x79\x07\x06\xBF\x34\x04\x41\x15\x09\x86\x05\x82\xE6\x41\x49\x41\x40\x19\x12\x49\x81\x45\xFF\x64\x75\x85\x86\xFF\x07\x04\x43\x86\x00\x02\x0F\x84\x41\x03\x23\x84\x86\x89\x00\x20\x8A\x88\x8A\x2B\xA7\x81\x43\x42\x2E\xA9\x84\x41\x01\x04\x46\x08\x88\x01\x2C\x98\x41\x42\x04\x19\x49\x8E\x7B\x8F\x40\x81\x92\x93\x90\x44\x85\x96\x93\x91\x48\x89\x9A\x90\x92\x1E\x3E\x8B\x93\x93\x4A\x9C\x4C\x84\x94\x54\x95\x96\x97\x95\x57\xA1\x43\x95\x96\x4E\x84\x9A\x95\x7C\xE4\x5F\x92\x9A\x48\x01\x63\x95\x98\x99\x00\x26\x99\x9B\x47\x67\xAD\x9B\x9A\x9B\x6A\xB1\x98\x9A\x9A\x58\xB5\x96\x9D\x9D\x5F\xB7\x9F\x3D\x9E\x49\xBC\x91\x9B\x9C\x80\xB0\x91\xA3\x9B\x84\xAA\x94\x4A\xA0\x88\x85\xA3\xA0\x9D\x7A\x8D\xAE\xA2\x91\x7E\xB8\x9D\x97\x90\x91\xA7\x49\xA2\x9C\x97\x8B\xAA\xA5\xA6\x9C\x8A\xAE\x9B\xA3\xA0\xA1\xAE\x79\xA4\x58\xA4\xA5\x91\xA4\x98\x9E\xAA\xA9\xAA",
|
|
"\xAC\x9B\xAB\xAB\xA0\x24\x28\x92\xAB\xAC\x8F\xA6\xA6\x96\xAD\x94\x89\x8D\xA9\xA7\xBB\xAF\xA1\x41\x4A\xBC\xAE\xAC\xA0\xAD\xC4\x92\xAB\x97\xAD\x93\x82\x98\xAA\xB0\xCC\x81\xBE\xB0\xA1\x2B\x4F\xB8\xAD\xB1\xD4\xBD\x99\xB0\x94\xD3\x81\x91\xA6\x4B\xD2\x8D\xBE\xAF\xB7\xBD\xBD\xA5\xB7\xB8\xE4\xA5\xB6\xBB\xB9\xE8\xA9\xBA\xBB\xBA\xEC\xAD\xBE\xBB\xBB\xF0\xB1\xB2\xBF\xBC\xF4\xB5\xB6\xBF\xBD\xF8\xB9\xBA\xBF\xBE\xFC\xBD\xBE\xBD\xB1\x31\x47\xBF\xBF\xC0\x04\xF3\xA4\x4E\xC0\xB4\xB7\x48\xC1\xC1\x0C\xE4\xBA\x4F\xC2\x0D\xD1\xC2\xC7\xC4\x14\xF8\xBD\x4C\xC4\x15\xD9\xCA\xC7\xC6\x50\x80\x58\xC4\xC7\x20\xE1\xC2\xCB\xC8\x24\xE5\xC6\xCB\xC9\x28\xE9\xCA\xCB\xCA\x2C\xDA\xB7\xB7\x93\xD9\x80\x9B\xB1\xB7\x34\xE0\xBE\xB5\xB8\x2F\xC3\x93\x51\x40\x3B\xC0\x0D\xCF\xCF\x44\x7C\xC1\xD0\x00\x46\x42\xD6\xD2\xCF\x43\xC0\xD7\xD2\xD2\x48\xCB\xD9\xD3\xD3\x4E\xD1\xDD\xD3\xD4\x4C\xD5\xD0\xD4\xD5\x57\xD6\xD2\xD6\xD6\x58\xDB\xD9\xD7\xD7\x52\xEE\x79\x51\x40\x63\xC0\x05\xDB\xD9\x48\x69\xD4\xDA\xDA\x66\xEC\xD1\x0C\xDB\x68\xEB\xD2\xDD\xDB\x73\xF1\xD4\xDF\xDD\x76",
|
|
"\xF9\xD0\xDF\xDE\x75\xFC\xD8\xDE\xDF\x7A\xFD\xD2\xE3\xDF\x83\xC1\xE4\xE3\xE1\x86\xF6\xD2\x92\x0C\x04\x4C\xEC\x86\xE3\x60\xBF\x30\xE5\xCB\x94\xD5\xE4\x93\x0C\x39\xD6\xEA\xE7\xE6\xEB\xB4\x09\xE4\xE7\x24\xF6\x0F\xE4\xBE\x35\x23\xED\xC9\xCC\x4B\xA8\xE3\xA9\x82\x37\x37\xCE\xE9\xCD\x38\xDD\xA6\xE6\xEA\xD6\x9F\xC8\x7B\xCC\x36\xF0\xEF\xE9\xEE\xBC\xF3\xE6\xE8\xA4\xA6\xF8\xE1\xEC\xEF\xC3\xC3\xF8\x0E\xAB\xBE\xF6\xE8\x90\xED\x7F\x9C\x85\xF3\xEE\xCF\xC1\x4B\x52\xEE\xCA\xE1\xCC\xF3\x91\xD7\xC2\xF0\xF6\x53\xD4\xC4\xFE\xB5\xF2\x91\xE5\xA1\xF2\xAE\xDB\xDD\xA0\x55\xF7\xD1\xC4\xA0\xFA\x9E\xD9\xE4\xF8\xF9\xF9\xDE\xF5\xCB\xFB\x9D\xED\xCE\xF0\xFD\xFA\xBD\x93\x5D\xF4\xE8\xFC\xFD\xFE\xFF\xFF\x00\x81\x82\x00\x83\x84\x81\x02\x86\x83\x63\x56\x35\x7B\x01\xD8\x4C\x6B\x06\x83\x6D\x68\x5D\x71\x82\x03\xDE\x64\x82\x09\xA0\x6E\x82\x15\x93\x80\x06\x9B\x8A\x83\x0E\x97\x86\x83\x47\x74\x55\x56\x0A\x8B\x80\x91\x49\x70\x70\x28\x93\x6F\xDB\x05\x79\x84\xC4\x6D\x87\x84\x2C\x91\x86\x0B\xB2\x80\x87\x19\xB6\x85\x86\x38\x8F\x87\xEF\x0F\x5C\x2B\xF0\x65\x85",
|
|
"\x64\x90\x73\x70\x7A\x42\x84\x3C\x22\xBF\x85\x7F\x5F\x20\x01\x12\xEE\x3B\x88\xF4\x09\x8F\x89\x5E\x31\x88\x58\x53\x8A\x88\x29\x95\x8C\x8A\x50\x98\x8A\x15\xD9\x87\x8B\x2E\x9C\x8F\x8B\x5B\x81\x8E\x16\xE3\x8E\x8A\x31\xA5\x8C\x8C\x60\x88\x8E\x19\xE9\x87\x8D\x36\x9C\x8F\x88\x7A\x42\x2C\x09\xF0\x84\x80\x21\x3B\x84\x8E\x78\x8F\x5F\x10\x77\x8C\x7F\xEB\x40\x7D\x7A\xDA\x6F\x7E\x20\xAA\x54\x09\xDD\x73\x7E\x4E\xF5\x71\x70\xFE\x3B\x75\x09\xFB\x5F\x7D\x72\x7E\x87\x57\xF8\x76\x73\x91\x45\x95\x92\x56\x90\x9C\x8E\xB2\x13\x9A\x90\x47\x97\x95\x53\x46\x0F\x90\xE5\x11\x9E\x4A\x4E\xAB\x75\x53\x47\x1E\x91\xFC\x2B\x93\x59\xD3\x5A\x96\x65\x80\x8E\x7C\x2B\xAA\x93\x78\x24\x22\x91\x8F\xB8\x98\x49\x12\x04\x2B\x97\x80\x3D\x90\x00\xBF\x81\x98\x2F\xC3\x91\x20\x25\x04\x98\x98\xC7\x82\x9A\x2F\xC9\x9C\x99\x65\x8E\x98\x99\xCF\x8A\x98\x34\xD3\x92\x9B\x6A\x8D\x9C\x9A\xD7\x96\x99\x34\xD9\x9C\x9B\x6D\x9E\x98\x9B\xDF\x9A\x98\x38\xD3\x9E\x3D\x25\x04\x26\x9C\x01\x28\x9C\x00\x6A\x9C\x9D\x73\xAE\x99\x9D\xEF\x8B\x9C\x41\x4C\x01\x9F\x76\xB0\x9F\x9E\xF2\x98",
|
|
"\x9E\x3D\xF9\x9C\x9F\x7D\xBE\x9D\x9E\x00\xBA\x9D\x40\xFD\x93\xA1\x7F\x82\xA7\xA0\x04\xA8\xA2\x41\x89\xAC\xA1\x85\xBB\x9C\x89\x56\x90\xA0\x87\x6C\x84\xA3\x35\x96\xA2\x8D\x18\xAE\x8F\x45\x9A\xA9\xA3\x8A\x9D\xA3\xA3\x1E\xBC\xA2\x48\xA1\xAF\x8D\x5C\xAB\x5D\x09\xAF\x86\xA6\x01\xCE\x09\xA4\x95\xAE\xA7\x09\x2D\xAC\x64\x29\xB9\x51\x96\x4A\xB3\x97\x93\xDF\x50\x0A\x21\x99\x93\x8E\x9A\xBE\x85\x94\x36\xB6\x93\x4D\xC3\xA2\x5C\x9E\xBF\xA5\x4A\x89\x87\x94\xA1\x51\x04\x97\xA6\xB2\x7E\xA8\xEC\x66\x97\xED\x4E\xAC\x76\x29\x14\xAD\x95\x32\xB1\xA7\x54\xB5\xAD\x93\x41\x93\x0F\xAA\xF0\x74\x4A\x38\xE3\xA7\x98\x63\xA1\x9D\x9B\xE3\x84\xAF\x59\xEB\xA9\xAC\xB4\xAA\xAD\xAD\x6C\xAF\xAE\x5C\xEE\xA4\xAE\xB6\xA2\x82\xAB\x2E\xBB\x5E\x43\x85\xAC\xAE\x7C\xB4\x9A\xA1\x7D\xAD\xA1\x60\xFB\xA0\xB1\xC2\x82\xB6\xB0\x84\xA7\xB2\x62\x89\xBC\xB1\xC1\xB8\xAD\x4A\x3D\x99\xAE\x64\x82\x84\x0B\xC7\x93\xB6\x72\x55\x16\xB3\x65\x8D\x66\x0A\xCD\x9B\xB7\x8F\x47\xB4\x49\x52\xDB\xA4\xA8\xB0\x83\x97\x90\xC6\x41\xB4\x2C\xDD\xA3\xA9\x2B\x26\xB5\xB4\x3D\xB9\x63\x4C\x9B",
|
|
"\x9C\xAA\xA5\x82\xAF\xB6\x54\xA8\xB6\xF8\x35\xB8\x3C\x2C\x2F\xB0\xB7\xFB\x7F\xB0\xE8\x59\x0E\xB2\xE1\x87\x4C\x2C\xB1\xA6\xBA\x72\xCA\x46\x2D\xE4\x9B\x73\xB6\xAB\xAA\x49\x20\xB0\xB4\xBA\xE0\xAA\xB6\x64\xD0\xB2\x66\x54\xCD\x75\xBB\x41\x69\x28\xA7\x45\xAB\xB9\xC4\x6C\x2E\xB8\xF1\xA6\xBF\xBC\xE8\xB5\x5D\x76\xBF\x43\xB4\xEE\x96\xBF\xBD\x61\xA9\xBF\xCA\x6F\x25\xBC\xF9\x91\x62\x2E\xF5\xB6\xBC\x2E\xFC\x1F\x1E\x7E\x13\x07\x1F\x9F\x0E\x13\x0F\x71\x15\x03\x47\x1D\x17\x2E\x05\x36\x50\x00\x4D\x41\x20\x06\xCB\xC4\x20\x0E\xD1\xC0\x84\x91\x21\x21\x89\x01\x20\x43\x00\x17\x21\x40\x1A\x21\x20\xFA\x31\x42\xC1\x0A\xC5\x41\x40\x0B\x41\x21\x06\x41\x27\x41\x01\x36\x3D\x40\x70\x38\x41\x06\xE6\x27\xC5\x6E\x40\xC4\x8C\x8F\xCE\xC5\x1A\xF4\xC7\xC6\x0E\xD0\x47\x8D\x91\x40\x01\xFC\x01\x23\x3F\x3B\x42\x43\x8C\x8A\xC2\x4A\x00\x0A\xC6\x23\x6E\x47\x52\x91\xC3\xC3\xC2\x1B\xF4\x46\xC6\x12\xC1\x21\x80\x01\x22\xC7\x80\x0A\xCD\xCA\x4B\xD6\xC4\x8E\x50\xCD\xC9\x2C\xC0\x05\xC8\x47\xCC\xC8\x95\xA4\x4D\xCA\x0F\x76\xC0\xCB\x0A\xD6\x47\x99\x88\x24\x20\x11",
|
|
"\x41\x25\x21\x63\xD1\xCD\x41\x00\x00",
|
|
};
|
|
vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\PARSERGEN_PRINTER\SYNTAXASTTOCODE.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl::glr::parsergen
|
|
{
|
|
using namespace collections;
|
|
using namespace stream;
|
|
|
|
namespace ast_printer
|
|
{
|
|
class SyntaxAstToStringVisitor
|
|
: public Object
|
|
, protected virtual GlrCondition::IVisitor
|
|
, protected virtual GlrSyntax::IVisitor
|
|
, protected virtual GlrClause::IVisitor
|
|
{
|
|
protected:
|
|
TextWriter& writer;
|
|
vint priority = -1;
|
|
|
|
public:
|
|
SyntaxAstToStringVisitor(
|
|
TextWriter& _writer
|
|
)
|
|
: writer(_writer)
|
|
{
|
|
}
|
|
|
|
void VisitClause(Ptr<GlrClause> clause)
|
|
{
|
|
clause->Accept(this);
|
|
}
|
|
protected:
|
|
|
|
void VisitString(const WString& str)
|
|
{
|
|
writer.WriteString(str);
|
|
}
|
|
|
|
void VisitConditionalLiteral(const WString& str)
|
|
{
|
|
writer.WriteString(str);
|
|
}
|
|
|
|
void VisitSyntax(GlrSyntax* node, vint _priority = 2)
|
|
{
|
|
vint oldPriority = priority;
|
|
priority = _priority;
|
|
node->Accept(this);
|
|
priority = oldPriority;
|
|
}
|
|
|
|
void VisitCondition(GlrCondition* node, vint _priority = 2)
|
|
{
|
|
vint oldPriority = priority;
|
|
priority = _priority;
|
|
node->Accept(this);
|
|
priority = oldPriority;
|
|
}
|
|
|
|
void VisitSwitchItems(List<Ptr<GlrSwitchItem>>& switches)
|
|
{
|
|
for (auto [switchItem, index] : indexed(switches))
|
|
{
|
|
if (index != 0) writer.WriteString(L", ");
|
|
if (switchItem->value == GlrSwitchValue::False) writer.WriteChar(L'!');
|
|
writer.WriteString(switchItem->name.value);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GlrCondition::IVisitor
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(GlrRefCondition* node) override
|
|
{
|
|
writer.WriteString(node->name.value);
|
|
}
|
|
|
|
void Visit(GlrNotCondition* node) override
|
|
{
|
|
writer.WriteChar(L'!');
|
|
VisitCondition(node->condition.Obj(), 0);
|
|
}
|
|
|
|
void Visit(GlrAndCondition* node) override
|
|
{
|
|
if (priority < 1) writer.WriteChar(L'(');
|
|
VisitCondition(node->first.Obj(), 1);
|
|
writer.WriteString(L"&&");
|
|
VisitCondition(node->second.Obj(), 1);
|
|
if (priority < 1) writer.WriteChar(L')');
|
|
}
|
|
|
|
void Visit(GlrOrCondition* node) override
|
|
{
|
|
if (priority < 2) writer.WriteChar(L'(');
|
|
VisitCondition(node->first.Obj(), 2);
|
|
writer.WriteString(L"||");
|
|
VisitCondition(node->second.Obj(), 2);
|
|
if (priority < 2) writer.WriteChar(L')');
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GlrSyntax::IVisitor
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(GlrRefSyntax* node) override
|
|
{
|
|
switch (node->refType)
|
|
{
|
|
case GlrRefType::Id:
|
|
writer.WriteString(node->literal.value);
|
|
break;
|
|
case GlrRefType::Literal:
|
|
VisitString(node->literal.value);
|
|
break;
|
|
case GlrRefType::ConditionalLiteral:
|
|
VisitConditionalLiteral(node->literal.value);
|
|
break;
|
|
default:;
|
|
}
|
|
if (node->field)
|
|
{
|
|
writer.WriteChar(L':');
|
|
writer.WriteString(node->field.value);
|
|
}
|
|
}
|
|
|
|
void Visit(GlrUseSyntax* node) override
|
|
{
|
|
writer.WriteChar(L'!');
|
|
writer.WriteString(node->name.value);
|
|
}
|
|
|
|
void Visit(GlrLoopSyntax* node) override
|
|
{
|
|
writer.WriteChar(L'{');
|
|
VisitSyntax(node->syntax.Obj());
|
|
if (node->delimiter)
|
|
{
|
|
writer.WriteString(L" ; ");
|
|
VisitSyntax(node->delimiter.Obj());
|
|
}
|
|
writer.WriteChar(L'}');
|
|
}
|
|
|
|
void Visit(GlrOptionalSyntax* node) override
|
|
{
|
|
switch (node->priority)
|
|
{
|
|
case GlrOptionalPriority::PreferTake:
|
|
writer.WriteChar(L'+');
|
|
break;
|
|
case GlrOptionalPriority::PreferSkip:
|
|
writer.WriteChar(L'-');
|
|
break;
|
|
case GlrOptionalPriority::Equal:
|
|
break;
|
|
default:;
|
|
}
|
|
writer.WriteChar(L'[');
|
|
VisitSyntax(node->syntax.Obj());
|
|
writer.WriteChar(L']');
|
|
}
|
|
|
|
void Visit(GlrSequenceSyntax* node) override
|
|
{
|
|
if (priority < 1) writer.WriteChar(L'(');
|
|
VisitSyntax(node->first.Obj(), 1);
|
|
writer.WriteChar(L' ');
|
|
VisitSyntax(node->second.Obj(), 1);
|
|
if (priority < 1) writer.WriteChar(L')');
|
|
}
|
|
|
|
void Visit(GlrAlternativeSyntax* node) override
|
|
{
|
|
if (priority < 2) writer.WriteChar(L'(');
|
|
VisitSyntax(node->first.Obj(), 2);
|
|
writer.WriteString(L" | ");
|
|
VisitSyntax(node->second.Obj(), 2);
|
|
if (priority < 2) writer.WriteChar(L')');
|
|
}
|
|
|
|
void Visit(GlrPushConditionSyntax* node) override
|
|
{
|
|
writer.WriteString(L"!(");
|
|
VisitSwitchItems(node->switches);
|
|
writer.WriteString(L"; ");
|
|
VisitSyntax(node->syntax.Obj());
|
|
writer.WriteChar(L')');
|
|
}
|
|
|
|
void Visit(GlrTestConditionSyntax* node) override
|
|
{
|
|
writer.WriteString(L"?(");
|
|
for (auto [branch, index] : indexed(node->branches))
|
|
{
|
|
if (index != 0) writer.WriteString(L" | ");
|
|
VisitCondition(branch->condition.Obj());
|
|
writer.WriteString(L": ");
|
|
if (branch->syntax)
|
|
{
|
|
VisitSyntax(branch->syntax.Obj());
|
|
}
|
|
else
|
|
{
|
|
writer.WriteChar(L';');
|
|
}
|
|
}
|
|
writer.WriteChar(L')');
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GlrClause::IVisitor
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(List<Ptr<GlrAssignment>>& assignments)
|
|
{
|
|
if (assignments.Count() > 0)
|
|
{
|
|
writer.WriteString(L" {");
|
|
for (auto [assignment, index] : indexed(assignments))
|
|
{
|
|
if (index != 0) writer.WriteString(L", ");
|
|
writer.WriteString(assignment->field.value);
|
|
if (assignment->type == GlrAssignmentType::Weak)
|
|
{
|
|
writer.WriteString(L" ?= ");
|
|
}
|
|
else
|
|
{
|
|
writer.WriteString(L" = ");
|
|
}
|
|
VisitString(assignment->value.value);
|
|
}
|
|
writer.WriteChar(L'}');
|
|
}
|
|
}
|
|
|
|
void Visit(GlrCreateClause* node) override
|
|
{
|
|
VisitSyntax(node->syntax.Obj());
|
|
writer.WriteString(L" as ");
|
|
writer.WriteString(node->type.value);
|
|
Visit(node->assignments);
|
|
}
|
|
|
|
void Visit(GlrPartialClause* node) override
|
|
{
|
|
VisitSyntax(node->syntax.Obj());
|
|
writer.WriteString(L" as partial ");
|
|
writer.WriteString(node->type.value);
|
|
Visit(node->assignments);
|
|
}
|
|
|
|
void Visit(GlrReuseClause* node) override
|
|
{
|
|
VisitSyntax(node->syntax.Obj());
|
|
Visit(node->assignments);
|
|
}
|
|
};
|
|
}
|
|
|
|
/***********************************************************************
|
|
SyntaxAstToCode
|
|
***********************************************************************/
|
|
|
|
void SyntaxAstToCode(
|
|
Ptr<GlrSyntaxFile> file,
|
|
TextWriter& writer
|
|
)
|
|
{
|
|
if (file->switches.Count() > 0)
|
|
{
|
|
writer.WriteString(L"switch ");
|
|
for (auto [switchItem, index] : indexed(file->switches))
|
|
{
|
|
if (index != 0) writer.WriteString(L", ");
|
|
if (switchItem->value == GlrSwitchValue::False) writer.WriteChar(L'!');
|
|
writer.WriteString(switchItem->name.value);
|
|
}
|
|
writer.WriteLine(L";");
|
|
writer.WriteLine(L"");
|
|
}
|
|
|
|
ast_printer::SyntaxAstToStringVisitor visitor(writer);
|
|
for (auto rule : file->rules)
|
|
{
|
|
if (rule->attPublic)
|
|
{
|
|
writer.WriteString(L"@public ");
|
|
}
|
|
if (rule->attParser)
|
|
{
|
|
writer.WriteString(L"@parser ");
|
|
}
|
|
writer.WriteString(rule->name.value);
|
|
if (rule->type)
|
|
{
|
|
writer.WriteString(L" : ");
|
|
writer.WriteString(rule->type.value);
|
|
}
|
|
writer.WriteLine(L"");
|
|
|
|
for (auto clause : rule->clauses)
|
|
{
|
|
writer.WriteString(L" ::= ");
|
|
visitor.VisitClause(clause);
|
|
writer.WriteLine(L"");
|
|
}
|
|
writer.WriteLine(L" ;");
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\PARSERGEN_PRINTER\TYPEASTTOCODE.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl::glr::parsergen
|
|
{
|
|
using namespace collections;
|
|
using namespace stream;
|
|
|
|
namespace ast_printer
|
|
{
|
|
class TypeAstToStringVisitor
|
|
: public Object
|
|
, protected virtual GlrType::IVisitor
|
|
{
|
|
protected:
|
|
TextWriter& writer;
|
|
|
|
public:
|
|
TypeAstToStringVisitor(
|
|
TextWriter& _writer
|
|
)
|
|
: writer(_writer)
|
|
{
|
|
}
|
|
|
|
void VisitType(Ptr<GlrType> clause)
|
|
{
|
|
clause->Accept(this);
|
|
}
|
|
protected:
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GlrType::IVisitor
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(GlrEnum* node) override
|
|
{
|
|
if (node->attPublic)
|
|
{
|
|
writer.WriteString(L"@public ");
|
|
}
|
|
writer.WriteString(L"enum ");
|
|
writer.WriteString(node->name.value);
|
|
writer.WriteLine(L"");
|
|
writer.WriteLine(L"{");
|
|
for (auto item : node->items)
|
|
{
|
|
writer.WriteString(L" ");
|
|
writer.WriteString(item->name.value);
|
|
writer.WriteLine(L",");
|
|
}
|
|
writer.WriteLine(L"}");
|
|
}
|
|
|
|
void Visit(GlrClass* node) override
|
|
{
|
|
if (node->attPublic)
|
|
{
|
|
writer.WriteString(L"@public ");
|
|
}
|
|
if (node->attAmbiguous)
|
|
{
|
|
writer.WriteString(L"@ambiguous ");
|
|
}
|
|
writer.WriteString(L"class ");
|
|
writer.WriteString(node->name.value);
|
|
if (node->baseClass)
|
|
{
|
|
writer.WriteString(L" : ");
|
|
writer.WriteString(node->baseClass.value);
|
|
}
|
|
writer.WriteLine(L"");
|
|
writer.WriteLine(L"{");
|
|
for (auto prop : node->props)
|
|
{
|
|
writer.WriteString(L" var ");
|
|
writer.WriteString(prop->name.value);
|
|
writer.WriteString(L" : ");
|
|
switch (prop->propType)
|
|
{
|
|
case GlrPropType::Token:
|
|
writer.WriteString(L"token");
|
|
break;
|
|
case GlrPropType::Type:
|
|
writer.WriteString(prop->propTypeName.value);
|
|
break;
|
|
case GlrPropType::Array:
|
|
writer.WriteString(prop->propTypeName.value);
|
|
writer.WriteString(L"[]");
|
|
break;
|
|
default:;
|
|
}
|
|
writer.WriteLine(L";");
|
|
}
|
|
writer.WriteLine(L"}");
|
|
}
|
|
};
|
|
}
|
|
|
|
/***********************************************************************
|
|
TypeAstToCode
|
|
***********************************************************************/
|
|
|
|
void TypeAstToCode(
|
|
Ptr<GlrAstFile> file,
|
|
TextWriter& writer
|
|
)
|
|
{
|
|
ast_printer::TypeAstToStringVisitor visitor(writer);
|
|
for (auto type : file->types)
|
|
{
|
|
visitor.VisitType(type);
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\PARSERGEN_PRINTER\TYPESYMBOLTOAST.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl::glr::parsergen
|
|
{
|
|
/***********************************************************************
|
|
TypeAstToCode
|
|
***********************************************************************/
|
|
|
|
Ptr<GlrAstFile> TypeSymbolToAst(
|
|
const AstSymbolManager& manager,
|
|
bool createGeneratedTypes
|
|
)
|
|
{
|
|
auto generated = Ptr(new GlrAstFile);
|
|
for (auto groupName : manager.FileGroupOrder())
|
|
{
|
|
auto group = manager.FileGroups()[groupName];
|
|
for (auto typeName : group->SymbolOrder())
|
|
{
|
|
auto symbol = group->Symbols()[typeName];
|
|
|
|
if (auto enumSymbol = dynamic_cast<AstEnumSymbol*>(symbol))
|
|
{
|
|
auto enumType = Ptr(new GlrEnum);
|
|
generated->types.Add(enumType);
|
|
|
|
if (enumSymbol->isPublic) enumType->attPublic.value = L"@public";
|
|
enumType->name.value = enumSymbol->Name();
|
|
|
|
for (auto itemName : enumSymbol->ItemOrder())
|
|
{
|
|
auto itemSymbol = enumSymbol->Items()[itemName];
|
|
|
|
auto enumItem = Ptr(new GlrEnumItem);
|
|
enumType->items.Add(enumItem);
|
|
|
|
enumItem->name.value = itemSymbol->Name();
|
|
}
|
|
}
|
|
|
|
if (auto classSymbol = dynamic_cast<AstClassSymbol*>(symbol))
|
|
{
|
|
if (!createGeneratedTypes && classSymbol->classType != AstClassType::Defined)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
auto classType = Ptr(new GlrClass);
|
|
generated->types.Add(classType);
|
|
|
|
if (classSymbol->isPublic) classType->attPublic.value = L"@public";
|
|
if (classSymbol->derivedClass_ToResolve) classType->attAmbiguous.value = L"@ambiguous";
|
|
classType->name.value = classSymbol->Name();
|
|
|
|
if (classSymbol->baseClass)
|
|
{
|
|
if (!createGeneratedTypes && classSymbol->baseClass->classType == AstClassType::Generated_Common)
|
|
{
|
|
classType->baseClass.value = classSymbol->baseClass->baseClass->Name();
|
|
}
|
|
else
|
|
{
|
|
classType->baseClass.value = classSymbol->baseClass->Name();
|
|
}
|
|
}
|
|
|
|
if (!createGeneratedTypes && classSymbol->derivedClass_Common)
|
|
{
|
|
classSymbol = classSymbol->derivedClass_Common;
|
|
}
|
|
for (auto propName : classSymbol->PropOrder())
|
|
{
|
|
auto propSymbol = classSymbol->Props()[propName];
|
|
|
|
auto classProp = Ptr(new GlrClassProp);
|
|
classType->props.Add(classProp);
|
|
|
|
classProp->name.value = propSymbol->Name();
|
|
switch (propSymbol->propType)
|
|
{
|
|
case AstPropType::Token:
|
|
classProp->propType = GlrPropType::Token;
|
|
break;
|
|
case AstPropType::Type:
|
|
classProp->propType = GlrPropType::Type;
|
|
break;
|
|
case AstPropType::Array:
|
|
classProp->propType = GlrPropType::Array;
|
|
break;
|
|
}
|
|
if (propSymbol->propSymbol) classProp->propTypeName.value = propSymbol->propSymbol->Name();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return generated;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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;
|
|
}
|
|
|
|
WString AstClassSymbolToString(AstClassSymbol* astType)
|
|
{
|
|
return GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WriteNssName(astType->Owner()->Owner()->cppNss, writer);
|
|
writer.WriteString(L"::");
|
|
writer.WriteString(astType->Owner()->Owner()->classPrefix);
|
|
writer.WriteString(astType->Name());
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
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"");
|
|
for (auto include : manager.Global().syntaxIncludes)
|
|
{
|
|
if (include.Length() > 0 && include[0] == L'<')
|
|
{
|
|
writer.WriteLine(L"#include " + include);
|
|
}
|
|
else
|
|
{
|
|
writer.WriteLine(L"#include \"" + include + 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::WString GetClassName(vl::vint32_t classIndex) const override;");
|
|
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 (ruleSymbol->isParser)
|
|
{
|
|
auto astType = AstClassSymbolToString(ruleSymbol->ruleType);
|
|
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::WString " + manager.name + L"::GetClassName(vl::vint32_t classIndex) const");
|
|
writer.WriteLine(prefix + L"{");
|
|
writer.WriteLine(prefix + L"\treturn vl::WString::Unmanaged(" + manager.Global().name + L"TypeName((" + manager.Global().name + L"Classes)classIndex));");
|
|
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->derivedClass_ToResolve != 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 (ruleSymbol->isParser)
|
|
{
|
|
auto astType = AstClassSymbolToString(ruleSymbol->ruleType);
|
|
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)
|
|
: ownerManager(_rule->Owner())
|
|
, rule(_rule)
|
|
{
|
|
}
|
|
|
|
void StateSymbol::GetOutEdgesInStableOrder(collections::List<StateSymbol*>& orderedStates, EdgeList& orderedEdges)
|
|
{
|
|
CopyFrom(orderedEdges, From(outEdges)
|
|
.OrderBy([&](EdgeSymbol* e1, EdgeSymbol* e2)
|
|
{
|
|
std::strong_ordering result = e1->input.type <=> e2->input.type;
|
|
if (result == 0)
|
|
{
|
|
switch (e1->input.type)
|
|
{
|
|
case EdgeInputType::Token:
|
|
result = e1->input.token <=> e2->input.token;
|
|
if (result == 0)
|
|
{
|
|
result = e1->input.condition <=> e2->input.condition;
|
|
}
|
|
break;
|
|
case EdgeInputType::Rule:
|
|
result = ownerManager->RuleOrder().IndexOf(e1->input.rule->Name()) <=> ownerManager->RuleOrder().IndexOf(e2->input.rule->Name());
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
if (result == 0)
|
|
{
|
|
result = orderedStates.IndexOf(e1->To()) <=> orderedStates.IndexOf(e2->To());
|
|
}
|
|
if (result == 0)
|
|
{
|
|
result = CompareEnumerable(e1->competitions, e2->competitions);
|
|
}
|
|
if (result == 0)
|
|
{
|
|
result = CompareEnumerable(e1->insAfterInput, e2->insAfterInput);
|
|
}
|
|
if (result == 0)
|
|
{
|
|
result = e1->returnEdges.Count() <=> e2->returnEdges.Count();
|
|
}
|
|
if (result == 0)
|
|
{
|
|
result = CompareEnumerable(
|
|
From(e1->returnEdges).Select([&](EdgeSymbol* e) { return orderedStates.IndexOf(e->To()); }),
|
|
From(e2->returnEdges).Select([&](EdgeSymbol* e) { return orderedStates.IndexOf(e->To()); })
|
|
);
|
|
}
|
|
return result;
|
|
}));
|
|
}
|
|
|
|
/***********************************************************************
|
|
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, vint _fileIndex)
|
|
: ownerManager(_ownerManager)
|
|
, name(_name)
|
|
, fileIndex(_fileIndex)
|
|
{
|
|
}
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager
|
|
***********************************************************************/
|
|
|
|
SyntaxSymbolManager::SyntaxSymbolManager(ParserSymbolManager& _global)
|
|
: global(_global)
|
|
{
|
|
}
|
|
|
|
RuleSymbol* SyntaxSymbolManager::CreateRule(const WString& name, vint fileIndex, bool isPublic, bool isParser, 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, fileIndex);
|
|
if (!rules.Add(name, rule))
|
|
{
|
|
AddError(
|
|
ParserErrorType::DuplicatedRule,
|
|
codeRange,
|
|
name
|
|
);
|
|
}
|
|
rule->isPublic = isPublic;
|
|
rule->isParser = isParser;
|
|
return rule;
|
|
}
|
|
|
|
void SyntaxSymbolManager::RemoveRule(const WString& name)
|
|
{
|
|
rules.Remove(name);
|
|
}
|
|
|
|
StateSymbol* SyntaxSymbolManager::CreateState(RuleSymbol* rule)
|
|
{
|
|
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));
|
|
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);
|
|
// TODO: (enumerable) Linq:Skip
|
|
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];
|
|
if (ruleSymbol->isPartial) continue;
|
|
auto orderedStates = From(groupedStates[ruleSymbol])
|
|
.OrderByKey([](StateSymbol* s)
|
|
{
|
|
return s->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;
|
|
|
|
vint count = usedFieldIds++;
|
|
edge->insAfterInput.Add({ AstInsType::Token,-1,count });
|
|
if (field != -1)
|
|
{
|
|
fieldIns.Add({ AstInsType::Field,field,count });
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
vint count = usedFieldIds++;
|
|
switch (ruleType)
|
|
{
|
|
case automaton::ReturnRuleType::Field:
|
|
CHECK_ERROR(field != -1, ERROR_MESSAGE_PREFIX L"Field must set for ReturnRuleType::Field.");
|
|
edge->insAfterInput.Add({ AstInsType::StackSlot,-1,count });
|
|
fieldIns.Add({ AstInsType::Field,field,count });
|
|
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::StackSlot,-1,count });
|
|
break;
|
|
case automaton::ReturnRuleType::Reuse:
|
|
CHECK_ERROR(field == -1, ERROR_MESSAGE_PREFIX L"Field must not set for ReturnRuleType::Reuse.");
|
|
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::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 || preferSkip)
|
|
{
|
|
vint32_t id = ++ruleSymbol->Owner()->usedCompetitionIds;
|
|
takeEdge->competitions.Add({ id,preferTake });
|
|
skipEdge->competitions.Add({ id,preferSkip });
|
|
}
|
|
|
|
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]();
|
|
// TODO: (enumerable) Linq:Skip
|
|
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"( ";
|
|
// TODO: (enumerable) foreach:indexed
|
|
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)
|
|
{
|
|
usedFieldIds = 0;
|
|
fieldIns.Clear();
|
|
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);
|
|
vint count = usedFieldIds++;
|
|
edge->insAfterInput.Add({ AstInsType::EnumItem,enumItem,count });
|
|
fieldIns.Add({ (weakAssignment ? AstInsType::FieldIfUnassigned : AstInsType::Field),field,count});
|
|
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->insAfterInput.Add({ AstInsType::StackBegin });
|
|
}
|
|
{
|
|
auto edge = CreateEdge(bodyPair.end, pair.end);
|
|
edge->insAfterInput.Add({ AstInsType::CreateObject,classId });
|
|
CopyFrom(edge->insAfterInput, fieldIns, true);
|
|
edge->insAfterInput.Add({ AstInsType::StackEnd });
|
|
}
|
|
endPoses.Add(pair.end, clauseDisplayText.Length());
|
|
return pair;
|
|
}
|
|
|
|
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->insAfterInput.Add({ AstInsType::StackBegin });
|
|
}
|
|
{
|
|
auto edge = CreateEdge(bodyPair.end, pair.end);
|
|
CopyFrom(edge->insAfterInput, fieldIns, true);
|
|
edge->insAfterInput.Add({ AstInsType::StackEnd });
|
|
}
|
|
endPoses.Add(pair.end, clauseDisplayText.Length());
|
|
return pair;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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.endingState = state->endingState;
|
|
}
|
|
|
|
List<EdgeSymbol*> edgesInOrder;
|
|
List<EdgeSymbol*> returnEdgesInOrder;
|
|
List<automaton::CompetitionDesc> competitionsInOrder;
|
|
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;
|
|
}
|
|
})
|
|
.OrderByKey([&](EdgeSymbol* e)
|
|
{
|
|
return statesInOrder.IndexOf(e->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;
|
|
}
|
|
|
|
// edgeDesc.competitions
|
|
edgeDesc.competitions.start = (vint32_t)competitionsInOrder.Count();
|
|
for (auto competition : edge->competitions)
|
|
{
|
|
competitionsInOrder.Add({ competition.competitionId, competition.highPriority });
|
|
}
|
|
edgeDesc.competitions.count = (vint32_t)competitionsInOrder.Count() - edgeDesc.competitions.start;
|
|
|
|
// edgeDesc.insAfterInput
|
|
edgeDesc.insAfterInput.start = (vint32_t)astInsInOrder.Count();
|
|
CopyFrom(astInsInOrder, edge->insAfterInput, true);
|
|
edgeDesc.insAfterInput.count = (vint32_t)astInsInOrder.Count() - edgeDesc.insAfterInput.start;
|
|
|
|
// edgeDesc.returnIndices
|
|
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.competitions.count == 0) edgeDesc.competitions.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());
|
|
returnDesc.ruleType = edge->input.ruleType;
|
|
|
|
// returnDesc.competitions
|
|
returnDesc.competitions.start = (vint32_t)competitionsInOrder.Count();
|
|
for (auto competition : edge->competitions)
|
|
{
|
|
competitionsInOrder.Add({ competition.competitionId, competition.highPriority });
|
|
}
|
|
returnDesc.competitions.count = (vint32_t)competitionsInOrder.Count() - returnDesc.competitions.start;
|
|
|
|
// returnDesc.insAfterInput
|
|
returnDesc.insAfterInput.start = (vint32_t)astInsInOrder.Count();
|
|
CopyFrom(astInsInOrder, edge->insAfterInput, true);
|
|
returnDesc.insAfterInput.count = (vint32_t)astInsInOrder.Count() - returnDesc.insAfterInput.start;
|
|
|
|
if (returnDesc.competitions.count == 0) returnDesc.competitions.start = -1;
|
|
if (returnDesc.insAfterInput.count == 0) returnDesc.insAfterInput.start = -1;
|
|
}
|
|
|
|
// executable.competitions
|
|
CopyFrom(executable.competitions, competitionsInOrder);
|
|
|
|
// 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(AstSymbolManager& ast, SyntaxSymbolManager& manager)
|
|
{
|
|
auto createRule = [&](const wchar_t* ruleName)
|
|
{
|
|
return manager.CreateRule(WString::Unmanaged(ruleName), -1, false, false);
|
|
};
|
|
|
|
manager.name = L"RuleParser";
|
|
|
|
auto _cond0 = createRule(L"Cond0");
|
|
auto _cond1 = createRule(L"Cond1");
|
|
auto _cond2 = createRule(L"Cond2");
|
|
auto _cond = createRule(L"Cond");
|
|
auto _switchItem = createRule(L"SwitchItem");
|
|
auto _testBranch = createRule(L"TestBranch");
|
|
auto _syntax0 = createRule(L"Syntax0");
|
|
auto _syntax1 = createRule(L"Syntax1");
|
|
auto _syntax2 = createRule(L"Syntax2");
|
|
auto _syntax = createRule(L"Syntax");
|
|
auto _assignment = createRule(L"Assignment");
|
|
auto _clause = createRule(L"Clause");
|
|
auto _rule = createRule(L"Rule");
|
|
auto _file = createRule(L"File");
|
|
|
|
_file->isParser = true;
|
|
_file->ruleType = dynamic_cast<AstClassSymbol*>(ast.Symbols()[L"SyntaxFile"][0]);
|
|
|
|
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
|
|
auto _switches = tok(T::SWITCH) + loop(rule(_switchItem, F::SyntaxFile_switches), tok(T::COMMA)) + tok(T::SEMICOLON);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// Syntax (primitive)
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// "[" Syntax:syntax "]" as partial OptionalSyntax
|
|
auto _optionalBody = tok(T::OPEN_SQUARE) + rule(_syntax, F::OptionalSyntax_syntax) + tok(T::CLOSE_SQUARE);
|
|
|
|
// ID:literal as partial RefSyntax {refType = Id}
|
|
// STRING:literal as partial RefSyntax {refType = Literal}
|
|
// CONDITIONAL_LITERAL:literal as partial RefSyntax {refType = ConditionalLiteral}
|
|
auto _token_Id = tok(T::ID, F::RefSyntax_literal) && with(F::RefSyntax_refType, GlrRefType::Id);
|
|
auto _token_Literal = tok(T::STRING, F::RefSyntax_literal) && with(F::RefSyntax_refType, GlrRefType::Literal);
|
|
auto _token_ConditionalLiteral = tok(T::CONDITIONAL_LITERAL, F::RefSyntax_literal) && with(F::RefSyntax_refType, GlrRefType::ConditionalLiteral);
|
|
auto _token = _token_Id | _token_Literal | _token_ConditionalLiteral;
|
|
|
|
// Token [":" ID:field] as RefSyntax
|
|
Clause{ _syntax0 } = create(_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) + _optionalBody, C::OptionalSyntax).with(F::OptionalSyntax_priority, GlrOptionalPriority::PreferTake);
|
|
|
|
// "-" OptionalBody as OptionalSyntax {priority = PreferSkip}
|
|
Clause{ _syntax0 } = create(tok(T::NEGATIVE) + _optionalBody, C::OptionalSyntax).with(F::OptionalSyntax_priority, GlrOptionalPriority::PreferSkip);
|
|
|
|
// OptionalBody as OptionalSyntax {priority = Equal}
|
|
Clause{ _syntax0 } = create(_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}
|
|
// "?=" as partial Assignment {type = Weak}
|
|
auto _assignmentOp_Strong = tok(T::ASSIGN) && with(F::Assignment_type, GlrAssignmentType::Strong);
|
|
auto _assignmentOp_Weak = tok(T::WEAK_ASSIGN) && with(F::Assignment_type, GlrAssignmentType::Weak);
|
|
auto _assignmentOp = _assignmentOp_Strong | _assignmentOp_Weak;
|
|
|
|
// ID:field AssignmentOp STRING:value as Assignment
|
|
Clause{ _assignment } = create(tok(T::ID, F::Assignment_field) + _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);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// File
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ["@public"] ["@parser"] ID:name {"::=" Clause:clauses} ";" as Rule
|
|
Clause{ _rule } = create(opt(tok(T::ATT_PUBLIC, F::Rule_attPublic)) + opt(tok(T::ATT_PARSER, F::Rule_attParser)) + 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(_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(AstSymbolManager& ast, SyntaxSymbolManager& manager)
|
|
{
|
|
auto createRule = [&](const wchar_t* ruleName)
|
|
{
|
|
return manager.CreateRule(WString::Unmanaged(ruleName), -1, false, false);
|
|
};
|
|
|
|
manager.name = L"TypeParser";
|
|
|
|
auto _enumItem = createRule(L"EnumItem");
|
|
auto _enum = createRule(L"Enum");
|
|
auto _classProp = createRule(L"classProp");
|
|
auto _class = createRule(L"Class");
|
|
auto _type = createRule(L"Type");
|
|
auto _file = createRule(L"File");
|
|
|
|
_file->isParser = true;
|
|
_file->ruleType = dynamic_cast<AstClassSymbol*>(ast.Symbols()[L"AstFile"][0]);
|
|
|
|
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);
|
|
|
|
// ["@public"] "enum" ID:name "{" {EnumItem} "}" as Enum
|
|
Clause{ _enum } = create(opt(tok(T::ATT_PUBLIC, F::Type_attPublic)) + 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"}
|
|
// ID:propTypeName as partial ClassProp {propType = "Type"}
|
|
// ID:propTypeName "[" "]" as partial ClassProp {propType = "Array"}
|
|
auto _classPropType_Token = tok(T::TOKEN) && with(F::ClassProp_propType, GlrPropType::Token);
|
|
auto _classPropType_Type = (tok(T::ID, F::ClassProp_propTypeName)) && with(F::ClassProp_propType, GlrPropType::Type);
|
|
auto _classPropType_Array = (tok(T::ID, F::ClassProp_propTypeName) + tok(T::OPEN_SQUARE) + tok(T::CLOSE_SQUARE)) && with(F::ClassProp_propType, GlrPropType::Array);
|
|
auto _classPropType = _classPropType_Token | _classPropType_Type | _classPropType_Array;
|
|
|
|
// "var" ID:name ":" ClassPropType ";" as ClassProp
|
|
Clause{ _classProp } = create(tok(T::VAR) + tok(T::ID, F::ClassProp_name) + tok(T::COLON) + _classPropType + tok(T::SEMICOLON), C::ClassProp);
|
|
|
|
// ID:name [":" ID:baseClass] "{" {ClassProp} "}" as partial Class
|
|
auto _classBody = (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));
|
|
|
|
// ["@public"] ["@ambiguous"] "class" ClassBody {ambiguity = Yes}
|
|
Clause{ _class } = create(opt(tok(T::ATT_PUBLIC, F::Type_attPublic)) + opt(tok(T::ATT_AMBIGUOUS, F::Class_attAmbiguous)) + tok(T::CLASS) + _classBody, C::Class);
|
|
|
|
// !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;
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::MergeEdgesWithSameInput
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::ApplyIncrementalChange(const IncrementalChange& ic, StateList& newStates, EdgeList& newEdges)
|
|
{
|
|
if (ic.createdStates.Count() + ic.createdEdges.Count() > 0)
|
|
{
|
|
for (vint i = newEdges.Count() - 1; i >= 0; i--)
|
|
{
|
|
auto edge = newEdges[i];
|
|
if (ic.reuseOps == !ic.opEdges.Contains(edge.Obj()))
|
|
{
|
|
if (edge->fromState) edge->fromState->outEdges.Remove(edge.Obj());
|
|
if (edge->toState) edge->toState->inEdges.Remove(edge.Obj());
|
|
newEdges.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
for (vint i = newStates.Count() - 1; i >= 0; i--)
|
|
{
|
|
auto state = newStates[i];
|
|
if (ic.reuseOps == !ic.opStates.Contains(state.Obj()))
|
|
{
|
|
newStates.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
CopyFrom(newStates, ic.createdStates, true);
|
|
CopyFrom(newEdges, ic.createdEdges, true);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::BuildCompactNFAInternal
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::BuildCompactNFAInternal()
|
|
{
|
|
Array<Pair<Ptr<StateList>, Ptr<EdgeList>>> newStatesAndEdges(rules.map.Count());
|
|
for (vint i = 0; i < newStatesAndEdges.Count(); i++)
|
|
{
|
|
newStatesAndEdges[i] = { Ptr(new StateList),Ptr(new EdgeList) };
|
|
}
|
|
|
|
for (auto [ruleSymbol, i] : indexed(rules.map.Values()))
|
|
{
|
|
auto&& newStates = *newStatesAndEdges[i].key.Obj();
|
|
auto&& newEdges = *newStatesAndEdges[i].value.Obj();
|
|
// remove all epsilon edges, potentially duplicating input edges
|
|
auto [startState, endState] = EliminateEpsilonEdges(ruleSymbol, newStates, newEdges);
|
|
ruleSymbol->startStates.Clear();
|
|
ruleSymbol->startStates.Add(startState);
|
|
|
|
// there will be only one start state per rule after EliminateEpsilonEdges
|
|
// detect and resolve direct left recursion
|
|
EliminateLeftRecursion(ruleSymbol, startState, endState, newStates, newEdges);
|
|
|
|
// merge as many input edges as possible to reduce wasted traces during parsing
|
|
// they consume same token or rule from the same state
|
|
// performance will be bad if duplicated parsing actually happen
|
|
// could save 20x wasted traces for Workflow parser
|
|
MergeEdgesWithSameInput(ruleSymbol, startState, newStates, newEdges);
|
|
MergeEdgesWithSameRuleUsingLeftrec(ruleSymbol, ruleSymbol->startStates[0], newStates, newEdges);
|
|
}
|
|
|
|
// further merging but introduces minimum cross-reference rule input to states in other rule
|
|
// this should only be done after performing local merging inside each rule
|
|
// detect and ban indirect left recursion
|
|
auto pmCache = CreatePrefixMergeCache();
|
|
if (!pmCache) return;
|
|
PrefixMergeCrossReference_Solve(pmCache.Obj(), prefixMergeSolutions);
|
|
|
|
// apply each solution
|
|
// unnecessary edges will be removed later as they could be still needed
|
|
// prefix-merge created Rule becomes PrefixMergeRule and later changed back to Rule
|
|
Array<IncrementalChange> ics(prefixMergeSolutions.Count());
|
|
for (auto [key, index] : indexed(prefixMergeSolutions.Keys()))
|
|
{
|
|
auto [ruleSymbol, currentState] = key;
|
|
auto solution = prefixMergeSolutions[key];
|
|
auto&& ic = ics[index];
|
|
ic.reuseOps = false;
|
|
PrefixMergeCrossReference_Apply(pmCache.Obj(), ruleSymbol, currentState, solution, ic);
|
|
}
|
|
|
|
// recycle unused states and edges
|
|
for (auto [key, index] : indexed(prefixMergeSolutions.Keys()))
|
|
{
|
|
auto [ruleSymbol, currentState] = key;
|
|
vint i = rules.map.Keys().IndexOf(ruleSymbol->Name());
|
|
auto&& newStates = *newStatesAndEdges[i].key.Obj();
|
|
auto&& newEdges = *newStatesAndEdges[i].value.Obj();
|
|
auto&& ic = ics[index];
|
|
ApplyIncrementalChange(ic, newStates, newEdges);
|
|
|
|
auto solution = prefixMergeSolutions[key];
|
|
for (auto application : solution->applications)
|
|
{
|
|
for (auto edge : application->edgesToMerge)
|
|
{
|
|
edge->input.type = EdgeInputType::PrefixMergeDiscardedRule;
|
|
}
|
|
}
|
|
|
|
for (auto edge : currentState->OutEdges())
|
|
{
|
|
if (edge->input.type == EdgeInputType::PrefixMergeRule)
|
|
{
|
|
edge->input.type = EdgeInputType::Rule;
|
|
}
|
|
}
|
|
}
|
|
|
|
// secure life cycle of states and edges
|
|
states.Clear();
|
|
edges.Clear();
|
|
for (vint i = 0; i < newStatesAndEdges.Count(); i++)
|
|
{
|
|
auto&& newStates = *newStatesAndEdges[i].key.Obj();
|
|
auto&& newEdges = *newStatesAndEdges[i].value.Obj();
|
|
CopyFrom(states, newStates, true);
|
|
CopyFrom(edges, newEdges, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\SYNTAX\SYNTAXSYMBOL_NFACOMPACT_ELIMINATEEPSILONEDGES.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
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:
|
|
{
|
|
// 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;
|
|
for (auto accumulatedEdge : accumulatedEdges)
|
|
{
|
|
CopyFrom(newEdge->insAfterInput, accumulatedEdge->insAfterInput, true);
|
|
CopyFrom(newEdge->competitions, accumulatedEdge->competitions, true);
|
|
}
|
|
}
|
|
break;
|
|
case EdgeInputType::Epsilon:
|
|
BuildEpsilonEliminatedEdgesInternal(edge->To(), newState, endState, visited, accumulatedEdges);
|
|
break;
|
|
case EdgeInputType::Ending:
|
|
// These edges are not involved
|
|
case EdgeInputType::LeftRec:
|
|
case EdgeInputType::PrefixMergeDiscardedRule:
|
|
case EdgeInputType::PrefixMergeRule:
|
|
case EdgeInputType::CrossReferencedToken:
|
|
// These edges do not 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->insAfterInput, accumulatedEdge->insAfterInput, true);
|
|
CopyFrom(newEdge->competitions, accumulatedEdge->competitions, true);
|
|
}
|
|
|
|
for (auto endingEdge : newState->OutEdges())
|
|
{
|
|
if (endingEdge != newEdge && endingEdge->input.type == EdgeInputType::Ending)
|
|
{
|
|
if (CompareEnumerable(endingEdge->insAfterInput, newEdge->insAfterInput) == 0)
|
|
{
|
|
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));
|
|
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::EliminateEpsilonEdges
|
|
***********************************************************************/
|
|
|
|
SyntaxSymbolManager::StartEndStatePair 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 = Ptr(new StateSymbol(rule));
|
|
newStates.Add(psuedoState);
|
|
for (auto startState : rule->startStates)
|
|
{
|
|
newEdges.Add(Ptr(new EdgeSymbol(psuedoState.Obj(), startState)));
|
|
}
|
|
|
|
CompactSyntaxBuilder builder(rule, newStates, newEdges);
|
|
auto compactStartState = builder.CreateCompactState(psuedoState.Obj());
|
|
compactStartState->label = L" BEGIN ";
|
|
|
|
auto compactEndState = Ptr(new StateSymbol(rule));
|
|
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
|
|
// TODO: (enumerable) foreach:alterable
|
|
for (vint i = 0; i < visited.Count(); i++)
|
|
{
|
|
auto current = visited[i];
|
|
builder.BuildEpsilonEliminatedEdges(current, compactEndState.Obj(), visited);
|
|
}
|
|
|
|
return { compactStartState,compactEndState.Obj()};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\SYNTAX\SYNTAXSYMBOL_NFACOMPACT_ELIMINATELEFTRECURSION.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::BuildLeftRecEdge
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::BuildLeftRecEdge(EdgeSymbol* newEdge, EdgeSymbol* endingEdge, EdgeSymbol* lrecPrefixEdge)
|
|
{
|
|
CopyFrom(newEdge->competitions, endingEdge->competitions, true);
|
|
CopyFrom(newEdge->competitions, lrecPrefixEdge->competitions, true);
|
|
|
|
newEdge->input.type = EdgeInputType::LeftRec;
|
|
CopyFrom(newEdge->insAfterInput, endingEdge->insAfterInput, true);
|
|
CopyFrom(newEdge->insAfterInput, lrecPrefixEdge->insAfterInput, true);
|
|
}
|
|
|
|
/***********************************************************************
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\SYNTAX\SYNTAXSYMBOL_NFACOMPACT_MERGEEDGESWITHSAMEINPUT.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
SymbolSet
|
|
***********************************************************************/
|
|
|
|
template<typename TSymbol, bool Ordered>
|
|
struct SymbolSetListType;
|
|
|
|
template<typename TSymbol>
|
|
struct SymbolSetListType<TSymbol, false>
|
|
{
|
|
using Type = List<TSymbol>;
|
|
};
|
|
|
|
template<typename TSymbol>
|
|
struct SymbolSetListType<TSymbol, true>
|
|
{
|
|
using Type = SortedList<TSymbol>;
|
|
};
|
|
|
|
template<typename TSymbol, bool Ordered>
|
|
using SymbolSetListType_t = typename SymbolSetListType<TSymbol, Ordered>::Type;;
|
|
|
|
template<typename TSymbol, bool Ordered>
|
|
struct SymbolSet
|
|
{
|
|
public:
|
|
using ListType = SymbolSetListType_t<TSymbol, Ordered>;
|
|
using ListPtr = Ptr<ListType>;
|
|
|
|
private:
|
|
static const ListType EmptySymbols;
|
|
ListPtr symbols;
|
|
|
|
public:
|
|
SymbolSet() = default;
|
|
SymbolSet(const SymbolSet&) = delete;
|
|
SymbolSet<TSymbol, Ordered>& operator=(const SymbolSet<TSymbol, Ordered>&) = delete;
|
|
|
|
SymbolSet<TSymbol, Ordered>(SymbolSet<TSymbol, Ordered>&& set)
|
|
{
|
|
symbols = set.symbols;
|
|
set.symbols = nullptr;
|
|
}
|
|
|
|
SymbolSet<TSymbol, Ordered>& operator=(SymbolSet<TSymbol, Ordered>&& set)
|
|
{
|
|
symbols = set.symbols;
|
|
set.symbols = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
SymbolSet(TSymbol _symbol)
|
|
{
|
|
Add(_symbol);
|
|
}
|
|
|
|
SymbolSet(const IEnumerable<TSymbol>& _symbols)
|
|
{
|
|
symbols = Ptr(new ListType);
|
|
CopyFrom(*symbols.Obj(), _symbols);
|
|
}
|
|
|
|
bool Add(TSymbol _symbol)
|
|
{
|
|
if (!symbols)
|
|
{
|
|
symbols = Ptr(new ListType);
|
|
}
|
|
if (symbols->Contains(_symbol)) return false;
|
|
symbols->Add(_symbol);
|
|
return true;
|
|
}
|
|
|
|
const ListType& Symbols() const
|
|
{
|
|
return symbols ? *symbols.Obj() : EmptySymbols;
|
|
}
|
|
|
|
ListPtr SymbolsPtr() const
|
|
{
|
|
return symbols;
|
|
}
|
|
|
|
std::strong_ordering operator<=>(const SymbolSet<TSymbol, Ordered>& set) const
|
|
{
|
|
if (!symbols && !set.symbols) return std::strong_ordering::equal;
|
|
if (!symbols) return std::strong_ordering::less;
|
|
if (!set.symbols) return std::strong_ordering::greater;
|
|
return CompareEnumerable(*symbols.Obj(), *set.symbols.Obj());
|
|
}
|
|
|
|
bool operator==(const SymbolSet<TSymbol, Ordered>& set) const
|
|
{
|
|
return (*this <=> set) == 0;
|
|
}
|
|
};
|
|
|
|
template<typename TSymbol, bool Ordered>
|
|
const SymbolSetListType_t<TSymbol, Ordered> SymbolSet<TSymbol, Ordered>::EmptySymbols;
|
|
|
|
struct LabeledState
|
|
{
|
|
WString label;
|
|
vint index;
|
|
StateSymbol* state = nullptr;
|
|
|
|
auto operator<=>(const LabeledState& ls) const = default;
|
|
bool operator==(const LabeledState&) const = default;
|
|
};
|
|
|
|
using StateSymbolSet = SymbolSet<LabeledState, true>;
|
|
using InsSymbolSet = SymbolSet<AstIns, false>;
|
|
using CompetitionSymbolSet = SymbolSet<EdgeCompetition, true>;
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::MergeEdgesWithSameInput
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::MergeEdgesWithSameInput(RuleSymbol* rule, StateSymbol* startState, StateList& newStates, EdgeList& newEdges)
|
|
{
|
|
/*
|
|
* Two edges can be merged if:
|
|
* They are both Token or Rule
|
|
* They have the same input, insAfterInput and competitions
|
|
* returnEdges of an edge is empty at this moment so it is ignored
|
|
*
|
|
* If a state has multiple outgoing edges that can be merged
|
|
* the target states will be merged into one
|
|
* all outgoing edges from target states will be recreated from the merged state
|
|
* mergable edges will be replaced by a new edge
|
|
*
|
|
* [BEFORE]
|
|
* +-(r)-> U -(b)-> X
|
|
* |
|
|
* A -+-(r)-> V -(b)-> Y
|
|
* |
|
|
* +-(r)-> W -(c)-> Z
|
|
*
|
|
* [AFTER]
|
|
*
|
|
* +-(b)-> XY
|
|
* |
|
|
* A -+-(r)-> UVW -+-(c)-> Z
|
|
*/
|
|
|
|
Dictionary<StateSymbolSet, Ptr<StateSymbol>> statesToMerged;
|
|
Dictionary<StateSymbol*, StateSymbolSet::ListPtr> mergedToStates;
|
|
|
|
List<StateSymbol*> workingStates;
|
|
IncrementalChange ic;
|
|
|
|
// Start from the start state
|
|
{
|
|
ic.opStates.Add(startState);
|
|
workingStates.Add(startState);
|
|
}
|
|
|
|
auto ReuseState = [&](StateSymbol* state)
|
|
{
|
|
if (!ic.opStates.Contains(state))
|
|
{
|
|
ic.opStates.Add(state);
|
|
workingStates.Add(state);
|
|
}
|
|
};
|
|
|
|
auto ReuseEdge = [&](EdgeSymbol* edge)
|
|
{
|
|
ReuseState(edge->To());
|
|
if (!ic.opEdges.Contains(edge))
|
|
{
|
|
ic.opEdges.Add(edge);
|
|
}
|
|
};
|
|
|
|
auto ApplyEdgeToMergedState = [&](EdgeSymbol* edge, StateSymbol* mergedState)
|
|
{
|
|
ReuseState(edge->To());
|
|
auto newEdge = Ptr(new EdgeSymbol(mergedState, edge->To()));
|
|
ic.createdEdges.Add(newEdge);
|
|
newEdge->input = edge->input;
|
|
CopyFrom(newEdge->competitions, edge->competitions);
|
|
CopyFrom(newEdge->insAfterInput, edge->insAfterInput);
|
|
};
|
|
|
|
for (vint i = 0; i < workingStates.Count(); i++)
|
|
{
|
|
auto currentState = workingStates[i];
|
|
vint currentMergedToStateIndex = mergedToStates.Keys().IndexOf(currentState);
|
|
|
|
Group<Tuple<EdgeInput, InsSymbolSet, CompetitionSymbolSet>, EdgeSymbol*> groupedEdges;
|
|
if (currentMergedToStateIndex == -1)
|
|
{
|
|
// if the current state is an original state
|
|
for (auto edge : currentState->OutEdges())
|
|
{
|
|
if (edge->input.type == EdgeInputType::Token || edge->input.type == EdgeInputType::Rule)
|
|
{
|
|
// only group Token or Rule edges
|
|
groupedEdges.Add(
|
|
{
|
|
edge->input,
|
|
InsSymbolSet{edge->insAfterInput},
|
|
CompetitionSymbolSet(edge->competitions)
|
|
}, edge);
|
|
}
|
|
else
|
|
{
|
|
// reuse others
|
|
ReuseEdge(edge);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if the current state is a merged state, search all of its original states
|
|
for (auto targetState : *mergedToStates.Values()[currentMergedToStateIndex].Obj())
|
|
{
|
|
for (auto edge : targetState.state->OutEdges())
|
|
{
|
|
if (edge->input.type == EdgeInputType::Token || edge->input.type == EdgeInputType::Rule)
|
|
{
|
|
// only group Token or Rule edges
|
|
groupedEdges.Add(
|
|
{
|
|
edge->input,
|
|
InsSymbolSet{edge->insAfterInput},
|
|
CompetitionSymbolSet(edge->competitions)
|
|
}, edge);
|
|
}
|
|
else
|
|
{
|
|
// duplicate others to start from the merged state
|
|
ApplyEdgeToMergedState(edge, currentState);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// see if multiple edges could be grouped together
|
|
for (vint groupedIndex = 0; groupedIndex < groupedEdges.Count(); groupedIndex++)
|
|
{
|
|
auto&& groupedKey = groupedEdges.Keys()[groupedIndex];
|
|
auto&& groupedValues = groupedEdges.GetByIndex(groupedIndex);
|
|
|
|
if (groupedValues.Count() == 1)
|
|
{
|
|
// if a group only has one edge, reuse the target state
|
|
if (currentMergedToStateIndex == -1)
|
|
{
|
|
ReuseEdge(groupedValues[0]);
|
|
}
|
|
else
|
|
{
|
|
ApplyEdgeToMergedState(groupedValues[0], currentState);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if a group has multiple edges, merge all target states into one
|
|
Ptr<StateSymbol> mergedState;
|
|
{
|
|
StateSymbolSet targetSet;
|
|
for (auto edge : groupedValues)
|
|
{
|
|
targetSet.Add({ edge->To()->label,newStates.IndexOf(edge->To()),edge->To() });
|
|
}
|
|
|
|
vint index = statesToMerged.Keys().IndexOf(targetSet);
|
|
if (index != -1)
|
|
{
|
|
// if the merged state already exists, reuse it
|
|
mergedState = statesToMerged.Values()[index];
|
|
}
|
|
else
|
|
{
|
|
// otherwise, create a new merged state
|
|
// its label is the combination of all originals
|
|
mergedState = Ptr(new StateSymbol(startState->Rule()));
|
|
ic.createdStates.Add(mergedState);
|
|
workingStates.Add(mergedState.Obj());
|
|
|
|
mergedState->label = stream::GenerateToStream([&](stream::TextWriter& writer)
|
|
{
|
|
writer.WriteString(L"{{");
|
|
for (auto [state, index] : indexed(targetSet.Symbols()))
|
|
{
|
|
if (index > 0) writer.WriteString(L" ; ");
|
|
writer.WriteString(state.label);
|
|
}
|
|
writer.WriteString(L"}}");
|
|
});
|
|
|
|
mergedToStates.Add(mergedState.Obj(), targetSet.SymbolsPtr());
|
|
statesToMerged.Add(std::move(targetSet), mergedState);
|
|
}
|
|
}
|
|
|
|
auto newEdge = Ptr(new EdgeSymbol(currentState, mergedState.Obj()));
|
|
ic.createdEdges.Add(newEdge);
|
|
|
|
newEdge->input = groupedKey.get<0>();
|
|
CopyFrom(newEdge->insAfterInput, groupedKey.get<1>().Symbols());
|
|
CopyFrom(newEdge->competitions, groupedKey.get<2>().Symbols());
|
|
}
|
|
}
|
|
}
|
|
|
|
ApplyIncrementalChange(ic, newStates, newEdges);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\SYNTAX\SYNTAXSYMBOL_NFACOMPACT_MERGEEDGESWITHSAMERULEUSINGLEFTREC.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::MergeEdgesWithSameRuleUsingLeftrec
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::MergeEdgesWithSameRuleUsingLeftrec(RuleSymbol* rule, StateSymbol* startState, StateList& newStates, EdgeList& newEdges)
|
|
{
|
|
/*
|
|
* Two edges can be merged if:
|
|
* They consume the same Rule, but they have different insAfterInput and competitions
|
|
* We only check rules because MergeEdgesWithSameInput already take care of those
|
|
*
|
|
* If a state has multiple outgoing edges that can be merged
|
|
* An edge with no insAfterInput and competitions will be inserted before these edges
|
|
* These edges will be converted to LeftRec
|
|
*
|
|
* [BEFORE]
|
|
* +-(r)-> U -(ending)-> X
|
|
* |
|
|
* A -+-(r)-> V -(b)-> Y
|
|
* |
|
|
* +-(r)-> W -+-(c)-> Z1
|
|
* |
|
|
* +-(ending)-> Z2
|
|
*
|
|
* [AFTER]
|
|
*
|
|
* +-(ending)-> X
|
|
* |
|
|
* A -(r)-> B -+-(leftrec)-> V -(b)-> Y
|
|
* |
|
|
* +-(leftrec)-> W -(c)-> Z1
|
|
* |
|
|
* +-(ending)-> Z2
|
|
*/
|
|
|
|
IncrementalChange ic;
|
|
CopyFrom(ic.opStates, From(newStates).Select([](auto p) {return p.Obj(); }));
|
|
CopyFrom(ic.opEdges, From(newEdges).Select([](auto p) {return p.Obj(); }));
|
|
|
|
SortedList<StateSymbol*> visitedStates;
|
|
List<StateSymbol*> workingStates;
|
|
workingStates.Add(startState);
|
|
|
|
// travel through all states
|
|
for (vint i = 0; i < workingStates.Count(); i++)
|
|
{
|
|
// group outgoing Rule edges by rules, ignore others
|
|
auto currentState = workingStates[i];
|
|
Group<RuleSymbol*, EdgeSymbol*> groupedEdges;
|
|
for (auto edge : currentState->OutEdges())
|
|
{
|
|
if (edge->input.type != EdgeInputType::Rule) continue;
|
|
groupedEdges.Add(edge->input.rule, edge);
|
|
}
|
|
|
|
for (vint j = 0; j < groupedEdges.Count(); j++)
|
|
{
|
|
// only process cases when multiple edges consume the same rule
|
|
// their insAfterInput or competitions are different
|
|
// otherwise they should have been merged in MergeEdgesWithSameInput
|
|
auto&& edges = groupedEdges.GetByIndex(j);
|
|
if (edges.Count() > 1)
|
|
{
|
|
// newState labeling [pm-lr] is made
|
|
auto newState = Ptr(new StateSymbol(rule));
|
|
ic.createdStates.Add(newState);
|
|
newState->label = currentState->label + L"[pm-lr]";
|
|
|
|
// currentState goes to newState by an Rule edge with empty insAfterInput and competitions
|
|
auto newEdge = Ptr(new EdgeSymbol(currentState, newState.Obj()));
|
|
ic.createdEdges.Add(newEdge);
|
|
newEdge->input = edges[0]->input;
|
|
|
|
// edit all original Rule edges
|
|
for (auto originalRuleEdge : edges)
|
|
{
|
|
// disconnect originalRuleEdge from currentState
|
|
originalRuleEdge->fromState->outEdges.Remove(originalRuleEdge);
|
|
originalRuleEdge->fromState = nullptr;
|
|
|
|
vint epsilonCount = 0;
|
|
vint inputCount = 0;
|
|
|
|
auto targetState = originalRuleEdge->toState;
|
|
for (auto targetEdge : targetState->outEdges)
|
|
{
|
|
if (targetEdge->input.type == EdgeInputType::Ending || targetEdge->input.type == EdgeInputType::LeftRec)
|
|
{
|
|
epsilonCount++;
|
|
}
|
|
else
|
|
{
|
|
inputCount++;
|
|
}
|
|
}
|
|
|
|
if (epsilonCount == 0)
|
|
{
|
|
// if all edges following originalRuleEdge are input edges
|
|
// reconnect it from newState and turn it into LeftRec
|
|
originalRuleEdge->fromState = newState.Obj();
|
|
originalRuleEdge->fromState->outEdges.Add(originalRuleEdge);
|
|
originalRuleEdge->input = { EdgeInputType::LeftRec };
|
|
}
|
|
else
|
|
{
|
|
// otherwise complex editing involves
|
|
Ptr<StateSymbol> newTargetState;
|
|
for (auto targetEdge : targetState->OutEdges())
|
|
{
|
|
if (targetEdge->input.type == EdgeInputType::Ending || targetEdge->input.type == EdgeInputType::LeftRec)
|
|
{
|
|
// for any epsilon edge following originalRuleEdge
|
|
// we don't want two epsilon edge as it would make the NFA non-compact
|
|
// a new edge will be made to merge originalRuleEdge and this following epsilon edge
|
|
auto newTargetEdge = Ptr(new EdgeSymbol(newState.Obj(), targetEdge->toState));
|
|
ic.createdEdges.Add(newTargetEdge);
|
|
|
|
newTargetEdge->input = targetEdge->input;
|
|
CopyFrom(newTargetEdge->competitions, originalRuleEdge->competitions, true);
|
|
CopyFrom(newTargetEdge->competitions, targetEdge->competitions, true);
|
|
CopyFrom(newTargetEdge->insAfterInput, originalRuleEdge->insAfterInput, true);
|
|
CopyFrom(newTargetEdge->insAfterInput, targetEdge->insAfterInput, true);
|
|
}
|
|
else
|
|
{
|
|
// for any input edge following originalRuleEdge
|
|
// as we can't change targetState which originalRuleEdge points to
|
|
// because there might be other edges connecting to targetState
|
|
// we will duplicate targetState to a [pm-dup]
|
|
// and make originalRuleEdge connect to it from newState as a LeftRec
|
|
if (!newTargetState)
|
|
{
|
|
newTargetState = Ptr(new StateSymbol(rule));
|
|
ic.createdStates.Add(newTargetState);
|
|
newTargetState->label = targetState->label + L"[pm-dup]";
|
|
|
|
originalRuleEdge->fromState = newState.Obj();
|
|
originalRuleEdge->fromState->outEdges.Add(originalRuleEdge);
|
|
originalRuleEdge->toState->inEdges.Remove(originalRuleEdge);
|
|
originalRuleEdge->toState = newTargetState.Obj();
|
|
originalRuleEdge->toState->inEdges.Add(originalRuleEdge);
|
|
originalRuleEdge->input = { EdgeInputType::LeftRec };
|
|
}
|
|
|
|
// and copy the input rule
|
|
auto newTargetEdge = Ptr(new EdgeSymbol(newTargetState.Obj(), targetEdge->toState));
|
|
ic.createdEdges.Add(newTargetEdge);
|
|
|
|
newTargetEdge->input = targetEdge->input;
|
|
CopyFrom(newTargetEdge->competitions, targetEdge->competitions, true);
|
|
CopyFrom(newTargetEdge->insAfterInput, targetEdge->insAfterInput, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (originalRuleEdge->fromState == nullptr)
|
|
{
|
|
// if originalRuleEdge is not reused, remove it
|
|
originalRuleEdge->toState->inEdges.Remove(originalRuleEdge);
|
|
ic.opEdges.Remove(originalRuleEdge);
|
|
}
|
|
|
|
if (targetState->inEdges.Count() == 0)
|
|
{
|
|
// after removing originalRuleEdge
|
|
// if no other state points to targetState
|
|
// remove it
|
|
// if a [pm-dup] is made, we won't reusing and just let that happen
|
|
ic.opStates.Remove(targetState);
|
|
for (auto targetEdge : targetState->OutEdges())
|
|
{
|
|
targetEdge->toState->inEdges.Remove(targetEdge);
|
|
ic.opEdges.Remove(targetEdge);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto edge : currentState->OutEdges())
|
|
{
|
|
if (!visitedStates.Contains(edge->To()))
|
|
{
|
|
visitedStates.Add(edge->To());
|
|
workingStates.Add(edge->To());
|
|
}
|
|
}
|
|
}
|
|
|
|
ApplyIncrementalChange(ic, newStates, newEdges);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\SYNTAX\SYNTAXSYMBOL_NFACOMPACT_PREFIXMERGECROSSREFERENCE.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace parsergen
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
BitSet
|
|
***********************************************************************/
|
|
|
|
struct BitSet
|
|
{
|
|
public:
|
|
static const BitSet Zero;
|
|
|
|
private:
|
|
vint wordCount = 0;
|
|
vuint64_t* words = nullptr;
|
|
|
|
static bool AllZero(vuint64_t* words, vint wordCount)
|
|
{
|
|
for (vint i = 0; i < wordCount; i++)
|
|
{
|
|
if (words[i] != 0) return false;
|
|
}
|
|
return true;
|
|
}
|
|
public:
|
|
BitSet& operator=(const BitSet& bs) noexcept
|
|
{
|
|
if (this != &bs)
|
|
{
|
|
wordCount = bs.wordCount;
|
|
if (words)
|
|
{
|
|
delete[] words;
|
|
words = nullptr;
|
|
}
|
|
if (bs.words)
|
|
{
|
|
words = new vuint64_t[wordCount];
|
|
memcpy(words, bs.words, sizeof(vuint64_t) * wordCount);
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
BitSet& operator=(BitSet&& bs) noexcept
|
|
{
|
|
if (this != &bs)
|
|
{
|
|
wordCount = bs.wordCount;
|
|
if (words)
|
|
{
|
|
delete[] words;
|
|
}
|
|
words = bs.words;
|
|
bs.wordCount = 0;
|
|
bs.words = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
BitSet() = default;
|
|
BitSet(const BitSet& bs) noexcept { *this = bs; }
|
|
BitSet(BitSet&& bs) noexcept { *this = std::move(bs); }
|
|
~BitSet() { if (words) delete[] words; }
|
|
|
|
auto operator<=>(const BitSet& bs) const
|
|
{
|
|
if (this == &bs) return std::strong_ordering::equal;
|
|
vint minWordCount = wordCount < bs.wordCount ? wordCount : bs.wordCount;
|
|
if (minWordCount > 0)
|
|
{
|
|
auto result = memcmp(words, bs.words, sizeof(vuint64_t) * minWordCount) <=> 0;
|
|
if (result != 0) return result;
|
|
}
|
|
|
|
auto result = wordCount <=> bs.wordCount;
|
|
if (result < 0)
|
|
{
|
|
return AllZero(bs.words + minWordCount, bs.wordCount - minWordCount) ? std::strong_ordering::equal : std::strong_ordering::less;
|
|
}
|
|
else if (result > 0)
|
|
{
|
|
return AllZero(words + minWordCount, wordCount - minWordCount) ? std::strong_ordering::equal : std::strong_ordering::greater;
|
|
}
|
|
else
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
bool operator==(const BitSet& bs) const
|
|
{
|
|
return (*this <=> bs) == 0;
|
|
}
|
|
|
|
bool operator[](vint index) const
|
|
{
|
|
vint wordIndex = index / 64;
|
|
vint bitIndex = index % 64;
|
|
if (wordIndex >= wordCount)
|
|
{
|
|
return false;
|
|
}
|
|
return (words[wordIndex] & (vuint64_t(1) << bitIndex)) != 0;
|
|
}
|
|
|
|
void Set(vint index)
|
|
{
|
|
vint wordIndex = index / 64;
|
|
vint bitIndex = index % 64;
|
|
if (wordIndex >= wordCount)
|
|
{
|
|
vint oldWordCount = wordCount;
|
|
wordCount = wordIndex + 1;
|
|
vuint64_t* newWords = new vuint64_t[wordCount];
|
|
memset(newWords, 0, sizeof(vuint64_t) * wordCount);
|
|
if (words)
|
|
{
|
|
memcpy(newWords, words, sizeof(vuint64_t) * oldWordCount);
|
|
delete[] words;
|
|
}
|
|
words = newWords;
|
|
}
|
|
words[wordIndex] |= (vuint64_t(1) << bitIndex);
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return !AllZero(words, wordCount);
|
|
}
|
|
|
|
BitSet operator|(const BitSet& bs) const
|
|
{
|
|
if (this == &bs) return *this;
|
|
BitSet result;
|
|
vint maxWordCount = wordCount > bs.wordCount ? wordCount : bs.wordCount;
|
|
if (maxWordCount > 0)
|
|
{
|
|
result.wordCount = maxWordCount;
|
|
result.words = new vuint64_t[maxWordCount];
|
|
for (vint i = 0; i < maxWordCount; i++)
|
|
{
|
|
vuint64_t w1 = i < wordCount ? words[i] : 0;
|
|
vuint64_t w2 = i < bs.wordCount ? bs.words[i] : 0;
|
|
result.words[i] = w1 | w2;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BitSet& operator|=(const BitSet& bs)
|
|
{
|
|
if (this == &bs) return *this;
|
|
*this = *this | bs;
|
|
return *this;
|
|
}
|
|
|
|
BitSet operator&(const BitSet& bs) const
|
|
{
|
|
if (this == &bs) return *this;
|
|
BitSet result;
|
|
vint minWordCount = wordCount < bs.wordCount ? wordCount : bs.wordCount;
|
|
if (minWordCount > 0)
|
|
{
|
|
result.wordCount = minWordCount;
|
|
result.words = new vuint64_t[minWordCount];
|
|
for (vint i = 0; i < minWordCount; i++)
|
|
{
|
|
result.words[i] = words[i] & bs.words[i];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BitSet& operator&=(const BitSet& bs)
|
|
{
|
|
if (this == &bs) return *this;
|
|
*this = *this & bs;
|
|
return *this;
|
|
}
|
|
|
|
BitSet& operator-=(const BitSet& bs)
|
|
{
|
|
if (this == &bs)
|
|
{
|
|
*this = Zero;
|
|
}
|
|
else
|
|
{
|
|
vint minWordCount = wordCount < bs.wordCount ? wordCount : bs.wordCount;
|
|
for (vint i = 0; i < minWordCount; i++)
|
|
{
|
|
words[i] &= ~bs.words[i];
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
const BitSet BitSet::Zero;
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::CreatePrefixMerge
|
|
***********************************************************************/
|
|
|
|
struct PrefixMergeCache
|
|
{
|
|
// prepared by CreatePrefixMergeCache
|
|
Array<RuleSymbol*> rules;
|
|
Array<RuleSymbol*> rulesByDeps; // if a begins with b, a is before b
|
|
Array<BitSet> directStartSetTokens, startSetTokens;
|
|
Array<BitSet> directStartSetRules, startSetRules, reverseStartSetRules;
|
|
};
|
|
|
|
Ptr<PrefixMergeCache> SyntaxSymbolManager::CreatePrefixMergeCache()
|
|
{
|
|
auto cache = Ptr(new PrefixMergeCache);
|
|
CopyFrom(cache->rules, rules.map.Values());
|
|
const vint ruleCount = cache->rules.Count();
|
|
|
|
cache->rulesByDeps.Resize(ruleCount);
|
|
cache->directStartSetTokens.Resize(ruleCount);
|
|
cache->startSetTokens.Resize(ruleCount);
|
|
cache->directStartSetRules.Resize(ruleCount);
|
|
cache->startSetRules.Resize(ruleCount);
|
|
cache->reverseStartSetRules.Resize(ruleCount);
|
|
for (auto [ruleSymbol, index] : indexed(cache->rules))
|
|
{
|
|
ruleSymbol->pmRuleIndex = index;
|
|
}
|
|
|
|
PartialOrderingProcessor pop;
|
|
{
|
|
Group<RuleSymbol*, RuleSymbol*> deps;
|
|
for (auto ruleSymbol : cache->rules)
|
|
{
|
|
auto startState = ruleSymbol->startStates[0];
|
|
BitSet directTokens, directRules;
|
|
for (auto edge : startState->OutEdges())
|
|
{
|
|
switch (edge->input.type)
|
|
{
|
|
case EdgeInputType::Token:
|
|
directTokens.Set(edge->input.token);
|
|
break;
|
|
case EdgeInputType::Rule:
|
|
directRules.Set(edge->input.rule->pmRuleIndex);
|
|
deps.Add(ruleSymbol, edge->input.rule);
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
cache->directStartSetTokens[ruleSymbol->pmRuleIndex] = directTokens;
|
|
cache->directStartSetRules[ruleSymbol->pmRuleIndex] = directRules;
|
|
}
|
|
pop.InitWithGroup(cache->rules, deps);
|
|
pop.Sort();
|
|
}
|
|
|
|
for (auto component : pop.components)
|
|
{
|
|
if (component.nodeCount > 1)
|
|
{
|
|
AddError(
|
|
ParserErrorType::RuleIsIndirectlyLeftRecursive,
|
|
{},
|
|
From(Range<vint>(0, component.nodeCount))
|
|
.Select([&](vint index) { return cache->rules[component.firstNode[index]]->Name(); })
|
|
.OrderBySelf()
|
|
.Aggregate([](auto&& a, auto&& b) { return a + L", " + b; })
|
|
);
|
|
}
|
|
}
|
|
if (global.Errors().Count() > 0) return nullptr;
|
|
|
|
for (auto [component, index] : indexed(pop.components))
|
|
{
|
|
auto ruleSymbol = cache->rules[*component.firstNode];
|
|
auto startSetTokens = cache->directStartSetTokens[ruleSymbol->pmRuleIndex];
|
|
auto startSetRules = cache->directStartSetRules[ruleSymbol->pmRuleIndex];
|
|
cache->rulesByDeps[ruleCount - 1 - index] = ruleSymbol;
|
|
|
|
auto startState = ruleSymbol->startStates[0];
|
|
for (auto edge : startState->OutEdges())
|
|
{
|
|
if (edge->input.type != EdgeInputType::Rule) continue;
|
|
startSetTokens |= cache->startSetTokens[edge->input.rule->pmRuleIndex];
|
|
startSetRules |= cache->startSetRules[edge->input.rule->pmRuleIndex];
|
|
}
|
|
cache->startSetTokens[ruleSymbol->pmRuleIndex] = startSetTokens;
|
|
cache->startSetRules[ruleSymbol->pmRuleIndex] = startSetRules;
|
|
}
|
|
|
|
for (vint i = 0; i < ruleCount; i++)
|
|
{
|
|
for (vint j = 0; j < ruleCount; j++)
|
|
{
|
|
if (cache->startSetRules[i][j])
|
|
{
|
|
cache->reverseStartSetRules[j].Set(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
return cache;
|
|
}
|
|
|
|
//#if defined VCZH_MSVC && defined _DEBUG
|
|
//#define LOG_DECISION_MAKING
|
|
//#define LOG console::Console::Write
|
|
//#define LOGL console::Console::WriteLine
|
|
//#endif
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::PrefixMergeCrossReference_SolveInState
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::PrefixMergeCrossReference_SolveInState(
|
|
PrefixMergeCache * cache,
|
|
RuleSymbol * rule,
|
|
StateSymbol * currentState,
|
|
Ptr<PrefixMergeSolutionApplication> application)
|
|
{
|
|
/*
|
|
* To find out the minimum start set of rules to inject
|
|
*
|
|
* Stores startSetRules[edge->input.rule] to startSetEdges
|
|
* Try each rule in cache->rulesByDeps
|
|
* If startSetRules[rule] satisfies both conditions on each edge to merge
|
|
* startSetEdges[edge] & startSetRules[rule] == startSetRules[rule]
|
|
* startSetEdges[edge] & startSetRules[rule] == BitSet::Zero
|
|
* Then this rule is one in the minimum start set, update startSetEdges by:
|
|
* extract startSetRules[rule]
|
|
* extract any parent rule where startSetRules[parent rule] has rule
|
|
* Repeat until the test results in all BitSet::Zero (or when all startSetEdges are BitSet::Zero)
|
|
*
|
|
* We can see indirectStartSetRules as the relationship in a partial ordered graph starting from a rule
|
|
* When a rule is picked up as a prefix rule
|
|
* it removes the rule and all its descendants from the graph
|
|
* and we will have to break all node that depends on this prefix rule into multiple prefix rules
|
|
* so those parents will never be prefix rules
|
|
* after parent nodes are removed, the graph breaks into multiple sub graphs, maybe disconnected
|
|
* The goal is to pick up all smaller graphs that:
|
|
* they are big enough
|
|
* their leaf nodes do no intersect with each other
|
|
* leaf nodes of the current graph is covered by them
|
|
*/
|
|
|
|
#define ERROR_MESSAGE_PREFIX L"vl::glr::parsergen::SyntaxSymbolManager::PrefixMergeCrossReference_SolveInState(PrefixMergeCache*, RuleSymbol*, StateSymbol*, Array<EdgeSymbol*>&, List<RuleSymbol*>&, PrefixMergeSolutionMap&)#"
|
|
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOG(L" [GROUPED] :");
|
|
for (auto [edge, index] : indexed(application->edgesToMerge))
|
|
{
|
|
LOG(L" " + edge->input.rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
#endif
|
|
// prepare startSetEdges to be startSetRules of each edge's input rule
|
|
Array<BitSet> startSetEdges(application->edgesToMerge.Count());
|
|
for (auto [edge, index] : indexed(application->edgesToMerge))
|
|
{
|
|
startSetEdges[index] = cache->startSetRules[edge->input.rule->pmRuleIndex];
|
|
startSetEdges[index].Set(edge->input.rule->pmRuleIndex);
|
|
}
|
|
|
|
// at this moment, application->prefixRules are part of the solution that has already been picked u
|
|
if (application->prefixRules.Count() > 0)
|
|
{
|
|
for (auto prefixRule : application->prefixRules)
|
|
{
|
|
// take away all rules that depends or reversed depends on the prefix rule
|
|
auto startSetRule = cache->startSetRules[prefixRule->pmRuleIndex];
|
|
startSetRule.Set(prefixRule->pmRuleIndex);
|
|
auto reverseStartSetRule = cache->reverseStartSetRules[prefixRule->pmRuleIndex];
|
|
auto startSetToExtract = startSetRule | reverseStartSetRule;
|
|
|
|
for (vint edgeIndex = 0; edgeIndex < application->edgesToMerge.Count(); edgeIndex++)
|
|
{
|
|
startSetEdges[edgeIndex] -= startSetToExtract;
|
|
}
|
|
}
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L" [APPLIED REUSED]");
|
|
for (auto [edge, index] : indexed(application->edgesToMerge))
|
|
{
|
|
LOG(L" " + edge->input.rule->Name() + L" :");
|
|
auto&& startSetEdge = startSetEdges[index];
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
if (startSetEdge[rule->pmRuleIndex]) LOG(L" " + rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
}
|
|
#endif
|
|
// if startSetEdges become all empty, no more prefix rule will be found
|
|
bool allZero = true;
|
|
for (vint edgeIndex = 0; edgeIndex < application->edgesToMerge.Count(); edgeIndex++)
|
|
{
|
|
if (startSetEdges[edgeIndex] != BitSet::Zero)
|
|
{
|
|
allZero = false;
|
|
break;
|
|
}
|
|
}
|
|
if (allZero) return;
|
|
}
|
|
|
|
{
|
|
FOUND_ONE_SOLUTION:
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L" [ITERATION]");
|
|
for (auto [edge, index] : indexed(application->edgesToMerge))
|
|
{
|
|
LOG(L" " + edge->input.rule->Name() + L" :");
|
|
auto&& startSetEdge = startSetEdges[index];
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
if (startSetEdge[rule->pmRuleIndex]) LOG(L" " + rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
}
|
|
#endif
|
|
|
|
bool matchedOthers = false;
|
|
|
|
// try each rule in dependency order
|
|
for (auto prefixRule : cache->rulesByDeps)
|
|
{
|
|
vint containedCount = 0;
|
|
vint exclusiveCount = 0;
|
|
vint otherCount = 0;
|
|
auto startSetRule = cache->startSetRules[prefixRule->pmRuleIndex];
|
|
startSetRule.Set(prefixRule->pmRuleIndex);
|
|
|
|
// compare the start set of this rule to remaining start set subset of each edge
|
|
// count each situation
|
|
for (vint edgeIndex = 0; edgeIndex < application->edgesToMerge.Count(); edgeIndex++)
|
|
{
|
|
auto& startSetEdge = startSetEdges[edgeIndex];
|
|
auto matchResult = startSetEdge & startSetRule;
|
|
if (matchResult == startSetRule)
|
|
{
|
|
// startSetEdge contains startSetRule
|
|
containedCount++;
|
|
}
|
|
else if (matchResult == BitSet::Zero)
|
|
{
|
|
// startSetEdge does no intercept with startSetRule
|
|
exclusiveCount++;
|
|
}
|
|
else
|
|
{
|
|
// others
|
|
otherCount++;
|
|
break;
|
|
}
|
|
}
|
|
if (otherCount > 0) matchedOthers = true;
|
|
|
|
// if some startSetEdge contains start set of the candidate rule
|
|
// and others are empty intersection
|
|
// we found a prefix rule
|
|
if (containedCount > 0 && otherCount == 0)
|
|
{
|
|
// take away all rules that depends or reversed depends on the prefix rule
|
|
auto reverseStartSetRule = cache->reverseStartSetRules[prefixRule->pmRuleIndex];
|
|
auto startSetToExtract = startSetRule | reverseStartSetRule;
|
|
|
|
for (vint edgeIndex = 0; edgeIndex < application->edgesToMerge.Count(); edgeIndex++)
|
|
{
|
|
startSetEdges[edgeIndex] -= startSetToExtract;
|
|
}
|
|
|
|
application->prefixRules.Add(prefixRule);
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOG(L" [FOUND " + prefixRule->Name() + L"] :");
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
if (startSetRule[rule->pmRuleIndex]) LOG(L" " + rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
#endif
|
|
goto FOUND_ONE_SOLUTION;
|
|
}
|
|
}
|
|
|
|
CHECK_ERROR(!matchedOthers, ERROR_MESSAGE_PREFIX L"Internal error: Unable to find a proper prefix merge solution.");
|
|
}
|
|
|
|
#undef ERROR_MESSAGE_PREFIX
|
|
}
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::PrefixMergeCrossReference_Solve
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::PrefixMergeCrossReference_Solve(
|
|
PrefixMergeCache* cache,
|
|
bool forStartState,
|
|
RuleSymbol* rule,
|
|
StateSymbol* startState,
|
|
PrefixMergeSolutionMap& prefixMergeSolutions)
|
|
{
|
|
auto logCache = [&]()
|
|
{
|
|
#ifdef LOG_DECISION_MAKING
|
|
if (prefixMergeSolutions.Count() == 0)
|
|
{
|
|
LOGL(L"[CACHE]");
|
|
LOGL(L" [RULES]");
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
LOG(L" " + rule->Name() + L" :");
|
|
auto&& startSetRule = cache->directStartSetRules[rule->pmRuleIndex];
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
if (startSetRule[rule->pmRuleIndex]) LOG(L" " + rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
}
|
|
LOGL(L" [START SET]");
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
LOG(L" " + rule->Name() + L" :");
|
|
auto&& startSetRule = cache->startSetRules[rule->pmRuleIndex];
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
if (startSetRule[rule->pmRuleIndex]) LOG(L" " + rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
}
|
|
LOGL(L" [REVERSED]");
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
LOG(L" " + rule->Name() + L" :");
|
|
auto&& startSetRule = cache->reverseStartSetRules[rule->pmRuleIndex];
|
|
for (auto rule : cache->rulesByDeps)
|
|
{
|
|
if (startSetRule[rule->pmRuleIndex]) LOG(L" " + rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
}
|
|
LOGL(L"");
|
|
}
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* If forStartState is true, only process the start state, otherwise process all reachable states except the start state
|
|
* forStartState == true will be applied all rules in start set dependency order first
|
|
* therefore whenever we see a rule input edge, its (rule, startState) should already have a solution
|
|
*
|
|
* When making a solution, if any Rule input edge already have a solution, reuse it
|
|
* Find edges whose start set have intersection, process each group
|
|
* Merge all solutions into one
|
|
*
|
|
* There are multiple applications in a solution
|
|
* Each application records what prefix rules will be injected into what edges
|
|
* For group that has only one edge, there will be no application
|
|
*
|
|
* For any start state, a solution will be created when there are groups with multiple edges, or any edge whose input rule has a solution on its start state
|
|
* For any other state, a solution will be created only when there are groups with multiple edges
|
|
*/
|
|
|
|
#define ERROR_MESSAGE_PREFIX L"vl::glr::parsergen::SyntaxSymbolManager::PrefixMergeCrossReference_Solve(PrefixMergeCache*, RuleSymbol*, StateSymbol*, PrefixMergeSolutionMap&)#"
|
|
SortedList<StateSymbol*> visitedStates;
|
|
List<StateSymbol*> workingStates;
|
|
workingStates.Add(startState);
|
|
|
|
// Traverse all states
|
|
for (vint i = 0; i < workingStates.Count(); i++)
|
|
{
|
|
auto currentState = workingStates[i];
|
|
|
|
if (forStartState == (currentState == startState))
|
|
{
|
|
Group<EdgeSymbol*, EdgeSymbol*> biDeps;
|
|
|
|
// Group all edges that have intersection in start set
|
|
for (vint j = 0; j < currentState->OutEdges().Count() - 1; j++)
|
|
{
|
|
auto edge1 = currentState->OutEdges()[j];
|
|
if (edge1->input.type != EdgeInputType::Rule) continue;
|
|
auto tokens1 = cache->startSetTokens[edge1->input.rule->pmRuleIndex];
|
|
auto rules1 = cache->startSetRules[edge1->input.rule->pmRuleIndex];
|
|
rules1.Set(edge1->input.rule->pmRuleIndex);
|
|
|
|
for (vint k = j + 1; k < currentState->OutEdges().Count(); k++)
|
|
{
|
|
auto edge2 = currentState->OutEdges()[k];
|
|
if (edge2->input.type != EdgeInputType::Rule) continue;
|
|
auto tokens2 = cache->startSetTokens[edge2->input.rule->pmRuleIndex];
|
|
auto rules2 = cache->startSetRules[edge2->input.rule->pmRuleIndex];
|
|
rules2.Set(edge2->input.rule->pmRuleIndex);
|
|
|
|
CHECK_ERROR(edge1->input.rule != edge2->input.rule, ERROR_MESSAGE_PREFIX L"Internal error: Two edges from the same state should not consume the same rule, this should have been eliminated by MergeEdgesWithSameRuleUsingLeftrec.");
|
|
if (!(tokens1 & tokens2)) continue;
|
|
if (!(rules1 & rules2)) continue;
|
|
|
|
biDeps.Add(edge1, edge2);
|
|
biDeps.Add(edge2, edge1);
|
|
}
|
|
}
|
|
|
|
PartialOrderingProcessor pop;
|
|
pop.InitWithGroup(currentState->OutEdges(), biDeps);
|
|
pop.Sort();
|
|
|
|
// Find if a solution needs to be created for the current state
|
|
bool hasSolution = false;
|
|
for (auto component : pop.components)
|
|
{
|
|
if (component.nodeCount > 1)
|
|
{
|
|
// if there is a group with multiple edges, yes
|
|
hasSolution = true;
|
|
break;
|
|
}
|
|
else if (currentState == startState)
|
|
{
|
|
// if the input rule has a solution on its start state, and the current state is the start state, yes
|
|
auto edge = currentState->OutEdges()[*component.firstNode];
|
|
if (edge->input.type == EdgeInputType::Rule)
|
|
{
|
|
auto prefixRule = edge->input.rule;
|
|
if (prefixMergeSolutions.Keys().Contains({ prefixRule, prefixRule->startStates[0] }))
|
|
{
|
|
hasSolution = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// skip the current state if no solution is needed
|
|
// edges are grouped by start set intersections
|
|
// so whenever a rule input has a solution on its start state or not
|
|
// the rule or its solution will never conflict with other groups
|
|
// since the solution will be a subset of union of all start sets for the group
|
|
if (hasSolution)
|
|
{
|
|
logCache();
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L"[PMCR] " + rule->Name() + L" @ " + currentState->label);
|
|
#endif
|
|
// Check all groups with single edge
|
|
auto solution = Ptr(new PrefixMergeSolutionValue);
|
|
for (auto component : pop.components)
|
|
{
|
|
if (component.nodeCount == 1)
|
|
{
|
|
auto edge = currentState->OutEdges()[*component.firstNode];
|
|
if (edge->input.type == EdgeInputType::Rule)
|
|
{
|
|
auto prefixRule = edge->input.rule;
|
|
vint solutionIndex = prefixMergeSolutions.Keys().IndexOf({ prefixRule, prefixRule->startStates[0] });
|
|
if (solutionIndex == -1)
|
|
{
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L" [SINGLE] " + prefixRule->Name());
|
|
#endif
|
|
// if the input rule has no solution on its start state
|
|
// but the current state needs a solution
|
|
// then the input rule is a prefix
|
|
solution->prefixRules.Add(prefixRule);
|
|
}
|
|
else
|
|
{
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L" [SINGLE USED] " + prefixRule->Name());
|
|
#endif
|
|
// otherwise, copy all prefix rules
|
|
CopyFrom(solution->prefixRules, prefixMergeSolutions.Values()[solutionIndex]->prefixRules, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check all groups with multiple edges, applications will be created on these groups
|
|
for (auto component : pop.components)
|
|
{
|
|
if (component.nodeCount > 1)
|
|
{
|
|
// collect all existing solutions for each edge
|
|
auto application = Ptr(new PrefixMergeSolutionApplication);
|
|
application->edgesToMerge.Resize(component.nodeCount);
|
|
for (vint j = 0; j < component.nodeCount; j++)
|
|
{
|
|
application->edgesToMerge[j] = currentState->OutEdges()[component.firstNode[j]];
|
|
}
|
|
for (auto edge : application->edgesToMerge)
|
|
{
|
|
auto prefixRule = edge->input.rule;
|
|
vint solutionIndex = prefixMergeSolutions.Keys().IndexOf({ prefixRule, prefixRule->startStates[0] });
|
|
if (solutionIndex != -1)
|
|
{
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L" [SINGLE USED] " + prefixRule->Name());
|
|
#endif
|
|
// copy all prefix rules, ensure no duplication
|
|
for (auto prefixRule : prefixMergeSolutions.Values()[solutionIndex]->prefixRules)
|
|
{
|
|
if (!application->prefixRules.Contains(prefixRule))
|
|
{
|
|
application->prefixRules.Add(prefixRule);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// solve for the current group
|
|
PrefixMergeCrossReference_SolveInState(cache, rule, currentState, application);
|
|
|
|
// copy all prefix rules, ensure no duplication
|
|
solution->applications.Add(application);
|
|
for (auto prefixRule : application->prefixRules)
|
|
{
|
|
if (!solution->prefixRules.Contains(prefixRule))
|
|
{
|
|
solution->prefixRules.Add(prefixRule);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
prefixMergeSolutions.Add({ rule, currentState }, solution);
|
|
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOG(L" [MATCHED] :");
|
|
for (auto rule : solution->prefixRules)
|
|
{
|
|
LOG(L" " + rule->Name());
|
|
}
|
|
LOGL(L"");
|
|
LOGL(L"");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// continue if required
|
|
if (!forStartState)
|
|
{
|
|
for (auto edge : currentState->OutEdges())
|
|
{
|
|
if (!visitedStates.Contains(edge->To()))
|
|
{
|
|
visitedStates.Add(edge->To());
|
|
workingStates.Add(edge->To());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#undef ERROR_MESSAGE_PREFIX
|
|
}
|
|
|
|
void SyntaxSymbolManager::PrefixMergeCrossReference_Solve(PrefixMergeCache* cache, PrefixMergeSolutionMap& prefixMergeSolutions)
|
|
{
|
|
for (auto rule : From(cache->rulesByDeps).Reverse())
|
|
{
|
|
PrefixMergeCrossReference_Solve(cache, true, rule, rule->startStates[0], prefixMergeSolutions);
|
|
}
|
|
for (auto rule : From(cache->rulesByDeps).Reverse())
|
|
{
|
|
PrefixMergeCrossReference_Solve(cache, false, rule, rule->startStates[0], prefixMergeSolutions);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::PrefixMergeCrossReference_AccumulatedEdges
|
|
***********************************************************************/
|
|
|
|
struct PrefixMergeApplicationItems
|
|
{
|
|
using EdgeList = List<EdgeSymbol*>;
|
|
using EdgeListPtr = Ptr<EdgeList>;
|
|
using RuleToEdgesMap = Group<RuleSymbol*, EdgeListPtr>;
|
|
using TokenToEdgesMap = Group<Pair<vint32_t, Nullable<WString>>, EdgeListPtr>;
|
|
|
|
BitSet coveredRules;
|
|
RuleToEdgesMap ruleToEdges;
|
|
TokenToEdgesMap tokenToEdges;
|
|
};
|
|
|
|
EdgeSymbol* SyntaxSymbolManager::PrefixMergeCrossReference_AccumulatedEdges(StateSymbol* fromState, const WString& pmLabel, const collections::List<PrefixMergeApplicationItems::EdgeListPtr>& accumulatedEdgesList, IncrementalChange& ic)
|
|
{
|
|
auto IsSingleReuseEdge = [](EdgeSymbol* edge)
|
|
{
|
|
if (edge->input.type != EdgeInputType::Rule) return false;
|
|
if (edge->input.ruleType != automaton::ReturnRuleType::Reuse) return false;
|
|
if (edge->competitions.Count() != 0) return false;
|
|
|
|
vint edgeIns = edge->insAfterInput.Count();
|
|
if (edgeIns >= 2) return false;
|
|
if (edgeIns == 1 && edge->insAfterInput[0].type != AstInsType::StackBegin) return false;
|
|
|
|
auto targetState = edge->To();
|
|
List<EdgeSymbol*> endingEdges;
|
|
CopyFrom(endingEdges, From(targetState->OutEdges()).Where([](EdgeSymbol* e)
|
|
{
|
|
return e->input.type == EdgeInputType::Ending;
|
|
}));
|
|
if (endingEdges.Count() != 1) return false;
|
|
|
|
auto endingEdge = endingEdges[0];
|
|
if (endingEdge->input.type != EdgeInputType::Ending) return false;
|
|
|
|
if (edgeIns == 0)
|
|
{
|
|
if (endingEdge->insAfterInput.Count() != 2) return false;
|
|
if (endingEdge->insAfterInput[0].type != AstInsType::StackBegin) return false;
|
|
if (endingEdge->insAfterInput[1].type != AstInsType::StackEnd) return false;
|
|
}
|
|
else
|
|
{
|
|
if (endingEdge->insAfterInput.Count() != 1) return false;
|
|
if (endingEdge->insAfterInput[0].type != AstInsType::StackEnd) return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Array<vint> accumulatedSizes(accumulatedEdgesList.Count());
|
|
for (auto [edges, index] : indexed(accumulatedEdgesList))
|
|
{
|
|
auto&& edgeList = *edges.Obj();
|
|
accumulatedSizes[index] = 0;
|
|
for (vint i = edgeList.Count(); i > 0; i--)
|
|
{
|
|
auto edge = edgeList[i - 1];
|
|
if (!IsSingleReuseEdge(edge))
|
|
{
|
|
accumulatedSizes[index] = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// newState labeling [pm-cr] is made if there are multiple choices
|
|
auto newState = Ptr(new StateSymbol(fromState->Rule()));
|
|
ic.createdStates.Add(newState);
|
|
newState->label = fromState->label + pmLabel;
|
|
|
|
// newEdge to connect fromState to newState
|
|
auto newEdge = Ptr(new EdgeSymbol(fromState, newState.Obj()));
|
|
ic.createdEdges.Add(newEdge);
|
|
|
|
SortedList<WString> contStateLabels;
|
|
Group<Pair<StateSymbol*, StateSymbol*>, EdgeSymbol*> createdContEdges;
|
|
for (auto [edges, index] : indexed(accumulatedEdgesList))
|
|
{
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOG(L" ");
|
|
for (auto [edge, edgeIndex] : indexed(*edges.Obj()))
|
|
{
|
|
if (edgeIndex > 0) LOG(L" -> ");
|
|
if (edgeIndex == accumulatedSizes[index])
|
|
{
|
|
LOG(L"| ");
|
|
}
|
|
if (edge->input.type == EdgeInputType::Rule)
|
|
{
|
|
LOG(edge->input.rule->Name());
|
|
}
|
|
else
|
|
{
|
|
LOG(L"[TOKEN] " + (edge->input.condition ? edge->input.condition.Value() : itow(edge->input.token)));
|
|
}
|
|
}
|
|
LOGL(L"");
|
|
#endif
|
|
auto&& edgeList = *edges.Obj();
|
|
vint accSize = accumulatedSizes[index];
|
|
for (vint i = edgeList.Count(); i >= accSize && i > 0; i--)
|
|
{
|
|
auto lastEdge = edgeList[i - 1];
|
|
|
|
Ptr<StateSymbol> contState;
|
|
auto lastState = lastEdge->To();
|
|
for (auto contEdge : lastState->OutEdges())
|
|
{
|
|
if (contEdge->input.type == EdgeInputType::PrefixMergeDiscardedRule)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (contEdge->input.type == EdgeInputType::LeftRec)
|
|
{
|
|
if (contEdge->returnEdges.Count() == 0);
|
|
else continue;
|
|
}
|
|
|
|
if (contEdge->input.type == EdgeInputType::Ending)
|
|
{
|
|
if (accSize == 0 && i == 1);
|
|
else if (i == accSize);
|
|
else continue;
|
|
}
|
|
|
|
auto AddNewContEdge = [&](StateSymbol* contFromState, bool useLastEdgeContent, bool useReturnEdges)
|
|
{
|
|
auto newContEdge = Ptr(new EdgeSymbol(contFromState, contEdge->To()));
|
|
|
|
newContEdge->input = contEdge->input;
|
|
if (useLastEdgeContent)
|
|
{
|
|
CopyFrom(newContEdge->competitions, lastEdge->competitions, true);
|
|
CopyFrom(newContEdge->insAfterInput, lastEdge->insAfterInput, true);
|
|
}
|
|
CopyFrom(newContEdge->competitions, contEdge->competitions, true);
|
|
CopyFrom(newContEdge->insAfterInput, contEdge->insAfterInput, true);
|
|
|
|
if (useReturnEdges)
|
|
{
|
|
for (vint j = 0; j < i - 1; j++)
|
|
{
|
|
newContEdge->returnEdges.Add(edgeList[j]);
|
|
}
|
|
}
|
|
|
|
auto key = Pair(newContEdge->From(), newContEdge->To());
|
|
vint index = createdContEdges.Keys().IndexOf(key);
|
|
if (index != -1)
|
|
{
|
|
for (auto created : createdContEdges.GetByIndex(index))
|
|
{
|
|
if (created->input != newContEdge->input) continue;
|
|
if (CompareEnumerable(created->competitions, newContEdge->competitions) != 0) continue;
|
|
if (CompareEnumerable(created->insAfterInput, newContEdge->insAfterInput) != 0) continue;
|
|
if (CompareEnumerable(created->returnEdges, newContEdge->returnEdges) != 0) continue;
|
|
|
|
newContEdge->From()->outEdges.Remove(newContEdge.Obj());
|
|
newContEdge->To()->inEdges.Remove(newContEdge.Obj());
|
|
return;
|
|
}
|
|
}
|
|
|
|
createdContEdges.Add(key, newContEdge.Obj());
|
|
ic.createdEdges.Add(newContEdge);
|
|
};
|
|
|
|
if (i == 1 && contEdge->input.type != EdgeInputType::Rule)
|
|
{
|
|
AddNewContEdge(newState.Obj(), true, false);
|
|
continue;
|
|
}
|
|
|
|
if (contEdge->input.type == EdgeInputType::LeftRec)
|
|
{
|
|
AddNewContEdge(newState.Obj(), true, true);
|
|
continue;
|
|
}
|
|
|
|
if (!contState)
|
|
{
|
|
auto label = fromState->label + pmLabel;
|
|
for (vint j = 0; j < i; j++)
|
|
{
|
|
auto&& input = edgeList[j]->input;
|
|
if (input.type == EdgeInputType::Rule)
|
|
{
|
|
label += L" " + input.rule->Name();
|
|
}
|
|
else
|
|
{
|
|
label += L" [TOKEN] " + (input.condition ? input.condition.Value() : itow(input.token));
|
|
}
|
|
}
|
|
if (contStateLabels.Contains(label)) continue;
|
|
contStateLabels.Add(label);
|
|
|
|
contState = Ptr(new StateSymbol(fromState->Rule()));
|
|
ic.createdStates.Add(contState);
|
|
contState->label = label;
|
|
|
|
auto lrEdge = Ptr(new EdgeSymbol(newState.Obj(), contState.Obj()));
|
|
ic.createdEdges.Add(lrEdge);
|
|
|
|
lrEdge->input.type = EdgeInputType::LeftRec;
|
|
CopyFrom(lrEdge->competitions, lastEdge->competitions, true);
|
|
for (vint j = 0; j < i - 1; j++)
|
|
{
|
|
lrEdge->returnEdges.Add(edgeList[j]);
|
|
}
|
|
CopyFrom(lrEdge->insAfterInput, lastEdge->insAfterInput, true);
|
|
}
|
|
|
|
{
|
|
AddNewContEdge(contState.Obj(), false, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return newEdge.Obj();
|
|
}
|
|
|
|
/***********************************************************************
|
|
SyntaxSymbolManager::PrefixMergeCrossReference_Apply
|
|
***********************************************************************/
|
|
|
|
void SyntaxSymbolManager::PrefixMergeCrossReference_Apply(PrefixMergeCache* cache, collections::List<EdgeSymbol*>& accumulatedEdges, PrefixMergeApplicationItems& pmai)
|
|
{
|
|
auto lastEdge = accumulatedEdges[accumulatedEdges.Count() - 1];
|
|
auto lastRule = lastEdge->input.rule;
|
|
|
|
if (pmai.coveredRules[lastRule->pmRuleIndex])
|
|
{
|
|
auto edges = Ptr(new List<EdgeSymbol*>);
|
|
CopyFrom(*edges.Obj(), accumulatedEdges);
|
|
pmai.ruleToEdges.Add(lastRule, edges);
|
|
}
|
|
else
|
|
{
|
|
for (auto edge : lastRule->startStates[0]->OutEdges())
|
|
{
|
|
switch (edge->input.type)
|
|
{
|
|
case EdgeInputType::Rule:
|
|
// RuleIsIndirectlyLeftRecursive has been checked so there will be no deadloop
|
|
accumulatedEdges.Add(edge);
|
|
PrefixMergeCrossReference_Apply(cache, accumulatedEdges, pmai);
|
|
accumulatedEdges.RemoveAt(accumulatedEdges.Count() - 1);
|
|
break;
|
|
case EdgeInputType::Token:
|
|
{
|
|
auto edges = Ptr(new List<EdgeSymbol*>);
|
|
CopyFrom(*edges.Obj(), accumulatedEdges);
|
|
edges->Add(edge);
|
|
pmai.tokenToEdges.Add({ edge->input.token, edge->input.condition }, edges);
|
|
}
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void SyntaxSymbolManager::PrefixMergeCrossReference_Apply(PrefixMergeCache* cache, RuleSymbol* rule, StateSymbol* currentState, Ptr<PrefixMergeSolutionValue> solution, IncrementalChange& ic)
|
|
{
|
|
/*
|
|
* For any state A whose prefix calls look like:
|
|
* A -> r1 -> ... rn -> (u1, v1, ...)
|
|
* A -> s1 -> ... sn -> (u1, v1, ...)
|
|
* The same (u1, v1, ...) will be merged.
|
|
* Especially when A indirectly reuses (u1, v1, ...), this approach removes duplicated ambiguous results.
|
|
* by not doing this, it produces two duplicated A -> (different paths) -> (u1, v1, ...)
|
|
* and parsing efforts are wasted if (u1, v1, ...) costs a large number of transitions
|
|
*
|
|
* Because a prefix will be produced and then passed into its parent rule like this:
|
|
* {CreateObject(u1)} ... {StackSlot(0), CreateObject(r1)} {StackSlot(0), CreateObject(A)}
|
|
* we can parse (u1, v1, ...) first, and then patch multiple EndingInput transitions directly into (rn, sn)
|
|
* such EndingInput transition will have non-empty returnEdges
|
|
*
|
|
* (u1, v1, ...) are not required to be reuse clauses which only contain one rule
|
|
* as even if they are, they may be followed by LeftRec transitions, it doesn't make the work simpler, but even more checking
|
|
* recursive cross-reference merges will not be implemented at the moment
|
|
* treat it as a special case which only merge prefixes in the size of one rule
|
|
*
|
|
* PrefixMergeCrossReference_Solve worked out how many transitions need to be reworked
|
|
* e.g. (a start set graph, assuming left nodes are selected prefix rules)
|
|
* +-> r2 ..
|
|
* | +-> r4 ..
|
|
* A -> r1 -+-> r3 -+-> r5 ..
|
|
* |
|
|
* +-> r6..
|
|
* when r4 merges, (r2, r5, r6) will need similar edges to start from A:
|
|
* A -+- r4 (injects into r3)
|
|
* +- r5 (injects into r3)
|
|
* +- r2 (injects into r1)
|
|
* +- r6 (injects into r1)
|
|
*/
|
|
|
|
for (auto application : solution->applications)
|
|
{
|
|
PrefixMergeApplicationItems pmai;
|
|
for (auto prefixRule : application->prefixRules)
|
|
{
|
|
pmai.coveredRules.Set(prefixRule->pmRuleIndex);
|
|
}
|
|
|
|
List<EdgeSymbol*> accumulatedEdges;
|
|
for (auto edge : application->edgesToMerge)
|
|
{
|
|
accumulatedEdges.Add(edge);
|
|
PrefixMergeCrossReference_Apply(cache, accumulatedEdges, pmai);
|
|
accumulatedEdges.RemoveAt(accumulatedEdges.Count() - 1);
|
|
}
|
|
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L"[PMAI] " + rule->Name() + L" @ " + currentState->label);
|
|
#endif
|
|
for (vint i = 0; i < pmai.ruleToEdges.Count(); i++)
|
|
{
|
|
auto pmRule = pmai.ruleToEdges.Keys()[i];
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L" [RULE] " + pmRule->Name() + L" :");
|
|
#endif
|
|
auto&& accumulatedEdgesList = pmai.ruleToEdges.GetByIndex(i);
|
|
auto newEdge = PrefixMergeCrossReference_AccumulatedEdges(currentState, (L"[pm-cr-rule: " + pmRule->Name() + L"]"), accumulatedEdgesList, ic);
|
|
newEdge->input.type = EdgeInputType::PrefixMergeRule;
|
|
newEdge->input.rule = pmRule;
|
|
}
|
|
for (vint i = 0; i < pmai.tokenToEdges.Count(); i++)
|
|
{
|
|
auto [pmToken, condition] = pmai.tokenToEdges.Keys()[i];
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L" [TOKEN] " + (condition ? condition.Value() : itow(pmToken)));
|
|
#endif
|
|
auto&& accumulatedEdgesList = pmai.tokenToEdges.GetByIndex(i);
|
|
auto newEdge = PrefixMergeCrossReference_AccumulatedEdges(currentState, (L"[pm-cr-token: " + (condition ? condition.Value() : itow(pmToken)) + L"]"), accumulatedEdgesList, ic);
|
|
newEdge->input.type = EdgeInputType::Token;
|
|
newEdge->input.token = pmToken;
|
|
newEdge->input.condition = condition;
|
|
}
|
|
#ifdef LOG_DECISION_MAKING
|
|
LOGL(L"");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef LOG_DECISION_MAKING
|
|
#undef LOG_DECISION_MAKING
|
|
#undef LOG
|
|
#undef LOGL
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\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:
|
|
{
|
|
// Cannot call CreateEdge here because it is checked as a public API
|
|
// But during NFA building we should still change the automaton
|
|
auto newEdge = Ptr(new EdgeSymbol(startState, edge->To()));
|
|
edges.Add(newEdge);
|
|
|
|
// Either prefix-merged or cross-referenced Token transition may have non-empty returnEdges
|
|
// There is no way to tell if a token is cross-referenced, which should be ignored during accumulation
|
|
// So we use CrossReferencedToken here and later renamed everything back to Token
|
|
newEdge->input = edge->input;
|
|
newEdge->input.type = EdgeInputType::CrossReferencedToken;
|
|
CopyFrom(newEdge->competitions, edge->competitions, true);
|
|
for (auto acc : accumulatedEdges)
|
|
{
|
|
CopyFrom(newEdge->returnEdges, acc->returnEdges, true);
|
|
newEdge->returnEdges.Add(acc);
|
|
}
|
|
CopyFrom(newEdge->insAfterInput, edge->insAfterInput, true);
|
|
}
|
|
break;
|
|
case EdgeInputType::Rule:
|
|
// RuleIsIndirectlyLeftRecursive has been checked so there will be no deadloop
|
|
accumulatedEdges.Add(edge);
|
|
FixCrossReferencedRuleEdge(startState, orderedEdges, accumulatedEdges);
|
|
accumulatedEdges.RemoveAt(accumulatedEdges.Count() - 1);
|
|
break;
|
|
case EdgeInputType::Epsilon:
|
|
case EdgeInputType::LeftRec:
|
|
case EdgeInputType::PrefixMergeDiscardedRule:
|
|
// These edges are not involved
|
|
case EdgeInputType::Ending:
|
|
case EdgeInputType::PrefixMergeRule:
|
|
case EdgeInputType::CrossReferencedToken:
|
|
// These edges do not exist in compact-NFA
|
|
break;
|
|
default:
|
|
CHECK_FAIL(L"<BuildCrossReferencedNFAInternal>Unhandled!");
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto state : states)
|
|
{
|
|
for (auto edge : state->OutEdges())
|
|
{
|
|
if (edge->input.type == EdgeInputType::CrossReferencedToken)
|
|
{
|
|
edge->input.type = EdgeInputType::Token;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|