/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
#include "VlppGlrParser.h"

/***********************************************************************
.\ASTBASE.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		using namespace collections;
		using namespace stream;
		using namespace astins_slots;

/***********************************************************************
JsonVisitorBase
***********************************************************************/

		void JsonVisitorBase::BeginObject()
		{
			writer.WriteString(L"{");
			indentation++;
			indices.Add(0);
		}

		void JsonVisitorBase::BeginField(const WString& field)
		{
			vint last = indices[indices.Count() - 1];
			if (last > 0)
			{
				writer.WriteString(L",");
			}
			writer.WriteLine(L"");
			WriteIndent();
			writer.WriteChar(L'\"');
			writer.WriteString(field);
			writer.WriteChar(L'\"');
			writer.WriteString(L": ");
		}

		void JsonVisitorBase::EndField()
		{
			indices[indices.Count() - 1]++;
		}

		void JsonVisitorBase::EndObject()
		{
			indices.RemoveAt(indices.Count() - 1);
			indentation--;
			writer.WriteLine(L"");
			WriteIndent();
			writer.WriteString(L"}");
		}

		void JsonVisitorBase::BeginArray()
		{
			writer.WriteString(L"[");
			indices.Add(0);
		}

		void JsonVisitorBase::BeginArrayItem()
		{
			vint last = indices[indices.Count() - 1];
			if (last > 0)
			{
				writer.WriteString(L", ");
			}
		}

		void JsonVisitorBase::EndArrayItem()
		{
			indices[indices.Count() - 1]++;
		}

		void JsonVisitorBase::EndArray()
		{
			indices.RemoveAt(indices.Count() - 1);
			writer.WriteString(L"]");
		}

		void JsonVisitorBase::WriteIndent()
		{
			for (vint i = 0; i < indentation; i++)
			{
				writer.WriteString(L"    ");
			}
		}

		void JsonVisitorBase::WriteRange(const ParsingTextRange& range)
		{
			writer.WriteString(L"{\"start\": {\"row\": ");
			writer.WriteString(itow(range.start.row));
			writer.WriteString(L", \"column\": ");
			writer.WriteString(itow(range.start.column));
			writer.WriteString(L", \"index\": ");
			writer.WriteString(itow(range.start.index));
			writer.WriteString(L"}, \"end\": {\"row\": ");
			writer.WriteString(itow(range.end.row));
			writer.WriteString(L", \"column\": ");
			writer.WriteString(itow(range.end.column));
			writer.WriteString(L", \"index\": ");
			writer.WriteString(itow(range.end.index));
			writer.WriteString(L"}, \"codeIndex\": ");
			writer.WriteString(itow(range.codeIndex));
			writer.WriteString(L"}");
		}

		void JsonVisitorBase::WriteToken(const ParsingToken& token)
		{
			if (printTokenCodeRange)
			{
				writer.WriteString(L"{ \"value\": ");
				WriteString(token.value);
				writer.WriteString(L", \"codeRange\": ");
				WriteRange(token.codeRange);
				writer.WriteString(L"}");
			}
			else
			{
				WriteString(token.value);
			}
		}

		void JsonVisitorBase::WriteType(const WString& type, ParsingAstBase* node)
		{
			if (printAstType && printAstCodeRange)
			{
				BeginField(L"$ast");
				writer.WriteString(L"{ \"type\": ");
				WriteString(type);
				writer.WriteString(L", \"codeRange\": ");
				WriteRange(node->codeRange);
				writer.WriteString(L"}");
				EndField();
			}
			else if (printAstType)
			{
				BeginField(L"$ast");
				WriteString(type);
				EndField();
			}
			else if (printAstCodeRange)
			{
				BeginField(L"$ast");
				writer.WriteString(L"{ \"codeRange\": ");
				WriteRange(node->codeRange);
				writer.WriteString(L"}");
				EndField();
			}
		}

		void JsonVisitorBase::WriteString(const WString& text)
		{
			writer.WriteChar(L'\"');
			JsonEscapeString(text, writer);
			writer.WriteChar(L'\"');
		}

		void JsonVisitorBase::WriteNull()
		{
			writer.WriteString(L"null");
		}

		JsonVisitorBase::JsonVisitorBase(stream::StreamWriter& _writer)
			:writer(_writer)
		{
		}

/***********************************************************************
Json Printing
***********************************************************************/

		void JsonEscapeString(const WString& text, stream::TextWriter& writer)
		{
			const wchar_t* reading = text.Buffer();
			while (wchar_t c = *reading++)
			{
				switch (c)
				{
				case L'\"': writer.WriteString(L"\\\""); break;
				case L'\\': writer.WriteString(L"\\\\"); break;
				case L'/': writer.WriteString(L"\\/"); break;
				case L'\b': writer.WriteString(L"\\b"); break;
				case L'\f': writer.WriteString(L"\\f"); break;
				case L'\n': writer.WriteString(L"\\n"); break;
				case L'\r': writer.WriteString(L"\\r"); break;
				case L'\t': writer.WriteString(L"\\t"); break;
				default: writer.WriteChar(c);
				}
			}
		}

		vuint16_t GetHex(wchar_t c)
		{
			if (L'0' <= c && c <= L'9')
			{
				return c - L'0';
			}
			else if (L'A' <= c && c <= L'F')
			{
				return c - L'A';
			}
			else if (L'a' <= c && c <= L'f')
			{
				return c - L'a';
			}
			else
			{
				return 0;
			}
		}

		void JsonUnescapeString(const WString& text, stream::TextWriter& writer)
		{
			const wchar_t* reading = text.Buffer();
			while (wchar_t c = *reading++)
			{
				if (c == L'\\' && *reading)
				{
					switch (c = *reading++)
					{
					case L'b': writer.WriteChar(L'\b'); break;
					case L'f': writer.WriteChar(L'\f'); break;
					case L'n': writer.WriteChar(L'\n'); break;
					case L'r': writer.WriteChar(L'\r'); break;
					case L't': writer.WriteChar(L'\t'); break;
					case L'u':
						{
							wchar_t h1, h2, h3, h4;
							if ((h1 = reading[0]) && (h2 = reading[1]) && (h3 = reading[2]) && (h4 = reading[3]))
							{
								reading += 4;
								wchar_t h = (wchar_t)(vuint16_t)(
									(GetHex(h1) << 12) +
									(GetHex(h2) << 8) +
									(GetHex(h3) << 4) +
									(GetHex(h4) << 0)
									);
								writer.WriteChar(h);
							}
						}
						break;
					default: writer.WriteChar(c);
					}
				}
				else
				{
					writer.WriteChar(c);
				}
			}
		}

/***********************************************************************
AstInsReceiverBase
***********************************************************************/

		void AstInsReceiverBase::EnsureContinuable()
		{
			if (corrupted)
			{
				throw AstInsException(
					L"An exception has been thrown therefore this receiver cannot be used anymore.",
					AstInsErrorType::Corrupted
					);
			}
			if (finished)
			{
				throw AstInsException(
					L"The finished instruction has been executed therefore this receiver cannot be used anymore.",
					AstInsErrorType::Finished
					);
			}
		}

		void AstInsReceiverBase::SetField(ParsingAstBase* object, vint32_t field, const SlotValue& value, bool weakAssignment)
		{
			value.Apply(Overloading(
				[&](const TokenSlot& tokenSlot)
				{
					if (weakAssignment)
					{
						throw AstInsException(
							L"Weak assignment only available for field of enum type",
							AstInsErrorType::FieldWeakAssignmentOnNonEnum,
							field
						);
					}
					SetField(object, field, tokenSlot.token, tokenSlot.index);
				},
				[&](const EnumItemSlot& enumItemSlot)
				{
					SetField(object, field, enumItemSlot.value, weakAssignment);
				},
				[&](const Ptr< ParsingAstBase>& objectSlot)
				{
					if (weakAssignment)
					{
						throw AstInsException(
							L"Weak assignment only available for field of enum type",
							AstInsErrorType::FieldWeakAssignmentOnNonEnum,
							field
						);
					}
					SetField(object, field, objectSlot);
				}
			));
		}

		void AstInsReceiverBase::Execute(AstIns instruction, const regex::RegexToken& token, vint32_t tokenIndex)
		{
			EnsureContinuable();
			try
			{
				switch (instruction.type)
				{
				case AstInsType::Token:
				case AstInsType::EnumItem:
				case AstInsType::StackSlot:
					{
						if (stackFrames.Count() == 0)
						{
							throw AstInsException(
								L"There is no stack frame to store slot values.",
								AstInsErrorType::NoStackFrame
							);
						}
						auto&& frame = stackFrames[stackFrames.Count() - 1];

						SlotValue slotValue;
						switch (instruction.type)
						{
						case AstInsType::Token:
							slotValue = SlotValue(TokenSlot{ token,tokenIndex });
							break;
						case AstInsType::EnumItem:
							slotValue = SlotValue(EnumItemSlot{ instruction.param });
							break;
						case AstInsType::StackSlot:
							{
								if (creatingObjects.Count() == 0)
								{
									throw AstInsException(
										L"There is no creating object to store in a stack slot.",
										AstInsErrorType::NoCreatingObjectForStackSlot
									);
								}
								auto astNode = creatingObjects[creatingObjects.Count() - 1].object;
								creatingObjects.RemoveAt(creatingObjects.Count() - 1);
								slotValue = SlotValue(astNode);

								if (frame.codeRangeStart > astNode->codeRange.start)
								{
									frame.codeRangeStart = astNode->codeRange.start;
								}
							}
							break;
						default:;
						}

						auto keyIndex = frame.slots.Keys().IndexOf(instruction.count);
						if (keyIndex == -1)
						{
							SlotStorage storage;
							storage.value = slotValue;
							frame.slots.Add(instruction.count, storage);
						}
						else
						{
							auto&& storage = const_cast<SlotStorage&>(frame.slots.Values()[keyIndex]);
							if (!storage.additionalValues)
							{
								storage.additionalValues = Ptr(new List<SlotValue>);
							}
							storage.additionalValues->Add(slotValue);
						}
					}
					break;
				case AstInsType::StackBegin:
					{
						stackFrames.Add({ {},ParsingTextPos::Start(&token) });
					}
					break;
				case AstInsType::CreateObject:
					{
						if (stackFrames.Count() == 0)
						{
							throw AstInsException(
								L"There is no stack frame to store slot values.",
								AstInsErrorType::NoStackFrame
							);
						}
						auto&& frame = stackFrames[stackFrames.Count() - 1];

						auto astNode = CreateAstNode(instruction.param);
						astNode->codeRange = { &token,&token };
						if (astNode->codeRange.start > frame.codeRangeStart)
						{
							astNode->codeRange.start = frame.codeRangeStart;
						}

						CreatingObject info;
						info.object = astNode;
						info.type = instruction.param;
						creatingObjects.Add(info);
					}
					break;
				case AstInsType::Field:
				case AstInsType::FieldIfUnassigned:
					{
						if (creatingObjects.Count() == 0)
						{
							throw AstInsException(
								L"There is no creating object to assign fields.",
								AstInsErrorType::NoCreatingObjectForField,
								instruction.param
							);
						}

						if (stackFrames.Count() == 0)
						{
							throw AstInsException(
								L"There is no stack frame to provide values for field assignment.",
								AstInsErrorType::NoStackFrame
							);
						}
						auto&& frame = stackFrames[stackFrames.Count() - 1];

						auto slotKeyIndex = frame.slots.Keys().IndexOf(instruction.count);
						if (slotKeyIndex == -1)
						{
							break;
						}

						auto storage = frame.slots.Values()[slotKeyIndex];
						auto object = creatingObjects[creatingObjects.Count() - 1].object.Obj();

						const bool weakAssignment = instruction.type == AstInsType::FieldIfUnassigned;
						auto assignValue = [&](const SlotValue& slotValue)
						{
							SetField(object, instruction.param, slotValue, weakAssignment);
						};

						SetField(object, instruction.param, storage.value, weakAssignment);
						if (storage.additionalValues)
						{
							for (auto&& additionalValue : *storage.additionalValues.Obj())
							{
								SetField(object, instruction.param, additionalValue, weakAssignment);
							}
						}
					}
					break;
				case AstInsType::StackEnd:
					{
						if (stackFrames.Count() == 0)
						{
							throw AstInsException(
								L"There is no stack frame to end.",
								AstInsErrorType::NoStackFrameForStackEnd
							);
						}
						if (creatingObjects.Count() == 0)
						{
							throw AstInsException(
								L"There is no creating object when ending the current stack frame.",
								AstInsErrorType::NoCreatingObjectForStackEnd
							);
						}

						auto&& frame = stackFrames[stackFrames.Count() - 1];
						auto astNode = creatingObjects[creatingObjects.Count() - 1].object.Obj();

						if (astNode->codeRange.start > frame.codeRangeStart)
						{
							astNode->codeRange.start = frame.codeRangeStart;
						}

						auto codeRangeEnd = ParsingTextPos::End(&token);
						if (astNode->codeRange.end < codeRangeEnd)
						{
							astNode->codeRange.end = codeRangeEnd;
						}

						stackFrames.RemoveAt(stackFrames.Count() - 1);
					}
					break;
				case AstInsType::ResolveAmbiguity:
					{
						if (stackFrames.Count() == 0)
						{
							throw AstInsException(
								L"There is no stack frame to resolve ambiguity.",
								AstInsErrorType::NoStackFrame
							);
						}
						auto&& frame = stackFrames[stackFrames.Count() - 1];

						auto slotKeyIndex = frame.slots.Keys().IndexOf(ResolveAmbiguitySlotIndex);
						if (slotKeyIndex == -1)
						{
							throw AstInsException(
								L"There are not enough candidates to create an ambiguity node.",
								AstInsErrorType::MissingAmbiguityCandidate
							);
						}

						auto storage = frame.slots.Values()[slotKeyIndex];
						vint candidateCount = 1;
						if (storage.additionalValues)
						{
							candidateCount += storage.additionalValues->Count();
						}
						if (candidateCount < 2)
						{
							throw AstInsException(
								L"There are not enough candidates to create an ambiguity node.",
								AstInsErrorType::MissingAmbiguityCandidate
							);
						}

						Array<Ptr<ParsingAstBase>> candidates(candidateCount);
						auto readCandidate = [&](const SlotValue& slotValue, vint index)
						{
							slotValue.Apply(Overloading(
								[&](const TokenSlot&)
								{
									throw AstInsException(
										L"Tokens cannot be ambiguity candidates.",
										AstInsErrorType::AmbiguityCandidateIsNotObject
									);
								},
								[&](const EnumItemSlot&)
								{
									throw AstInsException(
										L"Enum items cannot be ambiguity candidates.",
										AstInsErrorType::AmbiguityCandidateIsNotObject
									);
								},
								[&](const Ptr<ParsingAstBase>& objectSlot)
								{
									candidates[index] = objectSlot;
								}
							));
						};

						readCandidate(storage.value, 0);
						if (storage.additionalValues)
						{
							for (vint i = 0; i < storage.additionalValues->Count(); i++)
							{
								readCandidate(storage.additionalValues->Get(i), i + 1);
							}
						}

						auto resolved = ResolveAmbiguity(instruction.param, candidates);
						CreatingObject info;
						info.object = resolved;
						info.type = instruction.param;
						creatingObjects.Add(info);
					}
					break;
				}
			}
			catch (const AstInsException&)
			{
				corrupted = true;
				throw;
			}
		}

		Ptr<ParsingAstBase> AstInsReceiverBase::Finished()
		{
			EnsureContinuable();
			try
			{
				if (stackFrames.Count() > 0 || creatingObjects.Count() != 1)
				{
					throw AstInsException(
						L"No more instruction but the root object has not been completed yet.",
						AstInsErrorType::InstructionNotComplete
						);
				}

				auto object = creatingObjects[0].object;
				creatingObjects.RemoveAt(0);
				finished = true;
				return object;
			}
			catch (const AstInsException&)
			{
				corrupted = true;
				throw;
			}
		}

/***********************************************************************
IAstInsReceiver (Code Generation Error Templates)
***********************************************************************/

		Ptr<ParsingAstBase> AssemblyThrowCannotCreateAbstractType(vint32_t type, const wchar_t* cppTypeName)
		{
			if (cppTypeName)
			{
				throw AstInsException(
					WString::Unmanaged(L"Unable to create abstract class \"") +
					WString::Unmanaged(cppTypeName) +
					WString::Unmanaged(L"\"."),
					AstInsErrorType::UnsupportedAbstractType, type);
			}
			else
			{
				throw AstInsException(L"The type id does not exist.", vl::glr::AstInsErrorType::UnknownType, type);
			}
		}

		void AssemblyThrowFieldNotObject(vint32_t field, const wchar_t* cppFieldName)
		{
			if (cppFieldName)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" cannot be assigned with an object."),
					AstInsErrorType::ObjectTypeMismatchedToField, field);
			}
			else
			{
				throw AstInsException(L"The field id does not exist.", vl::glr::AstInsErrorType::UnknownField, field);
			}
		}

		void AssemblyThrowFieldNotToken(vint32_t field, const wchar_t* cppFieldName)
		{
			if (cppFieldName)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" cannot be assigned with a token."),
					AstInsErrorType::ObjectTypeMismatchedToField, field);
			}
			else
			{
				throw AstInsException(L"The field id does not exist.", vl::glr::AstInsErrorType::UnknownField, field);
			}
		}

		void AssemblyThrowFieldNotEnum(vint32_t field, const wchar_t* cppFieldName)
		{
			if (cppFieldName)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" cannot be assigned with an enum item."),
					AstInsErrorType::ObjectTypeMismatchedToField, field);
			}
			else
			{
				throw AstInsException(L"The field id does not exist.", vl::glr::AstInsErrorType::UnknownField, field);
			}
		}

		Ptr<ParsingAstBase> AssemblyThrowTypeNotAllowAmbiguity(vint32_t type, const wchar_t* cppTypeName)
		{
			if (cppTypeName)
			{
				throw AstInsException(
					WString::Unmanaged(L"Type \"") +
					WString::Unmanaged(cppTypeName) +
					WString::Unmanaged(L"\" is not configured to allow ambiguity."),
					AstInsErrorType::UnsupportedAmbiguityType, type);
			}
			else
			{
				throw AstInsException(L"The type id does not exist.", vl::glr::AstInsErrorType::UnknownType, type);
			}
		}

/***********************************************************************
Compression
***********************************************************************/

		void DecompressSerializedData(const char** buffer, bool decompress, vint solidRows, vint rows, vint block, vint remain, stream::IStream& outputStream)
		{
			if (decompress)
			{
				MemoryStream compressedStream;
				DecompressSerializedData(buffer, false, solidRows, rows, block, remain, compressedStream);
				compressedStream.SeekFromBegin(0);
				DecompressStream(compressedStream, outputStream);
			}
			else
			{
				for (vint i = 0; i < rows; i++)
				{
					vint size = i == solidRows ? remain : block;
					outputStream.Write((void*)buffer[i], size);
				}
			}
		}
	}

/***********************************************************************
Reflection
***********************************************************************/

	namespace reflection
	{
		namespace description
		{
#ifndef VCZH_DEBUG_NO_REFLECTION
			IMPL_TYPE_INFO_RENAME(vl::glr::ParsingTextPos, system::ParsingTextPos)
			IMPL_TYPE_INFO_RENAME(vl::glr::ParsingTextRange, system::ParsingTextRange)
			IMPL_TYPE_INFO_RENAME(vl::glr::ParsingToken, system::ParsingToken)
			IMPL_TYPE_INFO_RENAME(vl::glr::ParsingAstBase, system::ParsingAstBase)

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

			BEGIN_STRUCT_MEMBER(vl::glr::ParsingTextPos)
				STRUCT_MEMBER(index)
				STRUCT_MEMBER(row)
				STRUCT_MEMBER(column)
			END_STRUCT_MEMBER(vl::glr::ParsingTextPos)

			BEGIN_STRUCT_MEMBER(vl::glr::ParsingTextRange)
				STRUCT_MEMBER(start)
				STRUCT_MEMBER(end)
				STRUCT_MEMBER(codeIndex)
			END_STRUCT_MEMBER(vl::glr::ParsingTextRange)

			BEGIN_STRUCT_MEMBER(vl::glr::ParsingToken)
				STRUCT_MEMBER(codeRange)
				STRUCT_MEMBER(index)
				STRUCT_MEMBER(token)
				STRUCT_MEMBER(value)
			END_STRUCT_MEMBER(vl::glr::ParsingToken)

			BEGIN_CLASS_MEMBER(vl::glr::ParsingAstBase)
				CLASS_MEMBER_FIELD(codeRange)
			END_CLASS_MEMBER(vl::glr::ParsingAstBase)

			class Parsing2TypeLoader : public vl::Object, public ITypeLoader
			{
			public:
				void Load(ITypeManager* manager)
				{
					ADD_TYPE_INFO(vl::glr::ParsingTextPos)
					ADD_TYPE_INFO(vl::glr::ParsingTextRange)
					ADD_TYPE_INFO(vl::glr::ParsingToken)
					ADD_TYPE_INFO(vl::glr::ParsingAstBase)
				}

				void Unload(ITypeManager* manager)
				{
				}
			};
#endif
#endif
			bool LoadParsing2Types()
			{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				if (auto manager = GetGlobalTypeManager())
				{
					auto loader = Ptr(new Parsing2TypeLoader);
					return manager->AddTypeLoader(loader);
				}
#endif
				return false;
			}
		}
	}
}


/***********************************************************************
.\ASTPRINT.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{

/***********************************************************************
ParsingEmptyPrintNodeRecorder
***********************************************************************/

		ParsingEmptyPrintNodeRecorder::ParsingEmptyPrintNodeRecorder()
		{
		}

		ParsingEmptyPrintNodeRecorder::~ParsingEmptyPrintNodeRecorder()
		{
		}

		void ParsingEmptyPrintNodeRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range)
		{
		}

/***********************************************************************
ParsingMultiplePrintNodeRecorder
***********************************************************************/

		ParsingMultiplePrintNodeRecorder::ParsingMultiplePrintNodeRecorder()
		{
		}

		ParsingMultiplePrintNodeRecorder::~ParsingMultiplePrintNodeRecorder()
		{
		}

		void ParsingMultiplePrintNodeRecorder::AddRecorder(Ptr<IParsingPrintNodeRecorder> recorder)
		{
			recorders.Add(recorder);
		}

		void ParsingMultiplePrintNodeRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range)
		{
			for (auto recorder : recorders)
			{
				recorder->Record(node, range);
			}
		}

/***********************************************************************
ParsingOriginalLocationRecorder
***********************************************************************/

		ParsingOriginalLocationRecorder::ParsingOriginalLocationRecorder(Ptr<IParsingPrintNodeRecorder> _recorder)
			:recorder(_recorder)
		{
		}

		ParsingOriginalLocationRecorder::~ParsingOriginalLocationRecorder()
		{
		}

		void ParsingOriginalLocationRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range)
		{
			auto codeRange = node->codeRange;
			codeRange.codeIndex = range.codeIndex;
			recorder->Record(node, codeRange);
		}

/***********************************************************************
ParsingGeneratedLocationRecorder
***********************************************************************/

		ParsingGeneratedLocationRecorder::ParsingGeneratedLocationRecorder(RangeMap& _rangeMap)
			:rangeMap(_rangeMap)
		{
		}

		ParsingGeneratedLocationRecorder::~ParsingGeneratedLocationRecorder()
		{
		}

		void ParsingGeneratedLocationRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range)
		{
			rangeMap.Add(node, range);
		}

/***********************************************************************
ParsingUpdateLocationRecorder
***********************************************************************/

		ParsingUpdateLocationRecorder::ParsingUpdateLocationRecorder()
		{
		}

		ParsingUpdateLocationRecorder::~ParsingUpdateLocationRecorder()
		{
		}

		void ParsingUpdateLocationRecorder::Record(ParsingAstBase* node, const ParsingTextRange& range)
		{
			node->codeRange = range;
		}

/***********************************************************************
ParsingWriter
***********************************************************************/

		void ParsingWriter::HandleChar(wchar_t c)
		{
			lastPos = currentPos;
			switch (c)
			{
			case L'\n':
				currentPos.index++;
				currentPos.row++;
				currentPos.column = 0;
				break;
			default:
				currentPos.index++;
				currentPos.column++;
			}
		}

		ParsingWriter::ParsingWriter(stream::TextWriter& _writer, Ptr<IParsingPrintNodeRecorder> _recorder, vint _codeIndex)
			:writer(_writer)
			, recorder(_recorder)
			, codeIndex(_codeIndex)
			, lastPos(-1, 0, -1)
			, currentPos(0, 0, 0)
		{
		}

		ParsingWriter::~ParsingWriter()
		{
		}

		void ParsingWriter::WriteChar(wchar_t c)
		{
			writer.WriteChar(c);
			if (!recorder) return;
			HandleChar(c);
		}

		void ParsingWriter::WriteString(const wchar_t* string, vint charCount)
		{
			writer.WriteString(string, charCount);
			if (!recorder) return;
			for (vint i = 0; i < charCount; i++)
			{
				HandleChar(string[i]);
			}
		}

		void ParsingWriter::BeforePrint(ParsingAstBase* node)
		{
			if (!recorder) return;
			nodePositions.Add(NodePosPair(node, currentPos));
		}

		void ParsingWriter::AfterPrint(ParsingAstBase* node)
		{
			if (!recorder) return;

			auto pair = nodePositions[nodePositions.Count() - 1];
			nodePositions.RemoveAt(nodePositions.Count() - 1);
			CHECK_ERROR(pair.key == node, L"vl::parsing::ParsingWriter::AfterPrint(ParsingTreeNode*)#BeforePrint and AfterPrint should be call in pairs.");

			ParsingTextRange range(pair.value, lastPos, codeIndex);
			recorder->Record(node, range);
		}
	}
}

/***********************************************************************
.\EXECUTABLE.CPP
***********************************************************************/

namespace vl
{
	namespace stream
	{
		namespace internal
		{
			using namespace glr;
			using namespace glr::automaton;

			BEGIN_SERIALIZATION(AstIns)
				SERIALIZE(type)
				SERIALIZE(param)
				SERIALIZE(count)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(InstructionArray)
				SERIALIZE(start)
				SERIALIZE(count)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(StringLiteral)
				SERIALIZE(start)
				SERIALIZE(count)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(CompetitionArray)
				SERIALIZE(start)
				SERIALIZE(count)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(CompetitionDesc)
				SERIALIZE(competitionId)
				SERIALIZE(highPriority)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(ReturnIndexArray)
				SERIALIZE(start)
				SERIALIZE(count)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(EdgeArray)
				SERIALIZE(start)
				SERIALIZE(count)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(ReturnDesc)
				SERIALIZE(consumedRule)
				SERIALIZE(returnState)
				SERIALIZE(competitions)
				SERIALIZE(ruleType)
				SERIALIZE(insAfterInput)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(EdgeDesc)
				SERIALIZE(fromState)
				SERIALIZE(toState)
				SERIALIZE(condition)
				SERIALIZE(competitions)
				SERIALIZE(insAfterInput)
				SERIALIZE(returnIndices)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(StateDesc)
				SERIALIZE(rule)
				SERIALIZE(endingState)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(Executable)
				SERIALIZE(tokenCount)
				SERIALIZE(ruleCount)
				SERIALIZE(ruleStartStates)
				SERIALIZE(transitions)
				SERIALIZE(astInstructions)
				SERIALIZE(returnIndices)
				SERIALIZE(competitions)
				SERIALIZE(returns)
				SERIALIZE(edges)
				SERIALIZE(states)
				SERIALIZE(stringLiteralBuffer)
			END_SERIALIZATION
		}
	}

	namespace glr
	{
		namespace automaton
		{
			using namespace stream;

/***********************************************************************
Executable
***********************************************************************/

			Executable::Executable(stream::IStream& inputStream)
			{
				internal::ContextFreeReader reader(inputStream);
				reader << *this;
			}

			void Executable::Serialize(stream::IStream& outputStream)
			{
				internal::ContextFreeWriter writer(outputStream);
				writer << *this;
			}
		}
	}
}

/***********************************************************************
.\SYNTAXBASE.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
/***********************************************************************
ErrorArgs
***********************************************************************/

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnull-dereference"
#elif defined (__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnull-dereference"
#endif
		ErrorArgs ErrorArgs::UnrecognizedToken(const regex::RegexToken& token)
		{
			return {
				true,
				ErrorType::UnrecognizedToken,
				token.codeIndex,
				const_cast<regex::RegexToken&>(token),
				*static_cast<collections::List<regex::RegexToken>*>(nullptr),
				*static_cast<automaton::Executable*>(nullptr),
				nullptr,
				nullptr
			};
		}

		ErrorArgs ErrorArgs::InvalidToken(regex::RegexToken& token, collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::IExecutor* executor)
		{
			return {
				true,
				ErrorType::InvalidToken,
				token.codeIndex,
				token,
				tokens,
				executable,
				executor,
				nullptr
			};
		}

		ErrorArgs ErrorArgs::InputIncomplete(vint codeIndex, collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::IExecutor* executor)
		{
			return {
				true,
				ErrorType::InputIncomplete,
				codeIndex,
				*static_cast<regex::RegexToken*>(nullptr),
				tokens,
				executable,
				executor,
				nullptr
			};
		}

		ErrorArgs ErrorArgs::UnexpectedAstType(collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::IExecutor* executor, Ptr<ParsingAstBase> ast)
		{
			return {
				true,
				ErrorType::UnexpectedAstType,
				ast->codeRange.codeIndex,
				*static_cast<regex::RegexToken*>(nullptr),
				tokens,
				executable,
				executor,
				ast
			};
		}
#if defined (__clang__)
#pragma clang diagnostic pop
#elif defined (__GNUC__)
#pragma GCC diagnostic pop
#endif

		ParsingError ErrorArgs::ToParsingError()
		{
			switch (error)
			{
			case ErrorType::UnrecognizedToken:
				return {
					nullptr,
					{&token,&token},
					WString::Unmanaged(L"Unrecognized token: \"") + WString::CopyFrom(token.reading,token.length) + WString::Unmanaged(L"\".")
				};
			case ErrorType::InvalidToken:
				return {
					nullptr,
					{&token,&token},
					WString::Unmanaged(L"Parser stops at incorrect input: \"") + WString::CopyFrom(token.reading,token.length) + WString::Unmanaged(L"\".")
				};
			case ErrorType::InputIncomplete:
				if (tokens.Count() == 0)
				{
					return {
						nullptr,
						{&tokens[tokens.Count()-1],&tokens[tokens.Count() - 1]},
						L"Input is incomplete."
					};
				}
				else
				{
					return {
						nullptr,
						{{0,0,0},{0,0,0},codeIndex},
						L"Input is incomplete."
					};
				}
			case ErrorType::UnexpectedAstType:
				return {
					nullptr,
					ast->codeRange,
					L"Unexpected type of the created AST."
				};
			default:
				CHECK_FAIL(L"vl::glr::ErrorArgs::ToParsingError()#Unknown error type.");
			}
		}
	}
}

/***********************************************************************
.\JSON\GLRJSON.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace json
		{
			using namespace stream;
			using namespace collections;

/***********************************************************************
JsonUnescapeVisitor
***********************************************************************/

			class JsonUnescapeVisitor : public traverse_visitor::AstVisitor
			{
			protected:
				void Traverse(JsonObjectField* node) override
				{
					node->name.value = GenerateToStream(
						[node](TextWriter& writer)
						{
							JsonUnescapeString(node->name.value.Sub(1, node->name.value.Length() - 2), writer);
						});
				}

				void Traverse(JsonString* node) override
				{
					node->content.value = GenerateToStream(
						[node](TextWriter& writer)
						{
							JsonUnescapeString(node->content.value.Sub(1, node->content.value.Length() - 2), writer);
						});
				}
			};

/***********************************************************************
JsonFormatting
***********************************************************************/

			JsonFormatting::JsonFormatting()
				: indentation(L"  ")
			{
			}

/***********************************************************************
JsonIsCompactVisitor
***********************************************************************/

			class JsonIsCompactVisitorBase : public Object, public JsonNode::IVisitor
			{
			public:
				bool						result = true;

				void Visit(JsonLiteral* node) override
				{
				}

				void Visit(JsonString* node) override
				{
				}

				void Visit(JsonNumber* node) override
				{
				}
			};

			class JsonIsCompactFieldVisitor : public JsonIsCompactVisitorBase
			{
			public:
				void Visit(JsonArray* node) override
				{
					result = node->items.Count() == 0;
				}

				void Visit(JsonObject* node) override
				{
					result = node->fields.Count() == 0;
				}
			};

			class JsonIsCompactVisitor : public JsonIsCompactVisitorBase
			{
			public:
				void Visit(JsonArray* node) override
				{
					for (auto item : node->items)
					{
						JsonIsCompactFieldVisitor visitor;
						item->Accept(&visitor);
						if (!visitor.result)
						{
							result = false;
							break;
						}
					}
				}

				void Visit(JsonObject* node) override
				{
					for (auto field : node->fields)
					{
						JsonIsCompactFieldVisitor visitor;
						field->value->Accept(&visitor);
						if (!visitor.result)
						{
							result = false;
							break;
						}
					}
				}
			};

/***********************************************************************
JsonPrintVisitor
***********************************************************************/

			class JsonPrintVisitor : public Object, public JsonNode::IVisitor
			{
			public:
				JsonFormatting				formatting;
				TextWriter&					writer;
				vint						indent = 0;

				JsonPrintVisitor(JsonFormatting _formatting, TextWriter& _writer)
					: formatting(_formatting)
					, writer(_writer)
				{
				}

				void WriteIndentation()
				{
					for (vint i = 0; i < indent; i++)
					{
						writer.WriteString(formatting.indentation);
					}
				}

				bool IsCompact(JsonNode* node)
				{
					JsonIsCompactVisitor visitor;
					node->Accept(&visitor);
					return visitor.result;
				}

				void Visit(JsonLiteral* node) override
				{
					switch(node->value)
					{
					case JsonLiteralValue::True:
						writer.WriteString(L"true");
						break;
					case JsonLiteralValue::False:
						writer.WriteString(L"false");
						break;
					case JsonLiteralValue::Null:
						writer.WriteString(L"null");
						break;
					default:;
					}
				}

				void Visit(JsonString* node) override
				{
					writer.WriteChar(L'\"');
					JsonEscapeString(node->content.value, writer);
					writer.WriteChar(L'\"');
				}

				void Visit(JsonNumber* node) override
				{
					writer.WriteString(node->content.value);
				}

				void AfterOpeningObject(bool insertCrlf)
				{
					if (insertCrlf)
					{
						writer.WriteString(L"\r\n");
						indent++;
					}
				}

				void BeforeClosingObject(bool insertCrlf)
				{
					if (insertCrlf)
					{
						indent--;
						WriteIndentation();
					}
				}

				void BeforeChildNode(bool insertCrlf)
				{
					if (insertCrlf) WriteIndentation();
				}

				void AfterChildNode(bool insertCrlf, bool lastNode)
				{
					if (!lastNode)
					{
						if ((!insertCrlf || !formatting.crlf) && formatting.spaceAfterComma)
						{
							writer.WriteString(L", ");
						}
						else
						{
							writer.WriteChar(L',');
						}
					}
					if (insertCrlf) writer.WriteString(L"\r\n");
				}

				void Visit(JsonArray* node) override
				{
					writer.WriteChar(L'[');
					if (node->items.Count() > 0)
					{
						bool insertCrlf = formatting.crlf && !(formatting.compact && IsCompact(node));
						AfterOpeningObject(insertCrlf);
						for (auto [item, i] : indexed(node->items))
						{
							BeforeChildNode(insertCrlf);
							item->Accept(this);
							AfterChildNode(insertCrlf, i == node->items.Count() - 1);
						}
						BeforeClosingObject(insertCrlf);
					}
					writer.WriteChar(L']');
				}

				void Visit(JsonObject* node) override
				{
					writer.WriteChar(L'{');
					if (node->fields.Count() > 0)
					{
						bool insertCrlf = formatting.crlf && !(formatting.compact && IsCompact(node));
						AfterOpeningObject(insertCrlf);
						for (auto [field, i] : indexed(node->fields))
						{
							BeforeChildNode(insertCrlf);
							writer.WriteChar(L'\"');
							JsonEscapeString(field->name.value, writer);
							if (formatting.spaceAfterColon)
							{
								writer.WriteString(L"\": ");
							}
							else
							{
								writer.WriteString(L"\":");
							}
							field->value->Accept(this);
							AfterChildNode(insertCrlf, i == node->fields.Count() - 1);
						}
						BeforeClosingObject(insertCrlf);
					}
					writer.WriteChar(L'}');
				}
			};

/***********************************************************************
API
***********************************************************************/

			Ptr<JsonNode> JsonParse(const WString& input, const Parser& parser)
			{
				auto ast = parser.ParseJRoot(input);
				JsonUnescapeVisitor().InspectInto(ast.Obj());
				return ast;
			}

			void JsonPrint(Ptr<JsonNode> node, stream::TextWriter& writer, JsonFormatting formatting)
			{
				JsonPrintVisitor visitor(formatting, writer);
				node->Accept(&visitor);
			}

			WString JsonToString(Ptr<JsonNode> node, JsonFormatting formatting)
			{
				return GenerateToStream([&](StreamWriter& writer)
				{
					JsonPrint(node, writer, formatting);
				});
			}

			void JsonNodeListSerializer::Serialize(Ptr<Parser> parser, const SourceType& source, DestType& dest)
			{
				auto array = Ptr(new JsonArray);
				for (auto&& package : source)
				{
					array->items.Add(package);
				}
				dest = JsonToString(array);
			}

			void JsonNodeListSerializer::Deserialize(Ptr<Parser> parser, const DestType& source, SourceType& dest)
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::json::JsonNodeListSerializer::Deserialize(Ptr<Parser>, const WString&, SourceType&)#"
				auto value = JsonParse(source, *parser.Obj());
				auto array = value.Cast<JsonArray>();
				CHECK_ERROR(array, ERROR_MESSAGE_PREFIX L"The serialized channel package should be a JsonArray.");

				dest.Clear();
				for (auto&& package : array->items)
				{
					dest.Add(package);
				}
#undef ERROR_MESSAGE_PREFIX
			}
		}
	}
}


/***********************************************************************
.\JSON\GENERATED\JSONAST.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json
{
/***********************************************************************
Visitor Pattern Implementation
***********************************************************************/

	void JsonLiteral::Accept(JsonNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void JsonString::Accept(JsonNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void JsonNumber::Accept(JsonNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void JsonArray::Accept(JsonNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void JsonObject::Accept(JsonNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}
}
namespace vl::reflection::description
{
#ifndef VCZH_DEBUG_NO_REFLECTION

	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonNode, system::JsonNode)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonNode::IVisitor, system::JsonNode::IVisitor)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonLiteralValue, system::JsonLiteralValue)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonLiteral, system::JsonLiteral)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonString, system::JsonString)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonNumber, system::JsonNumber)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonArray, system::JsonArray)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonObjectField, system::JsonObjectField)
	IMPL_TYPE_INFO_RENAME(vl::glr::json::JsonObject, system::JsonObject)

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

	BEGIN_CLASS_MEMBER(vl::glr::json::JsonNode)
		CLASS_MEMBER_BASE(vl::glr::ParsingAstBase)

	END_CLASS_MEMBER(vl::glr::json::JsonNode)

	BEGIN_ENUM_ITEM(vl::glr::json::JsonLiteralValue)
		ENUM_ITEM_NAMESPACE(vl::glr::json::JsonLiteralValue)
		ENUM_NAMESPACE_ITEM(True)
		ENUM_NAMESPACE_ITEM(False)
		ENUM_NAMESPACE_ITEM(Null)
	END_ENUM_ITEM(vl::glr::json::JsonLiteralValue)

	BEGIN_CLASS_MEMBER(vl::glr::json::JsonLiteral)
		CLASS_MEMBER_BASE(vl::glr::json::JsonNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::json::JsonLiteral>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(value)
	END_CLASS_MEMBER(vl::glr::json::JsonLiteral)

	BEGIN_CLASS_MEMBER(vl::glr::json::JsonString)
		CLASS_MEMBER_BASE(vl::glr::json::JsonNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::json::JsonString>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(content)
	END_CLASS_MEMBER(vl::glr::json::JsonString)

	BEGIN_CLASS_MEMBER(vl::glr::json::JsonNumber)
		CLASS_MEMBER_BASE(vl::glr::json::JsonNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::json::JsonNumber>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(content)
	END_CLASS_MEMBER(vl::glr::json::JsonNumber)

	BEGIN_CLASS_MEMBER(vl::glr::json::JsonArray)
		CLASS_MEMBER_BASE(vl::glr::json::JsonNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::json::JsonArray>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(items)
	END_CLASS_MEMBER(vl::glr::json::JsonArray)

	BEGIN_CLASS_MEMBER(vl::glr::json::JsonObjectField)
		CLASS_MEMBER_BASE(vl::glr::ParsingAstBase)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::json::JsonObjectField>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(name)
		CLASS_MEMBER_FIELD(value)
	END_CLASS_MEMBER(vl::glr::json::JsonObjectField)

	BEGIN_CLASS_MEMBER(vl::glr::json::JsonObject)
		CLASS_MEMBER_BASE(vl::glr::json::JsonNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::json::JsonObject>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(fields)
	END_CLASS_MEMBER(vl::glr::json::JsonObject)

	BEGIN_INTERFACE_MEMBER(vl::glr::json::JsonNode::IVisitor)
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonLiteral* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonString* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonNumber* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonArray* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::json::JsonNode::IVisitor::*)(vl::glr::json::JsonObject* node))
	END_INTERFACE_MEMBER(vl::glr::json::JsonNode)

#endif

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
	class JsonAstTypeLoader : public vl::Object, public ITypeLoader
	{
	public:
		void Load(ITypeManager* manager)
		{
			ADD_TYPE_INFO(vl::glr::json::JsonNode)
			ADD_TYPE_INFO(vl::glr::json::JsonNode::IVisitor)
			ADD_TYPE_INFO(vl::glr::json::JsonLiteralValue)
			ADD_TYPE_INFO(vl::glr::json::JsonLiteral)
			ADD_TYPE_INFO(vl::glr::json::JsonString)
			ADD_TYPE_INFO(vl::glr::json::JsonNumber)
			ADD_TYPE_INFO(vl::glr::json::JsonArray)
			ADD_TYPE_INFO(vl::glr::json::JsonObjectField)
			ADD_TYPE_INFO(vl::glr::json::JsonObject)
		}

		void Unload(ITypeManager* manager)
		{
		}
	};
#endif
#endif

	bool JsonAstLoadTypes()
	{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
		if (auto manager = GetGlobalTypeManager())
		{
			auto loader = Ptr(new JsonAstTypeLoader);
			return manager->AddTypeLoader(loader);
		}
#endif
		return false;
	}
}


/***********************************************************************
.\JSON\GENERATED\JSONAST_BUILDER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json::builder
{

/***********************************************************************
MakeArray
***********************************************************************/

	MakeArray& MakeArray::items(const vl::Ptr<JsonNode>& value)
	{
		node->items.Add(value);
		return *this;
	}

/***********************************************************************
MakeLiteral
***********************************************************************/

	MakeLiteral& MakeLiteral::value(JsonLiteralValue value)
	{
		node->value = value;
		return *this;
	}

/***********************************************************************
MakeNumber
***********************************************************************/

	MakeNumber& MakeNumber::content(const vl::WString& value)
	{
		node->content.value = value;
		return *this;
	}

/***********************************************************************
MakeObject
***********************************************************************/

	MakeObject& MakeObject::fields(const vl::Ptr<JsonObjectField>& value)
	{
		node->fields.Add(value);
		return *this;
	}

/***********************************************************************
MakeObjectField
***********************************************************************/

	MakeObjectField& MakeObjectField::name(const vl::WString& value)
	{
		node->name.value = value;
		return *this;
	}

	MakeObjectField& MakeObjectField::value(const vl::Ptr<JsonNode>& value)
	{
		node->value = value;
		return *this;
	}

/***********************************************************************
MakeString
***********************************************************************/

	MakeString& MakeString::content(const vl::WString& value)
	{
		node->content.value = value;
		return *this;
	}
}


/***********************************************************************
.\JSON\GENERATED\JSONAST_COPY.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json::copy_visitor
{
	void AstVisitor::CopyFields(JsonArray* from, JsonArray* to)
	{
		CopyFields(static_cast<JsonNode*>(from), static_cast<JsonNode*>(to));
		for (auto&& listItem : from->items)
		{
			to->items.Add(CopyNode(listItem.Obj()));
		}
	}

	void AstVisitor::CopyFields(JsonLiteral* from, JsonLiteral* to)
	{
		CopyFields(static_cast<JsonNode*>(from), static_cast<JsonNode*>(to));
		to->value = from->value;
	}

	void AstVisitor::CopyFields(JsonNode* from, JsonNode* to)
	{
	}

	void AstVisitor::CopyFields(JsonNumber* from, JsonNumber* to)
	{
		CopyFields(static_cast<JsonNode*>(from), static_cast<JsonNode*>(to));
		to->content = from->content;
	}

	void AstVisitor::CopyFields(JsonObject* from, JsonObject* to)
	{
		CopyFields(static_cast<JsonNode*>(from), static_cast<JsonNode*>(to));
		for (auto&& listItem : from->fields)
		{
			to->fields.Add(CopyNode(listItem.Obj()));
		}
	}

	void AstVisitor::CopyFields(JsonObjectField* from, JsonObjectField* to)
	{
		to->name = from->name;
		to->value = CopyNode(from->value.Obj());
	}

	void AstVisitor::CopyFields(JsonString* from, JsonString* to)
	{
		CopyFields(static_cast<JsonNode*>(from), static_cast<JsonNode*>(to));
		to->content = from->content;
	}

	void AstVisitor::Visit(JsonObjectField* node)
	{
		auto newNode = vl::Ptr(new JsonObjectField);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(JsonLiteral* node)
	{
		auto newNode = vl::Ptr(new JsonLiteral);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(JsonString* node)
	{
		auto newNode = vl::Ptr(new JsonString);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(JsonNumber* node)
	{
		auto newNode = vl::Ptr(new JsonNumber);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(JsonArray* node)
	{
		auto newNode = vl::Ptr(new JsonArray);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(JsonObject* node)
	{
		auto newNode = vl::Ptr(new JsonObject);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	vl::Ptr<JsonNode> AstVisitor::CopyNode(JsonNode* node)
	{
		if (!node) return nullptr;
		node->Accept(static_cast<JsonNode::IVisitor*>(this));
		this->result->codeRange = node->codeRange;
		return this->result.Cast<JsonNode>();
	}

	vl::Ptr<JsonObjectField> AstVisitor::CopyNode(JsonObjectField* node)
	{
		if (!node) return nullptr;
		Visit(node);
		this->result->codeRange = node->codeRange;
		return this->result.Cast<JsonObjectField>();
	}

	vl::Ptr<JsonArray> AstVisitor::CopyNode(JsonArray* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<JsonNode*>(node)).Cast<JsonArray>();
	}

	vl::Ptr<JsonLiteral> AstVisitor::CopyNode(JsonLiteral* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<JsonNode*>(node)).Cast<JsonLiteral>();
	}

	vl::Ptr<JsonNumber> AstVisitor::CopyNode(JsonNumber* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<JsonNode*>(node)).Cast<JsonNumber>();
	}

	vl::Ptr<JsonObject> AstVisitor::CopyNode(JsonObject* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<JsonNode*>(node)).Cast<JsonObject>();
	}

	vl::Ptr<JsonString> AstVisitor::CopyNode(JsonString* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<JsonNode*>(node)).Cast<JsonString>();
	}

}


/***********************************************************************
.\JSON\GENERATED\JSONAST_EMPTY.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json::empty_visitor
{

/***********************************************************************
NodeVisitor
***********************************************************************/

	// Visitor Members -----------------------------------

	void NodeVisitor::Visit(JsonLiteral* node)
	{
	}

	void NodeVisitor::Visit(JsonString* node)
	{
	}

	void NodeVisitor::Visit(JsonNumber* node)
	{
	}

	void NodeVisitor::Visit(JsonArray* node)
	{
	}

	void NodeVisitor::Visit(JsonObject* node)
	{
	}
}


/***********************************************************************
.\JSON\GENERATED\JSONAST_JSON.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json::json_visitor
{
	void AstVisitor::PrintFields(JsonArray* node)
	{
		BeginField(vl::WString::Unmanaged(L"items"));
		BeginArray();
		for (auto&& listItem : node->items)
		{
			BeginArrayItem();
			Print(listItem.Obj());
			EndArrayItem();
		}
		EndArray();
		EndField();
	}
	void AstVisitor::PrintFields(JsonLiteral* node)
	{
		BeginField(vl::WString::Unmanaged(L"value"));
		switch (node->value)
		{
		case vl::glr::json::JsonLiteralValue::False:
			WriteString(vl::WString::Unmanaged(L"False"));
			break;
		case vl::glr::json::JsonLiteralValue::Null:
			WriteString(vl::WString::Unmanaged(L"Null"));
			break;
		case vl::glr::json::JsonLiteralValue::True:
			WriteString(vl::WString::Unmanaged(L"True"));
			break;
		default:
			WriteNull();
		}
		EndField();
	}
	void AstVisitor::PrintFields(JsonNode* node)
	{
	}
	void AstVisitor::PrintFields(JsonNumber* node)
	{
		BeginField(vl::WString::Unmanaged(L"content"));
		WriteToken(node->content);
		EndField();
	}
	void AstVisitor::PrintFields(JsonObject* node)
	{
		BeginField(vl::WString::Unmanaged(L"fields"));
		BeginArray();
		for (auto&& listItem : node->fields)
		{
			BeginArrayItem();
			Print(listItem.Obj());
			EndArrayItem();
		}
		EndArray();
		EndField();
	}
	void AstVisitor::PrintFields(JsonObjectField* node)
	{
		BeginField(vl::WString::Unmanaged(L"name"));
		WriteToken(node->name);
		EndField();
		BeginField(vl::WString::Unmanaged(L"value"));
		Print(node->value.Obj());
		EndField();
	}
	void AstVisitor::PrintFields(JsonString* node)
	{
		BeginField(vl::WString::Unmanaged(L"content"));
		WriteToken(node->content);
		EndField();
	}

	void AstVisitor::Visit(JsonLiteral* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Literal"), node);
		PrintFields(static_cast<JsonNode*>(node));
		PrintFields(static_cast<JsonLiteral*>(node));
		EndObject();
	}

	void AstVisitor::Visit(JsonString* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"String"), node);
		PrintFields(static_cast<JsonNode*>(node));
		PrintFields(static_cast<JsonString*>(node));
		EndObject();
	}

	void AstVisitor::Visit(JsonNumber* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Number"), node);
		PrintFields(static_cast<JsonNode*>(node));
		PrintFields(static_cast<JsonNumber*>(node));
		EndObject();
	}

	void AstVisitor::Visit(JsonArray* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Array"), node);
		PrintFields(static_cast<JsonNode*>(node));
		PrintFields(static_cast<JsonArray*>(node));
		EndObject();
	}

	void AstVisitor::Visit(JsonObject* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Object"), node);
		PrintFields(static_cast<JsonNode*>(node));
		PrintFields(static_cast<JsonObject*>(node));
		EndObject();
	}

	AstVisitor::AstVisitor(vl::stream::StreamWriter& _writer)
		: vl::glr::JsonVisitorBase(_writer)
	{
	}

	void AstVisitor::Print(JsonNode* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		node->Accept(static_cast<JsonNode::IVisitor*>(this));
	}

	void AstVisitor::Print(JsonObjectField* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"ObjectField"), node);
		PrintFields(static_cast<JsonObjectField*>(node));
		EndObject();
	}

}


/***********************************************************************
.\JSON\GENERATED\JSONAST_TRAVERSE.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json::traverse_visitor
{
	void AstVisitor::Traverse(vl::glr::ParsingToken& token) {}
	void AstVisitor::Traverse(vl::glr::ParsingAstBase* node) {}
	void AstVisitor::Traverse(JsonArray* node) {}
	void AstVisitor::Traverse(JsonLiteral* node) {}
	void AstVisitor::Traverse(JsonNode* node) {}
	void AstVisitor::Traverse(JsonNumber* node) {}
	void AstVisitor::Traverse(JsonObject* node) {}
	void AstVisitor::Traverse(JsonObjectField* node) {}
	void AstVisitor::Traverse(JsonString* node) {}

	void AstVisitor::Finishing(vl::glr::ParsingAstBase* node) {}
	void AstVisitor::Finishing(JsonArray* node) {}
	void AstVisitor::Finishing(JsonLiteral* node) {}
	void AstVisitor::Finishing(JsonNode* node) {}
	void AstVisitor::Finishing(JsonNumber* node) {}
	void AstVisitor::Finishing(JsonObject* node) {}
	void AstVisitor::Finishing(JsonObjectField* node) {}
	void AstVisitor::Finishing(JsonString* node) {}

	void AstVisitor::Visit(JsonLiteral* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<JsonNode*>(node));
		Traverse(static_cast<JsonLiteral*>(node));
		Finishing(static_cast<JsonLiteral*>(node));
		Finishing(static_cast<JsonNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(JsonString* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<JsonNode*>(node));
		Traverse(static_cast<JsonString*>(node));
		Traverse(node->content);
		Finishing(static_cast<JsonString*>(node));
		Finishing(static_cast<JsonNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(JsonNumber* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<JsonNode*>(node));
		Traverse(static_cast<JsonNumber*>(node));
		Traverse(node->content);
		Finishing(static_cast<JsonNumber*>(node));
		Finishing(static_cast<JsonNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(JsonArray* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<JsonNode*>(node));
		Traverse(static_cast<JsonArray*>(node));
		for (auto&& listItem : node->items)
		{
			InspectInto(listItem.Obj());
		}
		Finishing(static_cast<JsonArray*>(node));
		Finishing(static_cast<JsonNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(JsonObject* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<JsonNode*>(node));
		Traverse(static_cast<JsonObject*>(node));
		for (auto&& listItem : node->fields)
		{
			InspectInto(listItem.Obj());
		}
		Finishing(static_cast<JsonObject*>(node));
		Finishing(static_cast<JsonNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::InspectInto(JsonNode* node)
	{
		if (!node) return;
		node->Accept(static_cast<JsonNode::IVisitor*>(this));
	}

	void AstVisitor::InspectInto(JsonObjectField* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<JsonObjectField*>(node));
		Traverse(node->name);
		InspectInto(node->value.Obj());
		Finishing(static_cast<JsonObjectField*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

}


/***********************************************************************
.\JSON\GENERATED\JSONPARSER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Json
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json
{
	void JsonParserData(vl::stream::IStream& outputStream)
	{
		static const vl::vint dataLength = 1790; // 16729 bytes before compressing
		static const vl::vint dataBlock = 256;
		static const vl::vint dataRemain = 254;
		static const vl::vint dataSolidRows = 6;
		static const vl::vint dataRows = 7;
		static const char* compressed[] = {
			"\x59\x41\x00\x00\xF6\x06\x00\x00\x0C\x00\x01\x82\x80\x06\x03\x82\x81\x82\x06\x89\x82\x87\x0A\x80\x81\x84\x09\x0A\x98\x0A\x9D\x0A\x86\x65\x01\x84\xFF\x19\x9A\x99\x8A\x80\x03\x8D\x8D\x1D\x9D\x97\x89\x83\x96\x81\x93\x81\x02\x0A\xA7\x82\x8F\x8A\x8D\x8F\x96\x1C\x8A\xB0\x9F\x7F\x90\x99\x9B\x96\x37\x9F\x9D\x83\x0A\x92\x84\x03\x9E\x18\xB6\xB2\x82\xA1\xA0\x9F\xA0\xA3\x45\xBA\x87\xAA\xA9\xA0\x93\xA4\xA7\x4D\xAE\x8F\xB2\xA1\xA9\x99\xAA\x9A\x53\xD6\x86\x93\x99\x98\xAA\x83\x02\x40\xDB\x84\xA2\xB8\xA4\xB0\xA6\xB3\x5E\x83\x9C\xB9\xA8\xAF\xA9\xAE\xAA\x68\xF0\xAA\xA3\xB3\xBD\xB1\xBB\xB3\x77\xE9\x87\x81\xB9\xBA\xB8\x96\xBA\x7F\xF6\x81\xD8\xB3\xC2\xBD\x81\xB5\x6E\xEC\xAF\xBA\xAD\xBC\xC5\xC2\xBF\x87\x80\xD1\xC2\xC1\x84\x84\x92\xC5\x98\x89\xDA\xD1\xBE\xC3\xC8\xC2\xCF\x86\x9E\x92\xC2\xD4\xCC\xD3\xCE\xD3\xA1\x88\xDC\xCD\xB6\x80\x04\xBF\xC7\x9D\xA8\xD0\xD2\xD1\xDA\xD5\xC6\xD6\xB7\x8B\xF8\xD0\xDB\xD8\xD3\xD8\xDB\xBC\xBA\xC2\xEA\x89\x07\xD6\xDF\xDA\xA3\xC0\xC7\xFD\xD4\xDC\xE6\xE5\xE6\xC3\x9B\xF9\xD9\xCB\xD1\xE9\xEA\xEA\xD3\xD2\xC1\xF8",
			"\xEB\xEA\xEF\xE4\xEB\xD9\xD7\xC9\x8A\x06\xE0\xE8\xEF\xEF\xE7\xE6\xDE\xEA\xF2\xF5\xF5\xF1\xF7\xDD\xEE\xF1\xF0\xF8\xF3\xF7\x05\xF2\x0E\xA6\x8A\x8D\x05\xF6\x05\xF3\xE7\x0F\x3F\x79\x73\x80\xA5\x50\x05\x79\x04\x02\xA5\x60\x47\x65\xEB\x4F\x7E\x80\x81\xA7\x4F\x85\x6A\x84\x11\x90\x89\x6A\x85\xBF\x58\x88\x73\x84\x1A\x8E\x7D\x84\x78\xF3\x61\x81\x43\x04\x09\x95\x8C\x87\x89\x26\xA9\x87\x84\x8A\xA1\x54\x05\x8B\x8A\x2A\x99\x8C\x8A\x8C\x31\x9B\x85\x8E\x87\x33\xB6\x80\x8F\x8E\x34\xBC\x8A\x8D\x8F\x40\xBF\x82\x90\x8E\x37\xA0\x85\x7E\x7C\x47\xB4\x70\x01\x05\x2F\x81\x94\x92\x8F\x4F\xB3\x66\x05\x93\x43\x86\x9C\x7A\x92\x14\x90\x96\x95\x96\x4E\x96\x97\x04\x95\xCC\x52\x4C\x80\x92\x57\xA2\x85\x99\x92\x66\x9C\x95\x95\x7A\x6A\x91\x9B\x99\x83\x1F\xAC\x93\x69\x06\x60\x96\x9A\x05\x9D\x72\xB9\x8E\x9B\x9E\x5B\xB1\x90\x9D\x69\x1B\x38\x9F\x9D\x91\x79\x84\xA3\xA2\x96\x85\x88\xA7\xA1\x97\x89\x8C\xAB\xA3\x9B\x06\x5C\x05\x78\x45\x63\x83\x4E\x05\x79\x1F\x02\xA6\x40\x08\xE5\x61\x0A\xA6\x92\x22\x25\x73\x0B\xA7\x69\xA3\x64\x09\x79\x25\x25\x76\x09\x79",
			"\x27\x24\xA1\x40\x0A\xAE\xA7\x92\xAD\x0A\xE5\x6A\x01\xAF\x0A\xB1\xAD\x9D\x9E\x9E\xBB\x86\xA4\x9A\xAE\x8D\x90\xA8\x96\x9F\xBF\x84\xB3\x40\x0B\xE5\x6D\x09\xAE\xB1\xA5\xBC\xAA\x42\x0B\xE5\x6F\x05\x78\x0C\xE5\x71\x01\xAE\x0C\xCB\x8E\xB9\x43\x0C\xE5\x74\x09\xB6\xAF\xC3\x9A\xB5\xB2\xB8\xE1\xA0\xBD\xB2\xB9\x01\x75\x0F\xB6\xA2\xE3\xA8\xB2\xAC\xB0\x8F\xBC\x99\x7A\x0D\xEB\x8E\xAD\xB8\xBB\xE5\xB8\xB7\xBA\xBE\x68\x81\x47\x0D\xBD\xC2\xBB\xB6\xBD\xBE\x03\xC2\xC1\xC1\xBF\xEF\x8C\xB8\xC3\x73\x38\x31\xA9\x0C\xC0\xF2\xB1\xBD\xAC\xBF\x09\xE4\xB6\xC1\xC4\xF7\x85\xCB\xC2\xC2\x00\x3A\x00\xC7\xC4\x1A\xD5\xCE\xB8\xBC\x19\xC7\xC0\x03\x0E\x1F\xC1\xB8\xC4\xC1\x26\xE4\xCC\xCB\xCA\x02\x42\x2A\x41\x4A\x57\x6E\xC2\x40\xCD\xAB\x76\xC1\x40\xCE\xB7\x7A\xC0\x00\xCF\xBC\x7E\xC0\xD3\x72\x3E\xEB\x41\x42\xD1\x00\x08\xDF\x4D\xA5\xBC\x60\x5C\xD3\xD1\x0A\x56\x69\xCC\x4C\x48\xC3\xD9\xD2\x4F\x60\x8E\xDA\x7F\xD3\x00\x12\xDD\xCC\xD5\x21\x5C\xDB\xD3\xD6\xAB\x5A\xD3\x40\xD2\x48\xDE\xD1\xD0\x4C\x63\xC3\x4C\x4F\x55\x66\xF7\xC1\xDA\x41\x6A\xC4\xDC\xDA\x42\x08",
			"\x65\xD8\xDF\xDC\x03\x75\xDD\x73\x4C\x56\xF3\x42\xD0\x5B\x83\xF5\xCC\xC5\xE0\x82\xD6\xCB\xCC\xE1\x87\xCC\xEA\xE3\xCF\x8E\xEE\xB8\xE1\xE2\x14\xED\xD2\x41\xDC\xCB\x58\xE0\x02\xE5\x61\xDA\xEA\xE6\xD5\x7E\xD4\xE7\x8D\xD5\x91\xD4\xCA\x6F\xDB\x06\x53\xE2\xE8\xCC\x8B\xC6\xEF\xE0\xE7\x9B\xEC\x5A\xE4\xEA\x67\xD1\xD5\xEA\x93\xB4\xF3\xD0\xE3\xCC\xB7\xE6\xCA\xEA\xE8\x56\xBF\xE4\xE5\xF0\xBD\xEC\xE0\xE6\xEB\x92\xC5\xF6\x97\xE9\xBC\xC8\xF4\xC6\xF0\x89\xC4\xFE\xF1\xC8\xD0\xC2\xE2\xF7\xD4\x8F\xD5\xF5\xE0\xF6\xC9\xD3\xFE\xEE\xF2\xE9\x70\xEA\x6E\xE6\x22\x76\xEE\xF7\x9E\xB9\xE1\xDB\xED\x42\xDA\xCD\xE7\xFB\xF5\x5F\xD9\xF0\xFB\x7A\xED\xF2\xFF\xF9\x7A\xF5\xEE\xB1\xEB\xEA\x19\x7B\xFC\xFE\xFF\xAB\x79\x7F\xF3\x73\x74\x4C\x00\xA2\x76\x80\x94\x69\x7D\x73\x56\x62\x80\x8D\x0D\x81\x23\x0F\x9F\x1E\x02\xB3\x28\x69\x09\xA0\x69\x21\x16\x8D\x25\x05\xEC\x24\x75\xF3\x51\x82\x5D\x7C\x70\x69\x08\xD7\x63\x84\xA4\x5D\x26\x6A\x3B\x23\x84\x09\xA1\x8A\x68\x85\x1A\x71\x6F\xB5\x69\x20\x0C\x82\x28\x69\x19\xA2\x86\x20\x36\x87\x78\x0E\x8A\x2A\x81\x1C\xB5\x85",
			"\x3C\x7E\x69\x6C\x10\xC3\x8C\x7C\xF3\x46\x22\x81\x41\x86\x89\x0C\xE4\x6B\x89\x26\xB2\x68\x83\xE5\x28\x6A\x6B\x09\x25\x39\x11\xA4\x39\x21\xB0\x77\x88\x99\x1D\x28\x0F\xF2\x1D\x21\x50\xEB\x2A\x81\x1E\x65\x36\x6A\x49\x61\x8A\x21\x7A\x05\x3E\x02\xF7\x47\x8D\x84\x3B\x09\x8A\x0A\x28\x43\x7A\x1D\x2C\x0E\x38\x89\x22\x8E\x5B\x8A\x21\x1F\x65\x30\x77\x2F\x73\x8A\x21\x7E\x1C\x8E\x42\x7E\x89\x8F\x84\x3F\x0C\x8C\x0A\x3C\x51\x1B\x86\x20\x10\x35\x8A\x21\x53\x8B\x83\x21\x20\x65\x3C\x06\x15\xB0\x76\x67\x27\x89\x3D\x26\x92\x6D\x79\xD4\x5A\x94\x87\x2A\x7D\x20\xEC\x55\x7A\x84\x00\x1A\x76\x67\x39\x84\x96\x0A\xB9\x8E\x67\x29\x9E\x94\x7E\x29\x63\x3C\xD6\x11\x94\x87\x50\x8A\x26\x3F\x58\x81\x7D\x2C\x86\x2B\x40\x83\x17\x93\x34\x9A\x68\x6A\xCF\x53\x40\x8B\xF5\x3E\x86\x96\x09\x34\x4D\x31\x85\x8A\x21\xFB\x1C\x91\x21\x66\x8F\x94\x99\x55\x8E\x96\x64\x86\x27\x52\x45\x83\x86\xD5\x54\x98\x24\x6B\x83\x22\x91\xD2\x9D\x99\x36\x86\x2C\x9A\x81\x19\x86\x5D\xA1\x43\x9F\x40\x23\x94\x39\x5B\x9E\x9A\x20\xA7\x4A\x9F\x5E\x72\x91\x21\x72\x81\x26\x45\xCF\x86",
			"\x23\xAA\x74\x90\x00\x57\xA2\x9C\x9C\x2E\x8F\x9F\xAB\x1D\x93\x20\x2D\xBF\x9B\x20\xF6\x84\x22\x40\x80\x06\x56\x7E\xB9\x3F\xA0\x02\x26\xA2\x40\x7E\x97\x63\x8E\x08\x59\x97\xF6\x2D\x9D\x3E\x83\x24\x5A\xAE\x4F\x3F\xA1\x02\x38\x95\xC9\x4C\x36\x5A\x7E\x8F\x3A\xA4\x03\x26\x43\x46\x82\x2C\x5A\x8F\xA3\x30\xA5\x02\x2E\x9B\x48\x9D\x2E\x5A\x7E\xB0\xA7\x86\x03\x21\x41\x42\x32\xAF\x65\x8E\x34\x5C\x9F\x3A\xAC\x8A\x40\x2A\xA6\x20\xFE\x2B\xA1\x20\x0D\x6B\x9A\x92\x78\x89\xA5\x85\xA8\x66\xA5\xA5\x2C\xAA\x40\x41\xAD\xA6\x85\x15\x90\xAA\xA7\x3D\x97\x40\x78\x93\xA6\x85\x3D\x04\xA0\x66\x5C\xAB\x3A\x8B\xAF\x06\xB0\x81\x24\xA8\x10\xB7\x9E\x59\xA2\x61\x35\x20\x2B\xAA\xAB\x4F\x86\x22\x58\xE6\x9B\xA1\x21\x2B\xAB\xAE\xAD\x72\xAE\x3B\xC7\xA0\x01\x22\x2B\xAC\x98\xE1\x82\x20\x5E\x80\x03\xB0\x9F\x47\x0B\xAD\x62\x41\xB2\x5A\x89\x20\xB1\xAA\x89\x21\x09\xB1\x43\xB3\x29\x9C\x6A\x09\xB5\xAC\x8A\xB1\x84\xBB\x6C\x5F\xCC\x0B\xAD\x68\xA9\xAB\x49\xB3\x9D\xA9\x42\x4E\x0B\xAC\x6C\x98\xB4\x49\x26\xBC\x60\x14\x6B\xA0\x9D\xCF\xA8\xB7\x88\x0B\xB2\x0B\x5A\xE9",
			"\x97\xB5\xBD\xA2\xB6\x20\x54\x0B\xAD\x3C\xB5\xB9\x21\xC2\x9C\x66\x0A\x6B\xBB\x9C\x6F\xDF\x2B\xA0\x2C\x2B\xA8\x56\xFC\x8F\xB7\x40\x2C\x9C\x62\x2D\x2B\xAD\xA1\x98\xAD\xB2\x40\x24\x4C\xAE\x2E\x20\x93\x3D\x84\x83\x22\x74\x9B\x65\x35\x2F\x31\x51\xBB\x02\x2A\xB9\x45\x8A\x20\x0D\x58\x49\xB3\xAC\x7C\xA1\x0F\x5A\x97\xA2\xA9\x80\x27\xB9\xAE\x8E\xA6\x23\x18\x6B\xAA\x58\xAE\x6F\xB9\x20\xE7\x94\x61\x19\x6B\xA0\x5A\xFB\xB6\xB1\xBE\x03\x27\x0F\x5A\xD2\x5E\xBF\xDE\x8B\xA1\x0D\x6B\xBD\xA1\x7B\x80\x07\xBE\x53\x8B\xA3\x0D\x6B\xA5\xA7\x82\x8D\xCC\xB9\xC7\x6D\x0B\xAD\xD8\x5C\x6B\x65\x83\x2A\x99\xDB\x83\x27\x0D\xB1\x40\x8E\x41\x1D\xC0\xC0\x81\x30\x09\x56\x9E\xA2\x20\x89\xE3\xB9\x21\x38\x31\x54\x52\x06\x37\xA4\x5B\xB3\x32\x0F\xB5\xAD\xA3\xC1\x30\xDB\xAB\x42\xF4\x0B\xAD\x9A\x8B\xC0\x92\xD7\x8B\xA2\x1D\x31\x5D\xB4\x81\x26\xB5\xC4\x01\x37\x0D\xAC\x1E\x55\x94\x99\x0D\xCF\xC9\x61\x66\x86\x30\xD2\xC5\x7D\xB5\xBA\x82\x2D\x28\x99\xCB\x26\xCA\xAE\x6C\x99\x0A\x80\x00\x5F\xC1\xCE\x28\xE3\xC8\x22\xF1\x66\xCD\x23\xE4\x67\x95\x9A\xA5\x90",
		};
		vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);
	}

	const wchar_t* ParserRuleName(vl::vint index)
	{
		static const wchar_t* results[] = {
			L"JLiteral",
			L"JField",
			L"JObject",
			L"JArray",
			L"JValue",
			L"JRoot",
		};
		return results[index];
	}

	const wchar_t* ParserStateLabel(vl::vint index)
	{
		static const wchar_t* results[] = {
			L"[0][JLiteral] BEGIN ",
			L"[1][JLiteral] END [ENDING]",
			L"[2][JLiteral]< \"false\" @ >",
			L"[3][JLiteral]< \"null\" @ >",
			L"[4][JLiteral]< \"true\" @ >",
			L"[5][JLiteral]< NUMBER @ >",
			L"[6][JLiteral]< STRING @ >",
			L"[7][JField] BEGIN ",
			L"[8][JField] END [ENDING]",
			L"[9][JField]< STRING \":\" @ JValue >",
			L"[10][JField]< STRING \":\" JValue @ >",
			L"[11][JField]< STRING @ \":\" JValue >",
			L"[12][JObject] BEGIN ",
			L"[13][JObject] END [ENDING]",
			L"[14][JObject]< \"{\" @ { JField ; \",\" } \"}\" >",
			L"[15][JObject]< \"{\" { JField ; \",\" @ } \"}\" >",
			L"[16][JObject]< \"{\" { JField ; \",\" } \"}\" @ >",
			L"[17][JObject]< \"{\" { JField @ ; \",\" } \"}\" >",
			L"[18][JArray] BEGIN ",
			L"[19][JArray] END [ENDING]",
			L"[20][JArray]< \"[\" @ { JValue ; \",\" } \"]\" >",
			L"[21][JArray]< \"[\" { JValue ; \",\" @ } \"]\" >",
			L"[22][JArray]< \"[\" { JValue ; \",\" } \"]\" @ >",
			L"[23][JArray]< \"[\" { JValue @ ; \",\" } \"]\" >",
			L"[24][JValue] BEGIN ",
			L"[25][JValue] END [ENDING]",
			L"[26][JValue]<! !JArray @ !>",
			L"[27][JValue]<! !JLiteral @ !>",
			L"[28][JValue]<! !JObject @ !>",
			L"[29][JRoot] BEGIN ",
			L"[30][JRoot] END [ENDING]",
			L"[31][JRoot]<! !JArray @ !>",
			L"[32][JRoot]<! !JObject @ !>",
		};
		return results[index];
	}

	Parser::Parser()
		: vl::glr::ParserBase<JsonTokens, ParserStates, JsonAstInsReceiver>(&JsonTokenDeleter, &JsonLexerData, &JsonParserData)
	{
	}

	vl::WString Parser::GetClassName(vl::vint32_t classIndex) const
	{
		return vl::WString::Unmanaged(JsonTypeName((JsonClasses)classIndex));
	}

	vl::vint32_t Parser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const
	{
		return -1;
	}

	vl::Ptr<vl::glr::json::JsonNode> Parser::ParseJRoot(const vl::WString& input, vl::vint codeIndex) const
	{
		 return ParseWithString<vl::glr::json::JsonNode, ParserStates::JRoot>(input, this, codeIndex);
	}

	vl::Ptr<vl::glr::json::JsonNode> Parser::ParseJRoot(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex) const
	{
		 return ParseWithTokens<vl::glr::json::JsonNode, ParserStates::JRoot>(tokens, this, codeIndex);
	}
}


/***********************************************************************
.\JSON\GENERATED\JSON_ASSEMBLER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Json
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json
{

/***********************************************************************
JsonAstInsReceiver : public vl::glr::AstInsReceiverBase
***********************************************************************/

	vl::Ptr<vl::glr::ParsingAstBase> JsonAstInsReceiver::CreateAstNode(vl::vint32_t type)
	{
		auto cppTypeName = JsonCppTypeName((JsonClasses)type);
		switch((JsonClasses)type)
		{
		case JsonClasses::Array:
			return vl::Ptr(new vl::glr::json::JsonArray);
		case JsonClasses::Literal:
			return vl::Ptr(new vl::glr::json::JsonLiteral);
		case JsonClasses::Number:
			return vl::Ptr(new vl::glr::json::JsonNumber);
		case JsonClasses::Object:
			return vl::Ptr(new vl::glr::json::JsonObject);
		case JsonClasses::ObjectField:
			return vl::Ptr(new vl::glr::json::JsonObjectField);
		case JsonClasses::String:
			return vl::Ptr(new vl::glr::json::JsonString);
		default:
			return vl::glr::AssemblyThrowCannotCreateAbstractType(type, cppTypeName);
		}
	}

	void JsonAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr<vl::glr::ParsingAstBase> value)
	{
		auto cppFieldName = JsonCppFieldName((JsonFields)field);
		switch((JsonFields)field)
		{
		case JsonFields::Array_items:
			return vl::glr::AssemblerSetObjectField(&vl::glr::json::JsonArray::items, object, field, value, cppFieldName);
		case JsonFields::Object_fields:
			return vl::glr::AssemblerSetObjectField(&vl::glr::json::JsonObject::fields, object, field, value, cppFieldName);
		case JsonFields::ObjectField_value:
			return vl::glr::AssemblerSetObjectField(&vl::glr::json::JsonObjectField::value, object, field, value, cppFieldName);
		default:
			return vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName);
		}
	}

	void JsonAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex)
	{
		auto cppFieldName = JsonCppFieldName((JsonFields)field);
		switch((JsonFields)field)
		{
		case JsonFields::Number_content:
			return vl::glr::AssemblerSetTokenField(&vl::glr::json::JsonNumber::content, object, field, token, tokenIndex, cppFieldName);
		case JsonFields::ObjectField_name:
			return vl::glr::AssemblerSetTokenField(&vl::glr::json::JsonObjectField::name, object, field, token, tokenIndex, cppFieldName);
		case JsonFields::String_content:
			return vl::glr::AssemblerSetTokenField(&vl::glr::json::JsonString::content, object, field, token, tokenIndex, cppFieldName);
		default:
			return vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName);
		}
	}

	void JsonAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem, bool weakAssignment)
	{
		auto cppFieldName = JsonCppFieldName((JsonFields)field);
		switch((JsonFields)field)
		{
		case JsonFields::Literal_value:
			return vl::glr::AssemblerSetEnumField(&vl::glr::json::JsonLiteral::value, object, field, enumItem, weakAssignment, cppFieldName);
		default:
			return vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName);
		}
	}

	const wchar_t* JsonTypeName(JsonClasses type)
	{
		const wchar_t* results[] = {
			L"Array",
			L"Literal",
			L"Node",
			L"Number",
			L"Object",
			L"ObjectField",
			L"String",
		};
		vl::vint index = (vl::vint)type;
		return 0 <= index && index < 7 ? results[index] : nullptr;
	}

	const wchar_t* JsonCppTypeName(JsonClasses type)
	{
		const wchar_t* results[] = {
			L"vl::glr::json::JsonArray",
			L"vl::glr::json::JsonLiteral",
			L"vl::glr::json::JsonNode",
			L"vl::glr::json::JsonNumber",
			L"vl::glr::json::JsonObject",
			L"vl::glr::json::JsonObjectField",
			L"vl::glr::json::JsonString",
		};
		vl::vint index = (vl::vint)type;
		return 0 <= index && index < 7 ? results[index] : nullptr;
	}

	const wchar_t* JsonFieldName(JsonFields field)
	{
		const wchar_t* results[] = {
			L"Array::items",
			L"Literal::value",
			L"Number::content",
			L"Object::fields",
			L"ObjectField::name",
			L"ObjectField::value",
			L"String::content",
		};
		vl::vint index = (vl::vint)field;
		return 0 <= index && index < 7 ? results[index] : nullptr;
	}

	const wchar_t* JsonCppFieldName(JsonFields field)
	{
		const wchar_t* results[] = {
			L"vl::glr::json::JsonArray::items",
			L"vl::glr::json::JsonLiteral::value",
			L"vl::glr::json::JsonNumber::content",
			L"vl::glr::json::JsonObject::fields",
			L"vl::glr::json::JsonObjectField::name",
			L"vl::glr::json::JsonObjectField::value",
			L"vl::glr::json::JsonString::content",
		};
		vl::vint index = (vl::vint)field;
		return 0 <= index && index < 7 ? results[index] : nullptr;
	}

	vl::Ptr<vl::glr::ParsingAstBase> JsonAstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& candidates)
	{
		auto cppTypeName = JsonCppTypeName((JsonClasses)type);
		return vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName);
	}
}


/***********************************************************************
.\JSON\GENERATED\JSON_LEXER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Json
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::json
{
	bool JsonTokenDeleter(vl::vint token)
	{
		switch((JsonTokens)token)
		{
		case JsonTokens::SPACE:
			return true;
		default:
			return false;
		}
	}

	const wchar_t* JsonTokenId(JsonTokens token)
	{
		static const wchar_t* results[] = {
			L"TRUE_VALUE",
			L"FALSE_VALUE",
			L"NULL_VALUE",
			L"OBJOPEN",
			L"OBJCLOSE",
			L"ARROPEN",
			L"ARRCLOSE",
			L"COMMA",
			L"COLON",
			L"NUMBER",
			L"STRING",
			L"SPACE",
		};
		vl::vint index = (vl::vint)token;
		return 0 <= index && index < JsonTokenCount ? results[index] : nullptr;
	}

	const wchar_t* JsonTokenDisplayText(JsonTokens token)
	{
		static const wchar_t* results[] = {
			L"true",
			L"false",
			L"null",
			L"{",
			L"}",
			L"[",
			L"]",
			L",",
			L":",
			nullptr,
			nullptr,
			nullptr,
		};
		vl::vint index = (vl::vint)token;
		return 0 <= index && index < JsonTokenCount ? results[index] : nullptr;
	}

	const wchar_t* JsonTokenRegex(JsonTokens token)
	{
		static const wchar_t* results[] = {
			L"true",
			L"false",
			L"null",
			L"\\{",
			L"\\}",
			L"\\[",
			L"\\]",
			L",",
			L":",
			L"[\\-]?\\d+(.\\d+)?([eE][+\\-]?\\d+)?",
			L"\"([^\\\\\"]|\\\\[^u]|\\\\u\\d{4})*\"",
			L"\\s+",
		};
		vl::vint index = (vl::vint)token;
		return 0 <= index && index < JsonTokenCount ? results[index] : nullptr;
	}

	void JsonLexerData(vl::stream::IStream& outputStream)
	{
		static const vl::vint dataLength = 690; // 7754 bytes before compressing
		static const vl::vint dataBlock = 256;
		static const vl::vint dataRemain = 178;
		static const vl::vint dataSolidRows = 2;
		static const vl::vint dataRows = 3;
		static const char* compressed[] = {
			"\x4A\x1E\x00\x00\xAA\x02\x00\x00\x2A\x00\x01\xAB\x01\x84\x81\x80\x81\x80\x01\x04\x88\x04\x89\x04\x84\x82\x05\x0F\x84\x8B\x04\x8C\x04\x81\x06\x8B\x04\x8E\x04\x9F\x04\x80\x11\x8E\x82\x21\x20\x84\x82\x13\x94\x83\x10\x82\x07\x80\x03\x82\x84\x84\x15\x96\x82\x2D\x30\x84\x8E\x13\x9C\x83\x16\x9B\x04\xB0\x04\x99\x14\x82\x1D\x9E\x82\x3B\x04\x84\x24\x85\x24\xA0\x82\x23\x04\xDA\x04\x9B\x2B\xA4\x80\x2E\xA7\x04\xDD\x11\xA4\x8E\x2C\x80\x30\x82\x61\x58\x84\x82\x34\x84\x30\x83\x32\x5F\x84\xA6\x22\xB4\x87\x30\x83\x35\x04\xEC\x29\xA4\x8D\x34\xB4\x82\x37\x6F\x84\xAF\x24\x81\x3C\x82\x38\xBB\x04\xF3\x39\xA4\x84\x3C\xBC\x83\x3A\x7F\x84\xB6\x24\x8A\x3C\x83\x3C\xC3\x04\xFC\x09\xC4\x8D\x3C\xC4\x82\x3F\x04\xFF\x7F\x70\x00\x02\xCA\xC9\x8B\x01\x98\xD5\xD6\xCA\xCE\xCB\x7F\xCE\x96\x95\x81\x9E\xCE\xCB\x85\x80\x88\xA3\xA4\xD2\xD3\x81\x85\x85\xD4\xD5\x9E\x86\x11\xD6\xC7\x03\xD8\xD8\xD8\x02\x36\xF7\xDF\x73\x02\xDF\xDB\x84\xAF\xA4\xC4\x1A\xD5\x06\xDF\xDD\xE3\xC8\xC9\xCA\xEB\xEC\xE5\xE6\xE7\xE7\x1A\xC1\xCF\xF3\xE4\xED\xEA\xEB\xEB\xA4\x8F\x06\xF8",
			"\xEC\xED\xEE\xEF\xEF\xE0\xE1\xD5\xF4\xC2\xEA\xF2\xF3\xF3\xE8\xE9\xEA\xEB\xFC\xF5\xF6\xF7\xF7\xF0\xF1\xF2\xF3\xF4\xFD\xFA\xFB\xFB\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xF4\xD6\x9B\x7E\x72\x83\x7C\x12\x3A\x61\x07\x76\xFF\x13\x08\x80\x75\x0A\xA5\x73\x80\x05\x04\x50\x81\x42\x84\x00\x14\x86\x85\x84\x18\x81\x46\x05\x86\x15\x9C\x87\x87\x84\x1E\xA1\x80\x8B\x88\x00\x15\x02\x89\x87\x24\x9F\x88\x8B\x8A\x2A\xAD\x87\x8A\x8B\x29\x88\x87\x04\x41\x33\x81\x75\x8D\x80\xFF\x37\x83\x83\x8E\x3C\xBD\x88\x7C\x06\x0B\xBE\x82\x92\x6A\x19\x01\x93\x93\x91\xE0\x5A\x06\x90\x92\xDE\x45\x81\x73\x81\x0E\x89\x8B\x91\x73\x0D\xB8\x8C\x93\x7E\x1B\x13\x97\x94\x93\x1C\x3A\x6D\x95\x94\x1D\x1A\x9B\x94\x77\x30\xAC\x8F\x88\x41\x1B\xB1\x8A\x9A\x99\x6B\xA5\x94\x86\x89\x6D\xA7\x91\x9F\x9C\x6C\xB5\x9E\x9A\x6E\x1E\x04\x49\x9D\x40\x7B\x80\x0D\x9F\x9F\x7A\x81\xAC\x9E\xA0\x7E\x84\xA0\xA3\xA0\x88\x85\xA9\xA3\xA1\x8A\x8D\xAC\xA3\xA3\x86\x91\xAB\xA2\xA4\x8D\x9C\x43\xA7\xA5\x8D\xA3\x9A\xA5\x7B\x37\xBA\x86\x66\xA7\x92\x60\xAB\xA7\xA8\xA4\x9D\x7E\x45\x94\xA5\xA9\xAF\x79\x48",
			"\xA8\xAA\xAE\x8C\x49\xAD\xAE\xA8\x77\x49\x51\x95\x9F\x76\xAD\xB2\xB2\x71\x99\xAC\xB9\xAA\xA4\x0A\x98\xBD\x89\x77\x9C\x9D\x14\xA9\x96\x9E\x9C\xC7\xB4\x90\x9D\xB2\xCC\x83\xBD\xB0\xB2\x65\x83\x95\x08\xB0\xC1\x95\xB6\xB7\xB5\xE8\x66\x04\xB4\xB6\xDC\x9D\xBF\x70\xAD\x56\x96\x68\xAD\x77\xE3\x9E\xB6\x7B\xAF\xBC\xA6\xB8\x93\x09\xDB\xAA\xBE\xBB\xBB\xF4\x68\x0D\xB8\xBC\xFD\x69\x03\xBD\xB7\xCE\x8E\xB6\xB1\xBE\xD0\x88\xBB\xB0\xBF\xC4\xBD\xB1\xC0\x9D\x9E\x70\x3B\x0A\x30\x28\x12\x59\x49\x41\xA2\x40\x0D\xC1\xC3\xBD\x41\x43\x71\x40\xC5\x41\x42\x6D\x40\xB5\x41\x46\x6A\xC3\x0E\x41\x4D\xC0\x80\x0F\xD4\x4D\xC4\xC7\x1E\xE2\xC5\xCB\x69\x12\x66\xC4\xCB\xCA\xAE\x6C\xCA\xC9\xC3\x0C\xC4\x49\x6D\x6B\x23\xCD\xC0\x73\xCA\x21\xC1\x40",
		};
		vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);
	}
}


/***********************************************************************
.\TRACEMANAGER\TMINPUT.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
			using namespace collections;

/***********************************************************************
Initialize
***********************************************************************/

			void TraceManager::Initialize(vint32_t startState)
			{
				state = TraceManagerState::WaitingForInput;

				returnStacks.Clear();
				traces.Clear();
				competitions.Clear();
				attendingCompetitions.Clear();

				traces1.Clear();
				traces2.Clear();
				concurrentTraces = &traces1;
				backupTraces = &traces2;

				activeCompetitions = nullref;
				initialReturnStackCache = {};

				temporaryConditionStack.Clear();
				temporaryConditionStackSize = 0;
				MergeStack_MagicCounter = 0;

				traceExecs.Clear();
				insExecs.Resize(0);
				insExec_Stacks.Clear();
				insExec_InsRefLinks.Clear();
				insExec_StackRefLinks.Clear();
				insExec_StackArrayRefLinks.Clear();

				firstBranchTrace = nullref;
				firstMergeTrace = nullref;
				firstStack = nullref;
				firstStep = nullref;
				traceAmbiguities.Clear();
				traceAmbiguityLinks.Clear();
				executionSteps.Clear();

				initialTrace = AllocateTrace();
				initialTrace->state = startState;
				concurrentCount = 1;
				concurrentCountBeforeError.Reset();
				concurrentTraces->Add(initialTrace);
			}

/***********************************************************************
GetInitialTrace
***********************************************************************/

			Trace* TraceManager::GetInitialTrace()
			{
				return initialTrace;
			}

/***********************************************************************
GetInitialTrace
***********************************************************************/

			ExecutionStep* TraceManager::GetInitialExecutionStep()
			{
				return firstStep == nullref ? nullptr : GetExecutionStep(firstStep);
			}

/***********************************************************************
Input
***********************************************************************/

			bool TraceManager::Input(vint32_t currentTokenIndex, regex::RegexToken* token, regex::RegexToken* lookAhead)
			{
				CHECK_ERROR(state == TraceManagerState::WaitingForInput, L"vl::glr::automaton::TraceManager::Input(vint, vint)#Wrong timing to call this function.");
				vint32_t traceCount = concurrentCount;
				vint32_t input = Executable::TokenBegin + (vint32_t)token->token;

				BeginSwap();

				// for each surviving trace
				// step one TokenInput transition
				// followed by multiple and EndingInput, LeftrecInput and their combination
				// one surviving trace could create multiple surviving trace
				for (vint32_t traceIndex = 0; traceIndex < traceCount; traceIndex++)
				{
					auto currentTrace = concurrentTraces->Get(traceIndex);
					auto stateTrace = EnsureTraceWithValidStates(currentTrace);
					vint32_t transitionIndex = executable.GetTransitionIndex(stateTrace->state, input);
					auto&& edgeArray = executable.transitions[transitionIndex];
					WalkAlongTokenEdges(currentTokenIndex, input, token, lookAhead, { currentTrace, stateTrace }, edgeArray);
				}

				// if competitions happen between new surviving traces
				// remove traces that known to have lost the competition
				if (CheckBackupTracesBeforeSwapping(currentTokenIndex))
				{
					// after competition are closed
					// different surviving traces might be mergable
					// merge them and remove unnecessary traces
					TryMergeSurvivingTraces();
				}

				EndSwap();

				// if there are unused spaces in concurrentTraces
				// set them to nullptr to clear out traces from the last round
				for (vint32_t traceIndex = concurrentCount; traceIndex < concurrentTraces->Count(); traceIndex++)
				{
					concurrentTraces->Set(traceIndex, nullptr);
				}

				if (concurrentCount == 0)
				{
					bool ambiguityInvolved = false;
					concurrentCountBeforeError = traceCount;
					FillSuccessorsAfterEndOfInput(ambiguityInvolved);
				}
				return concurrentCount > 0;
			}

/***********************************************************************
FillSuccessorsAfterEndOfInput
***********************************************************************/

			void TraceManager::FillSuccessorsAfterEndOfInput(bool& ambiguityInvolved)
			{
				ambiguityInvolved = false;
				List<Trace*> visiting;

				if (concurrentCountBeforeError)
				{
					for (vint i = 0; i < concurrentCountBeforeError.Value(); i++)
					{
						visiting.Add(backupTraces->Get(i));
					}
				}
				else
				{
					// create a merge trace for multiple surviving traces
					if (concurrentCount > 1)
					{
						auto newTrace = GetTrace(traces.Allocate());
						for (vint32_t traceIndex = 0; traceIndex < concurrentCount; traceIndex++)
						{
							auto trace = concurrentTraces->Get(traceIndex);
							auto first = trace;
							auto last = trace;

							if (trace->state == -1)
							{
								// a surviving trace could also be a merge trace
								// in this case we move predecessors to the new trace
								first = GetTrace(trace->predecessors.first);
								last = GetTrace(trace->predecessors.last);
							}

							if (newTrace->predecessors.first == nullref)
							{
								newTrace->predecessors.first = first;
								newTrace->predecessors.last = last;
							}
							else
							{
								GetTrace(newTrace->predecessors.last)->predecessors.siblingNext = first;
								first->predecessors.siblingPrev = newTrace->predecessors.last;
								newTrace->predecessors.last = last;
							}
						}
						BeginSwap();
						AddTrace(newTrace);
						EndSwap();
					}
					visiting.Add(concurrentTraces->Get(0));
				}

				// fill successors based on predecessors
				bool initialTraceVisited = false;
				while (visiting.Count() > 0)
				{
					auto current = visiting[visiting.Count() - 1];
					visiting.RemoveAt(visiting.Count() - 1);

					// if (current->predecessorCount != 0)
					// it means this trace has been processed when comming from another sibling
					// but initialTrace->predecessorCount is always 0
					// so initialTraceVisited is introduced
					if (current == initialTrace)
					{
						if (initialTraceVisited) continue;
						initialTraceVisited = true;
					}
					else if (current->predecessorCount != 0)
					{
						continue;
					}

					// fill successors
					{
						auto predecessorId = current->predecessors.first;
						while (predecessorId != nullref)
						{
							auto predecessor = GetTrace(predecessorId);
							predecessorId = predecessor->predecessors.siblingNext;
							current->predecessorCount++;
							predecessor->successorCount++;
							AddTraceToCollection(predecessor, current, &Trace::successors);
						}
					}

					// add predecessors to the list to continue
					{
						auto predecessorId = current->predecessors.last;
						while (predecessorId != nullref)
						{
							auto predecessor = GetTrace(predecessorId);
							predecessorId = predecessor->predecessors.siblingPrev;
							visiting.Add(predecessor);
						}
					}

					// set ambiguityInvolved when a trace has multiple predecessors
					if (current->predecessorCount > 1)
					{
						ambiguityInvolved = true;
					}
				}
			}

/***********************************************************************
EndOfInput
***********************************************************************/

			bool TraceManager::EndOfInput(bool& ambiguityInvolved)
			{
				CHECK_ERROR(state == TraceManagerState::WaitingForInput, L"vl::glr::automaton::TraceManager::EndOfInput()#Wrong timing to call this function.");
				state = TraceManagerState::Finished;

				vint32_t traceCount = concurrentCount;
				BeginSwap();

				// check all surviving traces and remove all that
				//   1) does not stay in an ending state
				//   2) return stack is not empty
				// the remaining are all traces that successfully walked to the ending state of the root rule
				for (vint32_t traceIndex = 0; traceIndex < traceCount; traceIndex++)
				{
					auto trace = concurrentTraces->Get(traceIndex);
					auto actualTrace = EnsureTraceWithValidStates(trace);
					auto& stateDesc = executable.states[actualTrace->state];
					if (actualTrace->returnStack == nullref && stateDesc.endingState)
					{
						AddTrace(trace);
					}
				}

				EndSwap();
				if (concurrentCount == 0)
				{
					concurrentCountBeforeError = traceCount;
					FillSuccessorsAfterEndOfInput(ambiguityInvolved);
					return false;
				}

				FillSuccessorsAfterEndOfInput(ambiguityInvolved);
				if (!ambiguityInvolved)
				{
					state = TraceManagerState::ResolvedAmbiguity;
					auto step = GetExecutionStep(executionSteps.Allocate());
					firstStep = step;

					auto lastTrace = concurrentTraces->Get(0);
					TraceInsLists insList;
					ReadInstructionList(lastTrace, insList);

					step->et_i.startTrace = initialTrace->allocatedIndex;
					step->et_i.startIns = 0;
					step->et_i.endTrace = lastTrace->allocatedIndex;
					step->et_i.endIns = insList.countAll - 1;
				}
				return initialTrace;
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMINPUT_AMBIGUITY.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
			using namespace collections;

/***********************************************************************
EnsureTraceWithValidStates
***********************************************************************/

			Trace* TraceManager::EnsureTraceWithValidStates(Trace* trace)
			{
				if (trace->state == -1)
				{
					return GetTrace(trace->predecessors.first);
				}
				else
				{
					return trace;
				}
			}

/***********************************************************************
AreTwoEndingInputTraceEqual
***********************************************************************/

			bool TraceManager::AreTwoEndingInputTraceEqual(Trace* newTrace, Trace* candidate)
			{
				// two traces equal to each other if
				//   1) they are in the same state
				//   2) they have the same executedReturnStack and returnStack
				//   3) they are attending same competitions
				//   4) they have the same switchValues
				//   5) the candidate has an ending input

				candidate = EnsureTraceWithValidStates(candidate);

				if (candidate->byInput != Executable::EndingInput) return false;
				if (newTrace->state != candidate->state) return false;
				if (newTrace->executedReturnStack != candidate->executedReturnStack) return false;
				if (newTrace->returnStack != candidate->returnStack) return false;
				if (newTrace->competitionRouting.attendingCompetitions != candidate->competitionRouting.attendingCompetitions) return false;
				return true;
			}

/***********************************************************************
MergeTwoEndingInputTrace
***********************************************************************/

			Trace* TraceManager::MergeTwoEndingInputTrace(Trace* newTrace, Trace* candidate)
			{
				// goal of this function is to create a structure
				// NEWTRACE ---+->AMBIGUITY
				//             |
				// CANDIDATE --+

				// if CANDIDATE is not a merged trace
				// a former trace will copy CANDIDATE and insert before CANDIDATE
				// and CANDIDATE will be initialized to an empty trace

				// if a former trace is created to replace the candidate
				// in which case the candidate becomes a merge trace
				// the former trace is returned

				if (candidate->state == -1)
				{
					AddTraceToCollection(candidate, newTrace, &Trace::predecessors);
					return nullptr;
				}
				else
				{
					auto formerTrace = AllocateTrace();
					auto formerTraceId = formerTrace->allocatedIndex;
					auto candidateId = candidate->allocatedIndex;

					*formerTrace = *candidate;
					formerTrace->allocatedIndex = formerTraceId;

					*candidate = {};
					candidate->allocatedIndex = candidateId;

					AddTraceToCollection(candidate, formerTrace, &Trace::predecessors);
					AddTraceToCollection(candidate, newTrace, &Trace::predecessors);
					return formerTrace;
				}
			}

/***********************************************************************
TryMergeSurvivingTraces
***********************************************************************/

			void TraceManager::TryMergeSurvivingTraces()
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::TryMergeSurvivingTraces()#"
				if (concurrentCount == 0) return;

				struct EndingOrMergeTraceData
				{
					bool			surviving = true;			// becomes false when this trace does not survive anymore
				};

				vint32_t removedTracesCount = 0;
				Dictionary<Trace*, EndingOrMergeTraceData> endingOrMergeTraces;
				Group<vint32_t, Trace*> endingOrMergeTracesByState;

				// index surviving traces
				for (vint32_t i = 0; i < concurrentCount; i++)
				{
					auto trace = backupTraces->Get(i);
					endingOrMergeTraces.Add(trace, {});

					if (trace->state == -1)
					{
						endingOrMergeTracesByState.Add(EnsureTraceWithValidStates(trace)->state, trace);
					}
					else if (trace->byInput == Executable::EndingInput)
					{
						endingOrMergeTracesByState.Add(trace->state, trace);
					}
				}

#if defined VCZH_MSVC && defined _DEBUG
				// check assumptions
				for (vint32_t i = 0; i < concurrentCount; i++)
				{
					auto trace = backupTraces->Get(i);
					if (trace->state == -1)
					{
						auto predecessorId = trace->predecessors.first;
						while (predecessorId != nullref)
						{
							auto predecessor = GetTrace(predecessorId);
							predecessorId = predecessor->predecessors.siblingNext;

							CHECK_ERROR(endingOrMergeTraces.Keys().IndexOf(predecessor) == -1, ERROR_MESSAGE_PREFIX L"Internal error: Predecessors of a merge trace should not survive.");
						}
					}
					else if (trace->byInput == Executable::EndingInput)
					{
						CHECK_ERROR(trace->predecessors.first == trace->predecessors.last, ERROR_MESSAGE_PREFIX L"Internal error: Executable::EndingInput trace could not have multiple predecessors.");
					}
				}
#endif

				// unsurvive a trace
				auto unsurviveTrace = [&](Trace* trace, EndingOrMergeTraceData& data)
				{
					if (data.surviving)
					{
						data.surviving = false;
						removedTracesCount++;
					}
				};

				// check if a trace survived
				// if an Executable::EndingInput trace survived but its only predecessor does not
				// it becomes not survived
				auto ensureEndingTraceSurvived = [&](Trace* trace)
				{
					if (trace == initialTrace) return true;

					auto& data = const_cast<EndingOrMergeTraceData&>(endingOrMergeTraces[trace]);
					if (!data.surviving) return false;

					if (trace->state != -1)
					{
						auto predecessorId = trace->predecessors.first;
						if (predecessorId != nullref)
						{
							auto predecessor = GetTrace(predecessorId);
							if (!endingOrMergeTraces[predecessor].surviving)
							{
								unsurviveTrace(trace, data);
							}
						}
					}
					return data.surviving;
				};

				// find surviving traces that merge
				for (vint32_t i = 0; i < concurrentCount; i++)
				{
					// get the next surviving Executable::EndingInput trace
					auto trace = backupTraces->Get(i);
					if (trace->state != -1 && trace->byInput != Executable::EndingInput) continue;
					if (!ensureEndingTraceSurvived(trace)) continue;
					auto realTrace = EnsureTraceWithValidStates(trace);

					// find all traces Executable::EndingInput traces with the same state that after it
					auto&& candidates = endingOrMergeTracesByState[realTrace->state];
					vint index = candidates.IndexOf(trace);
					for (vint j = index + 1; j < candidates.Count(); j++)
					{
						// ensure the candidate also survived
						auto candidate = candidates[j];
						if (!ensureEndingTraceSurvived(candidate)) continue;
						auto realCandidate = EnsureTraceWithValidStates(candidate);

						if (AreTwoEndingInputTraceEqual(realTrace, realCandidate))
						{
							// merge two traces
							if (trace == realTrace)
							{
								// if trace is an ordinary trace
								if (candidate == realCandidate)
								{
									// if candidate is an ordinary trace
									// turn trace into a merge trace
									auto formerTrace = MergeTwoEndingInputTrace(candidate, trace);
									CHECK_ERROR(formerTrace != nullptr, ERROR_MESSAGE_PREFIX L"Internal error: formerTrace should not be null.");
									realTrace = formerTrace;
								}
								else
								{
									// if candidate is a merge trace
									// turn trace into a merge trace
									// give the rest of predecessors of candidate to trace
									auto candidateHead = GetTrace(candidate->predecessors.first);
									auto candidateNextId = candidateHead->predecessors.siblingNext;

									candidateHead->predecessors.siblingNext = nullref;
									auto formerTrace = MergeTwoEndingInputTrace(candidateHead, trace);
									CHECK_ERROR(formerTrace != nullptr, ERROR_MESSAGE_PREFIX L"Internal error: formerTrace should not be null.");
									realTrace = formerTrace;

									candidateHead->predecessors.siblingNext = candidateNextId;
									trace->predecessors.last = candidate->predecessors.last;
									candidate->predecessors.first = nullref;
									candidate->predecessors.last = nullref;
								}
							}
							else
							{
								// if trace is a merge trace
								if (candidate == realCandidate)
								{
									// if candidate is an ordinary trace
									// merge candidate into trace
									auto formerTrace = MergeTwoEndingInputTrace(candidate, trace);
									CHECK_ERROR(formerTrace == nullptr, ERROR_MESSAGE_PREFIX L"Internal error: formerTrace should be null.");
								}
								else
								{
									// if candidate is an ordinary trace
									// give all predecessors of candidate to trace
									auto traceTail = GetTrace(trace->predecessors.last);
									auto candidateHead = GetTrace(candidate->predecessors.first);

									traceTail->predecessors.siblingNext = candidateHead;
									candidateHead->predecessors.siblingPrev = traceTail;

									trace->predecessors.last = candidate->predecessors.last;
									candidate->predecessors.first = nullref;
									candidate->predecessors.last = nullref;
								}
							}

							auto& data = const_cast<EndingOrMergeTraceData&>(endingOrMergeTraces[candidate]);
							unsurviveTrace(candidate, data);
						}
					}
				}

				if (removedTracesCount > 0)
				{
					// mark all unsurviving traces
					for (vint32_t i = 0; i < concurrentCount; i++)
					{
						auto trace = backupTraces->Get(i);
						vint index = endingOrMergeTraces.Keys().IndexOf(trace);
						if (index == -1) continue;
						if (endingOrMergeTraces.Values()[index].surviving) continue;
						backupTraces->Set(i, nullptr);
					}

					// clean up surviving trace list
					vint writing = 0;
					for (vint32_t i = 0; i < concurrentCount; i++)
					{
						auto trace = backupTraces->Get(i);
						if (!trace) continue;
						backupTraces->Set(writing++, trace);
					}
					concurrentCount -= removedTracesCount;
				}

#undef ERROR_MESSAGE_PREFIX
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMINPUT_COMPETITION.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{

/***********************************************************************
AttendCompetition
***********************************************************************/

			void TraceManager::AttendCompetition(
				Trace* trace,
				Ref<AttendingCompetitions>& newAttendingCompetitions,
				Ref<AttendingCompetitions>& newCarriedCompetitions,
				Ref<ReturnStack> returnStack,
				vint32_t ruleId,
				CompetitionDesc comp
			)
			{
				// a competition is defined by its rule, competition id and the owner trace
				// but we don't need to compare the trace
				// since only transitions starting from that trace will search competitions in that trace
				// we only create a new Competition object if it has not been created for the trace yet
				Competition* competition = nullptr;
				{
					auto cid = trace->competitionRouting.holdingCompetitions;
					while (cid != nullref)
					{
						auto cpt = GetCompetition(cid);
						if (cpt->ruleId == ruleId && cpt->competitionId == comp.competitionId)
						{
							competition = cpt;
							break;
						}
						cid = cpt->nextHoldCompetition;
					}
				}

				if (!competition)
				{
					// create a Competition object
					competition = AllocateCompetition();
					competition->nextHoldCompetition = trace->competitionRouting.holdingCompetitions;
					trace->competitionRouting.holdingCompetitions = competition;

					competition->currentTokenIndex = trace->currentTokenIndex;
					competition->ruleId = ruleId;
					competition->competitionId = comp.competitionId;

					competition->nextActiveCompetition = activeCompetitions;
					activeCompetitions = competition;
				}

				// target traces from the current trace could attend different competitions
				// but they also inherit all attending competitions from the current trace
				// it is fine for different traces share all or part of AttendingCompetitions in their RuntimeRouting::attendingCompetitions linked list
				// because if a competition is settled in the future
				// AttendingCompetitions objects for this competition is going to be removed anyway
				// sharing a linked list doesn't change the result

				auto ac = AllocateAttendingCompetitions();
				ac->competition = competition;
				ac->forHighPriority = comp.highPriority;
				ac->returnStack = returnStack;

				ac->nextActiveAC = newAttendingCompetitions;
				newAttendingCompetitions = ac;

				ac->nextCarriedAC = newCarriedCompetitions;
				newCarriedCompetitions = ac;
			}

/***********************************************************************
AttendCompetitionIfNecessary
***********************************************************************/

			void TraceManager::AttendCompetitionIfNecessary(
				Trace* trace,
				vint32_t currentTokenIndex,
				EdgeDesc& edgeDesc,
				Ref<AttendingCompetitions>& newAttendingCompetitions,
				Ref<AttendingCompetitions>& newCarriedCompetitions,
				Ref<ReturnStack>& newReturnStack
			)
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::AttendCompetitionIfNecessary(Trace*, EdgeDesc&, vint32_t&, vint32_t&)#"
				newAttendingCompetitions = trace->competitionRouting.attendingCompetitions;
				newCarriedCompetitions = trace->competitionRouting.carriedCompetitions;
				newReturnStack = trace->returnStack;

				// visit each compact transition in order
				//   1) returns + token
				//   2) ending
				//   3) leftrec
				// find out if any of them attends a competition

				vint32_t edgeFromState = edgeDesc.fromState;
				for (vint32_t returnRef = 0; returnRef < edgeDesc.returnIndices.count; returnRef++)
				{
					auto returnIndex = executable.returnIndices[edgeDesc.returnIndices.start + returnRef];
					auto&& returnDesc = executable.returns[returnIndex];

					for (vint compRef = 0; compRef < returnDesc.competitions.count; compRef++)
					{
						auto&& comp = executable.competitions[returnDesc.competitions.start + compRef];
						// attend a competition from a ReturnDesc edge
						// find out the rule id and the competition id for this competition
						// a ReturnDesc is a compact transition which consumes a rule
						// so it does not points to the ending state
						// therefore we just need the toState of this ReturnDesc for reference
						auto&& returnState = executable.states[returnDesc.returnState];
						vint32_t competitionRule = returnState.rule;
						CHECK_ERROR(competitionRule != -1, ERROR_MESSAGE_PREFIX L"Illegal rule id.");
						CHECK_ERROR(comp.competitionId != -1, ERROR_MESSAGE_PREFIX L"Illegal competition id.");
						AttendCompetition(trace, newAttendingCompetitions, newCarriedCompetitions, newReturnStack, competitionRule, comp);
					}

					// push this ReturnDesc to the ReturnStack
					newReturnStack = PushReturnStack(
						newReturnStack, returnIndex,
						trace,
						currentTokenIndex,
						(returnDesc.ruleType != ReturnRuleType::Reuse)
					);
					edgeFromState = executable.ruleStartStates[returnDesc.consumedRule];
				}

				for (vint compRef = 0; compRef < edgeDesc.competitions.count; compRef++)
				{
					auto&& comp = executable.competitions[edgeDesc.competitions.start + compRef];
					// attend a competition from a ReturnDesc edge
					// find out the rule id and the competition id for this competition
					// a ReturnDesc is a compact transition which consumes a rule
					// so it does not points to the ending state
					// therefore we just need the toState of this ReturnDesc for reference
					auto&& fromState = executable.states[edgeFromState];
					auto&& toState = executable.states[edgeDesc.toState];
					vint32_t competitionRule = toState.endingState ? fromState.rule : toState.rule;
					CHECK_ERROR(competitionRule != -1, ERROR_MESSAGE_PREFIX L"Illegal rule id.");
					CHECK_ERROR(comp.competitionId != -1, ERROR_MESSAGE_PREFIX L"Illegal competition id.");
					AttendCompetition(trace, newAttendingCompetitions, newCarriedCompetitions, newReturnStack, competitionRule, comp);
				}
#undef ERROR_MESSAGE_PREFIX
			}

/***********************************************************************
CheckAttendingCompetitionsOnEndingEdge
***********************************************************************/

			void TraceManager::CheckAttendingCompetitionsOnEndingEdge(
				Trace* trace,
				EdgeDesc& edgeDesc,
				Ref<AttendingCompetitions> acId,
				Ref<ReturnStack> returnStack
			)
			{
				while (acId != nullref)
				{
					// when executing an EndingInput transition, we announce high priority win a competition if
					//   1) such EndingInput transitions ends the rule, and the state of the trace holding competition belongs to the same rule
					//      we ensure this by comparing rule id in Competition
					//      and compare ReturnStack object (not content) in AttendingCompetitions
					//      the reason returnStack is not in Competition is that
					//      different transitions always create new ReturnStack objects
					//   2) this trace bets high
					//   3) the competition has not been settled
					auto ac = GetAttendingCompetitions(acId);
					if (ac->returnStack == returnStack)
					{
						auto cpt = GetCompetition(ac->competition);
						// ensure that this EndingInput edge and the competition belong to the same rule
						auto&& stateDesc = executable.states[edgeDesc.fromState];
						if (cpt->ruleId == stateDesc.rule)
						{
							// check if it is a high bet
							if (ac->forHighPriority && cpt->status == CompetitionStatus::Holding)
							{
								cpt->status = CompetitionStatus::HighPriorityWin;
							}
						}
					}
					acId = ac->nextActiveAC;
				}
			}

/***********************************************************************
CheckBackupTracesBeforeSwapping
***********************************************************************/

			bool TraceManager::CheckBackupTracesBeforeSwapping(vint32_t currentTokenIndex)
			{
				bool closedCompetitions = false;
				// try to find if any competition could be settled at this moment

				{
					// reset highCounter and lowCounter for any active competitions
					auto cId = activeCompetitions;
					while (cId != nullref)
					{
						auto cpt = GetCompetition(cId);
						cpt->highCounter = 0;
						cpt->lowCounter = 0;
						cId = cpt->nextActiveCompetition;
					}
				}

				// for any surviving traces
				// add itself to the appriopriate counter for all attending competitions
				for (vint i = 0; i < concurrentCount; i++)
				{
					auto trace = EnsureTraceWithValidStates(backupTraces->Get(i));
					auto acId = trace->competitionRouting.attendingCompetitions;
					while (acId != nullref)
					{
						auto ac = GetAttendingCompetitions(acId);
						auto cpt = GetCompetition(ac->competition);
						(ac->forHighPriority ? cpt->highCounter : cpt->lowCounter)++;
						acId = ac->nextActiveAC;
					}
				}

				// revisit all active competitions
				// some competitions could have been settled
				// but settled competitions will only be removed before consuming the next token
				{
					auto cId = activeCompetitions;
					while (cId != nullref)
					{
						auto cpt = GetCompetition(cId);
						if (cpt->status == CompetitionStatus::Holding)
						{
							if (cpt->highCounter > 0 && cpt->lowCounter == 0)
							{
								// if only high bet traces survive, high priority win
								cpt->status = CompetitionStatus::HighPriorityWin;
							}
							else if (cpt->highCounter == 0 && cpt->lowCounter > 0)
							{
								// if only low bet traces survive
								// low priority win after at least one token is consumed from when the competition is created
								// low priority epsilon transitions could have been visited right after a competition is created
								// but high priority token transitions could only be visited when consuming the next token
								// if all high priority transitions are token transitions
								// and all low priority transitions are epsilon transitions
								// closing the competition too early will direct to a wrong result
								// so we need to wait at least one step to see if any trace will visit the high priority transition in the future
								if (cpt->currentTokenIndex != currentTokenIndex)
								{
									cpt->status = CompetitionStatus::LowPriorityWin;
								}
							}
						}
						cId = cpt->nextActiveCompetition;
					}
				}

				// for any surviving traces
				// if it loses any one of its attending competitions
				// this trace will be removed
				for (vint i = concurrentCount - 1; i >= 0; i--)
				{
					auto trace =EnsureTraceWithValidStates(backupTraces->Get(i));
					auto acId = trace->competitionRouting.attendingCompetitions;
					while (acId != nullref)
					{
						auto ac = GetAttendingCompetitions(acId);
						auto cpt = GetCompetition(ac->competition);
						if (cpt->status != CompetitionStatus::Holding)
						{
							ac->closed = true;
							if (ac->forHighPriority != (cpt->status == CompetitionStatus::HighPriorityWin))
							{
								concurrentCount--;
								backupTraces->RemoveAt(i);
								goto TRACE_REMOVED;
							}
						}
						acId = ac->nextActiveAC;
					}
				TRACE_REMOVED:;
				}

				// remove all settled competition from the active competitions linked list
				{
					auto pnext = &activeCompetitions;
					while (*pnext != nullref)
					{
						auto cpt = GetCompetition(*pnext);
						if (cpt->status != CompetitionStatus::Holding || (cpt->highCounter == 0 && cpt->lowCounter == 0))
						{
							*pnext = cpt->nextActiveCompetition;
						}
						else
						{
							pnext = &cpt->nextActiveCompetition;
						}
					}
				}

				// remove all settled AttendingCompetitions object from linked lists of any surviving trace
				for (vint i = 0; i < concurrentCount; i++)
				{
					auto trace = EnsureTraceWithValidStates(backupTraces->Get(i));
					auto attendingCompetitions = trace->competitionRouting.attendingCompetitions;
					auto* pnext = &trace->competitionRouting.attendingCompetitions;
					while (*pnext != nullref)
					{
						auto ac = GetAttendingCompetitions(*pnext);
						if (ac->closed)
						{
							*pnext = ac->nextActiveAC;
						}
						else
						{
							pnext = &ac->nextActiveAC;
						}
					}

					if (trace->competitionRouting.attendingCompetitions != attendingCompetitions)
					{
						// only check the head node since this could trigger merging
						closedCompetitions = true;
					}
				}

				return closedCompetitions;
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMINPUT_RETURNSTACK.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{

/***********************************************************************
GetCurrentSuccessorInReturnStack
***********************************************************************/

			ReturnStackSuccessors* TraceManager::GetCurrentSuccessorInReturnStack(Ref<ReturnStack> base, vint32_t currentTokenIndex)
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::GetCurrentSuccessorInReturnStack(vint32_t, vint32_t)#"
				auto& cache = base == nullref ? initialReturnStackCache : GetReturnStack(base)->cache;
				if (cache.successors.tokenIndex == currentTokenIndex)
				{
					return &cache.successors;
				}
				if (cache.lastSuccessors.tokenIndex == currentTokenIndex)
				{
					return &cache.lastSuccessors;
				}

				CHECK_ERROR(currentTokenIndex > cache.successors.tokenIndex, ERROR_MESSAGE_PREFIX L"ReturnStackSuccessors::tokenIndex corrupted.");
				cache.lastSuccessors = cache.successors;
				cache.successors = {};
				cache.successors.tokenIndex = currentTokenIndex;
				return &cache.successors;
#undef ERROR_MESSAGE_PREFIX
			}

/***********************************************************************
PushReturnStack
***********************************************************************/

			ReturnStack* TraceManager::PushReturnStack(Ref<ReturnStack> base, vint32_t returnIndex, Ref<Trace> fromTrace, vint32_t currentTokenIndex, bool allowReuse)
			{
				auto siblings = allowReuse ? GetCurrentSuccessorInReturnStack(base, currentTokenIndex) : nullptr;

				if (siblings)
				{
					auto successorId = siblings->first;
					while (successorId != nullref)
					{
						auto successor = GetReturnStack(successorId);
						successorId = successor->cache.next;

						if (successor->returnIndex == returnIndex && successor->fromTrace == fromTrace)
						{
							return successor;
						}
					}
				}

				auto returnStack = AllocateReturnStack();
				returnStack->previous = base;
				returnStack->returnIndex = returnIndex;
				returnStack->fromTrace = fromTrace;
				returnStack->cache.tokenIndex = currentTokenIndex;

				if (siblings)
				{
					if (siblings->first == nullref)
					{
						siblings->first = returnStack;
						siblings->last = returnStack;
					}
					else
					{
						GetReturnStack(siblings->last)->cache.next = returnStack;
						returnStack->cache.prev = siblings->last;
						siblings->last = returnStack;
					}
				}
				return returnStack;
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMINPUT_WALK.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{

/***********************************************************************
TraceManager::IsQualifiedTokenForCondition
***********************************************************************/

			bool TraceManager::IsQualifiedTokenForCondition(regex::RegexToken* token, StringLiteral condition)
			{
				if (condition.start == -1) return true;
				if (token->length != condition.count) return false;
				auto reading = executable.stringLiteralBuffer.Buffer();
				if (memcmp(token->reading, reading + condition.start, sizeof(wchar_t) * condition.count) != 0) return false;
				return true;
			}

/***********************************************************************
TraceManager::IsQualifiedTokenForEdgeArray
***********************************************************************/

			bool TraceManager::IsQualifiedTokenForEdgeArray(regex::RegexToken* token, EdgeArray& edgeArray)
			{
				for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++)
				{
					vint32_t byEdge = edgeArray.start + edgeRef;
					auto& edgeDesc = executable.edges[byEdge];
					if (IsQualifiedTokenForCondition(token, edgeDesc.condition)) return true;
				}
				return false;
			}

/***********************************************************************
TraceManager::TestLeftrecEdgeQualification
***********************************************************************/

			void TraceManager::TestLeftrecEdgeQualification(EdgeDesc& edgeDesc, regex::RegexToken* lookAhead, bool& acceptLookAhead, bool& acceptEndingInput)
			{
				if (lookAhead)
				{
					vint32_t lookAheadTransitionIndex = executable.GetTransitionIndex(edgeDesc.toState, Executable::TokenBegin + (vint32_t)lookAhead->token);
					auto& lookAheadEdgeArray = executable.transitions[lookAheadTransitionIndex];

					// mark this EndingInput if any LeftrecInput + lookAhead transition exists
					if (IsQualifiedTokenForEdgeArray(lookAhead, lookAheadEdgeArray))
					{
						acceptLookAhead = true;
					}
				}

				{
					vint32_t endingInputTransitionIndex = executable.GetTransitionIndex(edgeDesc.toState, Executable::EndingInput);
					auto& endingInputEdgeArray = executable.transitions[endingInputTransitionIndex];
					if (endingInputEdgeArray.count > 0)
					{
						acceptEndingInput = true;
					}
				}
			}

/***********************************************************************
TraceManager::WalkAlongSingleEdge
***********************************************************************/

			WalkingTrace TraceManager::WalkAlongSingleEdge(
				vint32_t currentTokenIndex,
				vint32_t input,
				WalkingTrace trace,
				vint32_t byEdge,
				EdgeDesc& edgeDesc
			)
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::WalkAlongSingleEdge(vint, vint, vint, Trace*, vint, EdgeDesc&)#"
				vint32_t state = edgeDesc.toState;
				Ref<ReturnStack> returnStack;
				Ref<AttendingCompetitions> attendingCompetitions;
				Ref<AttendingCompetitions> carriedCompetitions;
				Ref<ReturnStack> executedReturnStack;
				Trace* ambiguityTraceToMerge = nullptr;

				// attend a competition hold by the current trace if the priority is set for this output transition
				AttendCompetitionIfNecessary(trace.stateTrace, currentTokenIndex, edgeDesc, attendingCompetitions, carriedCompetitions, returnStack);

				if (input == Executable::EndingInput)
				{
					// an EndingInput transition consume return record in the return stack
					// such return will be popped from the return stack and stored in Trace::executedReturnStack
					CHECK_ERROR(edgeDesc.returnIndices.count == 0, ERROR_MESSAGE_PREFIX L"Ending input edge is not allowed to push something into the return stack.");
					if (returnStack != nullref)
					{
						executedReturnStack = returnStack;
						auto rs = GetReturnStack(returnStack);
						returnStack = rs->previous;
						state = executable.returns[rs->returnIndex].returnState;
					}

					// an EndingInput transition also settle a competition if
					//   1) there is a competition
					//   2) the returnStack of the trace holding the competition is the same to the current returnStack
					//   3) the target trace bets high priority
					// in this case, high priority traces wins the competition
					// but no traces are being removed for now, just mark the competition
					CheckAttendingCompetitionsOnEndingEdge(trace.stateTrace, edgeDesc, attendingCompetitions, trace.stateTrace->returnStack);
				}

				// create a new trace for this current move
				auto newTrace = AllocateTrace();
				AddTraceToCollection(newTrace, trace.currentTrace, &Trace::predecessors);
				newTrace->state = state;
				newTrace->returnStack = returnStack;
				newTrace->executedReturnStack = executedReturnStack;
				newTrace->byEdge = byEdge;
				newTrace->byInput = input;
				newTrace->currentTokenIndex = currentTokenIndex;
				newTrace->competitionRouting.attendingCompetitions = attendingCompetitions;
				newTrace->competitionRouting.carriedCompetitions = carriedCompetitions;

				if (input == Executable::EndingInput)
				{
					// see if the target trace has the same state to any other surviving trace
					for (vint i = 0; i < concurrentCount; i++)
					{
						auto& candidate = backupTraces->operator[](i);
						if (candidate->byInput == Executable::EndingInput || candidate->state == -1)
						{
							if (AreTwoEndingInputTraceEqual(newTrace, candidate))
							{
								// create a merging 
								MergeTwoEndingInputTrace(newTrace, candidate);
								return { nullptr,nullptr };
							}
						}
					}
				}

				// add to the current trace list only if it is not involved in ambiguity resolving
				AddTrace(newTrace);
				return { newTrace,newTrace };
#undef ERROR_MESSAGE_PREFIX
			}

/***********************************************************************
TraceManager::WalkAlongEpsilonEdges
***********************************************************************/

			void TraceManager::WalkAlongLeftrecEdges(
				vint32_t currentTokenIndex,
				regex::RegexToken* lookAhead,
				WalkingTrace trace,
				EdgeArray& edgeArray
			)
			{
				for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++)
				{
					vint32_t byEdge = edgeArray.start + edgeRef;
					auto& edgeDesc = executable.edges[byEdge];

					// see if the target state could consume that token
					bool acceptLookAhead = false;
					bool acceptEndingInput = false;
					TestLeftrecEdgeQualification(edgeDesc, lookAhead, acceptLookAhead, acceptEndingInput);

					if (acceptLookAhead || acceptEndingInput)
					{
						// proceed only if it can
						auto nextTrace = WalkAlongSingleEdge(currentTokenIndex, Executable::LeftrecInput, trace, byEdge, edgeDesc);

						if (acceptEndingInput && nextTrace)
						{
							// A LeftrecInput will be generated because of
							//   A real left-recursive rule
							//   Merging prefix inside a rule
							//   Merging prefix crossed-reference
							// The last two cases could connect LeftrecInput transitions to an ending state
							WalkAlongEpsilonEdges(currentTokenIndex, lookAhead, nextTrace);
						}
					}
				}
			}

			void TraceManager::WalkAlongEpsilonEdges(
				vint32_t currentTokenIndex,
				regex::RegexToken* lookAhead,
				WalkingTrace trace
			)
			{
				// if we could walk along multiple EndingInput transition
				// but the last several transition will fail
				// then creating them is wasting the performance
				// so we count how many EndingInput transition we could walk along first

				vint32_t endingCount = -1;
				{
					// if there is no more tokens
					// then we have to go all the way to the end anyway
					// otherwise we see how many EndingInput transition we need to walk along
					vint32_t currentCount = 0;
					vint32_t currentState = trace.stateTrace->state;
					auto currentReturnStack = trace.stateTrace->returnStack;

#define MARK_AT_LEAST_EXECUTE_TO_THIS_LEVEL endingCount = currentCount

					while (currentState != -1)
					{
						currentCount++;

						// try LeftrecInput + (lookAhead or EndingInput)
						{
							vint32_t transitionIndex = executable.GetTransitionIndex(currentState, Executable::LeftrecInput);
							auto&& edgeArray = executable.transitions[transitionIndex];
							for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++)
							{
								vint32_t byEdge = edgeArray.start + edgeRef;
								auto& edgeDesc = executable.edges[byEdge];

								bool acceptLookAhead = false;
								bool acceptEndingInput = false;
								TestLeftrecEdgeQualification(edgeDesc, lookAhead, acceptLookAhead, acceptEndingInput);

								// mark this EndingInput if any LeftrecInput + (lookAhead or EndingInput) transition exists
								if (acceptLookAhead || acceptEndingInput)
								{
									MARK_AT_LEAST_EXECUTE_TO_THIS_LEVEL;
									goto TRY_ENDING_INPUT;
								}
							}
						}

						// try lookAhead
						if (lookAhead)
						{
							vint32_t transitionIndex = executable.GetTransitionIndex(currentState, Executable::TokenBegin + (vint32_t)lookAhead->token);
							auto&& edgeArray = executable.transitions[transitionIndex];

							// mark this EndingInput if lookAhead transition exists
							if (IsQualifiedTokenForEdgeArray(lookAhead, edgeArray))
							{
								MARK_AT_LEAST_EXECUTE_TO_THIS_LEVEL;
							}
						}

						// try EndingInput
					TRY_ENDING_INPUT:
						{
							vint32_t transitionIndex = executable.GetTransitionIndex(currentState, Executable::EndingInput);
							auto&& edgeArray = executable.transitions[transitionIndex];

							if (edgeArray.count > 1)
							{
								// if there are multiple EndingInput transitions
								// assume they would all succeed, and do recursive calls later
								MARK_AT_LEAST_EXECUTE_TO_THIS_LEVEL;
								break;
							}
							else if (edgeArray.count == 1 && currentReturnStack != nullref)
							{
								auto rs = GetReturnStack(currentReturnStack);
								currentReturnStack = rs->previous;
								currentState = executable.returns[rs->returnIndex].returnState;
							}
							else if (lookAhead)
							{
								// lookAhead && (edgeArray.count == 0 || currentReturnStack == nullref)
								// if edgeArray.count == 0
								//   no further EndingInput transition could be walked
								// if currentReturnStack == nullref
								//   it means this is the last possible EndingInput
								//   no need to test forward
								//   because if the current EndingInput is doable
								//   it would have already been marked
								break;
							}
							else if (edgeArray.count == 0)
							{
								// !lookAhead && edgeArray.count == 0
								// if there is no more EndingInput to go
								// and the current state is not an ending state
								// then we just give up
								// it is possible that a LeftrecInput transition is available

								auto&& stateDesc = executable.states[currentState];
								if (stateDesc.endingState)
								{
									MARK_AT_LEAST_EXECUTE_TO_THIS_LEVEL;
								}
								break;
							}
							else
							{
								// !lookAhead && edgeArray.count == 1 && currentReturnStack == nullref
								vint32_t byEdge = edgeArray.start;
								auto& edgeDesc = executable.edges[byEdge];
								currentState = edgeDesc.toState;
							}
						}
					}
				}

#undef MARK_AT_LEAST_EXECUTE_TO_THIS_LEVEL

				for (vint32_t i = 0; trace && (i < endingCount || endingCount == -1); i++)
				{
					{
						// LeftrecInput transition is an epsilon transition
						vint32_t transitionIndex = executable.GetTransitionIndex(trace.stateTrace->state, Executable::LeftrecInput);
						auto&& edgeArray = executable.transitions[transitionIndex];
						WalkAlongLeftrecEdges(currentTokenIndex, lookAhead, trace, edgeArray);
					}

					// EndingInput transition is an epsilon transition
					vint32_t transitionIndex = executable.GetTransitionIndex(trace.stateTrace->state, Executable::EndingInput);
					auto&& edgeArray = executable.transitions[transitionIndex];

					// it has been ensured that edgeArray.count < 2
					if (edgeArray.count == 0)
					{
						trace = { nullptr,nullptr };
					}
					else
					{
						for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++)
						{
							vint32_t byEdge = edgeArray.start + edgeRef;
							auto& edgeDesc = executable.edges[byEdge];
							auto nextTrace = WalkAlongSingleEdge(currentTokenIndex, Executable::EndingInput, trace, byEdge, edgeDesc);

							if (edgeArray.count > 1)
							{
								// if the current trace has multiple EndingInput
								// we don't know if the current trace will survive or not
								// a following recursive call is necessary
								if (nextTrace)
								{
									WalkAlongEpsilonEdges(currentTokenIndex, lookAhead, nextTrace);
								}
							}
							else
							{
								trace = nextTrace;
							}
						}

						if (edgeArray.count > 1)
						{
							// when this for-loop ends, the outer for-loop also ends
							trace = { nullptr,nullptr };
						}

						// EndingInput could be followed by EndingInput or LeftrecInput
					}
				}
			}

/***********************************************************************
TraceManager::WalkAlongTokenEdges
***********************************************************************/

			void TraceManager::WalkAlongTokenEdges(
				vint32_t currentTokenIndex,
				vint32_t input,
				regex::RegexToken* token,
				regex::RegexToken* lookAhead,
				WalkingTrace trace,
				EdgeArray& edgeArray
			)
			{
				// find all transitions that has the expected input
				// there could be multiple transitions with the same input
				// but with different instructions and destinations
				for (vint32_t edgeRef = 0; edgeRef < edgeArray.count; edgeRef++)
				{
					vint32_t byEdge = edgeArray.start + edgeRef;
					auto& edgeDesc = executable.edges[byEdge];
					if (IsQualifiedTokenForCondition(token, edgeDesc.condition))
					{
						if (auto newTrace = WalkAlongSingleEdge(currentTokenIndex, input, trace, byEdge, edgeDesc))
						{
							// continue with as much EndingInput and LeftrecInput transitions as possible
							// TokenInput could be followed by EndingInput or LeftrecInput
							WalkAlongEpsilonEdges(currentTokenIndex, lookAhead, newTrace);
						}
					}
				}
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{

/***********************************************************************
PrepareTraceRoute
***********************************************************************/

			void TraceManager::PrepareTraceRoute()
			{
				CHECK_ERROR(state == TraceManagerState::Finished, L"vl::glr::automaton::TraceManager::PrepareTraceRoute()#Wrong timing to call this function.");
				state = TraceManagerState::PreparedTraceRoute;

				AllocateExecutionData();
				BuildAmbiguityStructures();
				PartialExecuteTraces();
				SummarizeInstructionRange();
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR_ALLOCATEEXECUTIONDATA.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
AllocateExecutionData
***********************************************************************/

			void TraceManager::AllocateExecutionData()
			{
#define TRACE_MAMAGER_PHRASE L"PrepareTraceRoute/AllocateExecutionData"
				vint32_t insExecCount = 0;
				auto nextBranchTrace = &firstBranchTrace;
				auto nextMergeTrace = &firstMergeTrace;
				IterateSurvivedTraces([&](Trace* trace, Trace* predecessor, vint32_t visitCount, vint32_t predecessorCount)
				{
					// ensure traceExecRef reflects the partial order of the execution order of traces
					if (predecessorCount > 1 && visitCount != predecessorCount) return;

					if (trace->traceExecRef != nullref)
					{
						throw TraceException(*this, trace, nullptr, TRACE_MAMAGER_PHRASE, L"IterateSurvivedTraces unexpectedly revisit a trace.");
					}
					trace->traceExecRef = traceExecs.Allocate();

					auto traceExec = GetTraceExec(trace->traceExecRef);
					traceExec->traceId = trace;
					ReadInstructionList(trace, traceExec->insLists);
					if (traceExec->insLists.countAll > 0)
					{
						traceExec->insExecRefs.start = insExecCount;
						traceExec->insExecRefs.count = traceExec->insLists.countAll;
						insExecCount += traceExec->insLists.countAll;
					}

					// fill branch trace linked list
					if (trace->successors.first != trace->successors.last)
					{
						*nextBranchTrace = trace;
						nextBranchTrace = &traceExec->nextBranchTrace;
					}

					// fill merge branch linked list
					if (trace->predecessors.first != trace->predecessors.last)
					{
						*nextMergeTrace = trace;
						nextMergeTrace = &traceExec->nextMergeTrace;
					}
				});
				insExecs.Resize(insExecCount);
#undef TRACE_MAMAGER_PHRASE
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR_BUILDAMBIGUITYSTRUCTURES.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
#define NEW_MERGE_STACK_MAGIC_COUNTER (void)(MergeStack_MagicCounter++)

/***********************************************************************
BuildAmbiguityStructures
***********************************************************************/

			Trace* TraceManager::StepForward(Trace* trace)
			{
				auto traceExec = GetTraceExec(trace->traceExecRef);

				// for ordinary trace, go to its forwardTrace
				if (traceExec->branchData.forwardTrace != trace)
				{
					return GetTrace(traceExec->branchData.forwardTrace);
				}

				// for initialTrace, stop
				if (trace->predecessors.first == nullref)
				{
					return nullptr;
				}

				// for merge trace, go to the forwardTrace of its commonForwardTrace
				if (trace->predecessors.first != trace->predecessors.last)
				{
					return GetTrace(GetTraceExec(GetTrace(traceExec->branchData.commonForwardBranch)->traceExecRef)->branchData.forwardTrace);
				}

				// otherwise, it is a successor of a branch trace
				// go to its predecessor's forwardTrace
				return GetTrace(GetTraceExec(GetTrace(trace->predecessors.first)->traceExecRef)->branchData.forwardTrace);
			}

			void TraceManager::BuildAmbiguityStructures()
			{
#define TRACE_MAMAGER_PHRASE L"PrepareTraceRoute/BuildAmbiguityStructures"
				IterateSurvivedTraces(
					[this](Trace* trace, Trace* predecessor, vint32_t visitCount, vint32_t predecessorCount)
					{
						auto traceExec = GetTraceExec(trace->traceExecRef);
						if (predecessorCount == 0)
						{
							// for initialTrace, forwardTrace is itself
							traceExec->branchData.forwardTrace = trace;
						}
						else if (predecessorCount == 1)
						{
							if (predecessor->successors.first != predecessor->successors.last)
							{
								// for any successors of a branch trace, forwardTrace is itself
								traceExec->branchData.forwardTrace = trace;
							}
							else
							{
								// if any ordinary trace, use the data from its predecessor
								traceExec->branchData.forwardTrace = GetTraceExec(predecessor->traceExecRef)->branchData.forwardTrace ;
							}
						}
						else
						{
							if (predecessor->state == -1)
							{
								throw TraceException(*this, trace, predecessor, TRACE_MAMAGER_PHRASE, L"Predecessor trace of a merge trace cannot be a merge trace.");
							}

							if (visitCount == 1)
							{
								// for any merge trace, forwardTrace is itself
								traceExec->branchData.forwardTrace = trace;

								// for the first visiting, set commonForwardBranch to the forwardTrace of its first predecessor
								traceExec->branchData.commonForwardBranch = GetTrace(GetTraceExec(predecessor->traceExecRef)->branchData.forwardTrace);
							}
							else
							{
								// find the latest forwardTrace of its commonForwardBranch and the forwardTrace of the predecessor
								NEW_MERGE_STACK_MAGIC_COUNTER;
								auto magicCommonForward = MergeStack_MagicCounter;

								auto currentTrace = GetTrace(traceExec->branchData.commonForwardBranch);
								while (currentTrace)
								{
									GetTraceExec(currentTrace->traceExecRef)->branchData.mergeCounter = magicCommonForward;
									currentTrace = StepForward(currentTrace);
								}

								currentTrace = GetTrace(GetTraceExec(predecessor->traceExecRef)->branchData.forwardTrace);
								while (currentTrace)
								{
									if (GetTraceExec(currentTrace->traceExecRef)->branchData.mergeCounter == magicCommonForward)
									{
										break;
									}
									currentTrace = StepForward(currentTrace);
								}
								if (currentTrace == nullptr)
								{
									throw TraceException(*this, currentTrace, nullptr, TRACE_MAMAGER_PHRASE, L"Cannot determine commonForwardBranch of a merge trace.");
								}
								traceExec->branchData.commonForwardBranch = currentTrace;
							}
						}
					}
				);
#undef TRACE_MAMAGER_PHRASE
			}

#undef NEW_MERGE_STACK_MAGIC_COUNTER
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR_PARTIALEXECUTETRACES.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
PartialExecuteTraces
***********************************************************************/

			void TraceManager::PartialExecuteTraces()
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::PartialExecuteTraces()#"
				IterateSurvivedTraces(
					[this](Trace* trace, Trace* predecessor, vint32_t visitCount, vint32_t predecessorCount)
					{
						if (predecessorCount <= 1)
						{
							PartialExecuteOrdinaryTrace(trace);
						}
						else
						{
							if (visitCount > 1)
							{
								EnsureInsExecContextCompatible(predecessor, GetTrace(trace->predecessors.first));
							}

							if (visitCount == predecessorCount)
							{
								MergeInsExecContext(trace);
							}
						}
					}
				);
#undef ERROR_MESSAGE_PREFIX
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR_PARTIALEXECUTETRACES_ENSUREINSEXECCONTEXTCOMPATIBLE.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
EnsureInsExecContextCompatible
***********************************************************************/

			void TraceManager::EnsureInsExecContextCompatible(Trace* baselineTrace, Trace* commingTrace)
			{
#define TRACE_MAMAGER_PHRASE L"PrepareTraceRoute/EnsureInsExecContextCompatible"
				auto&& contextComming = GetTraceExec(baselineTrace->traceExecRef)->context;
				auto&& contextBaseline = GetTraceExec(commingTrace->traceExecRef)->context;

				// check if the two objectStack have the same depth
				if ((contextBaseline.objectStack == nullref) != (contextComming.objectStack == nullref))
				{
					throw TraceException(*this, baselineTrace, commingTrace, TRACE_MAMAGER_PHRASE, L"Execution results of traces to merge do not have the same depth of objectStack.");
				}
				if (contextBaseline.objectStack != nullref)
				{
					auto objectStackBaseline = GetInsExec_StackArrayRefLink(contextBaseline.objectStack);
					auto objectStackComming = GetInsExec_StackArrayRefLink(contextComming.objectStack);
					if (objectStackBaseline->currentDepth != objectStackComming->currentDepth)
					{
						throw TraceException(*this, baselineTrace, commingTrace, TRACE_MAMAGER_PHRASE, L"Execution results of traces to merge do not have the same depth of objectStack.");
					}
				}

				// check if the two createStack have the same depth
				// check each corresponding createStack have the same stackBase
				auto stackBaseline = contextBaseline.createStack;
				auto stackComming = contextComming.createStack;
				while (stackBaseline != stackComming)
				{
					if (stackBaseline == nullref || stackComming == nullref)
					{
						throw TraceException(*this, baselineTrace, commingTrace, TRACE_MAMAGER_PHRASE, L"Execution results of traces to merge do not have the same depth of createStack.");
					}

					auto stackObjBaseline = GetInsExec_StackArrayRefLink(stackBaseline);
					auto stackObjComming = GetInsExec_StackArrayRefLink(stackComming);

					if (stackObjBaseline->objectStackDepthForCreateStack != stackObjComming->objectStackDepthForCreateStack)
					{
						throw TraceException(*this, baselineTrace, commingTrace, TRACE_MAMAGER_PHRASE, L"Execution results of traces to merge do not have the same depth of objectStack between one slice of both createStack.");
					}

					stackBaseline = stackObjBaseline->previous;
					stackComming = stackObjComming->previous;
				}
#undef TRACE_MAMAGER_PHRASE
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR_PARTIALEXECUTETRACES_MERGEINSEXECCONTEXT.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
			using namespace collections;

#define NEW_MERGE_STACK_MAGIC_COUNTER (void)(MergeStack_MagicCounter++)

/***********************************************************************
MergeInsExecContext
***********************************************************************/

			template<Ref<InsExec_StackArrayRefLink> (InsExec_Context::* stack), typename TMerge>
			Ref<InsExec_StackArrayRefLink> TraceManager::MergeStack(Trace* mergeTrace, TMerge&& merge)
			{
				Array<InsExec_StackArrayRefLink*> stacks(mergeTrace->predecessorCount);

				// fill the first level of stacks objects
				{
					vint index = 0;
					auto predecessorId = mergeTrace->predecessors.first;
					while (predecessorId != nullref)
					{
						auto predecessor = GetTrace(predecessorId);
						auto traceExec = GetTraceExec(predecessor->traceExecRef);

						auto stackId = traceExec->context.*stack;
						stacks[index++] = stackId == nullref ? nullptr : GetInsExec_StackArrayRefLink(stackId);
						predecessorId = predecessor->predecessors.siblingNext;
					}
				}

				Ref<InsExec_StackArrayRefLink> stackTop;
				auto pStackPrevious = &stackTop;
				while (stacks[0])
				{
					// check if all stack objects are the same
					bool sameStackObject = true;
					// TODO: (enumerable) Linq:Skip
					for (vint index = 1; index < stacks.Count(); index++)
					{
						if (stacks[0] != stacks[index])
						{
							sameStackObject = false;
							break;
						}
					}

					if (sameStackObject)
					{
						// if yes, reuse this stack object
						*pStackPrevious = stacks[0];
						break;
					}

					// otherwise, create a new stack object to merge all
					auto newStack = GetInsExec_StackArrayRefLink(insExec_StackArrayRefLinks.Allocate());
					*pStackPrevious = newStack;
					pStackPrevious = &(newStack->previous);

					{
						// call this macro to create a one-time set for InsExec*
						NEW_MERGE_STACK_MAGIC_COUNTER;
						auto magicPush = MergeStack_MagicCounter;
						// TODO: (enumerable) foreach
						for (vint index = 0; index < stacks.Count(); index++)
						{
							// do not visit the same stack object repeatly
							if (stacks[index]->mergeCounter == magicPush) continue;
							stacks[index]->mergeCounter = magicPush;
							merge(newStack, stacks[index]);

							// do not visit the same object repeatly
							auto currentLinkRef = stacks[index]->ids;
							while (currentLinkRef != nullref)
							{
								auto currentLink = GetInsExec_StackRefLink(currentLinkRef);
								currentLinkRef = currentLink->previous;
								auto currentStack = GetInsExec_Stack(currentLink->id);
								if (currentStack->mergeCounter == magicPush) continue;
								currentStack->mergeCounter = magicPush;
								PushStackRefLink(newStack->ids, currentStack);
							}
						}
					}

					// move to next level of stack objects
					for (vint index = 0; index < stacks.Count(); index++)
					{
						auto stackId = stacks[index]->previous;
						stacks[index] = stackId == nullref ? nullptr : GetInsExec_StackArrayRefLink(stackId);
					}
				}
				return stackTop;
			}

			void TraceManager::MergeInsExecContext(Trace* mergeTrace)
			{
				// merge stacks so that objects created in all branches are accessible
				auto traceExec = GetTraceExec(mergeTrace->traceExecRef);

				traceExec->context.objectStack = MergeStack<
					&InsExec_Context::objectStack
				>(
					mergeTrace,
					[this](InsExec_StackArrayRefLink* newStack, InsExec_StackArrayRefLink* commingStack)
					{
						newStack->currentDepth = commingStack->currentDepth;
					});

				traceExec->context.createStack = MergeStack<
					&InsExec_Context::createStack
				>(
					mergeTrace,
					[this](InsExec_StackArrayRefLink* newStack, InsExec_StackArrayRefLink* commingStack)
					{
						newStack->currentDepth = commingStack->currentDepth;
						newStack->objectStackDepthForCreateStack = commingStack->objectStackDepthForCreateStack;
					});

				NEW_MERGE_STACK_MAGIC_COUNTER;
				auto predecessorId = mergeTrace->predecessors.first;
				while (predecessorId != nullref)
				{
					auto predecessor = GetTrace(predecessorId);
					predecessorId = predecessor->predecessors.siblingNext;
					auto predecessorTraceExec = GetTraceExec(predecessor->traceExecRef);
				}
			}

#undef NEW_MERGE_STACK_MAGIC_COUNTER
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR_PARTIALEXECUTETRACES_PARTIALEXECUTEORDINARYTRACE.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
#define NEW_MERGE_STACK_MAGIC_COUNTER (void)(MergeStack_MagicCounter++)

/***********************************************************************
PartialExecuteOrdinaryTrace
***********************************************************************/

			InsExec_Stack* TraceManager::NewStack()
			{
				auto ieStack = GetInsExec_Stack(insExec_Stacks.Allocate());
				ieStack->previous = firstStack;
				firstStack = ieStack;
				return ieStack;
			}

			void TraceManager::PushInsRefLink(Ref<InsExec_InsRefLink>& link, InsRef insRef)
			{
				auto newLink = GetInsExec_InsRefLink(insExec_InsRefLinks.Allocate());
				newLink->previous = link;
				newLink->insRef = insRef;
				link = newLink;
			}

			void TraceManager::PushStackRefLink(Ref<InsExec_StackRefLink>& link, Ref<InsExec_Stack> id)
			{
				auto newLink = GetInsExec_StackRefLink(insExec_StackRefLinks.Allocate());
				newLink->previous = link;
				newLink->id = id;
				link = newLink;
			}

			void TraceManager::PushStackArrayRefLink(Ref<InsExec_StackArrayRefLink>& arrayLink, Ref<InsExec_Stack> id)
			{
				Ref<InsExec_StackRefLink> link;
				PushStackRefLink(link, id);
				PushStackArrayRefLink(arrayLink, link);
			}

			void TraceManager::PushStackArrayRefLink(Ref<InsExec_StackArrayRefLink>& arrayLink, Ref<InsExec_StackRefLink> link)
			{
				auto newArrayLink = GetInsExec_StackArrayRefLink(insExec_StackArrayRefLinks.Allocate());
				newArrayLink->previous = arrayLink;
				newArrayLink->ids = link;

				if (arrayLink == nullref)
				{
					newArrayLink->currentDepth = 0;
				}
				else
				{
					newArrayLink->currentDepth = GetInsExec_StackArrayRefLink(arrayLink)->currentDepth + 1;
				}
				arrayLink = newArrayLink;
			}

			Ref<InsExec_InsRefLink> TraceManager::JoinInsRefLink(Ref<InsExec_InsRefLink> first, Ref<InsExec_InsRefLink> second)
			{
				if (first == nullref) return second;
				if (second == nullref) return first;

				Ref<InsExec_InsRefLink> newInsRef;

				while (first != nullref)
				{
					auto insRef = GetInsExec_InsRefLink(first);
					first = insRef->previous;
					PushInsRefLink(newInsRef, insRef->insRef);
				}

				while (second != nullref)
				{
					auto insRef = GetInsExec_InsRefLink(second);
					second = insRef->previous;
					PushInsRefLink(newInsRef, insRef->insRef);
				}

				return newInsRef;
			}

			Ref<InsExec_StackRefLink> TraceManager::JoinStackRefLink(Ref<InsExec_StackRefLink> first, Ref<InsExec_StackRefLink> second)
			{
				if (first == nullref) return second;
				if (second == nullref) return first;

				Ref<InsExec_StackRefLink> newStack;

				while (first != nullref)
				{
					auto stack = GetInsExec_StackRefLink(first);
					first = stack->previous;
					PushStackRefLink(newStack, stack->id);
				}

				while (second != nullref)
				{
					auto stack = GetInsExec_StackRefLink(second);
					second = stack->previous;
					PushStackRefLink(newStack, stack->id);
				}

				return newStack;
			}

			void TraceManager::PartialExecuteOrdinaryTrace(Trace* trace)
			{
#define TRACE_MAMAGER_PHRASE L"PrepareTraceRoute/PartialExecuteOrdinaryTrace"
				InsExec_Context context;
				if (trace->predecessors.first != nullref)
				{
					auto predecessor = GetTrace(trace->predecessors.first);
					auto traceExec = GetTraceExec(predecessor->traceExecRef);
					context = traceExec->context;
				}

				auto ForEachStack = [this](Ref<InsExec_StackArrayRefLink> targetStack, auto&& callback)
				{
						auto topStackArray = GetInsExec_StackArrayRefLink(targetStack);
						auto topStackLinkRef = topStackArray->ids;
						while (topStackLinkRef != nullref)
						{
							auto topStackLink = GetInsExec_StackRefLink(topStackLinkRef);
							topStackLinkRef = topStackLink->previous;
							auto topStack = GetInsExec_Stack(topStackLink->id);
							callback(topStack);
						}
				};

				auto traceExec = GetTraceExec(trace->traceExecRef);
				for (vint32_t insRef = 0; insRef < traceExec->insLists.countAll; insRef++)
				{
					auto&& ins = ReadInstruction(insRef, traceExec->insLists);
					auto insExec = GetInsExec(traceExec->insExecRefs.start + insRef);
					insExec->contextBeforeExecution = context;

					switch (ins.type)
					{
					case AstInsType::CreateObject:
						{
							if (context.createStack == nullref)
							{
								throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"[CreateObject] context.createStack is empty.");
							}
							ForEachStack(context.createStack, [=, this](InsExec_Stack* topStack)
							{
								PushInsRefLink(topStack->createObjectInsRefs, { trace, insRef });
								PushStackRefLink(insExec->operatingStacks, topStack);
							});
						}
						break;
					case AstInsType::StackBegin:
						{
							auto newTopStack = NewStack();
							PushStackArrayRefLink(context.createStack, newTopStack);
							newTopStack->beginInsRef = { trace, insRef };
							PushStackRefLink(insExec->operatingStacks, newTopStack);

							auto newStackTop = GetInsExec_StackArrayRefLink(context.createStack);
							if (context.objectStack == nullref)
							{
								newStackTop->objectStackDepthForCreateStack = 0;
							}
							else
							{
								newStackTop->objectStackDepthForCreateStack = GetInsExec_StackArrayRefLink(context.objectStack)->currentDepth;
							}
						}
						break;
					case AstInsType::StackEnd:
						{
							if (context.createStack == nullref)
							{
								throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"[StackEnd] context.createStack is empty.");
							}
							bool endWithCreate = false;
							bool endWithReuse = false;
							ForEachStack(context.createStack, [&](InsExec_Stack* topStack)
							{
								bool executedCreateObject = false;
								if (topStack->createObjectInsRefs != nullref)
								{
									auto lastCreateObjectInsRefLink = GetInsExec_InsRefLink(topStack->createObjectInsRefs);
									executedCreateObject = lastCreateObjectInsRefLink->insRef.trace == trace;
								}

								if(executedCreateObject)
								{
									endWithCreate = true;
									PushInsRefLink(topStack->endWithCreateInsRefs, { trace,  insRef });
								}
								else
								{
									endWithReuse = true;
									PushInsRefLink(topStack->endWithReuseInsRefs, { trace, insRef });
								}

								PushStackRefLink(insExec->operatingStacks, topStack);
							});

							if (endWithCreate == endWithReuse)
							{
								throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"[StackEnd] Connected CreateObject and StackEnd should always be in the same trace.");
							}

							if (endWithReuse)
							{
								if (context.objectStack == nullref)
								{
									throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"[StackEnd] context.objectStack is empty.");
								}
								auto topObjects = GetInsExec_StackArrayRefLink(context.objectStack);
								context.objectStack = topObjects->previous;
								ForEachStack(context.createStack, [&](InsExec_Stack* topStack)
								{
									topStack->useFromStacks = JoinStackRefLink(topStack->useFromStacks, topObjects->ids);
								});
							}

							auto topStacks = GetInsExec_StackArrayRefLink(context.createStack);
							context.createStack = topStacks->previous;
							PushStackArrayRefLink(context.objectStack, topStacks->ids);
						}
						break;
					case AstInsType::StackSlot:
						{
							if (context.createStack == nullref)
							{
								throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"[StackSlot] context.createStack is empty.");
							}
							if (context.objectStack == nullref)
							{
								throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"[StackSlot] context.objectStack is empty.");
							}
							auto topObjects = GetInsExec_StackArrayRefLink(context.objectStack);
							context.objectStack = topObjects->previous;
							ForEachStack(context.createStack, [&](InsExec_Stack* topStack)
							{
								topStack->fieldStacks = JoinStackRefLink(topStack->fieldStacks, topObjects->ids);
							});
						}
						break;
					case AstInsType::Field:
					case AstInsType::FieldIfUnassigned:
					case AstInsType::Token:
					case AstInsType::EnumItem:
						break;
					case AstInsType::ResolveAmbiguity:
						throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"[ResolveAmbiguity] should not appear in traces.");
					default:;
						throw TraceException(*this, { trace, insRef }, TRACE_MAMAGER_PHRASE, L"Unrecognizabled instruction.");
					}
				}
				traceExec->context = context;
#undef TRACE_MAMAGER_PHRASE
			}

#undef NEW_MERGE_STACK_MAGIC_COUNTER
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMPTR_PARTIALEXECUTETRACES_SUMMARIZEINSTRUCTIONRANGE.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
			using namespace collections;

#define NEW_MERGE_STACK_MAGIC_COUNTER (void)(MergeStack_MagicCounter++)

/***********************************************************************
IterateStackWithDependency
***********************************************************************/

			template<typename TCallback>
			void TraceManager::IterateStackWithDependency(Ref<InsExec_StackRefLink>(InsExec_Stack::* dependencies), TCallback&& callback)
			{
				NEW_MERGE_STACK_MAGIC_COUNTER;
				auto stackMagicCounter = MergeStack_MagicCounter;

				// traverse through all stacks
				auto currentStackRef = firstStack;
				while (currentStackRef != nullref)
				{
					auto currentStack = GetInsExec_Stack(currentStackRef);
					currentStackRef = currentStack->previous;
					if (currentStack->mergeCounter == stackMagicCounter) continue;
					currentStack->mergeCounter = stackMagicCounter;

					List<InsExec_Stack*> indirectStacks;
					indirectStacks.Add(currentStack);

					// list all untouched dependencies in order, skipped processed ones
					for (vint i = 0; i < indirectStacks.Count(); i++)
					{
						auto stack = indirectStacks[i];
						auto currentInsRefLink = stack->*dependencies;
						while (currentInsRefLink != nullref)
						{
							auto insRefLink = GetInsExec_StackRefLink(currentInsRefLink);
							currentInsRefLink = insRefLink->previous;

							auto useFromStack = GetInsExec_Stack(insRefLink->id);
							if (useFromStack->mergeCounter == stackMagicCounter) continue;
							useFromStack->mergeCounter = stackMagicCounter;
							indirectStacks.Add(useFromStack);
						}
					}

					// process all listed stacks
					for (vint i = indirectStacks.Count() - 1; i >= 0; i--)
					{
						auto stack = indirectStacks[i];
						callback(stack);
					}
				}
			}

/***********************************************************************
SummarizeEarilestLocalInsRefs
***********************************************************************/

			void TraceManager::SummarizeEarilestLocalInsRefs()
			{
				IterateStackWithDependency(&InsExec_Stack::useFromStacks, [this](InsExec_Stack* stack)
				{
					SortedList<InsRef> insRefs;
					auto currentStackRefLink = stack->useFromStacks;
					while (currentStackRefLink != nullref)
					{
						auto stackRefLink = GetInsExec_StackRefLink(currentStackRefLink);
						currentStackRefLink = stackRefLink->previous;

						auto useFromStack = GetInsExec_Stack(stackRefLink->id);
						UpdateTopTrace(stack->summarizing.earliestLocalInsRef, useFromStack->summarizing.earliestLocalInsRef);
						CollectInsRefs(insRefs, useFromStack->summarizing.indirectCreateObjectInsRefs);
					}
					UpdateTopTrace(stack->summarizing.earliestLocalInsRef, stack->beginInsRef);
					CollectInsRefs(insRefs, stack->createObjectInsRefs);

					for (auto insRef : insRefs)
					{
						PushInsRefLink(stack->summarizing.indirectCreateObjectInsRefs, insRef);
					}
				});
			}

/***********************************************************************
SummarizeEarilestStackInsRefs
***********************************************************************/

			void TraceManager::SummarizeEarilestStackInsRefs()
			{
				{
					auto currentStackRef = firstStack;
					while (currentStackRef != nullref)
					{
						auto currentStack = GetInsExec_Stack(currentStackRef);
						currentStackRef = currentStack->previous;

						currentStack->allDependentStacks = JoinStackRefLink(currentStack->fieldStacks, currentStack->useFromStacks);
					}
				}
				IterateStackWithDependency(&InsExec_Stack::allDependentStacks, [this](InsExec_Stack* stack)
				{
					auto currentStackRefLink = stack->allDependentStacks;
					while (currentStackRefLink != nullref)
					{
						auto stackRefLink = GetInsExec_StackRefLink(currentStackRefLink);
						currentStackRefLink = stackRefLink->previous;

						auto fieldStack = GetInsExec_Stack(stackRefLink->id);
						UpdateTopTrace(stack->summarizing.earliestStackInsRef, fieldStack->summarizing.earliestStackInsRef);
					}
					UpdateTopTrace(stack->summarizing.earliestStackInsRef, stack->summarizing.earliestLocalInsRef);
				});
			}

/***********************************************************************
SummarizeEarilestInsRefs
***********************************************************************/

			void TraceManager::SummarizeEarilestInsRefs()
			{
				List<InsExec_Stack*> indirectStacks;

				// traverse through all stacks
				auto currentStackRef = firstStack;
				while (currentStackRef != nullref)
				{
					auto currentStack = GetInsExec_Stack(currentStackRef);
					currentStackRef = currentStack->previous;

					indirectStacks.Clear();
					indirectStacks.Add(currentStack);

					// traverse through all useFromStacks recursively
					for (vint i = 0; i < indirectStacks.Count(); i++)
					{
						auto stack = indirectStacks[i];
						// if earliestInsRef could be refreshed, propogate it into useFromStacks
						if (!UpdateTopTrace(stack->summarizing.earliestInsRef, currentStack->summarizing.earliestStackInsRef))
						{
							continue;
						}

						if (stack == currentStack)
						{
							stack->summarizing.bottomInsRefs = JoinInsRefLink(stack->endWithCreateInsRefs, stack->endWithReuseInsRefs);
						}
						else
						{
							stack->summarizing.bottomInsRefs = currentStack->summarizing.bottomInsRefs;
						}

						auto currentInsRefLink = stack->useFromStacks;
						while (currentInsRefLink != nullref)
						{
							auto insRefLink = GetInsExec_StackRefLink(currentInsRefLink);
							currentInsRefLink = insRefLink->previous;

							auto useFromStack = GetInsExec_Stack(insRefLink->id);
							indirectStacks.Add(useFromStack);
						}
					}
				}
			}

/***********************************************************************
SummarizeInstructionRange
***********************************************************************/

			bool TraceManager::UpdateTopTrace(InsRef& topInsRef, InsRef newInsRef)
			{
				if (
					topInsRef.trace == nullref ||
					topInsRef.trace > newInsRef.trace ||
					(topInsRef.trace == newInsRef.trace && topInsRef.ins > newInsRef.ins)
					)
				{
					topInsRef = newInsRef;
					return true;
				}
				else
				{
					return false;
				}
			}

			void TraceManager::CollectInsRefs(collections::SortedList<InsRef>& insRefs, Ref<InsExec_InsRefLink> link)
			{
				auto currentInsRefLink = link;
				while (currentInsRefLink != nullref)
				{
					auto insRefLink = GetInsExec_InsRefLink(currentInsRefLink);
					currentInsRefLink = insRefLink->previous;

					if (!insRefs.Contains(insRefLink->insRef))
					{
						insRefs.Add(insRefLink->insRef);
					}
				}
			}

			void TraceManager::SummarizeInstructionRange()
			{
				SummarizeEarilestLocalInsRefs();
				SummarizeEarilestStackInsRefs();
				SummarizeEarilestInsRefs();
			}

#undef NEW_MERGE_STACK_MAGIC_COUNTER
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMRA.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
ResolveAmbiguity
***********************************************************************/

			void TraceManager::ResolveAmbiguity()
			{
				CHECK_ERROR(state == TraceManagerState::PreparedTraceRoute, L"vl::glr::automaton::TraceManager::ResolveAmbiguity()#Wrong timing to call this function.");
				state = TraceManagerState::ResolvedAmbiguity;

				CheckMergeTraces();
				BuildExecutionOrder();
			}

#undef NEW_MERGE_STACK_MAGIC_COUNTER
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TMRA_BUILDEXECUTIONORDER.CPP
***********************************************************************/

#define DEFINE_EXECUTION_STEP_CONTEXT ExecutionStep*& root, ExecutionStep*& firstLeaf, ExecutionStep*& currentStep, ExecutionStep*& currentLeaf
#define PASS_EXECUTION_STEP_CONTEXT root, firstLeaf, currentStep, currentLeaf

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
			using namespace collections;
#define TRACE_MAMAGER_PHRASE L"ResolveAmbiguity/BuildExecutionOrder"

/***********************************************************************
ExecutionStep Operations
***********************************************************************/

			void TraceManager::AppendStepsAfterList(ExecutionStepLinkedList steps, ExecutionStepLinkedList& current)
			{
				if (!steps.first)
				{
					return;
				}
				if (!current.first)
				{
					current = steps;
				}
				else
				{
					steps.first->parent = current.last;
					current.last = steps.last;
				}
			}

			void TraceManager::AppendLeafToTree(ExecutionStep* leaf, ExecutionStepTree& tree)
			{
				if (!tree.firstLeaf)
				{
					tree.firstLeaf = leaf;
					tree.lastLeaf = leaf;
				}
				else
				{
					tree.lastLeaf->leafNext = leaf;
					tree.lastLeaf = leaf;
				}
			}

			ExecutionStepLinkedList TraceManager::ConvertStepTreeToList(ExecutionStepTree tree)
			{
				ExecutionStepLinkedList result;

				// initialize visitCount and copyCount
				{
					Ref<ExecutionStep> currentLeafRef = tree.firstLeaf;
					while (currentLeafRef != nullref)
					{
						auto currentLeaf = GetExecutionStep(currentLeafRef);
						currentLeafRef = currentLeaf->leafNext;

						Ref<ExecutionStep> currentStepRef = currentLeaf;
						while (currentStepRef != nullref)
						{
							auto currentStep = GetExecutionStep(currentStepRef);
							currentStepRef = currentStep->parent;

							currentStep->visitCount = 0;
							currentStep->copyCount = 0;
						}
					}
				}
				{
					Ref<ExecutionStep> currentLeafRef = tree.firstLeaf;
					while (currentLeafRef != nullref)
					{
						auto currentLeaf = GetExecutionStep(currentLeafRef);
						currentLeafRef = currentLeaf->leafNext;

						Ref<ExecutionStep> currentStepRef = currentLeaf;
						while (currentStepRef != nullref)
						{
							auto currentStep = GetExecutionStep(currentStepRef);
							currentStepRef = currentStep->parent;

							currentStep->copyCount++;
						}
					}
				}

				// traverse through each leaf
				// make a list from root to leaf
				// join them
				{
					Ref<ExecutionStep> currentLeafRef = tree.firstLeaf;
					while (currentLeafRef != nullref)
					{
						auto currentLeaf = GetExecutionStep(currentLeafRef);
						currentLeafRef = currentLeaf->leafNext;

						ExecutionStepLinkedList leafList{ currentLeaf,currentLeaf };
						auto walkingStep = currentLeaf;
						while (walkingStep->parent != nullref)
						{
							walkingStep = GetExecutionStep(walkingStep->parent);

							if (walkingStep->visitCount++ == walkingStep->copyCount)
							{
								leafList.first = walkingStep;
							}
							else
							{
								auto stepCopy = GetExecutionStep(executionSteps.Allocate());
								static_assert(sizeof(stepCopy->et_i) >= sizeof(stepCopy->et_ra));
								stepCopy->type = walkingStep->type;
								stepCopy->et_i = walkingStep->et_i;
								leafList.first->parent = stepCopy;
								leafList.first = stepCopy;
							}
						}
						AppendStepsAfterList(leafList, result);
					}
				}

				// clean leafPrev and leafNext
				{
					Ref<ExecutionStep> currentLeafRef = tree.firstLeaf;
					while (currentLeafRef != nullref)
					{
						auto currentLeaf = GetExecutionStep(currentLeafRef);
						currentLeafRef = currentLeaf->leafNext;

						currentLeaf->leafNext = nullref;
					}
				}

				return result;
			}

/***********************************************************************
CreateResolveAmbiguityStep
***********************************************************************/

			ExecutionStep* TraceManager::CreateResolveAmbiguityStep(TraceAmbiguity* ta)
			{
				auto taFirst = GetTrace(ta->firstTrace);
				auto taLast = GetTrace(ta->lastTrace);
				auto step = GetExecutionStep(executionSteps.Allocate());
				step->type = ExecutionType::RA_End;
				step->et_ra.type = -1;
				step->et_ra.trace = taLast->allocatedIndex;
				{
					if (typeCallback == nullptr)
					{
						throw TraceException(*this, TRACE_MAMAGER_PHRASE, L"Missing ITypeCallback to resolve the type from multiple objects.");
					}
					auto currentStackLinkRef = ta->bottomCreateObjectStacks;
					while (currentStackLinkRef != nullref)
					{
						auto currentStackLink = GetInsExec_StackRefLink(currentStackLinkRef);
						currentStackLinkRef = currentStackLink->previous;
						auto ieObject = GetInsExec_Stack(currentStackLink->id);

						// find all CreateObject instructions in that stack
						if (ieObject->summarizing.indirectCreateObjectInsRefs == nullref)
						{
							throw TraceException(*this, ieObject, TRACE_MAMAGER_PHRASE, L"indirectCreateObjectInsRefs should not be null.");
						}
						auto coInsRefLink = ieObject->summarizing.indirectCreateObjectInsRefs;
						while (coInsRefLink != nullref)
						{
							auto coInsRef = GetInsExec_InsRefLink(coInsRefLink);
							coInsRefLink = coInsRef->previous;

							auto coTrace = GetTrace(coInsRef->insRef.trace);
							auto coTraceExec = GetTraceExec(coTrace->traceExecRef);
							auto&& coIns = ReadInstruction(coInsRef->insRef.ins, coTraceExec->insLists);
							if (coIns.type != AstInsType::CreateObject || coIns.param == -1)
							{
								throw TraceException(*this, ieObject, TRACE_MAMAGER_PHRASE, L"indirectCreateObjectInsRefs points to an unexpected instruction.");
							}

							if (step->et_ra.type == -1)
							{
								step->et_ra.type = coIns.param;
							}
							else if (step->et_ra.type != coIns.param)
							{
								vint32_t baseClass = typeCallback->FindCommonBaseClass(step->et_ra.type, coIns.param);
								if (baseClass == -1)
								{
									throw UnableToResolveAmbiguityException(
										WString::Unmanaged(L"Unable to resolve ambiguity type from ") +
										typeCallback->GetClassName(step->et_ra.type) +
										WString::Unmanaged(L" and ") +
										typeCallback->GetClassName(coIns.param) +
										WString::Unmanaged(L"."),
										step->et_ra.type,
										coIns.param,
										EnsureTraceWithValidStates(taFirst)->currentTokenIndex,
										EnsureTraceWithValidStates(taLast)->currentTokenIndex
									);
								}
								step->et_ra.type = baseClass;
							}
						}
					}
				}
				return step;
			}

/***********************************************************************
CollectNestedAmbiguities
***********************************************************************/

			Ptr<TraceManager::NestedAmbiguityInfo> TraceManager::CollectNestedAmbiguities(TraceAmbiguity* ta)
			{
				auto taFirst = GetTrace(ta->firstTrace);
				auto taBranch = GetTrace(ta->branchTrace);

				Ptr<NestedAmbiguityInfo> nestedTas;
				{
					auto criticalTrace = taFirst;
					while (criticalTrace && criticalTrace->traceExecRef <= taBranch->traceExecRef)
					{
						auto criticalTraceExec = GetTraceExec(criticalTrace->traceExecRef);
						if (criticalTraceExec->ambiguityBegins != nullref)
						{
							auto taLink = GetTraceAmbiguityLink(criticalTraceExec->ambiguityBegins);
							auto nestedTa = GetTraceAmbiguity(taLink->ambiguity);
							if (nestedTa != ta)
							{
								auto nestedTaLast = GetTrace(nestedTa->lastTrace);
								if (nestedTaLast->traceExecRef > taBranch->traceExecRef)
								{
									if (!nestedTas) nestedTas = Ptr(new NestedAmbiguityInfo);
									nestedTas->nestedAmbiguities.Add(nestedTa);
								}
								else
								{
									criticalTrace = GetTrace(nestedTa->mergeTrace);
									continue;
								}
							}
						}

						auto criticalRef = criticalTraceExec->nextAmbiguityCriticalTrace;
						criticalTrace = criticalRef == nullref ? nullptr : GetTrace(criticalRef);
					}
				}

				if (nestedTas)
				{
					nestedTas->branchTraces.Add(GetTrace(ta->branchTrace), ta);
					for (auto nestedTa : nestedTas->nestedAmbiguities)
					{
						auto branchTrace = GetTrace(nestedTa->branchTrace);
						nestedTas->branchTraces.Add(branchTrace, nestedTa);
					}

					for (auto nestedTa : nestedTas->nestedAmbiguities)
					{
						auto currentTraceRef = nestedTa->branchTrace;
						while (currentTraceRef != nullref)
						{
							auto currentTrace = GetTrace(currentTraceRef);
							if (currentTrace->traceExecRef < taFirst->traceExecRef)
							{
								break;
							}

							if (currentTrace->successors.siblingNext != currentTrace->successors.siblingPrev)
							{
								auto predecessor = GetTrace(currentTrace->predecessors.first);
								if (nestedTas->branchTraces.Keys().Contains(predecessor))
								{
									nestedTas->branchSelections.Add(nestedTa, currentTrace);
								}
							}

							auto currentTraceExec = GetTraceExec(currentTrace->traceExecRef);
							if (currentTraceExec->branchData.forwardTrace == currentTrace)
							{
								currentTraceRef = currentTrace->predecessors.first;
							}
							else
							{
								currentTraceRef = currentTraceExec->branchData.forwardTrace;
							}
						}
					}
				}

				return nestedTas;
			}

/***********************************************************************
BuildStepLeafsForAmbiguityBranch
***********************************************************************/

			void TraceManager::BuildStepLeafsForAmbiguityBranch(
				TraceAmbiguity* ta,
				ExecutionStep* lastSharedStep,
				Trace* ambiguityBranchStartTrace,
				vint32_t* ambiguityBranchStartIns,
				ExecutionStepTree& ambiguityStepTree)
			{
				auto taFirst = GetTrace(ta->firstTrace);
				auto taLast = GetTrace(ta->lastTrace);
				auto taMerge = GetTrace(ta->mergeTrace);
				auto taFirstExec = GetTraceExec(taFirst->traceExecRef);
				auto taLastExec = GetTraceExec(taLast->traceExecRef);
				auto taMergeExec = GetTraceExec(taMerge->traceExecRef);
				vint32_t prefixExtra = ta->prefix - taFirstExec->insLists.countAll;
				vint32_t postfixExtra = ta->postfix - taLastExec->insLists.countAll;

				ExecutionStepLinkedList branchList;
				// Execute the branch
				{
					Trace* rawBranchTrace = nullptr;
					auto steps = BuildStepListUntilFirstRawBranchTrace(
						ambiguityBranchStartTrace,
						ambiguityBranchStartIns ? *ambiguityBranchStartIns : (prefixExtra <= 0 ? 0 : prefixExtra),
						taMerge,
						(taMergeExec->insLists.countAll - 1 - (postfixExtra <= 0 ? 0 : postfixExtra)),
						nullptr,
						&rawBranchTrace
					);

					if (rawBranchTrace)
					{
						if (steps.first)
						{
							steps.first->parent = lastSharedStep;
						}

						auto successorId = rawBranchTrace->successors.first;
						while (successorId != nullref)
						{
							auto successor = GetTrace(successorId);
							successorId = successor->successors.siblingNext;
							BuildStepLeafsForAmbiguityBranch(ta, (steps.first ? steps.last : lastSharedStep), successor, nullptr, ambiguityStepTree);
						}
						return;
					}
					AppendStepsAfterList(steps, branchList);
				}

				// Execute from taMerge to taLast
				if (postfixExtra < 0)
				{
					auto steps = BuildStepList(
						taMerge,
						0,
						taLast,
						-postfixExtra - 1,
						nullptr
					);
					AppendStepsAfterList(steps, branchList);
				}

				// Append RA_BRANCH
				{
					auto step = GetExecutionStep(executionSteps.Allocate());
					step->type = ExecutionType::RA_Branch;
					step->et_ra.trace = taLast->allocatedIndex;
					step->et_ra.type = -1;
					AppendStepsAfterList({ step,step }, branchList);
				}

				branchList.first->parent = lastSharedStep;
				AppendLeafToTree(branchList.last, ambiguityStepTree);
			}

/***********************************************************************
BuildStepLeafsForNestedAmbiguityBranch
***********************************************************************/

			void TraceManager::BuildStepLeafsForNestedAmbiguityBranch(
				TraceAmbiguity* ta,
				ExecutionStep* lastSharedStep,
				BSLA_Guidance* guidance,
				ExecutionStepTree& ambiguityStepTree)
			{
				ExecutionStepLinkedList stepsBeforeBranch;
				auto nta = guidance->nestedTas->nestedAmbiguities[guidance->nextAmbiguityIndex];

				auto taFirst = GetTrace(ta->firstTrace);
				auto ntaFirst = GetTrace(nta->firstTrace);

				// Execute from taFirst until the nested TraceAmbiguity
				{
					auto ntaFirst = GetTrace(nta->firstTrace);
					auto steps = BuildStepList(
						taFirst,
						ta->prefix,
						ntaFirst,
						-1,
						nullptr
					);
					AppendStepsAfterList(steps, stepsBeforeBranch);
				}

				// Execute the nested TraceAmbiguity
				Trace* currentTrace = ntaFirst;
				vint32_t currentIns = 0;
				{
					auto steps = BuildStepListThroughAmbiguity(
						currentTrace,
						currentIns,
						nta,
						guidance
					);
					AppendStepsAfterList(steps, stepsBeforeBranch);
				}


				// Execute the rest
				stepsBeforeBranch.first->parent = lastSharedStep;
				lastSharedStep = stepsBeforeBranch.last;
				BuildStepLeafsForAmbiguityBranch(
					ta,
					lastSharedStep,
					currentTrace,
					&currentIns,
					ambiguityStepTree
				);
			}

/***********************************************************************
BuildStepListForAmbiguity
***********************************************************************/

			ExecutionStepLinkedList TraceManager::BuildStepListForAmbiguity(
				TraceAmbiguity* ta,
				BSLA_Guidance* guidance)
			{
				BSLA_Guidance DoNotUse_BSLA_Guidance;
				BSL_Guidance DoNotUse_BSL_Guidance;

				ExecutionStepLinkedList result;
				auto taFirst = GetTrace(ta->firstTrace);
				auto taBranch = GetTrace(ta->branchTrace);
				auto taFirstExec = GetTraceExec(taFirst->traceExecRef);
				auto taBranchExec = GetTraceExec(taBranch->traceExecRef);
				vint32_t prefixExtra = ta->prefix - taFirstExec->insLists.countAll;

				// Find the first nested TraceAmbiguity between taFirst and taBranch
				bool currentAmbiguityIsNested = guidance != nullptr;
				if (!guidance && (DoNotUse_BSLA_Guidance.nestedTas = CollectNestedAmbiguities(ta)))
				{
					guidance = &DoNotUse_BSLA_Guidance;
				}

				if (currentAmbiguityIsNested)
				{
					guidance->nextAmbiguityIndex++;
				}
				bool nestedAmbiguityAvailable = guidance && guidance->nextAmbiguityIndex < guidance->nestedTas->nestedAmbiguities.Count();

				// Append RA_BEGIN
				{
					auto step = GetExecutionStep(executionSteps.Allocate());
					step->type = ExecutionType::RA_Begin;
					step->et_ra.trace = taFirst->allocatedIndex;
					step->et_ra.type = -1;
					AppendStepsAfterList({ step,step }, result);
				}

				{
					ExecutionStepTree branchSteps;
					// If there is a nested TraceAmbiguity, Execute it first
					if (nestedAmbiguityAvailable)
					{
						BuildStepLeafsForNestedAmbiguityBranch(ta, nullptr, guidance, branchSteps);
					}

					ExecutionStepLinkedList sharedSteps;
					// Execute from taFirst to taBranch
					if (prefixExtra < 0)
					{
						if (guidance)
						{
							DoNotUse_BSL_Guidance = {
								(currentAmbiguityIsNested ? &guidance->nestedTas->branchSelections[ta] : nullptr),
								&guidance->nestedTas->nestedAmbiguities,
							};
						}
						sharedSteps = BuildStepList(
							taFirst,
							ta->prefix,
							taBranch,
							taBranchExec->insLists.countAll - 1,
							(guidance ? &DoNotUse_BSL_Guidance : nullptr)
						);
					}

					// Nested TraceAmbiguity is not implemented, so all successors of taBranch are needed
					auto successorId = taBranch->successors.first;
					while (successorId != nullref)
					{
						auto successor = GetTrace(successorId);
						successorId = successor->successors.siblingNext;

						if (guidance)
						{
							// Skip visited branches
							for (vint i = guidance->nextAmbiguityIndex; i < guidance->nestedTas->nestedAmbiguities.Count(); i++)
							{
								auto nta = guidance->nestedTas->nestedAmbiguities[i];
								for (auto selection : guidance->nestedTas->branchSelections[nta])
								{
									if (selection == successor)
									{
										goto SKIP_CURRENT_SUCCESSOR;
									}
								}
							}
						}
						BuildStepLeafsForAmbiguityBranch(ta, sharedSteps.last, successor, nullptr, branchSteps);
					SKIP_CURRENT_SUCCESSOR:;
					}

					AppendStepsAfterList(ConvertStepTreeToList(branchSteps), result);
				}

				if (currentAmbiguityIsNested)
				{
					guidance->nextAmbiguityIndex--;
				}

				// Append RA_END
				{
					auto step = CreateResolveAmbiguityStep(ta);
					AppendStepsAfterList({ step,step }, result);
				}

				return result;
			}

/***********************************************************************
BuildStepListThroughAmbiguity
***********************************************************************/

			ExecutionStepLinkedList TraceManager::BuildStepListThroughAmbiguity(
				Trace*& currentTrace,
				vint32_t& currentIns,
				TraceAmbiguity* ta,
				BSLA_Guidance* guidance
			)
			{
				ExecutionStepLinkedList result;

				auto taFirst = GetTrace(ta->firstTrace);
				auto taLast = GetTrace(ta->lastTrace);
				auto taFirstExec = GetTraceExec(taFirst->traceExecRef);
				auto taLastExec = GetTraceExec(taLast->traceExecRef);
				vint32_t prefixExtra = ta->prefix - taFirstExec->insLists.countAll;
				vint32_t postfixExtra = ta->postfix - taLastExec->insLists.countAll;

				if (currentTrace->traceExecRef < taFirst->traceExecRef || currentIns < ta->prefix)
				{
					auto step = GetExecutionStep(executionSteps.Allocate());
					step->et_i.startTrace = currentTrace->allocatedIndex;
					step->et_i.startIns = currentIns;
					if (ta->prefix == 0)
					{
						if (taFirst->predecessors.first != taFirst->predecessors.last)
						{
							throw TraceException(*this, ta, nullptr, TRACE_MAMAGER_PHRASE, L"The prefix of the TraceAmbiguity is 0, but its firstTrace is a merge trace.");
						}
						auto taFirstPrev = GetTrace(taFirst->predecessors.first);
						auto taFirstPrevExec = GetTraceExec(taFirstPrev->traceExecRef);
						step->et_i.endTrace = taFirstPrev->allocatedIndex;
						step->et_i.endIns = taFirstPrevExec->insLists.countAll - 1;
					}
					else if (prefixExtra <= 0)
					{
						step->et_i.endTrace = taFirst->allocatedIndex;
						step->et_i.endIns = ta->prefix - 1;
					}
					else
					{
						step->et_i.endTrace = taFirst->allocatedIndex;
						step->et_i.endIns = taFirstExec->insLists.countAll - 1;
					}
					AppendStepsAfterList({ step, step }, result);
				}

				if (prefixExtra > 0)
				{
					// at the moment taFirst should be taBranch
					// TraceAmbiguity begins at each successors of taBranch, instead of before taBranch
					auto taFirstSuccessor = GetTrace(taFirst->successors.first);
					auto step = GetExecutionStep(executionSteps.Allocate());
					step->et_i.startTrace = taFirstSuccessor->allocatedIndex;
					step->et_i.startIns = 0;
					step->et_i.endTrace = taFirstSuccessor->allocatedIndex;
					step->et_i.endIns = prefixExtra - 1;
					AppendStepsAfterList({ step, step }, result);
				}

				// Execute the next TraceAmbiguity
				auto taSteps = BuildStepListForAmbiguity(ta, guidance);
				AppendStepsAfterList(taSteps, result);

				// Step (currentTrace, currentIns) forward to right after TraceAmbiguity
				if (postfixExtra > 0)
				{
					// at the moment taLast should be taMerge
					// TraceAmbiguity ends at each predecessor of taMerge, instead of after taMerge
					auto taLastPredecessor = GetTrace(taLast->predecessors.first);
					auto taLastPredecessorExec = GetTraceExec(taLastPredecessor->traceExecRef);
					auto step = GetExecutionStep(executionSteps.Allocate());
					step->et_i.startTrace = taLastPredecessor->allocatedIndex;
					step->et_i.startIns = taLastPredecessorExec->insLists.countAll - postfixExtra;
					step->et_i.endTrace = taLastPredecessor->allocatedIndex;
					step->et_i.endIns = taLastPredecessorExec->insLists.countAll - 1;
					AppendStepsAfterList({ step, step }, result);
				}

				if (ta->postfix == 0)
				{
					if (taLast->successors.first == nullref)
					{
						currentTrace = nullptr;
					}
					else if (taLast->successors.first != taLast->successors.last)
					{
						throw TraceException(*this, ta, nullptr, TRACE_MAMAGER_PHRASE, L"The postfix of the TraceAmbiguity is 0, but its lastTrace is a branch trace.");
					}
					else
					{
						currentTrace = GetTrace(taLast->successors.first);
						currentIns = 0;
					}
				}
				else
				{
					currentTrace = taLast;
					currentIns = -(postfixExtra <= 0 ? postfixExtra : 0);
				}

				return result;
			}

/***********************************************************************
BuildStepList
***********************************************************************/

			ExecutionStepLinkedList TraceManager::BuildStepListUntilFirstRawBranchTrace(
				Trace* startTrace,
				vint32_t startIns,
				Trace* endTrace,
				vint32_t endIns,
				BSL_Guidance* guidance,
				Trace** rawBranchTrace)
			{
				ExecutionStepLinkedList result;
				Trace* currentTrace = startTrace;
				vint32_t currentIns = startIns;

				while (currentTrace)
				{
					auto currentTraceExec = GetTraceExec(currentTrace->traceExecRef);

					// Find the next critical trace
					Trace* criticalTrace = nullptr;
					if (currentTraceExec->nextAmbiguityCriticalTrace != nullref)
					{
						criticalTrace = currentTrace;
					}
					else
					{
						criticalTrace = GetTrace(currentTraceExec->branchData.forwardTrace);
					}

					while (criticalTrace && criticalTrace->traceExecRef <= currentTrace->traceExecRef)
					{
						auto nextRef = GetTraceExec(criticalTrace->traceExecRef)->nextAmbiguityCriticalTrace;
						if (nextRef == nullref)
						{
							if (criticalTrace->successors.first != criticalTrace->successors.last)
							{
								// When there is no more next critical trace before a branch trace
								auto criticalTraceExec = GetTraceExec(criticalTrace->traceExecRef);
								if (criticalTraceExec->ambiguityBegins != nullref)
								{
									// If it is associated with a TraceAmbiguity, it is a critical trace we are looking for
									break;
								}
								throw TraceException(*this, currentTrace, nullptr, TRACE_MAMAGER_PHRASE, L"Failed to find a TraceAmbiguity between this trace and the next branch trace.");
							}
							else
							{
								// When there is no more next critical trace, we are about to reach the end
								// Ignore the current critical trace, stop searching, just run through the end
								goto NO_CRITICAL_TRACE;
							}
						}

						// When it runs past (endTrace, endIns)
						// Ignore the current critical trace, stop searching, just run through the end
						criticalTrace = nextRef == nullref ? nullptr : GetTrace(nextRef);
						if (criticalTrace->traceExecRef >= endTrace->traceExecRef)
						{
							goto NO_CRITICAL_TRACE;
						}
						else if (endIns < 0 && criticalTrace->successors.first == endTrace)
						{
							goto NO_CRITICAL_TRACE;
						}
					}

					// If the current critical trace is associated with a TraceAmbiguity
					// and the TraceAmbiguity is what configured to skip
					// treat it as an ordinary trace
					auto criticalTraceExec = GetTraceExec(criticalTrace->traceExecRef);
					bool ignoreCriticalAmgiguity = false;
					if (guidance && guidance->ambiguitiesToSkip && criticalTraceExec->ambiguityBegins != nullref)
					{
						auto ta = GetTraceAmbiguity(GetTraceAmbiguityLink(criticalTraceExec->ambiguityBegins)->ambiguity);
						for (auto nestedTa : *guidance->ambiguitiesToSkip)
						{
							if (nestedTa == ta)
							{
								ignoreCriticalAmgiguity = true;
								break;
							}
						}
					}

					if (ignoreCriticalAmgiguity || criticalTraceExec->ambiguityBegins == nullref)
					{
						// If the current critical trace is a branch trace
						// and there is a specified successor to execute
						// treat it as an ordinary trace
						// otherwise, exit properly
						Trace* specifieidBranchSelection = nullptr;
						if (criticalTrace->successors.first != criticalTrace->successors.last)
						{
							if (guidance && guidance->branchSelections)
							{
								for (auto selection : *guidance->branchSelections)
								{
									if (criticalTrace == selection->predecessors.first)
									{
										specifieidBranchSelection = selection;
										break;
									}
								}
							}

							if (!specifieidBranchSelection)
							{
								if (rawBranchTrace)
								{
									*rawBranchTrace = criticalTrace;
									endTrace = criticalTrace;
									endIns = GetTraceExec(endTrace->traceExecRef)->insLists.countAll - 1;
									goto NO_CRITICAL_TRACE;
								}
								else
								{
									throw TraceException(*this, currentTrace, criticalTrace, TRACE_MAMAGER_PHRASE, L"The next critical trace after the current trace is not associated with a TraceAmbiguity.");
								}
							}
						}

						// A critical trace could be a predecessor of a merge trace
						// Execute until here and continue
						auto step = GetExecutionStep(executionSteps.Allocate());
						step->et_i.startTrace = currentTrace->allocatedIndex;
						step->et_i.startIns = currentIns;
						step->et_i.endTrace = criticalTrace->allocatedIndex;
						step->et_i.endIns = criticalTraceExec->insLists.countAll - 1;
						AppendStepsAfterList({ step, step }, result);

						if(specifieidBranchSelection)
						{
							currentTrace = specifieidBranchSelection;
						}
						else if (criticalTrace->successors.first == nullref)
						{
							currentTrace = nullptr;
						}
						else
						{
							currentTrace = GetTrace(criticalTrace->successors.first);
							currentIns = 0;
						}
						continue;
					}

					// Execute from (currentTrace, currentIns) until the next TraceAmbiguity
					auto ta = GetTraceAmbiguity(GetTraceAmbiguityLink(criticalTraceExec->ambiguityBegins)->ambiguity);
					auto steps = BuildStepListThroughAmbiguity(currentTrace, currentIns, ta, nullptr);
					AppendStepsAfterList(steps, result);
				}
			NO_CRITICAL_TRACE:

				if (endIns < 0 && endIns != GetTraceExec(endTrace->traceExecRef)->insLists.countAll - 1)
				{
					// The real endTrace is a predecessor of endTrace, but we need to find out which
					auto realEndTrace = currentTrace;
					while (realEndTrace->successors.first != endTrace)
					{
						realEndTrace = GetTrace(realEndTrace->successors.first);
					}

					auto realEndTraceExec = GetTraceExec(realEndTrace->traceExecRef);
					endTrace = realEndTrace;
					endIns = realEndTraceExec->insLists.countAll + endIns;
				}

				if (currentTrace)
				{
					if (
						currentTrace->traceExecRef < endTrace->traceExecRef ||
						(currentTrace->traceExecRef == endTrace->traceExecRef && currentIns <= endIns)
						)
					{
						// Execute from (currentTrace, currentIns) to (endTrace, endIns)
						auto step = GetExecutionStep(executionSteps.Allocate());
						step->et_i.startTrace = currentTrace->allocatedIndex;
						step->et_i.startIns = currentIns;
						step->et_i.endTrace = endTrace->allocatedIndex;
						step->et_i.endIns = endIns;
						AppendStepsAfterList({ step, step }, result);
					}
					else
					{
						throw TraceException(*this, currentTrace, endTrace, TRACE_MAMAGER_PHRASE, L"BuildStepList corrupted with a currentTrace after startIns.");
					}
				}

				return result;
			}

			ExecutionStepLinkedList TraceManager::BuildStepList(
				Trace* startTrace,
				vint32_t startIns,
				Trace* endTrace,
				vint32_t endIns,
				BSL_Guidance* guidance)
			{
				return BuildStepListUntilFirstRawBranchTrace(startTrace, startIns, endTrace, endIns, guidance, nullptr);
			}

/***********************************************************************
BuildExecutionOrder
***********************************************************************/

			void TraceManager::BuildExecutionOrder()
			{
				// get the instruction range
				auto startTrace = initialTrace;
				vint32_t startIns = 0;
				auto endTrace = concurrentTraces->Get(0);
				vint32_t endIns = GetTraceExec(endTrace->traceExecRef)->insLists.countAll - 1;

				auto steps = BuildStepList(startTrace, startIns, endTrace, endIns, nullptr);
				{
					auto current = steps.last;
					while (current != steps.first)
					{
						auto parent = GetExecutionStep(current->parent);
						parent->next = current;
						current = parent;
					}
				}
				firstStep = steps.first;
			}
#undef TRACE_MAMAGER_PHRASE
		}
	}
}

#undef PASS_EXECUTION_STEP_CONTEXT
#undef DEFINE_EXECUTION_STEP_CONTEXT

/***********************************************************************
.\TRACEMANAGER\TMRA_CHECKMERGETRACES.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
			using namespace collections;

#define NEW_MERGE_STACK_MAGIC_COUNTER (void)(MergeStack_MagicCounter++)

/***********************************************************************
CheckAmbiguityResolution
***********************************************************************/

			template<typename TCallback>
			bool TraceManager::EnumerateObjects(Ref<InsExec_StackRefLink> stackRefLinkStartSet, bool withCounter, TCallback&& callback)
			{
				// check every object in the link
				auto magicIterating = MergeStack_MagicCounter;
				auto linkId = stackRefLinkStartSet;
				while (linkId != nullref)
				{
					auto stackRefLink = GetInsExec_StackRefLink(linkId);
					linkId = stackRefLink->previous;
					auto ieObject = GetInsExec_Stack(stackRefLink->id);

					if (withCounter)
					{
						// skip if it has been searched
						if (ieObject->mergeCounter == magicIterating) goto CHECK_NEXT_OBJECT;
						ieObject->mergeCounter = magicIterating;
					}

					if (!callback(ieObject)) return false;
				CHECK_NEXT_OBJECT:;
				}
				return true;
			}

			template<typename TCallback>
			bool TraceManager::EnumerateBottomInstructions(InsExec_Stack* ieObject, TCallback&& callback)
			{
				auto insRefLinkId = ieObject->summarizing.bottomInsRefs;
				while (insRefLinkId != nullref)
				{
					auto insRefLink = GetInsExec_InsRefLink(insRefLinkId);
					insRefLinkId = insRefLink->previous;
					if (!callback(GetTrace(insRefLink->insRef.trace), insRefLink->insRef.ins)) return false;
				}

				return true;
			}

			bool TraceManager::ComparePrefix(TraceExec* baselineTraceExec, TraceExec* commingTraceExec, vint32_t prefix)
			{
				if (commingTraceExec->insLists.countAll < prefix) return false;
				for (vint32_t i = 0; i < prefix; i++)
				{
					auto&& insBaseline = ReadInstruction(i, baselineTraceExec->insLists);
					auto&& insComming = ReadInstruction(i, baselineTraceExec->insLists);
					if (insBaseline != insComming) return false;
				}

				return true;
			}

			bool TraceManager::ComparePostfix(TraceExec* baselineTraceExec, TraceExec* commingTraceExec, vint32_t postfix)
			{
				if (commingTraceExec->insLists.countAll < postfix) return false;
				for (vint32_t i = 0; i < postfix; i++)
				{
					auto&& insBaseline = ReadInstruction(baselineTraceExec->insLists.countAll - i - 1, baselineTraceExec->insLists);
					auto&& insComming = ReadInstruction(baselineTraceExec->insLists.countAll - i - 1, baselineTraceExec->insLists);
					if (insBaseline != insComming) return false;
				}

				return true;
			}

			template<typename TCallback>
			bool TraceManager::CheckAmbiguityResolution(TraceAmbiguity* ta, collections::List<Ref<InsExec_StackRefLink>>& visitingIds, collections::List<WString>* failureReasons, TCallback&& callback)
			{
				// following conditions need to be satisfies if multiple objects could be the result of ambiguity
				//
				// StackBegin that create objects must be
				//   the same instruction in the same trace
				//   in different trace
				//     these traces share the same predecessor
				//     prefix in these traces are the same
				//
				// StackEnd that end objects must be
				//   the same instruction in the same trace
				//   in different trace
				//     these traces share the same successor
				//     postfix in these traces are the same

				// initialize TraceAmbiguity
				Trace* first = nullptr;
				Trace* last = nullptr;
				TraceExec* firstTraceExec = nullptr;
				TraceExec* lastTraceExec = nullptr;

				vint firstTraceCount = 0;
				vint firstSameTraceCount = 0;
				vint firstSamePredecessorCount = 0;

				bool foundEndSame = false;
				bool foundEndPostfix = false;
				bool succeeded = false;

				// iterate all top objects
				if (failureReasons)
				{
					failureReasons->Add(L"[InsExec_Stack->summarizing.earliestInsRef]");
				}
				succeeded = callback([&](Ref<InsExec_StackRefLink> objRefLink)
				{
					return EnumerateObjects(objRefLink, false, [&](InsExec_Stack* ieObject)
					{
						auto createTrace = GetTrace(ieObject->summarizing.earliestInsRef.trace);
						if (failureReasons)
						{
							failureReasons->Add(L"  Verifying object " +
								itow(ieObject->allocatedIndex) +
								L", its earliestInsRef is " +
								itow(ieObject->summarizing.earliestInsRef.trace.handle) + L"@" + itow(ieObject->summarizing.earliestInsRef.ins) +
								L".");
						}
						if (!first)
						{
							first = createTrace;
							firstTraceExec = GetTraceExec(first->traceExecRef);
							ta->firstTrace = createTrace;
							ta->prefix = ieObject->summarizing.earliestInsRef.ins;
							if (failureReasons)
							{
								failureReasons->Add(L"  This is the first object in the list.");
							}
						}
						else
						{
							firstTraceCount++;

							if (first == createTrace)
							{
								// check if two instruction is the same
								if (ta->prefix != ieObject->summarizing.earliestInsRef.ins)
								{
									if (failureReasons)
									{
										failureReasons->Add(L"  It has a different prefix, stopped.");
									}
									return false;
								}
								firstSameTraceCount++;
							}

							if (first->predecessors.first == createTrace->predecessors.first)
							{
								// check if two instruction shares the same prefix
								if (first->predecessors.first != createTrace->predecessors.first)
								{
								}
								auto createTraceExec = GetTraceExec(createTrace->traceExecRef);
								if (!ComparePrefix(firstTraceExec, createTraceExec, ta->prefix))
								{
									if (failureReasons)
									{
										failureReasons->Add(L"  They has a different postfix, stopped");
									}
									return false;
								}
								firstSamePredecessorCount++;
							}

							if (first != createTrace && first->predecessors.first != createTrace->predecessors.first)
							{
								if (failureReasons)
								{
									failureReasons->Add(L"  The predecessor of the trace where the earliestInsRef of the first object is " +
										itow(first->predecessors.first.handle) +
										L", meanwhile the one for the current object is " +
										itow(createTrace->predecessors.first.handle) +
										L", they are different, stopped.");
								}
								return false;
							}
						}

						return true;
					});
				});
				if (!succeeded) return false;

				// iterate all bottom instructions
				{
					if (failureReasons)
					{
						failureReasons->Add(L"[InsExec_Stack->endWithCreateInsRefs/endWithReuseInsRefs]");
					}
					// endWith(Create|Reuse)InsRefs need to be filtered again
					// because the object from the first branch could be a field in the object from the second branch
					// in this case, that object could have multiple incompatible endWith(Create|Reuse)InsRefs
					// so we try eoTrace and the unique and existing eoTrace->successors.first
					// see which wins
					Group<Trace*, InsRef> postfixesAtSelf, postfixesAtSuccessor;

					NEW_MERGE_STACK_MAGIC_COUNTER;
					callback([&](Ref<InsExec_StackRefLink> objRefLink)
					{
						return EnumerateObjects(objRefLink, true, [&](InsExec_Stack* ieObject)
						{
							if (failureReasons)
							{
								failureReasons->Add(L"  Verifying object " +
									itow(ieObject->allocatedIndex) +
									L" which has StackEnd instructions:");
							}
							PushStackRefLink(ta->bottomCreateObjectStacks, ieObject);

							// check if EO satisfies the condition
							return EnumerateBottomInstructions(ieObject, [&](Trace* eoTrace, vint32_t eoIns)
							{
								if (failureReasons)
								{
									failureReasons->Add(L"    " +
										itow(eoTrace->allocatedIndex) + L"@" + itow(eoIns) +
										L".");
								}
								auto eoTraceExec = GetTraceExec(eoTrace->traceExecRef);
								InsRef insRef{ eoTrace,eoTraceExec->insLists.countAll - eoIns - 1 };
								postfixesAtSelf.Add(eoTrace, insRef);

								Trace* successorTrace = nullptr;
								if (eoTrace->successorCount == 1)
								{
									successorTrace = GetTrace(eoTrace->successors.first);
								}
								postfixesAtSuccessor.Add(successorTrace, insRef);
								return true;
							});
						});
					});

					if (failureReasons)
					{
						failureReasons->Add(L"  [postfixesAtSelf]");
						for (vint i = 0; i < postfixesAtSelf.Count(); i++)
						{
							auto key = postfixesAtSelf.Keys()[i];
							WString message = L"  " + itow(key ? key->allocatedIndex : -1) + L" ->";
							for (auto&& value : postfixesAtSelf.GetByIndex(i))
							{
								message += L" " + itow(value.trace.handle) + L"@-" + itow(value.ins);
							}
							failureReasons->Add(message);
						}

						failureReasons->Add(L"  [postfixesAtSuccessor]");
						for (vint i = 0; i < postfixesAtSuccessor.Count(); i++)
						{
							auto key = postfixesAtSuccessor.Keys()[i];
							WString message = L"  " + itow(key ? key->allocatedIndex : -1) + L" ->";
							for (auto&& value : postfixesAtSuccessor.GetByIndex(i))
							{
								message += L" " + itow(value.trace.handle) + L"@-" + itow(value.ins);
							}
							failureReasons->Add(message);
						}
					}

					// find the most possible answer from postfixesAtSelf and postfixesAtSuccessor
					// bottom bottomInsRefs are splitted into multiple group
					// find the unique one that has the maximum capacity
					vint maxOccurences = -1;
					for (vint i = 0; i < postfixesAtSelf.Count(); i++)
					{
						vint count = postfixesAtSelf.GetByIndex(i).Count();
						if (count > maxOccurences)
						{
							maxOccurences = count;
						}
					}
					for (vint i = 0; i < postfixesAtSuccessor.Count(); i++)
					{
						vint count = postfixesAtSuccessor.GetByIndex(i).Count();
						if (count > maxOccurences)
						{
							maxOccurences = count;
						}
					}

					vint uniqueAtSelf = -1;
					for (vint i = 0; i < postfixesAtSelf.Count(); i++)
					{
						vint count = postfixesAtSelf.GetByIndex(i).Count();
						if (count == maxOccurences)
						{
							if (uniqueAtSelf == -1)
							{
								uniqueAtSelf = i;
							}
							else
							{
								uniqueAtSelf = -2;
								break;
							}
						}
					}

					vint uniqueAtSuccessor = -1;
					for (vint i = 0; i < postfixesAtSuccessor.Count(); i++)
					{
						vint count = postfixesAtSuccessor.GetByIndex(i).Count();
						if (count == maxOccurences)
						{
							if (uniqueAtSuccessor == -1)
							{
								uniqueAtSuccessor = i;
							}
							else
							{
								uniqueAtSuccessor = -2;
								break;
							}
						}
					}

					InsRef lastPostfix;
					if (uniqueAtSelf >= 0)
					{
						// if all bottom traces are the same, their first successors are also the same
						lastPostfix = postfixesAtSelf.GetByIndex(uniqueAtSelf)[0];
					}
					else if (uniqueAtSuccessor >= 0)
					{
						lastPostfix = postfixesAtSuccessor.GetByIndex(uniqueAtSuccessor)[0];
						foundEndPostfix = true;
					}

					if (failureReasons)
					{
						failureReasons->Add(L"  [unique possible largest group]");
						failureReasons->Add(L"  postfixesAtSelf -> " + itow(uniqueAtSelf));
						failureReasons->Add(L"  postfixesAtSuccessor -> " + itow(uniqueAtSuccessor));
						failureReasons->Add(L"  lastPostfix -> " + itow(lastPostfix.trace.handle) + L"@" + itow(lastPostfix.ins));
					}

					if (lastPostfix.trace == nullref)
					{
						if (failureReasons)
						{
							failureReasons->Add(L"  lastPostfix has an empty trace, stopped.");
						}
						succeeded = false;
					}
					else
					{
						// TODO: check if last is in the same thread and is or after the merge trace
						last = GetTrace(lastPostfix.trace);
						ta->lastTrace = last;
						ta->postfix = lastPostfix.ins;
						succeeded = true;
					}
				}
				if (!succeeded) return false;

				if (failureReasons)
				{
					failureReasons->Add(L"[TraceAmbiguity]");
				}

				// ensure the statistics result is compatible
				if (last && !foundEndSame && !foundEndPostfix) foundEndSame = true;
				if (firstTraceCount != firstSameTraceCount && firstTraceCount != firstSamePredecessorCount)
				{
					if (failureReasons)
					{
						failureReasons->Add(L"Some StackBegin instructions share the same trace while some share the same predecessor, stopped.");
					}
					return false;
				}
				if (foundEndSame == foundEndPostfix)
				{
					if (failureReasons)
					{
						failureReasons->Add(L"Some StackEnd instructions share the same trace while some share the same successor, stopped.");
					}
					return false;
				}

				// fix prefix if necessary
				if (firstTraceCount != firstSameTraceCount)
				{
					auto first = GetTrace(GetTrace(ta->firstTrace)->predecessors.first);
					auto traceExec = GetTraceExec(first->traceExecRef);
					ta->firstTrace = first;
					ta->prefix += traceExec->insLists.countAll;
				}

				// fix postfix if necessary
				if (foundEndPostfix)
				{
					// last will be a merge trace
					// so ta->postfix doesn't need to change
					auto last = GetTrace(GetTrace(ta->lastTrace)->successors.first);
					auto traceExec = GetTraceExec(last->traceExecRef);
					ta->lastTrace = last;
				}

				// ensure firstTrace and lastTrace are in the same branch
				auto firstForward = GetTrace(GetTraceExec(GetTrace(ta->firstTrace)->traceExecRef)->branchData.forwardTrace);
				auto lastForward = GetTrace(GetTraceExec(GetTrace(ta->lastTrace)->traceExecRef)->branchData.forwardTrace);

				if (failureReasons)
				{
					failureReasons->Add(L"firstTrace: " + itow(ta->firstTrace.handle));
					failureReasons->Add(L"prefix: " + itow(ta->prefix));
					failureReasons->Add(L"lastTrace: " + itow(ta->lastTrace.handle));
					failureReasons->Add(L"postfix: " + itow(ta->postfix));
					failureReasons->Add(L"firstForward: " + itow(firstForward->allocatedIndex));
					failureReasons->Add(L"lastForward (currentForward): " + itow(lastForward->allocatedIndex));
				}

				auto currentForward = lastForward;
				while (true)
				{
					if (currentForward->traceExecRef < firstForward->traceExecRef)
					{
						if (failureReasons)
						{
							failureReasons->Add(L"currentForward is before firstForward, stopped.");
						}
						return false;
					}
					if (currentForward == firstForward)
					{
						return true;
					}

					auto currentExec = GetTraceExec(currentForward->traceExecRef);
					auto nextForwardRef = currentExec->branchData.commonForwardBranch;
					if (nextForwardRef == nullptr)
					{
						nextForwardRef = currentExec->branchData.forwardTrace;
					}

					auto nextForward = GetTrace(currentExec->branchData.forwardTrace);
					if (currentForward != nextForward)
					{
						currentForward = nextForward;
						if (failureReasons)
						{
							failureReasons->Add(L"currentForward steps forward to: " +
								itow(currentForward->allocatedIndex) +
								L".");
						}
					}
					else if (currentForward->predecessorCount > 0)
					{
						currentForward = GetTrace(GetTraceExec(GetTrace(currentForward->predecessors.first)->traceExecRef)->branchData.forwardTrace);
						if (failureReasons)
						{
							failureReasons->Add(L"currentForward steps forward passing a branch to: " +
								itow(currentForward->allocatedIndex) +
								L".");
						}
					}
					else
					{
						if (failureReasons)
						{
							failureReasons->Add(L"currentForward reaches the beginning of the trace, stopped.");
						}
						break;
					}
				}

				return false;
			}

/***********************************************************************
CheckSingleMergeTrace
***********************************************************************/

			bool TraceManager::CheckSingleMergeTrace(TraceAmbiguity* ta, Trace* trace, TraceExec* traceExec, collections::List<Ref<InsExec_StackRefLink>>& visitingIds, collections::List<WString>* failureReasons)
			{
				if (failureReasons)
				{
					failureReasons->Add(L"Trying to merge trace " +
						itow(trace->allocatedIndex)
						+ L".");
				}

				// when a merge trace is the last trace
				// objects in the top object stack are the result of ambiguity
				if (trace->successorCount == 0)
				{
					if (failureReasons)
					{
						failureReasons->Add(L"This is the last trace, compare all concurrent objects in the objectStack top.");
					}
					auto ieOSTop = GetInsExec_StackArrayRefLink(traceExec->context.objectStack);
					return CheckAmbiguityResolution(ta, visitingIds, failureReasons, [=](auto&& callback)
					{
						return callback(ieOSTop->ids);
					});
				}

				// otherwise
				// objects in the top create stack are the result of ambiguity
				// even when there is only one object in the stack

				// but in some cases
				// objects in the top object stack are the result of ambiguity
				// when these objects are the only difference in branches
				// here we need to test if the condition satisfied

				{
					// [CONDITION]
					// the first predecessor must has a StackEnd instruction
					// count the number of instructions after StackEnd
					// these instructions are the postfix
					vint32_t postfix = -1;
					auto firstTrace = GetTrace(trace->predecessors.first);
					auto firstTraceExec = GetTraceExec(firstTrace->traceExecRef);
					for (vint32_t i = firstTraceExec->insLists.countAll - 1; i >= 0; i--)
					{
						auto&& ins = ReadInstruction(i, firstTraceExec->insLists);
						if (ins.type == AstInsType::StackEnd)
						{
							postfix = firstTraceExec->insLists.countAll - i - 1;
							break;
						}
					}
					if (postfix == -1)
					{
						if (failureReasons)
						{
							failureReasons->Add(L"The first predecessor " +
								itow(firstTrace->allocatedIndex) +
								L" has no StackEnd.");
						}

						goto CHECK_OBJECTS_IN_TOP_CREATE_STACK;
					}

					if (failureReasons)
					{
						failureReasons->Add(L"The first predecessor " +
							itow(firstTrace->allocatedIndex) +
							L" has StackEnd, its postfix is " +
							itow(postfix) +
							L".");
					}

					// [CONDITION]
					// all predecessor must have a StackEnd instruction
					// posftix of all predecessors must be the same
					{
						auto predecessorId = trace->predecessors.last;
						while (predecessorId != firstTrace)
						{
							auto predecessor = GetTrace(predecessorId);
							predecessorId = predecessor->predecessors.siblingPrev;
							if (!ComparePostfix(firstTraceExec, GetTraceExec(predecessor->traceExecRef), postfix + 1))
							{
								if (failureReasons)
								{
									failureReasons->Add(L"Another predecessor " +
										itow(predecessor->allocatedIndex) +
										L" has no StackEnd or has a different postfix.");
								}
								goto CHECK_OBJECTS_IN_TOP_CREATE_STACK;
							}
						}
					}

					// check if all StackEnd ended objects are the result of ambiguity
					if (postfix == 0)
					{
						// if StackEnd is the last instruction of predecessors
						// then their objRefs has been written to the top object stack
						if (failureReasons)
						{
							failureReasons->Add(L"The postfix is 0, compare all concurrent objects in the objectStack top.");
						}
						auto ieOSTop = GetInsExec_StackArrayRefLink(traceExec->context.objectStack);
						auto succeeded = CheckAmbiguityResolution(ta, visitingIds, failureReasons, [=](auto&& callback)
						{
							return callback(ieOSTop->ids);
						});
						if (succeeded) return true;
					}
					else
					{
						// otherwise find all objRefs of StackEnd
						if (failureReasons)
						{
							failureReasons->Add(L"The postfix > 0, compare all concurrent objects in all StackEnd instructions.");
						}
						auto succeeded = CheckAmbiguityResolution(ta, visitingIds, failureReasons, [=, this, &visitingIds](auto&& callback)
						{
							auto predecessorId = trace->predecessors.first;
							while (predecessorId != nullref)
							{
								auto predecessor = GetTrace(predecessorId);
								predecessorId = predecessor->predecessors.siblingNext;

								// search for the object it ends
								if (failureReasons)
								{
									failureReasons->Add(L"Verifying predecessor " +
										itow(predecessor->allocatedIndex) +
										L".");
								}
								auto predecessorTraceExec = GetTraceExec(predecessor->traceExecRef);
								auto indexEO = predecessorTraceExec->insLists.countAll - postfix - 1;
								auto insExecEO = GetInsExec(predecessorTraceExec->insExecRefs.start + indexEO);
								if (!callback(insExecEO->operatingStacks)) return false;
							}
							return true;
						});
						if (succeeded) return true;
					}
				}
			CHECK_OBJECTS_IN_TOP_CREATE_STACK:
				if (failureReasons)
				{
					failureReasons->Add(L"All condition dissatisfied, compare all concurrent objects in the createStack top.");
				}
				auto ieCSTop = GetInsExec_StackArrayRefLink(traceExec->context.createStack);
				return CheckAmbiguityResolution(ta, visitingIds, failureReasons, [=](auto&& callback)
				{
					return callback(ieCSTop->ids);
				});
			}

/***********************************************************************
LinkAmbiguityCriticalTrace
***********************************************************************/

			void TraceManager::LinkAmbiguityCriticalTrace(Ref<Trace> traceId)
			{
				auto trace = GetTrace(traceId);
				auto forward = GetTrace(GetTraceExec(trace->traceExecRef)->branchData.forwardTrace);
				if (trace == forward) return;

				auto nextAct = &GetTraceExec(forward->traceExecRef)->nextAmbiguityCriticalTrace;
				while (*nextAct != nullref)
				{
					if (*nextAct == traceId) return;
					if (*nextAct > traceId) break;
					nextAct = &GetTraceExec(GetTrace(*nextAct)->traceExecRef)->nextAmbiguityCriticalTrace;
				}

				auto traceExec = GetTraceExec(trace->traceExecRef);
				traceExec->nextAmbiguityCriticalTrace = *nextAct;
				*nextAct = traceId;
			}

/***********************************************************************
CheckTraceAmbiguity
***********************************************************************/

			void TraceManager::CheckTraceAmbiguity(TraceAmbiguity* ta)
			{
#define TRACE_MAMAGER_PHRASE L"ResolveAmbiguity/CheckMergeTraces/CheckTraceAmbiguity"
				auto teFirst = GetTraceExec(GetTrace(ta->firstTrace)->traceExecRef);

				if (teFirst->ambiguityBegins == nullref)
				{
					LinkAmbiguityCriticalTrace(ta->firstTrace);
				}

				// search in all ambiguityBegins and try to find one has the same lastTrace
				TraceAmbiguityLink* taLinkToOverride = nullptr;
				auto taLinkRef = teFirst->ambiguityBegins;
				while (taLinkRef != nullref)
				{
					auto taLink = GetTraceAmbiguityLink(taLinkRef);
					taLinkRef = taLink->previous;

					auto ta2 = GetTraceAmbiguity(taLink->ambiguity);
					if (ta->lastTrace == ta2->lastTrace)
					{
						// if there is any, try to override this TraceAmbiguity
						taLinkToOverride = taLink;
						break;
					}
				}

				if (taLinkToOverride)
				{
					// if there is a TraceAmbiguity to override
					// ensure they are equivalent
					auto ta2 = GetTraceAmbiguity(taLinkToOverride->ambiguity);
					if (ta2->prefix != ta->prefix || ta2->postfix != ta->postfix)
					{
						throw TraceException(*this, ta, ta2, TRACE_MAMAGER_PHRASE, L"Incompatible TraceAmbiguity has been assigned at the same place");
					}
					// override ambiguityBegins
					taLinkToOverride->ambiguity = ta;

					// override TraceAmbiguity
					ta->overridedAmbiguity = ta2;
				}
				else
				{
					// otherwise, append itself to the list
					auto taLink = GetTraceAmbiguityLink(traceAmbiguityLinks.Allocate());
					taLink->ambiguity = ta;
					taLink->previous = teFirst->ambiguityBegins;
					teFirst->ambiguityBegins = taLink;
				}
#undef TRACE_MAMAGER_PHRASE
			}

/***********************************************************************
CategorizeTraceAmbiguities
***********************************************************************/

			void TraceManager::MarkAmbiguityCoveredForward(Trace* currentTrace, TraceAmbiguity* ta, Trace* firstTrace, TraceExec* firstTraceExec)
			{
#define TRACE_MAMAGER_PHRASE L"ResolveAmbiguity/CheckMergeTraces/MarkAmbiguityCoveredForward"
				while (true)
				{
					auto forward = GetTrace(GetTraceExec(currentTrace->traceExecRef)->branchData.forwardTrace);
					if (forward->traceExecRef <= firstTraceExec)
					{
						throw TraceException(*this, forward, nullptr, TRACE_MAMAGER_PHRASE, L"Unexpected ambiguity resolving structure found.");
					}

					auto forwardExec = GetTraceExec(forward->traceExecRef);
					if (forward->predecessors.first != forward->predecessors.last)
					{
						if (forwardExec->ambiguityDetected != nullref && forwardExec->ambiguityDetected != ta)
						{
							currentTrace = GetTrace(GetTraceAmbiguity(forwardExec->ambiguityDetected)->firstTrace);
						}
						else
						{
							auto predecessorId = forward->predecessors.first;
							while (predecessorId != nullref)
							{
								auto predecessor = GetTrace(predecessorId);
								predecessorId = predecessor->predecessors.siblingNext;
								MarkAmbiguityCoveredForward(predecessor, ta, firstTrace, firstTraceExec);
							}
							return;
						}
					}
					else if (forward->predecessors.first != firstTrace)
					{
						currentTrace = GetTrace(forward->predecessors.first);
					}
					else
					{
						return;
					}
				}
#undef TRACE_MAMAGER_PHRASE
			}

			void TraceManager::CategorizeTraceAmbiguities(Trace* trace, TraceExec* traceExec)
			{
				// find all ambiguityBegins whose first ambiguity instruction is in successors
				auto taLinkRef = traceExec->ambiguityBegins;
				while (taLinkRef != nullref)
				{
					auto taLink = GetTraceAmbiguityLink(taLinkRef);
					taLinkRef = taLink->previous;

					auto ta = GetTraceAmbiguity(taLink->ambiguity);
					if (ta->prefix >= traceExec->insLists.countAll)
					{
						// mark ambiguityCoveredInForward
						MarkAmbiguityCoveredForward(GetTrace(ta->lastTrace), ta, trace, traceExec);
					}
				}
			}

/***********************************************************************
CheckMergeTraces
***********************************************************************/

			void TraceManager::CheckMergeTraces()
			{
#define TRACE_MAMAGER_PHRASE L"ResolveAmbiguity/CheckMergeTraces"
				// mark all branch trace critical
				{
					auto traceId = firstBranchTrace;
					while (traceId != nullref)
					{
						LinkAmbiguityCriticalTrace(traceId);
						traceId = GetTraceExec(GetTrace(traceId)->traceExecRef)->nextBranchTrace;
					}
				}

				// mark all predecessor of merge trace critical
				{
					auto traceId = firstMergeTrace;
					while (traceId != nullref)
					{
						auto trace = GetTrace(traceId);
						auto predecessorId = trace->predecessors.first;
						while (predecessorId != nullref)
						{
							LinkAmbiguityCriticalTrace(predecessorId);
							predecessorId = GetTrace(predecessorId)->predecessors.siblingNext;
						}
						traceId = GetTraceExec(trace->traceExecRef)->nextMergeTrace;
					}
				}

				// iterating TraceMergeExec
				List<Ref<InsExec_StackRefLink>> visitingIds;
				auto traceId = firstMergeTrace;
				while (traceId != nullref)
				{
					auto trace = GetTrace(traceId);
					auto traceExec = GetTraceExec(trace->traceExecRef);
					traceId = traceExec->nextMergeTrace;

					auto ta = GetTraceAmbiguity(traceAmbiguities.Allocate());
					bool succeeded = CheckSingleMergeTrace(ta, trace, traceExec, visitingIds, nullptr);
					if (!succeeded)
					{
						List<WString> failureReasons;
						CheckSingleMergeTrace(ta, trace, traceExec, visitingIds, &failureReasons);

						throw TraceException(*this, trace, nullptr, TRACE_MAMAGER_PHRASE, stream::GenerateToStream([&](stream::TextWriter& writer)
						{
							writer.WriteLine(L"Failed to find ambiguous objects in a merge trace.");
							writer.WriteLine(L"[Details]");
							for (auto&& reason : failureReasons)
							{
								writer.WriteLine(reason);
							}
						}));
					}
					traceExec->ambiguityDetected = ta;

					// record branch and merge trace
					ta->mergeTrace = trace;
					{
						auto currentBranchTrace = trace;
						auto predecessorRef = trace->predecessors.first;
						while (predecessorRef != nullref)
						{
							// when traces look like this
							// the first predecessor locates B while the correct one should be A
							// so all predecessors need to test
							// 
							//   A
							//   |
							// +-+-+
							// |   |
							// B   C
							// |   |
							// +-+ |
							// | | |
							// D E F
							// | | |
							// +-+-+
							// |
							// G

							auto predecessor = GetTrace(predecessorRef);
							predecessorRef = predecessor->predecessors.siblingNext;

							Trace* branchTrace = nullptr;
							auto predecessorForward = GetTrace(GetTraceExec(predecessor->traceExecRef)->branchData.forwardTrace);
							if (predecessorForward->predecessors.first == predecessorForward->predecessors.last)
							{
								branchTrace = predecessorForward;
							}
							else
							{
								branchTrace = GetTrace(GetTraceExec(predecessorForward->traceExecRef)->branchData.commonForwardBranch);
							}

							// when traces look like this
							// some branchTrace may be the root, ignores
							// 
							//   A
							//   |
							// +-+-+
							// | | |
							// B C D
							// | | |
							// +-+ |
							// |   |
							// E   F
							// |   |
							// +---+
							// |
							// G

							if (branchTrace->predecessors.first != nullref)
							{
								branchTrace = GetTrace(branchTrace->predecessors.first);
								if (currentBranchTrace->traceExecRef > branchTrace->traceExecRef)
								{
									currentBranchTrace = branchTrace;
								}
							}
						}
						ta->branchTrace = currentBranchTrace;
					}
					if (ta->firstTrace == ta->mergeTrace)
					{
						throw TraceException(*this, trace, nullptr, TRACE_MAMAGER_PHRASE, L"Failed to find TraceAmbiguity::branchTrace.");
					}

					// check if existing TraceAmbiguity in firstTrace are compatible
					CheckTraceAmbiguity(ta);
				}

				// find all branch trace with ambiguityBegins
				{
					auto traceId = firstBranchTrace;
					while (traceId != nullref)
					{
						auto trace = GetTrace(traceId);
						auto traceExec = GetTraceExec(trace->traceExecRef);
						traceId = traceExec->nextBranchTrace;

						if (traceExec->ambiguityBegins != nullref)
						{
							CategorizeTraceAmbiguities(trace, traceExec);
						}
					}
				}
#undef TRACE_MAMAGER_PHRASE
			}

#undef NEW_MERGE_STACK_MAGIC_COUNTER
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TRACEMANAGER.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{

/***********************************************************************
TraceManager
***********************************************************************/

			void TraceManager::BeginSwap()
			{
				concurrentCount = 0;
			}

			void TraceManager::AddTrace(Trace* trace)
			{
				if (concurrentCount < backupTraces->Count())
				{
					backupTraces->Set(concurrentCount, trace);
				}
				else
				{
					backupTraces->Add(trace);
				}
				concurrentCount++;
			}

			void TraceManager::EndSwap()
			{
				auto t = concurrentTraces;
				concurrentTraces = backupTraces;
				backupTraces = t;
			}

			void TraceManager::AddTraceToCollection(Trace* owner, Trace* element, TraceCollection(Trace::* collection))
			{
				auto errorMessage = L"vl::glr::automaton::TraceManager::AddTraceToCollection(Trace*, Trace*, TraceCollection(Trace::*))#Multiple to multiple predecessor-successor relationship is not supported.";
				auto&& elementCollection = element->*collection;
				if (elementCollection.siblingNext == nullref && elementCollection.siblingPrev == nullref)
				{
					auto&& ownerCollection = owner->*collection;
					if (ownerCollection.first == nullref)
					{
						ownerCollection.first = element;
						ownerCollection.last = element;
					}
					else
					{
						auto sibling = GetTrace(ownerCollection.last);
						auto&& siblingCollection = sibling->*collection;
						CHECK_ERROR(siblingCollection.siblingNext == nullref, errorMessage);

						siblingCollection.siblingNext = element;
						elementCollection.siblingPrev = sibling;
						ownerCollection.last = element;
					}
				}
				else if (collection == &Trace::predecessors)
				{
					// there is a valid scenario when
					//                B(ending) ---+
					//                             |
					// O(origin) -+-> A(ending) -+-+-> C(merged)
					//                           |
					//                           +---> D(token)

					// in this case, we need to copy A(ending) to avoid the multiple to multiple relationship
					// the reason we cannot have such relationship is that
					// TraceCollection::(siblingPrev|siblingNext) is a linked list
					// it represents a predecessor collections of owner
					// if a trace is shared in two predecessor collections
					// there is no place for a second linked list
					// the data structure is not able to represent such relationship

					// but this it is not doable if A also has multiple predecessors
					// because copying A replaces a new multiple to multiple relationship to an old one like this
					// O1(origin) -+-+   B(ending) -+
					//             | |              |
					// O2(origin) -+-+-> A(ending) -+-> C(merged)
					//             |
					//             +---> X(ending) ---> D(token)
					CHECK_ERROR(element->predecessors.first == element->predecessors.last, errorMessage);

					auto copiedElement = AllocateTrace();
					{
						vint32_t copiedId = copiedElement->allocatedIndex;
						*copiedElement = *element;
						copiedElement->allocatedIndex = copiedId;
					}

					// clear sibilingPrev and sibilingNext because it belongs to no collection at this moment
					// keep first and last so that it still knows its predecessors
					copiedElement->predecessors.siblingPrev = nullref;
					copiedElement->predecessors.siblingNext = nullref;

					// now it becomes
					//                B(ending) -+
					//                           |
					// O(origin) -+-> A(ending) -+-> C(merged)
					//            |
					//            +-> X(ending) ---> D(token)
					AddTraceToCollection(owner, copiedElement, collection);
				}
				else
				{
					// Trace::predecessors is filled by Input
					// Trace::successors is filled by EndOfInput
					// if Input and EndOfInput succeeded
					// there should not be any multiple to multiple relationship
					CHECK_FAIL(errorMessage);
				}
			}

			TraceManager::TraceManager(Executable& _executable, const ITypeCallback* _typeCallback, vint blockSize)
				: executable(_executable)
				, typeCallback(_typeCallback)
				, returnStacks(blockSize)
				, traces(blockSize)
				, competitions(blockSize)
				, attendingCompetitions(blockSize)
				, traceExecs(blockSize)
				, insExec_Stacks(blockSize)
				, insExec_InsRefLinks(blockSize)
				, insExec_StackRefLinks(blockSize)
				, insExec_StackArrayRefLinks(blockSize)
				, traceAmbiguities(blockSize)
				, traceAmbiguityLinks(blockSize)
				, executionSteps(blockSize)
			{
			}

			ReturnStack* TraceManager::GetReturnStack(Ref<ReturnStack> index)
			{
				return returnStacks.Get(index);
			}

			ReturnStack* TraceManager::AllocateReturnStack()
			{
				return returnStacks.Get(returnStacks.Allocate());
			}

			Trace* TraceManager::GetTrace(Ref<Trace> index)
			{
				return traces.Get(index);
			}

			Trace* TraceManager::AllocateTrace()
			{
				return traces.Get(traces.Allocate());
			}

			Competition* TraceManager::GetCompetition(Ref<Competition> index)
			{
				return competitions.Get(index);
			}

			Competition* TraceManager::AllocateCompetition()
			{
				return competitions.Get(competitions.Allocate());
			}

			AttendingCompetitions* TraceManager::GetAttendingCompetitions(Ref<AttendingCompetitions> index)
			{
				return attendingCompetitions.Get(index);
			}

			AttendingCompetitions* TraceManager::AllocateAttendingCompetitions()
			{
				return attendingCompetitions.Get(attendingCompetitions.Allocate());
			}

			InsExec* TraceManager::GetInsExec(vint32_t index)
			{
				return &insExecs[index];
			}

			InsExec_Stack* TraceManager::GetInsExec_Stack(Ref<InsExec_Stack> index)
			{
				return insExec_Stacks.Get(index);
			}

			InsExec_InsRefLink* TraceManager::GetInsExec_InsRefLink(Ref<InsExec_InsRefLink> index)
			{
				return insExec_InsRefLinks.Get(index);
			}

			InsExec_StackRefLink* TraceManager::GetInsExec_StackRefLink(Ref<InsExec_StackRefLink> index)
			{
				return insExec_StackRefLinks.Get(index);
			}

			InsExec_StackArrayRefLink* TraceManager::GetInsExec_StackArrayRefLink(Ref<InsExec_StackArrayRefLink	> index)
			{
				return insExec_StackArrayRefLinks.Get(index);
			}

			TraceExec* TraceManager::GetTraceExec(Ref<TraceExec> index)
			{
				return traceExecs.Get(index);
			}

			TraceAmbiguity* TraceManager::GetTraceAmbiguity(Ref<TraceAmbiguity> index)
			{
				return traceAmbiguities.Get(index);
			}

			TraceAmbiguityLink* TraceManager::GetTraceAmbiguityLink(Ref<TraceAmbiguityLink> index)
			{
				return traceAmbiguityLinks.Get(index);
			}

			ExecutionStep* TraceManager::GetExecutionStep(Ref<ExecutionStep> index)
			{
				return executionSteps.Get(index);
			}

/***********************************************************************
CreateExecutor
***********************************************************************/

			Ptr<IExecutor> CreateExecutor(Executable& executable, const IExecutor::ITypeCallback* typeCallback, vint blockSize)
			{
				return Ptr(new TraceManager(executable, typeCallback, blockSize));
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TRACEMANAGER_COMMON.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
ReadInstructionList
***********************************************************************/

			void TraceManager::ReadInstructionList(Trace* trace, TraceInsLists& insLists)
			{
				// this function collects the following instructions in order:
				//   2) byEdge.insAfterInput
				//   3) executedReturnStack.returnIndex.insAfterInput in order
				if (trace->byEdge != -1)
				{
					auto& edgeDesc = executable.edges[trace->byEdge];
					insLists.edgeInsAfterInput = edgeDesc.insAfterInput;
				}
				else
				{
					insLists.edgeInsAfterInput = {};
				}
				if (trace->executedReturnStack != nullref)
				{
					auto returnStack = GetReturnStack(trace->executedReturnStack);
					auto& returnDesc = executable.returns[returnStack->returnIndex];
					insLists.returnInsAfterInput = returnDesc.insAfterInput;
				}
				else
				{
					insLists.returnInsAfterInput = {};
				}

				insLists.countAfterInput = (vint32_t)(insLists.edgeInsAfterInput.count);
				insLists.countAll = (vint32_t)(insLists.countAfterInput + insLists.returnInsAfterInput.count);
			}

/***********************************************************************
ReadInstruction
***********************************************************************/

			AstIns& TraceManager::ReadInstruction(vint32_t instruction, TraceInsLists& insLists)
			{
				// access the instruction object from a trace
				// the index is the instruction in a virtual instruction array
				// defined by all InstructionArray in TraceInsLists combined together
#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::ReadInstruction(vint, TraceInsLists&)#"
				CHECK_ERROR(0 <= instruction && instruction < insLists.countAll, ERROR_MESSAGE_PREFIX L"Instruction index out of range.");

				vint32_t insRef = -1;
				if (instruction < insLists.countAfterInput)
				{
					insRef = insLists.edgeInsAfterInput.start + instruction;
				}
				else if (instruction < insLists.countAll)
				{
					insRef = insLists.returnInsAfterInput.start + (instruction - insLists.countAfterInput);
				}
				else
				{
					CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Instruction index out of range.");
				}

				return executable.astInstructions[insRef];
#undef ERROR_MESSAGE_PREFIX
			}
		}
	}
}

/***********************************************************************
.\TRACEMANAGER\TRACEMANAGER_EXECUTETRACE.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
TraceManager::ExecuteTrace
***********************************************************************/

#define ERROR_MESSAGE_PREFIX L"vl::glr::automaton::TraceManager::ExecuteTrace(Trace*, IAstInsReceiver&, List<RegexToken>&)#"

			class AstInsOptimizer : public Object, public virtual IAstInsReceiver
			{
			protected:
				IAstInsReceiver&				receiver;

				bool							cachedStackBegin = false;
				const regex::RegexToken*		cachedStackBeginToken = nullptr;
				vint32_t						cachedStackBeginTokenIndex = -1;

			public:
				AstInsOptimizer(IAstInsReceiver& _receiver)
					:receiver(_receiver)
				{
				}

				void Execute(AstIns instruction, const regex::RegexToken& token, vint32_t tokenIndex) override
				{
					if (cachedStackBegin)
					{
						if (instruction.type == AstInsType::StackEnd)
						{
							cachedStackBegin = false;
							return;
						}

						receiver.Execute({ AstInsType::StackBegin }, *cachedStackBeginToken, cachedStackBeginTokenIndex);
						cachedStackBegin = false;
					}

					if (instruction.type == AstInsType::StackBegin)
					{
						cachedStackBegin = true;
						cachedStackBeginToken = &token;
						cachedStackBeginTokenIndex = tokenIndex;
						return;
					}

					receiver.Execute(instruction, token, tokenIndex);
				}

				Ptr<ParsingAstBase> Finished() override
				{
					if (cachedStackBegin)
					{
						receiver.Execute({ AstInsType::StackBegin }, *cachedStackBeginToken, cachedStackBeginTokenIndex);
						cachedStackBegin = false;
					}
					return receiver.Finished();
				}
			};

			void TraceManager::ExecuteSingleTrace(IAstInsReceiver& receiver, Trace* trace, vint32_t firstIns, vint32_t lastIns, TraceInsLists& insLists, collections::List<regex::RegexToken>& tokens)
			{
				for (vint32_t i = firstIns; i <= lastIns; i++)
				{
					auto& ins = ReadInstruction(i, insLists);
					auto& token = tokens[trace->currentTokenIndex];
					receiver.Execute(ins, token, trace->currentTokenIndex);
				}
			}

			void TraceManager::ExecuteSingleStep(IAstInsReceiver& receiver, ExecutionStep* step, collections::List<regex::RegexToken>& tokens)
			{
				TraceInsLists temp;

				switch (step->type)
				{
				case ExecutionType::Instruction:
					{
						// execute from the start trace
						auto trace = GetTrace(Ref<Trace>(step->et_i.startTrace));

						while (trace)
						{
							vint32_t firstIns = -1;
							vint32_t lastIns = -1;
							auto insLists = &temp;
							if (trace->traceExecRef == nullref)
							{
								ReadInstructionList(trace, temp);
							}
							else
							{
								insLists = &GetTraceExec(trace->traceExecRef)->insLists;
							}

							// find instruction range to execute
							if (trace->allocatedIndex == step->et_i.startTrace)
							{
								firstIns = step->et_i.startIns;
							}
							else
							{
								firstIns = 0;
							}

							if (trace->allocatedIndex == step->et_i.endTrace)
							{
								lastIns = step->et_i.endIns;
							}
							else
							{
								lastIns = insLists->countAll - 1;
							}

							// execute instructions
							ExecuteSingleTrace(receiver, trace, firstIns, lastIns, *insLists, tokens);

							// find the next trace
							if (step->et_i.endTrace == trace->allocatedIndex)
							{
								break;
							}
							else if (trace->successors.first == nullref)
							{
								CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Successor trace missing!");
							}
							else if (trace->successors.first == trace->successors.last)
							{
								trace = GetTrace(trace->successors.first);
							}
							else
							{
								CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Ambiguity should not happen inside one execution step!");
							}
						}
					}
					break;
				default:
					{
						auto raTrace = GetTrace(Ref<Trace>(step->et_ra.trace));
						raTrace = EnsureTraceWithValidStates(raTrace);
						auto raToken = raTrace->currentTokenIndex;

						switch (step->type)
						{
						case ExecutionType::RA_Begin:
							{
								if (raToken == -1) raToken = 0;
								AstIns ins = { AstInsType::StackBegin };
								receiver.Execute(ins, tokens[raToken], raToken);
							}
							break;
						case ExecutionType::RA_Branch:
							{
								AstIns ins = { AstInsType::StackSlot,-1,ResolveAmbiguitySlotIndex };
								receiver.Execute(ins, tokens[raToken], raToken);
							}
							break;
						case ExecutionType::RA_End:
							{
								AstIns ins = { AstInsType::ResolveAmbiguity,step->et_ra.type,0 };
								receiver.Execute(ins, tokens[raToken], raToken);
							}
							{
								AstIns ins = { AstInsType::StackEnd };
								receiver.Execute(ins, tokens[raToken], raToken);
							}
							break;
						default:;
						}
					}
				}
			}

			Ptr<ParsingAstBase> TraceManager::ExecuteTrace(IAstInsReceiver& receiver, collections::List<regex::RegexToken>& tokens)
			{
				CHECK_ERROR(state == TraceManagerState::ResolvedAmbiguity, ERROR_MESSAGE_PREFIX L"Wrong timing to call this function.");

				// execute from the first step
				AstInsOptimizer optimizedReceiver(receiver);
				auto step = GetInitialExecutionStep();
				CHECK_ERROR(step != nullptr, L"Internal error: execution steps not built!");
				while (step)
				{
					// execute step
					ExecuteSingleStep(optimizedReceiver, step, tokens);

					// find the next step
					step = step->next == nullref ? nullptr : GetExecutionStep(step->next);
				}

				return optimizedReceiver.Finished();
			}
#undef ERROR_MESSAGE_PREFIX
		}
	}
}

/***********************************************************************
.\XML\GLRXML.CPP
***********************************************************************/

namespace vl
{
	namespace glr
	{
		namespace xml
		{
			using namespace stream;
			using namespace collections;
			using namespace regex;

/***********************************************************************
XmlUnescapeVisitor
***********************************************************************/

			class XmlUnescapeVisitor : public traverse_visitor::AstVisitor
			{
			protected:
				List<RegexToken>&					tokens;

			public:
				XmlUnescapeVisitor(List<RegexToken>& _tokens)
					:tokens(_tokens)
				{
				}

			protected:
				void Traverse(XmlAttribute* node) override
				{
					node->value.value = XmlUnescapeValue(node->value.value.Sub(1, node->value.value.Length() - 2));
				}

				void Traverse(XmlCData* node) override
				{
					node->content.value = XmlUnescapeCData(node->content.value);
				}

				void Traverse(XmlComment* node) override
				{
					node->content.value = XmlUnescapeComment(node->content.value);
				}

				void Traverse(XmlElement* node) override
				{
					vint begin = -1;
					vint end = -1;
					for (vint i = node->subNodes.Count() - 1; i >= -1; i--)
					{
						if (i == -1)
						{
							if (end != -1) begin = 0;
						}
						else if (node->subNodes[i].Cast<XmlText>())
						{
							if (end == -1) end = i;
						}
						else
						{
							if (end != -1) begin = i + 1;
						}
						if (begin != -1 && end != -1)
						{
							vint beginTokenIndex = node->subNodes[begin].Cast<XmlText>()->content.index;
							vint endTokenIndex = node->subNodes[end].Cast<XmlText>()->content.index;

							auto& beginToken = tokens[beginTokenIndex];
							auto& endToken = tokens[endTokenIndex];

							auto textBegin = beginToken.reading;
							auto textEnd = endToken.reading + endToken.length;

							if (beginTokenIndex > 0)
							{
								auto& previousToken = tokens[beginTokenIndex - 1];
								textBegin = previousToken.reading + previousToken.length;
							}

							if (endTokenIndex < tokens.Count() - 1)
							{
								auto& nextToken = tokens[endTokenIndex + 1];
								textEnd = nextToken.reading;
							}

							WString text = WString::CopyFrom(textBegin, vint(textEnd - textBegin));
							ParsingTextRange range(&beginToken, &endToken);

							auto xmlText = Ptr(new XmlText);
							xmlText->codeRange = range;
							xmlText->content.codeRange = range;
							xmlText->content.value = XmlUnescapeValue(text);

							node->subNodes.RemoveRange(begin, end - begin + 1);
							node->subNodes.Insert(begin, xmlText);

							begin = -1;
							end = -1;
						}
					}
				}
			};

/***********************************************************************
XmlPrintVisitor
***********************************************************************/

			class XmlPrintVisitor : public Object, public XmlNode::IVisitor
			{
			public:
				TextWriter&					writer;

				XmlPrintVisitor(TextWriter& _writer)
					:writer(_writer)
				{
				}

				void Visit(XmlText* node)
				{
					writer.WriteString(XmlEscapeValue(node->content.value));
				}

				void Visit(XmlCData* node)
				{
					writer.WriteString(XmlEscapeCData(node->content.value));
				}

				void Visit(XmlAttribute* node)
				{
					writer.WriteString(node->name.value);
					writer.WriteString(L"=\"");
					writer.WriteString(XmlEscapeValue(node->value.value));
					writer.WriteString(L"\"");
				}

				void Visit(XmlComment* node)
				{
					writer.WriteString(XmlEscapeComment(node->content.value));
				}

				void Visit(XmlElement* node)
				{
					writer.WriteChar(L'<');
					writer.WriteString(node->name.value);
					for (auto att : node->attributes)
					{
						writer.WriteChar(L' ');
						Visit(att.Obj());
					}
					if(node->subNodes.Count()==0)
					{
						writer.WriteString(L"/>");
					}
					else
					{
						writer.WriteChar(L'>');
						for (auto subNode : node->subNodes)
						{
							subNode->Accept(this);
						}
						writer.WriteString(L"</");
						writer.WriteString(node->name.value);
						writer.WriteChar(L'>');
					}
				}

				void Visit(XmlInstruction* node)
				{
					writer.WriteString(L"<?");
					writer.WriteString(node->name.value);
					for (auto att : node->attributes)
					{
						writer.WriteChar(L' ');
						Visit(att.Obj());
					}
					writer.WriteString(L"?>");
				}

				void Visit(XmlDocument* node)
				{
					for (auto prolog : node->prologs)
					{
						prolog->Accept(this);
					}
					node->rootElement->Accept(this);
				}
			};

/***********************************************************************
Escaping and Unescaping
***********************************************************************/

			WString XmlEscapeValue(const WString& value)
			{
				WString result;
				const wchar_t* reading = value.Buffer();
				while (wchar_t c = *reading++)
				{
					switch (c)
					{
					case L'<':
						result += L"&lt;";
						break;
					case L'>':
						result += L"&gt;";
						break;
					case L'&':
						result += L"&amp;";
						break;
					case L'\'':
						result += L"&apos;";
						break;
					case L'\"':
						result += L"&quot;";
						break;
					default:
						result += WString::FromChar(c);
					}
				}
				return result;
			}

			WString XmlUnescapeValue(const WString& value)
			{
				WString result;
				const wchar_t* reading = value.Buffer();
				while (*reading)
				{
					if (wcsncmp(reading, L"&lt;", 4) == 0)
					{
						result += WString::FromChar(L'<');
						reading += 4;
					}
					else if (wcsncmp(reading, L"&gt;", 4) == 0)
					{
						result += WString::FromChar(L'>');
						reading += 4;
					}
					else if (wcsncmp(reading, L"&amp;", 5) == 0)
					{
						result += WString::FromChar(L'&');
						reading += 5;
					}
					else if (wcsncmp(reading, L"&apos;", 6) == 0)
					{
						result += WString::FromChar(L'\'');
						reading += 6;
					}
					else if (wcsncmp(reading, L"&quot;", 6) == 0)
					{
						result += WString::FromChar(L'\"');
						reading += 6;
					}
					else
					{
						result += WString::FromChar(*reading++);
					}
				}
				return result;
			}

			WString XmlEscapeCData(const WString& value)
			{
				return L"<![CDATA[" + value + L"]]>";
			}

			WString XmlUnescapeCData(const WString& value)
			{
				return value.Sub(9, value.Length() - 12);
			}

			WString XmlEscapeComment(const WString& value)
			{
				return L"<!--" + value + L"-->";
			}

			WString XmlUnescapeComment(const WString& value)
			{
				return value.Sub(4, value.Length() - 7);
			}

/***********************************************************************
Parsing and Printing
***********************************************************************/

			Ptr<XmlDocument> XmlParseDocument(const WString& input, const Parser& parser)
			{
				List<RegexToken> tokens;
				parser.Tokenize(input, tokens);
				auto ast = parser.ParseXDocument(tokens);
				XmlUnescapeVisitor(tokens).InspectInto(ast.Obj());
				return ast;
			}

			Ptr<XmlElement> XmlParseElement(const WString& input, const Parser& parser)
			{
				List<RegexToken> tokens;
				parser.Tokenize(input, tokens);
				auto ast = parser.ParseXElement(tokens);
				XmlUnescapeVisitor(tokens).InspectInto(ast.Obj());
				return ast;
			}

			void XmlPrint(Ptr<XmlNode> node, stream::TextWriter& writer)
			{
				XmlPrintVisitor visitor(writer);
				node->Accept(&visitor);
			}

			void XmlPrintContent(Ptr<XmlElement> element, stream::TextWriter& writer)
			{
				XmlPrintVisitor visitor(writer);
				for (auto node : element->subNodes)
				{
					node->Accept(&visitor);
				}
			}

			WString XmlToString(Ptr<XmlNode> node)
			{
				return GenerateToStream([&](StreamWriter& writer)
				{
					XmlPrint(node, writer);
				});
			}

/***********************************************************************
Utility
***********************************************************************/

			Ptr<XmlAttribute> XmlGetAttribute(Ptr<XmlElement> element, const WString& name)
			{
				return XmlGetAttribute(element.Obj(), name);
			}

			Ptr<XmlElement> XmlGetElement(Ptr<XmlElement> element, const WString& name)
			{
				return XmlGetElement(element.Obj(), name);
			}

			collections::LazyList<Ptr<XmlElement>> XmlGetElements(Ptr<XmlElement> element)
			{
				return XmlGetElements(element.Obj());
			}

			collections::LazyList<Ptr<XmlElement>> XmlGetElements(Ptr<XmlElement> element, const WString& name)
			{
				return XmlGetElements(element.Obj(), name);
			}

			WString XmlGetValue(Ptr<XmlElement> element)
			{
				return XmlGetValue(element.Obj());
			}

			Ptr<XmlAttribute> XmlGetAttribute(XmlElement* element, const WString& name)
			{
				for (auto att : element->attributes)
				{
					if (att->name.value == name)
					{
						return att;
					}
				}
				return nullptr;
			}

			Ptr<XmlElement> XmlGetElement(XmlElement* element, const WString& name)
			{
				for (auto node : element->subNodes)
				{
					Ptr<XmlElement> subElement = node.Cast<XmlElement>();
					if (subElement && subElement->name.value == name)
					{
						return subElement;
					}
				}
				return nullptr;
			}

			collections::LazyList<Ptr<XmlElement>> XmlGetElements(XmlElement* element)
			{
				return From(element->subNodes).FindType<XmlElement>();
			}

			collections::LazyList<Ptr<XmlElement>> XmlGetElements(XmlElement* element, const WString& name)
			{
				return XmlGetElements(element)
					.Where([name](auto&& e) {return e->name.value == name; });
			}

			WString XmlGetValue(XmlElement* element)
			{
				WString result;
				for (auto node : element->subNodes)
				{
					if (auto text = node.Cast<XmlText>())
					{
						result += text->content.value;
					}
					else if (auto text = node.Cast<XmlCData>())
					{
						result += text->content.value;
					}
				}
				return result;
			}

/***********************************************************************
XmlElementListSerializer
***********************************************************************/

			void XmlElementListSerializer::Serialize(Ptr<Parser> parser, const SourceType& source, DestType& dest)
			{
				auto array = Ptr(new XmlElement);
				array->name.value = L"Array";
				for (auto&& element : source)
				{
					array->subNodes.Add(element);
				}
				dest = GenerateToStream([&](StreamWriter& writer)
				{
					XmlPrint(array, writer);
				});
			}

			void XmlElementListSerializer::Deserialize(Ptr<Parser> parser, const DestType& source, SourceType& dest)
			{
				auto array = XmlParseElement(source, *parser.Obj());
				auto elements = XmlGetElements(array);

				dest.Clear();
				for (auto&& element : elements)
				{
					dest.Add(element);
				}
			}

/***********************************************************************
XmlElementWriter
***********************************************************************/

			XmlElementWriter::XmlElementWriter(Ptr<XmlElement> _element, const XmlElementWriter* _previousWriter)
				: element(_element)
				, previousWriter(_previousWriter)
			{
			}

			XmlElementWriter::~XmlElementWriter()
			{
			}

			const XmlElementWriter& XmlElementWriter::Attribute(const WString& name, const WString& value)const
			{
				auto node = Ptr(new XmlAttribute);
				node->name.value = name;
				node->value.value = value;
				element->attributes.Add(node);
				return *this;
			}

			XmlElementWriter XmlElementWriter::Element(const WString& name)const
			{
				auto node = Ptr(new XmlElement);
				node->name.value = name;
				element->subNodes.Add(node);
				return XmlElementWriter(node, this);
			}

			const XmlElementWriter& XmlElementWriter::End()const
			{
				return *previousWriter;
			}

			const XmlElementWriter& XmlElementWriter::Text(const WString& value)const
			{
				auto node = Ptr(new XmlText);
				node->content.value = value;
				element->subNodes.Add(node);
				return *this;
			}

			const XmlElementWriter& XmlElementWriter::CData(const WString& value)const
			{
				auto node = Ptr(new XmlCData);
				node->content.value = value;
				element->subNodes.Add(node);
				return *this;
			}

			const XmlElementWriter& XmlElementWriter::Comment(const WString& value)const
			{
				auto node = Ptr(new XmlComment);
				node->content.value = value;
				element->subNodes.Add(node);
				return *this;
			}
		}
	}
}


/***********************************************************************
.\XML\GENERATED\XMLAST.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml
{
/***********************************************************************
Visitor Pattern Implementation
***********************************************************************/

	void XmlText::Accept(XmlNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void XmlCData::Accept(XmlNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void XmlComment::Accept(XmlNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void XmlElement::Accept(XmlNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void XmlInstruction::Accept(XmlNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}

	void XmlDocument::Accept(XmlNode::IVisitor* visitor)
	{
		visitor->Visit(this);
	}
}
namespace vl::reflection::description
{
#ifndef VCZH_DEBUG_NO_REFLECTION

	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlNode, system::XmlNode)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlNode::IVisitor, system::XmlNode::IVisitor)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlText, system::XmlText)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlCData, system::XmlCData)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlAttribute, system::XmlAttribute)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlComment, system::XmlComment)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlElement, system::XmlElement)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlInstruction, system::XmlInstruction)
	IMPL_TYPE_INFO_RENAME(vl::glr::xml::XmlDocument, system::XmlDocument)

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlNode)
		CLASS_MEMBER_BASE(vl::glr::ParsingAstBase)

	END_CLASS_MEMBER(vl::glr::xml::XmlNode)

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlText)
		CLASS_MEMBER_BASE(vl::glr::xml::XmlNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::xml::XmlText>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(content)
	END_CLASS_MEMBER(vl::glr::xml::XmlText)

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlCData)
		CLASS_MEMBER_BASE(vl::glr::xml::XmlNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::xml::XmlCData>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(content)
	END_CLASS_MEMBER(vl::glr::xml::XmlCData)

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlAttribute)
		CLASS_MEMBER_BASE(vl::glr::ParsingAstBase)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::xml::XmlAttribute>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(name)
		CLASS_MEMBER_FIELD(value)
	END_CLASS_MEMBER(vl::glr::xml::XmlAttribute)

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlComment)
		CLASS_MEMBER_BASE(vl::glr::xml::XmlNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::xml::XmlComment>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(content)
	END_CLASS_MEMBER(vl::glr::xml::XmlComment)

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlElement)
		CLASS_MEMBER_BASE(vl::glr::xml::XmlNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::xml::XmlElement>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(name)
		CLASS_MEMBER_FIELD(closingName)
		CLASS_MEMBER_FIELD(attributes)
		CLASS_MEMBER_FIELD(subNodes)
	END_CLASS_MEMBER(vl::glr::xml::XmlElement)

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlInstruction)
		CLASS_MEMBER_BASE(vl::glr::xml::XmlNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::xml::XmlInstruction>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(name)
		CLASS_MEMBER_FIELD(attributes)
	END_CLASS_MEMBER(vl::glr::xml::XmlInstruction)

	BEGIN_CLASS_MEMBER(vl::glr::xml::XmlDocument)
		CLASS_MEMBER_BASE(vl::glr::xml::XmlNode)

		CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::glr::xml::XmlDocument>(), NO_PARAMETER)

		CLASS_MEMBER_FIELD(prologs)
		CLASS_MEMBER_FIELD(rootElement)
	END_CLASS_MEMBER(vl::glr::xml::XmlDocument)

	BEGIN_INTERFACE_MEMBER(vl::glr::xml::XmlNode::IVisitor)
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlText* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlCData* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlComment* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlElement* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlInstruction* node))
		CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::glr::xml::XmlNode::IVisitor::*)(vl::glr::xml::XmlDocument* node))
	END_INTERFACE_MEMBER(vl::glr::xml::XmlNode)

#endif

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
	class XmlAstTypeLoader : public vl::Object, public ITypeLoader
	{
	public:
		void Load(ITypeManager* manager)
		{
			ADD_TYPE_INFO(vl::glr::xml::XmlNode)
			ADD_TYPE_INFO(vl::glr::xml::XmlNode::IVisitor)
			ADD_TYPE_INFO(vl::glr::xml::XmlText)
			ADD_TYPE_INFO(vl::glr::xml::XmlCData)
			ADD_TYPE_INFO(vl::glr::xml::XmlAttribute)
			ADD_TYPE_INFO(vl::glr::xml::XmlComment)
			ADD_TYPE_INFO(vl::glr::xml::XmlElement)
			ADD_TYPE_INFO(vl::glr::xml::XmlInstruction)
			ADD_TYPE_INFO(vl::glr::xml::XmlDocument)
		}

		void Unload(ITypeManager* manager)
		{
		}
	};
#endif
#endif

	bool XmlAstLoadTypes()
	{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
		if (auto manager = GetGlobalTypeManager())
		{
			auto loader = Ptr(new XmlAstTypeLoader);
			return manager->AddTypeLoader(loader);
		}
#endif
		return false;
	}
}


/***********************************************************************
.\XML\GENERATED\XMLAST_BUILDER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml::builder
{

/***********************************************************************
MakeAttribute
***********************************************************************/

	MakeAttribute& MakeAttribute::name(const vl::WString& value)
	{
		node->name.value = value;
		return *this;
	}

	MakeAttribute& MakeAttribute::value(const vl::WString& value)
	{
		node->value.value = value;
		return *this;
	}

/***********************************************************************
MakeCData
***********************************************************************/

	MakeCData& MakeCData::content(const vl::WString& value)
	{
		node->content.value = value;
		return *this;
	}

/***********************************************************************
MakeComment
***********************************************************************/

	MakeComment& MakeComment::content(const vl::WString& value)
	{
		node->content.value = value;
		return *this;
	}

/***********************************************************************
MakeDocument
***********************************************************************/

	MakeDocument& MakeDocument::prologs(const vl::Ptr<XmlNode>& value)
	{
		node->prologs.Add(value);
		return *this;
	}

	MakeDocument& MakeDocument::rootElement(const vl::Ptr<XmlElement>& value)
	{
		node->rootElement = value;
		return *this;
	}

/***********************************************************************
MakeElement
***********************************************************************/

	MakeElement& MakeElement::attributes(const vl::Ptr<XmlAttribute>& value)
	{
		node->attributes.Add(value);
		return *this;
	}

	MakeElement& MakeElement::closingName(const vl::WString& value)
	{
		node->closingName.value = value;
		return *this;
	}

	MakeElement& MakeElement::name(const vl::WString& value)
	{
		node->name.value = value;
		return *this;
	}

	MakeElement& MakeElement::subNodes(const vl::Ptr<XmlNode>& value)
	{
		node->subNodes.Add(value);
		return *this;
	}

/***********************************************************************
MakeInstruction
***********************************************************************/

	MakeInstruction& MakeInstruction::attributes(const vl::Ptr<XmlAttribute>& value)
	{
		node->attributes.Add(value);
		return *this;
	}

	MakeInstruction& MakeInstruction::name(const vl::WString& value)
	{
		node->name.value = value;
		return *this;
	}

/***********************************************************************
MakeText
***********************************************************************/

	MakeText& MakeText::content(const vl::WString& value)
	{
		node->content.value = value;
		return *this;
	}
}


/***********************************************************************
.\XML\GENERATED\XMLAST_COPY.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml::copy_visitor
{
	void AstVisitor::CopyFields(XmlAttribute* from, XmlAttribute* to)
	{
		to->name = from->name;
		to->value = from->value;
	}

	void AstVisitor::CopyFields(XmlCData* from, XmlCData* to)
	{
		CopyFields(static_cast<XmlNode*>(from), static_cast<XmlNode*>(to));
		to->content = from->content;
	}

	void AstVisitor::CopyFields(XmlComment* from, XmlComment* to)
	{
		CopyFields(static_cast<XmlNode*>(from), static_cast<XmlNode*>(to));
		to->content = from->content;
	}

	void AstVisitor::CopyFields(XmlDocument* from, XmlDocument* to)
	{
		CopyFields(static_cast<XmlNode*>(from), static_cast<XmlNode*>(to));
		for (auto&& listItem : from->prologs)
		{
			to->prologs.Add(CopyNode(listItem.Obj()));
		}
		to->rootElement = CopyNode(from->rootElement.Obj());
	}

	void AstVisitor::CopyFields(XmlElement* from, XmlElement* to)
	{
		CopyFields(static_cast<XmlNode*>(from), static_cast<XmlNode*>(to));
		for (auto&& listItem : from->attributes)
		{
			to->attributes.Add(CopyNode(listItem.Obj()));
		}
		to->closingName = from->closingName;
		to->name = from->name;
		for (auto&& listItem : from->subNodes)
		{
			to->subNodes.Add(CopyNode(listItem.Obj()));
		}
	}

	void AstVisitor::CopyFields(XmlInstruction* from, XmlInstruction* to)
	{
		CopyFields(static_cast<XmlNode*>(from), static_cast<XmlNode*>(to));
		for (auto&& listItem : from->attributes)
		{
			to->attributes.Add(CopyNode(listItem.Obj()));
		}
		to->name = from->name;
	}

	void AstVisitor::CopyFields(XmlNode* from, XmlNode* to)
	{
	}

	void AstVisitor::CopyFields(XmlText* from, XmlText* to)
	{
		CopyFields(static_cast<XmlNode*>(from), static_cast<XmlNode*>(to));
		to->content = from->content;
	}

	void AstVisitor::Visit(XmlAttribute* node)
	{
		auto newNode = vl::Ptr(new XmlAttribute);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(XmlText* node)
	{
		auto newNode = vl::Ptr(new XmlText);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(XmlCData* node)
	{
		auto newNode = vl::Ptr(new XmlCData);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(XmlComment* node)
	{
		auto newNode = vl::Ptr(new XmlComment);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(XmlElement* node)
	{
		auto newNode = vl::Ptr(new XmlElement);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(XmlInstruction* node)
	{
		auto newNode = vl::Ptr(new XmlInstruction);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	void AstVisitor::Visit(XmlDocument* node)
	{
		auto newNode = vl::Ptr(new XmlDocument);
		CopyFields(node, newNode.Obj());
		this->result = newNode;
	}

	vl::Ptr<XmlNode> AstVisitor::CopyNode(XmlNode* node)
	{
		if (!node) return nullptr;
		node->Accept(static_cast<XmlNode::IVisitor*>(this));
		this->result->codeRange = node->codeRange;
		return this->result.Cast<XmlNode>();
	}

	vl::Ptr<XmlAttribute> AstVisitor::CopyNode(XmlAttribute* node)
	{
		if (!node) return nullptr;
		Visit(node);
		this->result->codeRange = node->codeRange;
		return this->result.Cast<XmlAttribute>();
	}

	vl::Ptr<XmlCData> AstVisitor::CopyNode(XmlCData* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<XmlNode*>(node)).Cast<XmlCData>();
	}

	vl::Ptr<XmlComment> AstVisitor::CopyNode(XmlComment* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<XmlNode*>(node)).Cast<XmlComment>();
	}

	vl::Ptr<XmlDocument> AstVisitor::CopyNode(XmlDocument* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<XmlNode*>(node)).Cast<XmlDocument>();
	}

	vl::Ptr<XmlElement> AstVisitor::CopyNode(XmlElement* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<XmlNode*>(node)).Cast<XmlElement>();
	}

	vl::Ptr<XmlInstruction> AstVisitor::CopyNode(XmlInstruction* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<XmlNode*>(node)).Cast<XmlInstruction>();
	}

	vl::Ptr<XmlText> AstVisitor::CopyNode(XmlText* node)
	{
		if (!node) return nullptr;
		return CopyNode(static_cast<XmlNode*>(node)).Cast<XmlText>();
	}

}


/***********************************************************************
.\XML\GENERATED\XMLAST_EMPTY.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml::empty_visitor
{

/***********************************************************************
NodeVisitor
***********************************************************************/

	// Visitor Members -----------------------------------

	void NodeVisitor::Visit(XmlText* node)
	{
	}

	void NodeVisitor::Visit(XmlCData* node)
	{
	}

	void NodeVisitor::Visit(XmlComment* node)
	{
	}

	void NodeVisitor::Visit(XmlElement* node)
	{
	}

	void NodeVisitor::Visit(XmlInstruction* node)
	{
	}

	void NodeVisitor::Visit(XmlDocument* node)
	{
	}
}


/***********************************************************************
.\XML\GENERATED\XMLAST_JSON.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml::json_visitor
{
	void AstVisitor::PrintFields(XmlAttribute* node)
	{
		BeginField(vl::WString::Unmanaged(L"name"));
		WriteToken(node->name);
		EndField();
		BeginField(vl::WString::Unmanaged(L"value"));
		WriteToken(node->value);
		EndField();
	}
	void AstVisitor::PrintFields(XmlCData* node)
	{
		BeginField(vl::WString::Unmanaged(L"content"));
		WriteToken(node->content);
		EndField();
	}
	void AstVisitor::PrintFields(XmlComment* node)
	{
		BeginField(vl::WString::Unmanaged(L"content"));
		WriteToken(node->content);
		EndField();
	}
	void AstVisitor::PrintFields(XmlDocument* node)
	{
		BeginField(vl::WString::Unmanaged(L"prologs"));
		BeginArray();
		for (auto&& listItem : node->prologs)
		{
			BeginArrayItem();
			Print(listItem.Obj());
			EndArrayItem();
		}
		EndArray();
		EndField();
		BeginField(vl::WString::Unmanaged(L"rootElement"));
		Print(node->rootElement.Obj());
		EndField();
	}
	void AstVisitor::PrintFields(XmlElement* node)
	{
		BeginField(vl::WString::Unmanaged(L"attributes"));
		BeginArray();
		for (auto&& listItem : node->attributes)
		{
			BeginArrayItem();
			Print(listItem.Obj());
			EndArrayItem();
		}
		EndArray();
		EndField();
		BeginField(vl::WString::Unmanaged(L"closingName"));
		WriteToken(node->closingName);
		EndField();
		BeginField(vl::WString::Unmanaged(L"name"));
		WriteToken(node->name);
		EndField();
		BeginField(vl::WString::Unmanaged(L"subNodes"));
		BeginArray();
		for (auto&& listItem : node->subNodes)
		{
			BeginArrayItem();
			Print(listItem.Obj());
			EndArrayItem();
		}
		EndArray();
		EndField();
	}
	void AstVisitor::PrintFields(XmlInstruction* node)
	{
		BeginField(vl::WString::Unmanaged(L"attributes"));
		BeginArray();
		for (auto&& listItem : node->attributes)
		{
			BeginArrayItem();
			Print(listItem.Obj());
			EndArrayItem();
		}
		EndArray();
		EndField();
		BeginField(vl::WString::Unmanaged(L"name"));
		WriteToken(node->name);
		EndField();
	}
	void AstVisitor::PrintFields(XmlNode* node)
	{
	}
	void AstVisitor::PrintFields(XmlText* node)
	{
		BeginField(vl::WString::Unmanaged(L"content"));
		WriteToken(node->content);
		EndField();
	}

	void AstVisitor::Visit(XmlText* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Text"), node);
		PrintFields(static_cast<XmlNode*>(node));
		PrintFields(static_cast<XmlText*>(node));
		EndObject();
	}

	void AstVisitor::Visit(XmlCData* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"CData"), node);
		PrintFields(static_cast<XmlNode*>(node));
		PrintFields(static_cast<XmlCData*>(node));
		EndObject();
	}

	void AstVisitor::Visit(XmlComment* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Comment"), node);
		PrintFields(static_cast<XmlNode*>(node));
		PrintFields(static_cast<XmlComment*>(node));
		EndObject();
	}

	void AstVisitor::Visit(XmlElement* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Element"), node);
		PrintFields(static_cast<XmlNode*>(node));
		PrintFields(static_cast<XmlElement*>(node));
		EndObject();
	}

	void AstVisitor::Visit(XmlInstruction* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Instruction"), node);
		PrintFields(static_cast<XmlNode*>(node));
		PrintFields(static_cast<XmlInstruction*>(node));
		EndObject();
	}

	void AstVisitor::Visit(XmlDocument* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Document"), node);
		PrintFields(static_cast<XmlNode*>(node));
		PrintFields(static_cast<XmlDocument*>(node));
		EndObject();
	}

	AstVisitor::AstVisitor(vl::stream::StreamWriter& _writer)
		: vl::glr::JsonVisitorBase(_writer)
	{
	}

	void AstVisitor::Print(XmlNode* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		node->Accept(static_cast<XmlNode::IVisitor*>(this));
	}

	void AstVisitor::Print(XmlAttribute* node)
	{
		if (!node)
		{
			WriteNull();
			return;
		}
		BeginObject();
		WriteType(vl::WString::Unmanaged(L"Attribute"), node);
		PrintFields(static_cast<XmlAttribute*>(node));
		EndObject();
	}

}


/***********************************************************************
.\XML\GENERATED\XMLAST_TRAVERSE.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Ast
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml::traverse_visitor
{
	void AstVisitor::Traverse(vl::glr::ParsingToken& token) {}
	void AstVisitor::Traverse(vl::glr::ParsingAstBase* node) {}
	void AstVisitor::Traverse(XmlAttribute* node) {}
	void AstVisitor::Traverse(XmlCData* node) {}
	void AstVisitor::Traverse(XmlComment* node) {}
	void AstVisitor::Traverse(XmlDocument* node) {}
	void AstVisitor::Traverse(XmlElement* node) {}
	void AstVisitor::Traverse(XmlInstruction* node) {}
	void AstVisitor::Traverse(XmlNode* node) {}
	void AstVisitor::Traverse(XmlText* node) {}

	void AstVisitor::Finishing(vl::glr::ParsingAstBase* node) {}
	void AstVisitor::Finishing(XmlAttribute* node) {}
	void AstVisitor::Finishing(XmlCData* node) {}
	void AstVisitor::Finishing(XmlComment* node) {}
	void AstVisitor::Finishing(XmlDocument* node) {}
	void AstVisitor::Finishing(XmlElement* node) {}
	void AstVisitor::Finishing(XmlInstruction* node) {}
	void AstVisitor::Finishing(XmlNode* node) {}
	void AstVisitor::Finishing(XmlText* node) {}

	void AstVisitor::Visit(XmlText* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<XmlNode*>(node));
		Traverse(static_cast<XmlText*>(node));
		Traverse(node->content);
		Finishing(static_cast<XmlText*>(node));
		Finishing(static_cast<XmlNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(XmlCData* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<XmlNode*>(node));
		Traverse(static_cast<XmlCData*>(node));
		Traverse(node->content);
		Finishing(static_cast<XmlCData*>(node));
		Finishing(static_cast<XmlNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(XmlComment* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<XmlNode*>(node));
		Traverse(static_cast<XmlComment*>(node));
		Traverse(node->content);
		Finishing(static_cast<XmlComment*>(node));
		Finishing(static_cast<XmlNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(XmlElement* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<XmlNode*>(node));
		Traverse(static_cast<XmlElement*>(node));
		for (auto&& listItem : node->attributes)
		{
			InspectInto(listItem.Obj());
		}
		Traverse(node->closingName);
		Traverse(node->name);
		for (auto&& listItem : node->subNodes)
		{
			InspectInto(listItem.Obj());
		}
		Finishing(static_cast<XmlElement*>(node));
		Finishing(static_cast<XmlNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(XmlInstruction* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<XmlNode*>(node));
		Traverse(static_cast<XmlInstruction*>(node));
		for (auto&& listItem : node->attributes)
		{
			InspectInto(listItem.Obj());
		}
		Traverse(node->name);
		Finishing(static_cast<XmlInstruction*>(node));
		Finishing(static_cast<XmlNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::Visit(XmlDocument* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<XmlNode*>(node));
		Traverse(static_cast<XmlDocument*>(node));
		for (auto&& listItem : node->prologs)
		{
			InspectInto(listItem.Obj());
		}
		InspectInto(node->rootElement.Obj());
		Finishing(static_cast<XmlDocument*>(node));
		Finishing(static_cast<XmlNode*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

	void AstVisitor::InspectInto(XmlNode* node)
	{
		if (!node) return;
		node->Accept(static_cast<XmlNode::IVisitor*>(this));
	}

	void AstVisitor::InspectInto(XmlAttribute* node)
	{
		if (!node) return;
		Traverse(static_cast<vl::glr::ParsingAstBase*>(node));
		Traverse(static_cast<XmlAttribute*>(node));
		Traverse(node->name);
		Traverse(node->value);
		Finishing(static_cast<XmlAttribute*>(node));
		Finishing(static_cast<vl::glr::ParsingAstBase*>(node));
	}

}


/***********************************************************************
.\XML\GENERATED\XMLPARSER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Xml
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml
{
	void XmlParserData(vl::stream::IStream& outputStream)
	{
		static const vl::vint dataLength = 2277; // 22621 bytes before compressing
		static const vl::vint dataBlock = 256;
		static const vl::vint dataRemain = 229;
		static const vl::vint dataSolidRows = 8;
		static const vl::vint dataRows = 9;
		static const char* compressed[] = {
			"\x5D\x58\x00\x00\xDD\x08\x00\x00\x0D\x00\x01\x82\x80\x08\x03\x82\x81\x82\x06\x89\x82\x85\x0A\x83\x06\x84\x07\x0A\x91\x0A\x9C\x0A\x82\x12\x84\x14\x0A\xA3\x42\x09\x8F\x7D\x8E\x8F\x8E\x0A\x80\x1F\x9F\x81\x93\x92\x8F\x92\x26\xFF\x68\x86\x9B\x93\x91\x96\x92\x0A\xA9\xAA\x91\x99\x91\x91\x91\x00\x34\xAC\xB9\x8E\x9B\x98\x98\x8F\x9A\x3D\xA7\x81\xA0\x93\xA3\x9B\x9E\x9D\x47\xBC\x89\xBE\x96\x82\x9B\x96\xA1\x4B\xD0\x8D\xA0\xA1\xAC\xA1\xAA\xA3\x53\xC8\x99\xAA\xAB\xAC\xA7\x80\xA7\x45\xCF\x96\xBD\xA2\xAF\xAC\xAA\xB2\x63\xE6\x9A\xAA\xBC\xAC\xB6\xAE\x81\x60\xD7\xB7\x8A\x88\x9A\xB9\xB1\xBB\x76\x89\x9B\x89\x85\xB8\xB4\xAC\xB7\x65\xF0\xA7\xA0\xC9\xB2\xC3\xB4\xC3\x6D\x88\xEF\xA1\x81\xBE\xBE\xB1\xBF\x8A\x81\xCC\xC3\xC1\xCD\xC3\xC9\xC3\x97\x89\xD9\xCB\xC2\x94\xCB\xCC\xC9\x9D\x98\xE1\xDA\xC3\xD4\xCD\xC7\x81\x03\x74\xB8\xAE\xCB\xD4\xC0\xC9\xCF\x96\xA5\xE0\xC7\xD5\xCF\xD6\xD9\xD8\xB4\xB0\xF6\xD9\xD7\xDB\xDE\xCE\x00\x04\x2A\xC9\x8C\x8C\xBA\x86\x02\xE1\xAC\xF9\x86\x87\x08\xE6\xD7\xC7\xE7\xAD\xB5\xD0\xEA\xEE\xE1\xEA\xDD\xE9\xC9\xD9\xD5\xF4",
			"\xE2\xEA\x84\x84\x83\x7D\xDB\xDA\xFD\xEC\xEF\xEA\xEB\xDE\xD8\xE2\xEA\xE4\xF3\xF6\xF1\xF2\x00\x09\x4D\xEC\xEB\xFE\xF5\xF4\xF5\xF3\xBC\xF9\xFF\xDA\xF2\xD4\xFC\xD2\xDE\x0A\x32\x75\x7C\x7D\xF7\x6F\x7E\x7E\x69\xFB\x49\x8D\x7E\x82\xFF\x4C\x88\x82\x68\x0E\x45\x76\x82\x83\xB3\x54\x88\x6E\x85\xBE\x4B\x8A\x85\x83\x1B\x8F\x8C\x87\x87\x1E\xA1\x85\x85\x87\x23\xA0\x85\x8A\x88\x17\xA4\x89\x88\x69\x0C\x02\x85\x82\x7D\x07\xA7\x82\x8F\x8A\x28\x99\x86\x88\x8D\x33\xB6\x85\x8D\x7A\xF3\x7D\x81\x40\x40\x12\xB0\x88\x84\x8F\x03\xBE\x8F\x88\x81\x31\xB8\x8A\x92\x8E\x39\x84\x97\x92\x91\x49\x8C\x9B\x92\x93\x51\x8E\x90\x45\x90\x48\x83\x98\x7E\x96\x13\xAA\x82\x97\x97\x54\x9C\x92\x92\x97\x4E\x8F\x0E\x89\x95\x5B\xA4\x99\x9B\x8D\x60\xAB\x9B\x8E\x9B\x4D\xB0\x93\x96\x9C\xB6\x50\x07\x9A\x98\x59\xAA\x9D\x94\x9B\x61\xBA\x93\x98\x9F\x74\xBD\x90\xA3\x9E\x6F\x84\xA1\x9E\xA1\x73\x88\xAD\x9B\x7B\x12\x58\x90\x94\x9E\x8F\xBE\x99\x9F\xA0\xF6\x52\x07\x9E\x68\x13\x17\xA4\x68\x05\x9A\x85\xAF\x9E\xA7\x93\xA0\xA1\xA4\x69\x15\x1D\xA0\x6A\x05\xA6\xB1\x67\x05\xAA",
			"\x8B\x9F\xA7\xA2\x41\x18\x2C\xA2\xA2\xA8\x45\xB5\xAF\x92\xAD\x68\x8A\xA3\xAF\xAB\xA1\xBC\xA2\x41\x06\xB2\x8A\x4A\x05\xB0\x09\x5B\x0E\x88\x45\x8E\x81\x4D\x06\x8B\x1E\x2E\x8F\x06\x8B\x20\x04\xBE\xA9\xA2\xF6\x61\x02\xB7\x40\x16\x49\xB7\xAC\x00\x23\x2E\x84\x0A\x8B\x25\x2E\x86\x0A\x8B\x27\x2E\x88\x46\xB6\xB9\x93\xBD\xA9\xAF\xD4\xAC\xB6\x6D\x0A\xD7\xA3\xA4\xAF\xB6\x2A\x31\xB8\xAC\xA4\xF7\x92\xA2\xBE\xAF\xF9\x94\xAE\xBB\xAE\xED\xBB\xB1\xC1\x40\x2B\x36\xBB\xB5\xBA\xFF\x81\xAA\xC2\xAE\xE7\x6C\x06\xC1\x0B\x2E\xAE\x0E\x8B\x0B\x2E\xB0\x0E\x89\x0C\x2E\xB2\x06\xC0\xC2\x02\xEB\xBD\xC4\xC0\x1E\xFD\xB3\xBC\xC7\x01\x73\x0B\xC4\xBE\x07\xE8\xC4\xC9\xCA\xFA\xA2\xCC\xBC\x00\x34\x27\xCD\xC8\xCB\xFE\x9F\xCB\xC2\xBA\x20\xE1\x45\x0E\xCC\x35\xEE\xC3\xC0\xCD\x23\xEA\xC2\xD2\x68\x36\x3C\xC1\xD3\xCC\x2B\xC9\xD3\xD1\xCF\x40\xEF\xC7\x0E\xD1\x2F\xCA\xD8\xD3\xD2\x47\xCC\xD2\xD6\xD5\x54\xD1\xD9\xD7\xCF\x57\xD5\xDE\xD6\xD6\x53\xE2\x68\x0C\xD4\x5C\xDB\xD1\xCB\xB6\x39\x24\xD7\xDB\xCA\x3A\x2A\xD9\xCF\xCD\x09\xC9\x4B\x0E\xDB\x70\xC6\x9C\x0C\xDD\x0C",
			"\xEF\x7D\x0C\xDE\x38\xF5\xDE\xCF\xDA\x66\xEF\xD9\xDE\x41\x3E\x3C\xD4\x83\x0F\x86\xF6\xC9\x40\x10\x89\xFF\xD2\xE1\xDF\x83\xF1\xD0\xE7\xE4\x92\xD5\xE2\x41\x10\x8D\xDB\xB2\x11\xE6\x2B\xC3\x1C\xE7\x6F\x44\x1F\xE1\xD8\xD6\xA3\xDF\xD5\xD9\xE9\x2F\xC5\x12\xE8\x69\x46\x2B\xE3\xBF\x11\xAE\xE0\x69\x2A\x42\x7B\x7E\x5B\xCB\x63\xB5\xC3\x41\x72\x4D\x7E\x44\x7C\xEF\xEF\xBE\xC3\x41\x7A\x40\xB9\xC2\x4C\x73\x55\x51\x83\xF1\x41\xF1\xBA\x6B\xCC\xF1\x6F\xCE\xC5\x51\xF4\xF2\x28\xFB\xEB\x71\x51\xC1\xC2\x4D\x8B\xEF\xC6\xD2\xF9\x4A\xF5\x03\x47\xFD\xEE\x42\xDB\xDC\xF0\x02\xF8\xAE\x72\x40\xF9\xF7\x57\x59\xF1\x41\xF9\xDC\xE8\xF5\x6E\xFA\x0A\x72\xFA\x6E\xFB\x00\x30\xFF\xEE\xFD\xD0\xE9\x4F\xF2\x4C\x2B\x6B\x7D\x40\x4A\x7D\x36\xFC\x4F\x79\x24\xFC\x60\x82\xFF\x5E\x73\x66\x01\x80\x07\x7F\x29\x38\x7D\x6A\x66\x77\x7C\x06\xA3\x20\x82\x0A\x93\x5F\x63\x04\x8F\x31\x09\xA6\x7C\x7E\x7A\x36\x82\x06\xC5\x2E\x82\xEE\x60\x86\x20\x18\x99\x83\xCF\x0E\x8E\x80\x99\x38\x7F\x3B\xC2\x6A\x20\xFE\x47\x31\x85\xE1\x0A\x21\x3E\x36\x99\x87\xF5\x09\x2C\x7F\x04\xAA\x81",
			"\x47\x34\x88\x86\x08\xAF\x69\x84\x15\x8E\x4D\x88\x19\x87\x8B\x10\xBF\x68\x88\x05\x8A\x8C\x7A\x33\x6D\x88\x00\xCE\x4F\x31\x20\x83\x22\x8A\xD3\x76\x74\xCA\x58\x8B\x8B\x25\xA7\x6C\x8B\x51\x9E\x8B\x13\xDA\x83\x67\xC7\x3C\x7C\x85\xD8\x7E\x3A\x8B\x33\x84\x76\x19\xB7\x86\x8D\x3A\x81\x7D\xFD\x73\x80\x8A\x36\x70\x84\x78\x62\x87\x3C\x18\xCC\x6B\x8F\x79\x7D\x8C\x88\x79\x8F\x3F\x1F\xCC\x81\x90\xFB\x3E\x87\x87\xFF\x07\x93\x0F\x8A\x9A\x84\x46\x99\x83\x90\x67\x7B\x80\x05\xBD\x35\x84\x3C\xB5\x8B\x84\x57\x35\x93\xF2\x05\x94\x40\x07\xB8\x7E\x85\x0D\x2B\x8E\x42\x01\x45\x87\x1D\xA4\x8F\x82\x9C\x86\x48\x24\xE3\x89\x7D\x2E\x97\x90\x90\xAF\x84\x91\x2C\xE7\x6E\x80\x4D\x85\x82\x21\x0E\x81\x24\xFE\x0E\x84\x80\xFC\x46\x84\x8E\xA7\x9F\x23\x2A\xFA\x89\x94\x5B\x43\x9F\x3D\xB6\x92\x27\xF3\x49\x9B\x81\x84\x0C\x9E\x24\xBF\x93\x94\x24\xD3\x9E\x8B\x67\xA3\x22\x82\x45\x2B\x99\x36\xED\x83\x96\x6B\x9C\x30\x92\xDE\x9E\x23\xF3\x60\x95\x28\x02\xA1\x99\x36\xE7\x9F\x1E\x36\xD7\x26\x9D\xF3\x29\x9B\x9D\x7E\x24\x82\xC5\x14\x84\x80\x78\x97\x88\x97\xDC\x86",
			"\x22\x03\xCF\x7B\x9E\x38\x82\x89\x21\x56\x96\x92\x3E\xC0\x98\x34\x82\x82\x26\x81\x67\x86\xA1\x40\x08\xAE\x9E\x39\x80\xA2\xA1\xC0\x2A\x22\x2D\xE8\x89\x20\x4F\x86\x38\x9F\x09\x37\x8D\x40\x38\x86\x20\x52\x86\x21\x42\x06\x3A\x7F\x8F\x0F\x2A\x20\x33\x49\x26\x4E\x09\x2D\x52\x41\x16\x54\x83\x4C\x54\x85\x54\xEF\x21\x27\x24\x2E\x41\x24\x98\xB6\x39\x24\x94\x02\x95\x42\x31\x51\xA6\x85\x15\x16\x45\x0E\x96\x58\x32\x8A\x26\x12\x17\x44\x85\x59\x43\xA9\x23\x25\x2E\x46\x97\x68\x49\xAE\x20\x98\x0E\x47\xF3\x4F\x5F\xA9\x81\x19\x12\xA7\xB0\x47\x3D\x48\x1A\x14\xA6\x85\x23\x5D\xA7\x09\x3B\x11\x57\x89\x2F\xAB\x9B\x8A\x24\x13\x2E\x41\xA1\x40\x75\x50\xAC\x83\x1D\x11\x9F\xBA\x6A\x21\xC1\x6D\xA3\x21\x4F\x30\xAA\x20\xB6\x8E\x60\x5D\x82\x21\x15\xBB\x81\x22\xAD\x00\x0C\xAE\x59\x89\x23\x14\xA0\xB2\xAA\xAB\x0A\x24\x14\x53\x8A\x2A\xAF\xC1\x86\x25\x14\x69\xAA\x22\x60\x84\x41\x24\x53\x06\xB1\x21\x73\xAE\xB3\x40\x27\x1B\xB1\x84\x0D\xB4\xB2\x0A\x28\x16\x8B\x48\x03\x93\x16\xA8\x61\x24\x52\x88\xB6\x44\xFE\x6F\x80\x83\x76\x94\x80\x2B\x73\xA3\x79\x7D",
			"\x91\x72\xF6\x60\x3F\x3C\xF8\x6E\x93\xCF\x1A\xAD\xB5\xF7\x38\x7C\xA3\x96\x61\x22\x47\xF7\x9E\xB6\x35\xB5\xB7\x7D\x7E\xBB\x58\xFE\x43\xBA\x70\x83\x17\x4F\x9F\x86\x97\xA3\x71\x80\x08\xA4\x83\x29\x99\x24\xBC\xA0\xB3\xCA\x2E\xA6\xBB\xF3\x00\xBA\x20\xDA\xA8\x64\xAA\x4E\x97\x3C\xE6\xBF\xAC\xB5\xC0\x44\xBF\x7B\x20\xA3\x20\x20\x54\x72\x20\xC8\x50\xB8\x81\x6E\xB3\x20\x91\x8D\x69\x36\x48\xBD\xBB\x7B\x4F\xB3\x21\xEA\x81\xB8\x00\x42\xB2\xBE\x91\x7E\xB2\x20\x93\xAF\xB9\x20\xDD\x4A\xBE\x7D\x2A\xA3\x20\xEE\xBF\xBD\xAC\xC4\xB6\x3E\x83\x82\x2C\x53\xE9\xA7\x5F\xB6\xEF\x35\xC2\x41\x63\xB7\xC0\x00\x30\x58\x5D\xBF\x3A\xC3\x40\x2B\x53\xBB\xC9\x82\x20\xB6\x21\xD8\xA1\x87\x99\xB1\xC2\xEE\x44\x86\xA6\x03\x3C\xC3\x7F\x90\x60\xC4\xD1\x30\xC2\x20\x24\xDD\xC2\xC4\x35\xC4\x54\x15\xFF\xBC\x62\xA5\x91\x86\xB6\x32\xC2\x20\x96\x9D\xC0\x63\x0F\xAF\x3D\x8E\x83\x29\xBD\x0E\xCF\x6C\xC7\x9C\x2B\xCA\x40\x13\xCE\x70\x85\x23\x69\xC8\x02\xAD\xC4\x8E\x90\xAC\x6D\xE4\xB4\xB6\x20\x52\xDB\xA0\x6B\xF7\x68\xCB\xF3\xA5\xC8\x00\x61\xC4\x20\x6B\x85\x77\xCC\xDE",
			"\x8F\x79\xCD\x04\xD5\xCB\xE2\x49\xB6\xBD\xDE\xA0\xCA\x21\xF4\xAD\xBB\x40\x1B\x77\xCC\xFB\xAF\xCB\x94\xAC\xA1\x77\x99\xFC\xB9\xCA\x81\x3C\xA6\x20\x4D\xDF\xBD\xEB\x50\xC0\x35\x43\xCD\xC4\xB5\xB0\x67\xCD\x9C\xF6\xC3\x20\x47\xF6\xB7\xBF\x49\x09\xBA\x91\xDA\xC1\x20\x4B\xE2\xCB\xBA\x4B\x09\xBA\x88\x85\xDD\xD2\xE3\x9D\xC5\x09\xC9\xA4\xCB\x26\xBB\xAA\x21\x49\xEB\x67\x09\xC9\xBE\xD0\xA5\x86\xD8\xCE\xD6\x91\x09\xB9\xC3\x47\xCE\xAC\xF5\xCB\x65\x29\x09\xB9\xBE\x9C\xC0\x01\xA2\x82\x26\x59\xE9\x95\x0E\x60\xB9\xCB\xA4\x6B\xD6\x02\xBA\xFB\x05\xDE\x20\xC9\xDF\xBC\x17\x06\x60\xD9\x29\xEC\xB5\x0B\xC9\xB9\xBE\x90\x86\x25\xDB\x80\x3A\xB7\x6C\x5F\x09\xB8\x55\x98\xCC\xDB\x37\x93\xB9\x0C\xC9\xAE\xA8\xB9\x83\x2D\xDA\x35\xD3\xBB\x0C\xC9\xA1\xC3\xB6\xEC\xDD\xD4\xD6\xA5\x09\xB9\xD9\x4B\xDC\x7C\xB5\xD3\xBB\x33\x09\xB9\xC1\xFA\xC1\x21\xBB\xBC\xD8\x65\x34\x09\xBF\x5B\xDA\x5A\xDA\x40\x4B\x53\xBB\x35\x06\x63\xDC\x03\x2C\xE1\x87\xEC\x06\x60\x75\xD1\xE4\xB5\x6D\x06\x62\xBC\x8B\xEC\xB4\x37\x06\x61\xDF\x03\x28\xE1\x87\xEF\x09\xB8\xDE\x22\xE3\x20",
			"\xE1\x53\xB9\x1C\x06\x69\xE4\x83\x25\x5B\xBA\x72\x0C\xE6\x8F\xFA\xC2\x21\x39\x09\xBD\xE5\xF3\xC2\x20\x84\x82\x2F\xE5\x0E\xF5\x0E\x60\x3B\xEB\xA0\x6B\xF6\x09\xB9\xA0\xC0\x04\x80\x3D\xE3\x20\xC0\xFF\xB8\x0F\x99\xF6\x57\xC2\x21\xEC\xB4\x1F\x49\xB9\xE9\x13\xD7\x22\x21\x54\xD7\xBE\x6D\x7E\x09\xB8\xA8\xD6\xE9\x21\x5E\xE1\x22\xAB\xA8\x60\x11\xE4\x9F\xC1\xE0\x81\xAA\x23\xC9\xB4\xE1\x20\x41\x09\xBE\xC4\x03\x92\xB0\xD6\xAC\xB4\x11\xE4\xAC\xC7\xEB\x06\x30\xEC\x75\xAC\xB6\x11\xE4\x9F\xB0\xEF\x03\x37\xED\x40\x67\xEF\xBE\x44\x0D\xA6\x48\x7F\xE1\x23\xDA\xF2\xC6\x21\x46\x09\xBC\xC6\x68\xE9\xF0\x00\x59\xEB\x65\x47\x09\xBB\xC7\x91\xF5\xDF\x74\x91\x19\xB8\x20\xE8\xE8\xF2\x93\x9C\x21\xE8\xBF\x7C\x82\xD8\xA5\xF3\x2E\x34\xA7\x83\xFF\x07\x86\x96\x00\x09\x9D\xF5\xB9\x8D\x85\xEC\xA1\x23\xF6\xA7\xC2\xEE\xF6\x11\xB8\xF4\xFE\x00\x0F\x93\xDD\xFE\xF2\x97\x21\x20\xB0\x00\x5A\xB2\xF9\xE2\xC1\xF8\x81\xC8\xFC\x20\xFF\x15\x80\xA2\x9B\x00",
		};
		vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);
	}

	const wchar_t* ParserRuleName(vl::vint index)
	{
		static const wchar_t* results[] = {
			L"XAttribute",
			L"XText",
			L"XCData",
			L"XComment",
			L"XElement",
			L"XSubNode",
			L"XInstruction",
			L"XDocument",
		};
		return results[index];
	}

	const wchar_t* ParserStateLabel(vl::vint index)
	{
		static const wchar_t* results[] = {
			L"[0][XAttribute] BEGIN ",
			L"[1][XAttribute] END [ENDING]",
			L"[2][XAttribute]< NAME \"=\" @ ATTVALUE >",
			L"[3][XAttribute]< NAME \"=\" ATTVALUE @ >",
			L"[4][XAttribute]< NAME @ \"=\" ATTVALUE >",
			L"[5][XText] BEGIN ",
			L"[6][XText] END [ENDING]",
			L"[7][XText]< \"=\" @ >",
			L"[8][XText]< ATTVALUE @ >",
			L"[9][XText]< NAME @ >",
			L"[10][XText]< TEXT @ >",
			L"[11][XCData] BEGIN ",
			L"[12][XCData] END [ENDING]",
			L"[13][XCData]< CDATA @ >",
			L"[14][XComment] BEGIN ",
			L"[15][XComment] END [ENDING]",
			L"[16][XComment]< COMMENT @ >",
			L"[17][XElement] BEGIN ",
			L"[18][XElement] END [ENDING]",
			L"[19][XElement]< \"<\" @ NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"</\" NAME \">\" ) >",
			L"[20][XElement]< \"<\" NAME @ { XAttribute } ( \"/>\" | \">\" { XSubNode } \"</\" NAME \">\" ) >",
			L"[21][XElement]< \"<\" NAME { XAttribute @ } ( \"/>\" | \">\" { XSubNode } \"</\" NAME \">\" ) >",
			L"[22][XElement]< \"<\" NAME { XAttribute } ( \"/>\" @ | \">\" { XSubNode } \"</\" NAME \">\" ) >",
			L"[23][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" @ { XSubNode } \"</\" NAME \">\" ) >",
			L"[24][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode @ } \"</\" NAME \">\" ) >",
			L"[25][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"</\" @ NAME \">\" ) >",
			L"[26][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"</\" NAME \">\" @ ) >",
			L"[27][XElement]< \"<\" NAME { XAttribute } ( \"/>\" | \">\" { XSubNode } \"</\" NAME @ \">\" ) >",
			L"[28][XSubNode] BEGIN ",
			L"[29][XSubNode] END [ENDING]",
			L"[30][XSubNode]<! ( !XText @ | !XCData | !XComment | !XElement ) !>",
			L"[31][XSubNode]<! ( !XText | !XCData @ | !XComment | !XElement ) !>",
			L"[32][XSubNode]<! ( !XText | !XCData | !XComment @ | !XElement ) !>",
			L"[33][XSubNode]<! ( !XText | !XCData | !XComment | !XElement @ ) !>",
			L"[34][XInstruction] BEGIN ",
			L"[35][XInstruction] END [ENDING]",
			L"[36][XInstruction]< \"<?\" @ NAME { XAttribute } \"?>\" >",
			L"[37][XInstruction]< \"<?\" NAME @ { XAttribute } \"?>\" >",
			L"[38][XInstruction]< \"<?\" NAME { XAttribute @ } \"?>\" >",
			L"[39][XInstruction]< \"<?\" NAME { XAttribute } \"?>\" @ >",
			L"[40][XDocument] BEGIN ",
			L"[41][XDocument] END [ENDING]",
			L"[42][XDocument]< { ( XInstruction @ | XComment ) } XElement >",
			L"[43][XDocument]< { ( XInstruction | XComment ) } XElement @ >",
			L"[44][XDocument]< { ( XInstruction | XComment @ ) } XElement >",
		};
		return results[index];
	}

	Parser::Parser()
		: vl::glr::ParserBase<XmlTokens, ParserStates, XmlAstInsReceiver>(&XmlTokenDeleter, &XmlLexerData, &XmlParserData)
	{
	}

	vl::WString Parser::GetClassName(vl::vint32_t classIndex) const
	{
		return vl::WString::Unmanaged(XmlTypeName((XmlClasses)classIndex));
	}

	vl::vint32_t Parser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const
	{
		return -1;
	}

	vl::Ptr<vl::glr::xml::XmlElement> Parser::ParseXElement(const vl::WString& input, vl::vint codeIndex) const
	{
		 return ParseWithString<vl::glr::xml::XmlElement, ParserStates::XElement>(input, this, codeIndex);
	}

	vl::Ptr<vl::glr::xml::XmlElement> Parser::ParseXElement(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex) const
	{
		 return ParseWithTokens<vl::glr::xml::XmlElement, ParserStates::XElement>(tokens, this, codeIndex);
	}

	vl::Ptr<vl::glr::xml::XmlDocument> Parser::ParseXDocument(const vl::WString& input, vl::vint codeIndex) const
	{
		 return ParseWithString<vl::glr::xml::XmlDocument, ParserStates::XDocument>(input, this, codeIndex);
	}

	vl::Ptr<vl::glr::xml::XmlDocument> Parser::ParseXDocument(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex) const
	{
		 return ParseWithTokens<vl::glr::xml::XmlDocument, ParserStates::XDocument>(tokens, this, codeIndex);
	}
}


/***********************************************************************
.\XML\GENERATED\XML_ASSEMBLER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Xml
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml
{

/***********************************************************************
XmlAstInsReceiver : public vl::glr::AstInsReceiverBase
***********************************************************************/

	vl::Ptr<vl::glr::ParsingAstBase> XmlAstInsReceiver::CreateAstNode(vl::vint32_t type)
	{
		auto cppTypeName = XmlCppTypeName((XmlClasses)type);
		switch((XmlClasses)type)
		{
		case XmlClasses::Attribute:
			return vl::Ptr(new vl::glr::xml::XmlAttribute);
		case XmlClasses::CData:
			return vl::Ptr(new vl::glr::xml::XmlCData);
		case XmlClasses::Comment:
			return vl::Ptr(new vl::glr::xml::XmlComment);
		case XmlClasses::Document:
			return vl::Ptr(new vl::glr::xml::XmlDocument);
		case XmlClasses::Element:
			return vl::Ptr(new vl::glr::xml::XmlElement);
		case XmlClasses::Instruction:
			return vl::Ptr(new vl::glr::xml::XmlInstruction);
		case XmlClasses::Text:
			return vl::Ptr(new vl::glr::xml::XmlText);
		default:
			return vl::glr::AssemblyThrowCannotCreateAbstractType(type, cppTypeName);
		}
	}

	void XmlAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr<vl::glr::ParsingAstBase> value)
	{
		auto cppFieldName = XmlCppFieldName((XmlFields)field);
		switch((XmlFields)field)
		{
		case XmlFields::Document_prologs:
			return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlDocument::prologs, object, field, value, cppFieldName);
		case XmlFields::Document_rootElement:
			return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlDocument::rootElement, object, field, value, cppFieldName);
		case XmlFields::Element_attributes:
			return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlElement::attributes, object, field, value, cppFieldName);
		case XmlFields::Element_subNodes:
			return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlElement::subNodes, object, field, value, cppFieldName);
		case XmlFields::Instruction_attributes:
			return vl::glr::AssemblerSetObjectField(&vl::glr::xml::XmlInstruction::attributes, object, field, value, cppFieldName);
		default:
			return vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName);
		}
	}

	void XmlAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex)
	{
		auto cppFieldName = XmlCppFieldName((XmlFields)field);
		switch((XmlFields)field)
		{
		case XmlFields::Attribute_name:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlAttribute::name, object, field, token, tokenIndex, cppFieldName);
		case XmlFields::Attribute_value:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlAttribute::value, object, field, token, tokenIndex, cppFieldName);
		case XmlFields::CData_content:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlCData::content, object, field, token, tokenIndex, cppFieldName);
		case XmlFields::Comment_content:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlComment::content, object, field, token, tokenIndex, cppFieldName);
		case XmlFields::Element_closingName:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlElement::closingName, object, field, token, tokenIndex, cppFieldName);
		case XmlFields::Element_name:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlElement::name, object, field, token, tokenIndex, cppFieldName);
		case XmlFields::Instruction_name:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlInstruction::name, object, field, token, tokenIndex, cppFieldName);
		case XmlFields::Text_content:
			return vl::glr::AssemblerSetTokenField(&vl::glr::xml::XmlText::content, object, field, token, tokenIndex, cppFieldName);
		default:
			return vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName);
		}
	}

	void XmlAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem, bool weakAssignment)
	{
		auto cppFieldName = XmlCppFieldName((XmlFields)field);
		return vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName);
	}

	const wchar_t* XmlTypeName(XmlClasses type)
	{
		const wchar_t* results[] = {
			L"Attribute",
			L"CData",
			L"Comment",
			L"Document",
			L"Element",
			L"Instruction",
			L"Node",
			L"Text",
		};
		vl::vint index = (vl::vint)type;
		return 0 <= index && index < 8 ? results[index] : nullptr;
	}

	const wchar_t* XmlCppTypeName(XmlClasses type)
	{
		const wchar_t* results[] = {
			L"vl::glr::xml::XmlAttribute",
			L"vl::glr::xml::XmlCData",
			L"vl::glr::xml::XmlComment",
			L"vl::glr::xml::XmlDocument",
			L"vl::glr::xml::XmlElement",
			L"vl::glr::xml::XmlInstruction",
			L"vl::glr::xml::XmlNode",
			L"vl::glr::xml::XmlText",
		};
		vl::vint index = (vl::vint)type;
		return 0 <= index && index < 8 ? results[index] : nullptr;
	}

	const wchar_t* XmlFieldName(XmlFields field)
	{
		const wchar_t* results[] = {
			L"Attribute::name",
			L"Attribute::value",
			L"CData::content",
			L"Comment::content",
			L"Document::prologs",
			L"Document::rootElement",
			L"Element::attributes",
			L"Element::closingName",
			L"Element::name",
			L"Element::subNodes",
			L"Instruction::attributes",
			L"Instruction::name",
			L"Text::content",
		};
		vl::vint index = (vl::vint)field;
		return 0 <= index && index < 13 ? results[index] : nullptr;
	}

	const wchar_t* XmlCppFieldName(XmlFields field)
	{
		const wchar_t* results[] = {
			L"vl::glr::xml::XmlAttribute::name",
			L"vl::glr::xml::XmlAttribute::value",
			L"vl::glr::xml::XmlCData::content",
			L"vl::glr::xml::XmlComment::content",
			L"vl::glr::xml::XmlDocument::prologs",
			L"vl::glr::xml::XmlDocument::rootElement",
			L"vl::glr::xml::XmlElement::attributes",
			L"vl::glr::xml::XmlElement::closingName",
			L"vl::glr::xml::XmlElement::name",
			L"vl::glr::xml::XmlElement::subNodes",
			L"vl::glr::xml::XmlInstruction::attributes",
			L"vl::glr::xml::XmlInstruction::name",
			L"vl::glr::xml::XmlText::content",
		};
		vl::vint index = (vl::vint)field;
		return 0 <= index && index < 13 ? results[index] : nullptr;
	}

	vl::Ptr<vl::glr::ParsingAstBase> XmlAstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& candidates)
	{
		auto cppTypeName = XmlCppTypeName((XmlClasses)type);
		return vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName);
	}
}


/***********************************************************************
.\XML\GENERATED\XML_LEXER.CPP
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Xml
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/


namespace vl::glr::xml
{
	bool XmlTokenDeleter(vl::vint token)
	{
		switch((XmlTokens)token)
		{
		case XmlTokens::SPACE:
			return true;
		default:
			return false;
		}
	}

	const wchar_t* XmlTokenId(XmlTokens token)
	{
		static const wchar_t* results[] = {
			L"INSTRUCTION_OPEN",
			L"INSTRUCTION_CLOSE",
			L"COMPLEX_ELEMENT_OPEN",
			L"SINGLE_ELEMENT_CLOSE",
			L"ELEMENT_OPEN",
			L"ELEMENT_CLOSE",
			L"EQUAL",
			L"NAME",
			L"ATTVALUE",
			L"COMMENT",
			L"CDATA",
			L"TEXT",
			L"SPACE",
		};
		vl::vint index = (vl::vint)token;
		return 0 <= index && index < XmlTokenCount ? results[index] : nullptr;
	}

	const wchar_t* XmlTokenDisplayText(XmlTokens token)
	{
		static const wchar_t* results[] = {
			L"<?",
			L"?>",
			L"</",
			L"/>",
			L"<",
			L">",
			L"=",
			nullptr,
			nullptr,
			nullptr,
			nullptr,
			nullptr,
			nullptr,
		};
		vl::vint index = (vl::vint)token;
		return 0 <= index && index < XmlTokenCount ? results[index] : nullptr;
	}

	const wchar_t* XmlTokenRegex(XmlTokens token)
	{
		static const wchar_t* results[] = {
			L"/</?",
			L"/?/>",
			L"/<//",
			L"///>",
			L"/<",
			L"/>",
			L"/=",
			L"[a-zA-Z0-9:._/-]+",
			L"\"[^<>\"]*\"|\'[^<>\']*\'",
			L"/</!--([^/-]|-[^/-]|--[^>])*--/>",
			L"/</!/[CDATA/[([^/]]|/][^/]]|/]/]+[^/]>])*/]/]+/>",
			L"([^<>=\"\' /r/n/ta-zA-Z0-9:._/-])+|\"|\'",
			L"/s+",
		};
		vl::vint index = (vl::vint)token;
		return 0 <= index && index < XmlTokenCount ? results[index] : nullptr;
	}

	void XmlLexerData(vl::stream::IStream& outputStream)
	{
		static const vl::vint dataLength = 1105; // 7530 bytes before compressing
		static const vl::vint dataBlock = 256;
		static const vl::vint dataRemain = 81;
		static const vl::vint dataSolidRows = 4;
		static const vl::vint dataRows = 5;
		static const char* compressed[] = {
			"\x6A\x1D\x00\x00\x49\x04\x00\x00\x2D\x00\x01\xA7\x01\x84\x81\x82\x12\x82\x01\x04\x88\x04\x89\x04\x84\x82\x05\x0F\x84\x8B\x04\x8C\x04\x81\x06\x8B\x04\x8E\x04\x9F\x04\x80\x11\x8E\x82\x21\x20\x84\x82\x13\x94\x83\x10\x82\x07\x82\x84\x83\x81\x80\x14\x82\x16\x04\x80\x81\x92\x90\x06\x14\x82\x9B\x01\xAF\x04\x9A\x91\x80\x18\x83\x1C\x04\xBA\x01\xA4\x8B\x1C\xA0\x82\x1E\x47\x84\xBD\x0A\xA4\x86\x1D\xA6\x82\x3F\x50\x84\x80\x23\xAC\x81\x20\xAB\x04\xC2\x19\xA4\x83\x24\xAC\x82\x22\x5F\x84\x85\x24\x83\x2C\x80\x2A\xB3\x04\xD5\x04\x9A\x24\x83\x2D\xB6\x82\x5C\x70\x84\x9D\x23\xBC\x82\x2E\xBB\x04\xDF\x39\xA4\x80\x34\xBC\x83\x30\x04\xFA\x04\x9B\x34\x87\x7F\x7E\x08\x00\x0D\x81\x90\x8B\xC6\x85\xC7\x80\x8A\x80\x0C\xC9\xC4\x87\x02\xC6\x00\x0B\x90\xC4\x86\x0B\xCC\x83\x01\xCE\x01\x9C\xDA\xC1\x89\x81\x81\x02\x82\x04\x04\x82\x17\xC2\xD0\x01\xD7\xD7\xA0\xAE\xF1\xD1\xC4\xDC\xD6\xDB\xD1\x00\x06\xFA\xDB\xDC\xDD\xDE\xDE\xDE\x17\x81\xBF\xC3\xEE\xDD\x8A\xE0\xE2\xC8\x86\xD3\x87\xE9\xE5\xE6\xE7\xE7\xC9\x8F\x05\xDE\xD2\xEC\xE7\x7F\xEA\xB9\xBA\xD8\xFB",
			"\xDB\xEA\xEF\xE9\xDE\xDD\xE0\xDF\xFC\xDA\x89\x80\xED\xF0\xD0\xC3\xE7\xE4\x8B\xF6\xE8\xF5\xF7\xE3\xDC\xE3\xF0\xFE\xF3\xF9\xF8\xEF\xD6\xF2\xF9\xFA\xD8\xC6\xF0\xF7\xFB\xE9\x7C\x6D\x78\x00\x03\xBA\x79\x76\x61\xE8\x41\x8A\x83\x82\x0C\x8D\x8E\x83\x83\x10\x91\x82\x87\x84\x14\x95\x86\x85\x7A\x11\x04\x49\x86\x75\x1B\x80\x0D\x87\x83\x1D\xA1\x8A\x87\x88\x01\x62\x8B\x7C\x71\x1F\xBA\x69\x89\x6F\x12\x04\x4D\x89\x40\x2F\x80\x01\x8F\x8C\x2E\xB5\x81\x43\x04\x36\xB2\x89\x8C\x8D\x30\xBB\x89\x8F\x6E\x31\x80\x9E\x8D\x8F\x44\xBA\x85\x90\x8F\x46\x89\x98\x93\x92\x3F\xBA\x64\x04\x41\x4F\x81\x41\x94\x00\x53\x95\x90\x97\x95\x52\x98\x90\x01\x05\x5A\x96\x99\x97\x97\x54\x9A\x9B\x6F\x94\x63\x9D\x96\x98\x98\x5E\xA1\x98\x9B\x99\x6A\xAD\x99\x9A\x81\xBF\x74\x77\x83\x75\xF6\x75\x77\x88\x9D\x77\x89\x84\x77\x7F\x77\x8B\x83\x81\x81\xF8\x73\x9A\x9E\x61\x16\x04\x45\xA2\x75\x87\xB3\x99\xA3\x85\x8C\x8D\xAE\xA3\xA3\x90\x91\xA2\xA7\xA4\x94\x95\xA6\xA5\xA4\x17\x00\x87\xA5\x7A\x18\x1A\xAB\xA7\xA7\xA0\x95\xA3\xA0\x9E\x82\xB5\x95\xAA\x9D\x73\xB0\x9B\x9D\x9F",
			"\x81\xA3\xAE\x9C\x9F\x04\xB0\xAA\xA8\x82\x9E\xA1\xA6\xAF\xAD\xB8\xBF\x36\x8B\x9C\xBB\xA0\x84\x8A\x87\xBF\xBB\xAB\x89\x73\xC3\x83\xB2\x93\x91\x43\x8A\x99\x8C\x8E\xC8\x8D\xBA\xB2\xB3\x41\xBA\x61\xB6\x61\x4C\x90\xB9\xB1\xB5\xCF\x99\xB8\x91\xAE\xDC\x9D\xBF\x3D\x9A\xE0\xAC\x91\xB9\x40\x5C\xAB\x96\xBA\x9B\x62\x8E\x93\x7B\xB8\xE8\xA7\xBC\xBB\xBB\xE2\xB5\xAE\xB7\xBC\x96\x89\xAB\xA2\x6E\xF7\x84\xA2\xBC\xBD\xFC\xB7\xA9\x07\xBE\xFD\x81\xC2\xC1\x72\x1A\x00\xC2\xA7\x06\x04\x48\xC1\x42\xC2\x00\x0C\xCE\xC1\xC2\x10\xCB\xC1\xC5\xC3\x13\xDC\x03\xC7\xC3\x12\xD9\xC4\xC6\xC6\x18\xDB\xCE\xC5\xC7\x20\xD7\xC2\xC8\xC7\x23\xDE\xC3\xC3\xA7\x1D\x06\xCD\xA1\xC8\x24\xED\xCF\xC5\xC9\x0C\xD6\xCE\xC8\xCB\x2F\xF3\xC0\xCF\xCD\x36\xF9\xC5\xCE\xC9\xBA\x5E\x04\x42\xCF\x01\x40\xD0\x02\xD0\x44\xFF\xC6\xD1\xD0\x47\xC3\xD9\xD0\x47\x48\xCD\xDA\xD2\xD3\x45\xD0\xD9\xD1\xD4\x4F\xD5\xD4\xD7\xD5\x53\xD9\xD2\xD6\xD3\x27\xCC\xAE\x44\xAB\xB7\xB4\xC2\xD8\xCE\x3B\xF2\xCB\xCF\xD8\x3A\xE8\xD7\xD8\xD9\x6A\xDD\xCB\x6D\x48\x01\x70\xD0\x02\xDC\x74\xE2\x41\xDE\xDD\x73",
			"\xF8\xD5\xDF\xDD\x7C\xF9\xDD\xDF\xDE\x7E\xC1\xE4\x4B\xDF\x7A\xC5\xE4\xE3\xE1\x81\xC0\xEA\xE0\xDE\x5D\xF9\xA7\x48\xD8\x14\xAD\xDC\xD8\xD9\x66\xD2\xE9\xDB\xE4\x97\xD9\xEB\xDA\xC6\x8D\xDD\xEE\xE5\xB7\x24\x2A\xCF\xE7\xE8\x13\xA5\x02\xE8\x74\x29\x40\x09\xEB\xEA\x28\x6D\xE6\x42\xEB\xAA\xF0\xEC\xEB\xEB\xB4\xF1\xE5\xEF\xEC\xB6\xF9\xE8\xEF\xEE\xB2\xFD\xE7\xEC\xEC\x2C\x7A\xEE\xED\xEE\xBB\x7C\xEF\xEF\xF1\xC2\xC8\xF6\xF1\xF2\xCC\xCB\xFE\xF3\xF0\xCF\xF5\xE1\xF1\xF4\xC4\xFA\x6E\x49\x4B\x04\x57\xF0\x02\xF6\xDC\xD9\xFE\xF4\xF6\xE0\xDB\xFF\xF6\xF8\xE1\xDD\xF5\xFB\xF8\xE6\xE4\xFA\xF9\xFA\xEC\xE8\xFE\xF9\x40\x29\x2F\xFB\xFB\xF8\xC5\xD0\xF6\xFE\xF2\xF7\xCD\xF9\xFC\xF5\xFC\xFB\xFB\x4A\xFF\xB5\x7B\x37\x0A\x04\x23\x81\x80\x05\x80\x00\x07\x89\x80\x01\x8B\x86\x80\x06\x88\x86\x81\x0A\x8D\x82\x04\x8F\x83\x83\x08\x80\x00\x26\x15\x90\x82\x06\x99\x8C\x82\x0A\x80\x02\x05\x1B\x9E\x82\x05\x82\x81\x84\x0B\xA6\x85\x84\x28\x9D\x83\x09\x93\x88\x82\x11\xA9\x86\x85\x2A\x8E\x80\x08\xB1\x8D\x83\xFA\x78\x7F\x86\xFA\x78\x85\xFF\x3A\x80\x81\x1C\xBE\x83",
			"\x7A\x3D\x84\x76\x10\x8A\x4E\x1F\x6F\x2B\x08\x00\x04\x10\x00\x4D\x05\x29\x35\x80\x0B\x38\x00\x4F\x87\x35\x68\x15\x32\x23\x2A\x8E\x8C\x22\x05\x2A\x34\x46\x24\x36\x8A\x00\x1F\x31\x20\x96\x21\x21\x70\x18\x3B\x8A\x32\x81\x26\x38\x00\x03\x8E\x1A\xE5\x8B\x8C\x31\xAC\x8F\x8D\xB8\x2D\x8D\x1A\xF0\x83\x8E\x37\xB6\x8D\x8E\x92\x24\x20",
		};
		vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);
	}
}

