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

/***********************************************************************
.\ASTBASE.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_ASTBASE
#define VCZH_PARSER2_ASTBASE


namespace vl
{
	namespace glr
	{
/***********************************************************************
ParsingTextPos
***********************************************************************/

		/// <summary>A type representing text position.</summary>
		struct ParsingTextPos
		{
			static const vint	UnknownValue = -2;
			/// <summary>Character index, begins at 0.</summary>
			vint				index;
			/// <summary>Row number, begins at 0.</summary>
			vint				row;
			/// <summary>Column number, begins at 0.</summary>
			vint				column;

			ParsingTextPos()
				:index(UnknownValue)
				, row(UnknownValue)
				, column(UnknownValue)
			{
			}

			ParsingTextPos(vint _index)
				:index(_index)
				, row(UnknownValue)
				, column(UnknownValue)
			{
			}

			ParsingTextPos(vint _row, vint _column)
				:index(UnknownValue)
				, row(_row)
				, column(_column)
			{
			}

			ParsingTextPos(vint _index, vint _row, vint _column)
				:index(_index)
				, row(_row)
				, column(_column)
			{
			}

			/// <summary>Test if this position a valid position.</summary>
			/// <returns>Returns true if this position is a valid position.</returns>
			bool IsInvalid()const
			{
				return index < 0 && row < 0 && column < 0;
			}

			static ParsingTextPos Start(const regex::RegexToken* token)
			{
				return { token->start,token->rowStart,token->columnStart };
			}

			static ParsingTextPos End(const regex::RegexToken* token)
			{
				return { token->start + token->length - 1,token->rowEnd,token->columnEnd };
			}

			friend std::strong_ordering operator<=>(const ParsingTextPos& a, const ParsingTextPos& b)
			{
				if (a.IsInvalid() && b.IsInvalid())
				{
					return std::strong_ordering::equal;
				}
				else if (a.IsInvalid())
				{
					return std::strong_ordering::less;
				}
				else if (b.IsInvalid())
				{
					return std::strong_ordering::greater;
				}
				else if (a.index >= 0 && b.index >= 0)
				{
					return a.index <=> b.index;
				}
				else if (a.row >= 0 && a.column >= 0 && b.row >= 0 && b.column >= 0)
				{
					if (a.row == b.row)
					{
						return a.column <=> b.column;
					}
					else
					{
						return a.row <=> b.row;
					}
				}
				else
				{
					return std::strong_ordering::equal;
				}
			}

			friend bool operator==(const ParsingTextPos& a, const ParsingTextPos& b)
			{
				return(a <=> b) == 0;
			}
		};

/***********************************************************************
ParsingTextRange
***********************************************************************/

		/// <summary>A type representing text range.</summary>
		struct ParsingTextRange
		{
			/// <summary>Text position for the first character.</summary>
			ParsingTextPos	start;
			/// <summary>Text position for the last character.</summary>
			ParsingTextPos	end;
			/// <summary>Code index, refer to [F:vl.regex.RegexToken.codeIndex]</summary>
			vint			codeIndex = -1;

			ParsingTextRange() = default;

			ParsingTextRange(const ParsingTextPos& _start, const ParsingTextPos& _end, vint _codeIndex = -1)
				: start(_start)
				, end(_end)
				, codeIndex(_codeIndex)
			{
			}

			ParsingTextRange(const regex::RegexToken* startToken, const regex::RegexToken* endToken)
				: start(ParsingTextPos::Start(startToken))
				, end(ParsingTextPos::End(endToken))
				, codeIndex(startToken->codeIndex)
			{
			}

			bool Contains(const ParsingTextPos& pos)const { return start <= pos && pos <= end; }
			bool Contains(const ParsingTextRange& range)const { return start <= range.start && range.end <= end; }

			friend std::strong_ordering operator<=>(const ParsingTextRange& a, const ParsingTextRange& b)
			{
				std::strong_ordering
					result = a.start <=> b.start; if (result != 0) return result;
				result = a.end <=> b.end; if (result != 0) return result;
				return std::strong_ordering::equal;
			}

			friend bool operator==(const ParsingTextRange& a, const ParsingTextRange& b)
			{
				return (a <=> b) == 0;
			}
		};

/***********************************************************************
ParsingError
***********************************************************************/

		class ParsingAstBase;

		struct ParsingError
		{
			ParsingAstBase*						node = nullptr;
			ParsingTextRange					codeRange;
			WString								message;
		};

/***********************************************************************
AST
***********************************************************************/

		/// <summary>Base type of all strong typed syntax tree. Normally all strong typed syntax tree are generated from a grammar file using ParserGen.exe in Tools project.</summary>
		class ParsingAstBase : public Object, public reflection::Description<ParsingAstBase>
		{
		public:
			/// <summary>Range of all tokens that form this object.</summary>
			ParsingTextRange					codeRange;
		};

		/// <summary>Strong typed token syntax node, for all class fields of type "token" in the grammar file. See [T:vl.parsing.tabling.ParsingTable] for details.</summary>
		struct ParsingToken
		{
		public:
			/// <summary>Range of all tokens that form this object.</summary>
			ParsingTextRange					codeRange;
			/// <summary>Index of the token in the token list provided to the parser.</summary>
			vint								index = -1;
			/// <summary>Type of the token, representing the index of a regular expression that creates this token in the regular expression list in the grammar file.</summary>
			vint								token = -1;
			/// <summary>Content of the token.</summary>
			WString								value;

			operator bool() const { return value.Length() > 0; }
		};

/***********************************************************************
AST (Builder)
***********************************************************************/

		template<typename TAst>
		class ParsingAstBuilder
		{
		protected:
			Ptr<TAst> node{ new TAst };
			ParsingAstBuilder() {}
		public:

			template<typename TExpected>
			operator Ptr<TExpected>() const
			{
				return node;
			}
		};

/***********************************************************************
AST (Visitor)
***********************************************************************/

		class CopyVisitorBase : public Object
		{
		protected:
			Ptr<ParsingAstBase>					result;
		};

		class JsonVisitorBase : public Object
		{
		private:
			stream::StreamWriter&				writer;
			vint								indentation = 0;
			collections::List<vint>				indices;

		protected:

			void								BeginObject();
			void								BeginField(const WString& field);
			void								EndField();
			void								EndObject();
			void								BeginArray();
			void								BeginArrayItem();
			void								EndArrayItem();
			void								EndArray();
			void								WriteIndent();
			void								WriteRange(const ParsingTextRange& range);
			void								WriteToken(const ParsingToken& token);
			void								WriteType(const WString& type, ParsingAstBase* node);
			void								WriteString(const WString& text);
			void								WriteNull();
		public:
			bool								printTokenCodeRange = true;
			bool								printAstCodeRange = true;
			bool								printAstType = true;

			JsonVisitorBase(stream::StreamWriter& _writer);
		};

		extern void								JsonEscapeString(const WString& text, stream::TextWriter& writer);
		extern void								JsonUnescapeString(const WString& text, stream::TextWriter& writer);

/***********************************************************************
Instructions
***********************************************************************/

		constexpr vint32_t ResolveAmbiguitySlotIndex = -2;

		enum class AstInsType
		{
			Token,										// Token(Count)						: Put the current token in the Count-th slot.
			EnumItem,									// EnumItem(Value, Count)			: Put an enum item in the Count-th slot.
			StackBegin,									// StackBegin()						: Begin a new stack frame.
			StackSlot,									// StackSlot(Count)					: Assign the just created object to the Count-th slot. Reset the creating object.
			CreateObject,								// CreateObject(Type)				: Create an AST node, it becomes the creating object. Error if the previous creating object has not been reset.
			Field,										// Field(Field, Count)				: Associate a field name of the creating object with the value in the Count-th slot. Ignored if the Count-th slot is empty.
			FieldIfUnassigned,							// FieldIfUnassigned(Field, Count)	: Like Field(Field) but only take effect if such field has never been assigned.
			StackEnd,									// StackEnd()						: End the current stack frame. Leave the creating object as is.
			ResolveAmbiguity,							// ResolveAmbiguity(Type)			: Combine several values in the specified slot to one using an ambiguity node. Type is the type of each value.
		};

		struct AstIns
		{
			AstInsType									type = AstInsType::Token;
			vint32_t									param = -1;
			vint										count = -1;

			std::strong_ordering operator<=>(const AstIns& ins) const
			{
				std::strong_ordering
				result = type <=> ins.type; if (result != 0) return result;
				result = param <=> ins.param; if (result != 0) return result;
				result = count <=> ins.count; if (result != 0) return result;
				return result;
			}

			bool operator==(const AstIns& ins) const
			{
				return (*this <=> ins) == 0;
			}
		};

		enum class AstInsErrorType
		{
			UnknownType,								// UnknownType(Type)					: The type id does not exist.
			UnknownField,								// UnknownField(Field)					: The field id does not exist.
			UnsupportedAbstractType,					// UnsupportedAbstractType(Type)		: Unable to create abstract class.
			FieldNotExistsInType,						// FieldNotExistsInType(Field)			: The type doesn't have such field.
			FieldReassigned,							// FieldReassigned(Field)				: An object is assigned to a field but this field has already been assigned.
			FieldWeakAssignmentOnNonEnum,				// FieldWeakAssignmentOnNonEnum(Field)	: Weak assignment only available for field of enum type.
			ObjectTypeMismatchedToField,				// ObjectTypeMismatchedToField(Field)	: Unable to assign an object to a field because the type does not match.

			UnsupportedAmbiguityType,					// UnsupportedAmbiguityType(Type)		: The type is not configured to allow ambiguity.
			UnexpectedAmbiguousCandidate,				// UnexpectedAmbiguousCandidate(Type)	: The type of the ambiguous candidate is not compatible to the required type.
			MissingAmbiguityCandidate,					// MissingAmbiguityCandidate()			: There are less than two candidates to create an ambiguity node.
			AmbiguityCandidateIsNotObject,				// AmbiguityCandidateIsNotObject()		: Tokens or enum items cannot be ambiguity candidates.

			NoStackFrame,								// NoStackFrame()						: Stack operations are executed while no stack frame exists.
			NoStackFrameForStackEnd,					// NoStackFrameForStackEnd()			: StackEnd when no stack frame exists.
			NoCreatingObjectForField,					// NoCreatingObjectForField()			: Field when no creating object.
			NoCreatingObjectForStackSlot,				// NoCreatingObjectForStackSlot()		: StackSlot when no creating object.
			NoCreatingObjectForStackEnd,				// NoCreatingObjectForStackEnd()		: StackEnd when no creating object.
			
			InstructionNotComplete,						// InstructionNotComplete()				: No more instruction but the root object has not been completed yet.
			Corrupted,									// Corrupted()							: An exception has been thrown therefore this receiver cannot be used anymore.
			Finished,									// Finished()							: The finished instruction has been executed therefore this receiver cannot be used anymore.
		};

		class AstInsException : public Exception
		{
		public:
			AstInsErrorType								error = AstInsErrorType::Corrupted;
			vint32_t									paramTypeOrField = -1;

			AstInsException(const WString& message, AstInsErrorType _error, vint32_t _typeOrField = -1)
				: Exception(message)
				, error(_error)
				, paramTypeOrField(_typeOrField)
			{
			}
		};

/***********************************************************************
IAstInsReceiver
***********************************************************************/

		class IAstInsReceiver : public virtual Interface
		{
		public:
			virtual void								Execute(AstIns instruction, const regex::RegexToken& token, vint32_t tokenIndex) = 0;
			virtual Ptr<ParsingAstBase>					Finished() = 0;
		};

		namespace astins_slots
		{
			struct TokenSlot
			{
				regex::RegexToken						token;
				vint32_t								index = -1;

				auto operator<=>(const TokenSlot& slot) const
				{
					auto result = token.length <=> slot.token.length;
					if (result != 0) return result;
					result = token.token <=> slot.token.token;
					if (result != 0) return result;
					result = token.reading <=> slot.token.reading;
					if (result != 0) return result;
					return index <=> slot.index;
				}

				bool operator==(const TokenSlot& slot) const
				{
					return (*this <=> slot) == 0;
				}
			};

			struct EnumItemSlot
			{
				vint32_t								value = -1;

				auto operator<=>(const EnumItemSlot&) const = default;
				bool operator==(const EnumItemSlot& slot) const
				{
					return (*this <=> slot) == 0;
				}
			};

			using SlotValue = Variant<TokenSlot, EnumItemSlot, Ptr<ParsingAstBase>>;

			inline auto operator<=>(const SlotValue& a, const SlotValue& b)
			{
				auto result = a.Index() <=> b.Index();
				if (result != 0) return result;
				switch (a.Index())
				{
				case 0:
					return a.Get<TokenSlot>() <=> b.Get<TokenSlot>();
				case 1:
					return a.Get<EnumItemSlot>() <=> b.Get<EnumItemSlot>();
				case 2:
					return a.Get<Ptr<ParsingAstBase>>() <=> b.Get<Ptr<ParsingAstBase>>();
				default:
					return std::strong_ordering::equal;
				}
			}

			inline auto operator==(const SlotValue& a, const SlotValue& b)
			{
				return (a <=> b) == 0;
			}

			struct SlotStorage
			{
				SlotValue								value;
				Ptr<collections::List<SlotValue>>		additionalValues;

				auto operator<=>(const SlotStorage& slotStorage) const
				{
					auto result = value <=> slotStorage.value;
					if (result != 0) return result;
					result = static_cast<bool>(additionalValues) <=> static_cast<bool>(slotStorage.additionalValues);
					if (result != 0) return result;

					if (additionalValues)
					{
						result = collections::CompareEnumerable(*additionalValues.Obj(), *slotStorage.additionalValues.Obj());
						if (result != 0) return result;
					}
					return std::strong_ordering::equal;
				}

				bool operator==(const SlotStorage& slotStorage) const
				{
					return (*this <=> slotStorage) == 0;
				}
			};
			using SlotMap = collections::Dictionary<vint, SlotStorage>;
		}

		class AstInsReceiverBase : public Object, public virtual IAstInsReceiver
		{
		private:

			struct StackFrame
			{
				astins_slots::SlotMap									slots;
				ParsingTextPos							codeRangeStart;
			};
			using StackFrameList = collections::List<StackFrame>;

			struct CreatingObject
			{
				Ptr<ParsingAstBase>						object;
				vint32_t								type = -1;
			};
			using CreatingObjectList = collections::List<CreatingObject>;

			CreatingObjectList							creatingObjects;
			StackFrameList								stackFrames;
			bool										finished = false;
			bool										corrupted = false;

			void										EnsureContinuable();
			void										SetField(ParsingAstBase* object, vint32_t field, const astins_slots::SlotValue& value, bool weakAssignment);

		protected:
			virtual Ptr<ParsingAstBase>					CreateAstNode(vint32_t type) = 0;
			virtual void								SetField(ParsingAstBase* object, vint32_t field, Ptr<ParsingAstBase> value) = 0;
			virtual void								SetField(ParsingAstBase* object, vint32_t field, const regex::RegexToken& token, vint32_t tokenIndex) = 0;
			virtual void								SetField(ParsingAstBase* object, vint32_t field, vint32_t enumValue, bool weakAssignment) = 0;
			virtual Ptr<ParsingAstBase>					ResolveAmbiguity(vint32_t type, collections::Array<Ptr<ParsingAstBase>>& candidates) = 0;

		public:
			AstInsReceiverBase() = default;
			~AstInsReceiverBase() = default;

			void										Execute(AstIns instruction, const regex::RegexToken& token, vint32_t tokenIndex) override;
			Ptr<ParsingAstBase>							Finished() override;
		};

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

		template<typename TClass, typename TField>
		void AssemblerSetObjectField(Ptr<TField>(TClass::* member), ParsingAstBase* object, vint32_t field, Ptr<ParsingAstBase> value, const wchar_t* cppFieldName)
		{
			auto typedObject = dynamic_cast<TClass*>(object);
			if (!typedObject)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" does not exist in the current object."),
					AstInsErrorType::FieldNotExistsInType, field);
			}
			if ((typedObject->*member))
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" has already been assigned."),
					AstInsErrorType::FieldReassigned, field);
			}

			auto typedValue = value.Cast<TField>();
			if (!typedValue)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" cannot be assigned with an uncompatible value."),
					AstInsErrorType::ObjectTypeMismatchedToField, field);
			}
			(typedObject->*member) = typedValue;
		}

		template<typename TClass, typename TField>
		void AssemblerSetObjectField(collections::List<Ptr<TField>>(TClass::* member), ParsingAstBase* object, vint32_t field, Ptr<ParsingAstBase> value, const wchar_t* cppFieldName)
		{
			auto typedObject = dynamic_cast<TClass*>(object);
			if (!typedObject)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" does not exist in the current object."),
					AstInsErrorType::FieldNotExistsInType, field);
			}

			auto typedValue = value.Cast<TField>();
			if (!typedValue)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" cannot be assigned with an uncompatible value."),
					AstInsErrorType::ObjectTypeMismatchedToField, field);
			}
			(typedObject->*member).Add(typedValue);
		}

		template<typename TClass>
		void AssemblerSetTokenField(ParsingToken(TClass::* member), ParsingAstBase* object, vint32_t field, const regex::RegexToken& token, vint32_t tokenIndex, const wchar_t* cppFieldName)
		{
			auto typedObject = dynamic_cast<TClass*>(object);
			if (!typedObject)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" does not exist in the current object."),
					AstInsErrorType::FieldNotExistsInType, field);
			}
			if ((typedObject->*member).value.Length() != 0)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" has already been assigned."),
					AstInsErrorType::FieldReassigned, field);
			}

			ParsingToken& tokenField = typedObject->*member;
			tokenField.codeRange = { &token,&token };
			tokenField.index = tokenIndex;
			tokenField.token = token.token;
			tokenField.value = WString::CopyFrom(token.reading, token.length);
		}

		template<typename TClass, typename TField>
		void AssemblerSetEnumField(TField(TClass::* member), ParsingAstBase* object, vint32_t field, vint32_t enumItem, bool weakAssignment, const wchar_t* cppFieldName)
		{
			auto typedObject = dynamic_cast<TClass*>(object);
			if (!typedObject)
			{
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" does not exist in the current object."),
					AstInsErrorType::FieldNotExistsInType, field);
			}
			if ((typedObject->*member) != TField::UNDEFINED_ENUM_ITEM_VALUE)
			{
				if (weakAssignment) return;
				throw AstInsException(
					WString::Unmanaged(L"Field \"") +
					WString::Unmanaged(cppFieldName) +
					WString::Unmanaged(L"\" has already been assigned."),
					AstInsErrorType::FieldReassigned, field);
			}
			(typedObject->*member) = (TField)enumItem;
		}

		template<typename TElement, typename TAmbiguity>
		Ptr<ParsingAstBase> AssemblerResolveAmbiguity(vint32_t type, collections::Array<Ptr<ParsingAstBase>>& candidates, const wchar_t* cppTypeName)
		{
			auto ast = Ptr(new TAmbiguity());
			if (candidates.Count() > 0)
			{
				ast->codeRange = candidates[0]->codeRange;
			}
			for (auto candidate : candidates)
			{
				if (auto typedAst = candidate.Cast<TElement>())
				{
					ast->candidates.Add(typedAst);
				}
				else if (auto ambiguityAst = candidate.Cast<TAmbiguity>())
				{
					CopyFrom(ast->candidates, ambiguityAst->candidates, true);
				}
				else
				{
					throw AstInsException(
						WString::Unmanaged(L"The type of the ambiguous candidate is not compatible to the required type \"") +
						WString::Unmanaged(cppTypeName) +
						WString::Unmanaged(L"\"."),
						AstInsErrorType::UnexpectedAmbiguousCandidate, type);
				}
			}
			return ast;
		}

		template<vint32_t Size>
		vint32_t AssemblerFindCommonBaseClass(vint32_t class1, vint32_t class2, vint32_t(&matrix)[Size][Size])
		{
			if (class1 < 0 || class1 >= Size) throw glr::AstInsException(L"The type id does not exist.", glr::AstInsErrorType::UnknownType, class1);
			if (class2 < 0 || class2 >= Size) throw glr::AstInsException(L"The type id does not exist.", glr::AstInsErrorType::UnknownType, class2);
			return matrix[class1][class2];
		}

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

		extern Ptr<ParsingAstBase>	AssemblyThrowCannotCreateAbstractType(vint32_t type, const wchar_t* cppTypeName);
		extern void					AssemblyThrowFieldNotObject(vint32_t field, const wchar_t* cppFieldName);
		extern void					AssemblyThrowFieldNotToken(vint32_t field, const wchar_t* cppFieldName);
		extern void					AssemblyThrowFieldNotEnum(vint32_t field, const wchar_t* cppFieldName);
		extern Ptr<ParsingAstBase>	AssemblyThrowTypeNotAllowAmbiguity(vint32_t type, const wchar_t* cppTypeName);

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

		extern void			DecompressSerializedData(const char** buffer, bool decompress, vint solidRows, vint rows, vint block, vint remain, stream::IStream& outputStream);
	}

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

	namespace reflection
	{
		namespace description
		{
#ifndef VCZH_DEBUG_NO_REFLECTION
			DECL_TYPE_INFO(vl::glr::ParsingTextPos)
			DECL_TYPE_INFO(vl::glr::ParsingTextRange)
			DECL_TYPE_INFO(vl::glr::ParsingToken)
			DECL_TYPE_INFO(vl::glr::ParsingAstBase)
#endif
			extern bool		LoadParsing2Types();
		}
	}
}

#endif


/***********************************************************************
.\ASTPRINT.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_ASTPRINT
#define VCZH_PARSER2_ASTPRINT


namespace vl
{
	namespace glr
	{
/***********************************************************************
IParsingPrintNodeRecorder
***********************************************************************/

		class IParsingPrintNodeRecorder : public virtual Interface
		{
		public:
			virtual void						Record(ParsingAstBase* node, const ParsingTextRange& range) = 0;
		};

		class ParsingEmptyPrintNodeRecorder : public Object, public virtual IParsingPrintNodeRecorder
		{
		public:
			ParsingEmptyPrintNodeRecorder();
			~ParsingEmptyPrintNodeRecorder();

			void								Record(ParsingAstBase* node, const ParsingTextRange& range)override;
		};

		class ParsingMultiplePrintNodeRecorder : public Object, public virtual IParsingPrintNodeRecorder
		{
			typedef collections::List<Ptr<IParsingPrintNodeRecorder>>				RecorderList;
		protected:
			RecorderList						recorders;

		public:
			ParsingMultiplePrintNodeRecorder();
			~ParsingMultiplePrintNodeRecorder();

			void								AddRecorder(Ptr<IParsingPrintNodeRecorder> recorder);
			void								Record(ParsingAstBase* node, const ParsingTextRange& range)override;
		};

		class ParsingOriginalLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
		{
		protected:
			Ptr<IParsingPrintNodeRecorder>		recorder;

		public:
			ParsingOriginalLocationRecorder(Ptr<IParsingPrintNodeRecorder> _recorder);
			~ParsingOriginalLocationRecorder();

			void								Record(ParsingAstBase* node, const ParsingTextRange& range)override;
		};

		class ParsingGeneratedLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
		{
			typedef collections::Dictionary<ParsingAstBase*, ParsingTextRange>		RangeMap;
		protected:
			RangeMap&							rangeMap;

		public:
			ParsingGeneratedLocationRecorder(RangeMap& _rangeMap);
			~ParsingGeneratedLocationRecorder();

			void								Record(ParsingAstBase* node, const ParsingTextRange& range)override;
		};

		class ParsingUpdateLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
		{
		public:
			ParsingUpdateLocationRecorder();
			~ParsingUpdateLocationRecorder();

			void								Record(ParsingAstBase* node, const ParsingTextRange& range)override;
		};

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

		class ParsingWriter : public stream::TextWriter
		{
			typedef collections::Pair<ParsingAstBase*, ParsingTextPos>				NodePosPair;
			typedef collections::List<NodePosPair>											NodePosList;
		protected:
			stream::TextWriter&					writer;
			Ptr<IParsingPrintNodeRecorder>		recorder;
			vint								codeIndex;
			ParsingTextPos						lastPos;
			ParsingTextPos						currentPos;
			NodePosList							nodePositions;

			void								HandleChar(wchar_t c);
		public:
			ParsingWriter(stream::TextWriter& _writer, Ptr<IParsingPrintNodeRecorder> _recorder = nullptr, vint _codeIndex = -1);
			~ParsingWriter();

			using stream::TextWriter::WriteString;
			void								WriteChar(wchar_t c)override;
			void								WriteString(const wchar_t* string, vint charCount)override;
			void								BeforePrint(ParsingAstBase* node);
			void								AfterPrint(ParsingAstBase* node);
		};
	}
}

#endif

/***********************************************************************
.\EXECUTABLE.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_EXECUTABLE
#define VCZH_PARSER2_EXECUTABLE


namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
Executable
***********************************************************************/

			struct InstructionArray
			{
				vint32_t							start = -1;
				vint32_t							count = 0;
			};

			struct StringLiteral
			{
				vint32_t							start = -1;
				vint32_t							count = 0;
			};

			struct CompetitionArray
			{
				vint32_t							start = -1;
				vint32_t							count = 0;
			};

			struct ReturnIndexArray
			{
				vint32_t							start = -1;
				vint32_t							count = -1;
			};

			struct EdgeArray
			{
				vint32_t							start = -1;
				vint32_t							count = 0;
			};

			struct CompetitionDesc
			{
				vint32_t							competitionId = -1;
				bool								highPriority = false;
			};

			enum class ReturnRuleType
			{
				Field,
				Partial,
				Discard,
				Reuse,
			};

			struct ReturnDesc
			{
				vint32_t							consumedRule = -1;
				vint32_t							returnState = -1;
				CompetitionArray					competitions;
				ReturnRuleType						ruleType = ReturnRuleType::Field;
				InstructionArray					insAfterInput;
			};

			struct EdgeDesc
			{
				vint32_t							fromState = -1;
				vint32_t							toState = -1;
				StringLiteral						condition;
				CompetitionArray					competitions;
				InstructionArray					insAfterInput;
				ReturnIndexArray					returnIndices;
			};

			struct StateDesc
			{
				vint32_t							rule = -1;
				bool								endingState = false;
			};

			struct Executable
			{
				static constexpr vint32_t			EndOfInputInput = -1;
				static constexpr vint32_t			EndingInput = 0;
				static constexpr vint32_t			LeftrecInput = 1;
				static constexpr vint32_t			TokenBegin = 2;

				vint32_t							tokenCount = 0;
				vint32_t							ruleCount = 0;
				collections::Array<vint32_t>		ruleStartStates;		// ruleStartStates[rule] = the start state of this rule.
				collections::Array<EdgeArray>		transitions;			// transitions[state * (TokenBegin + tokenCount) + input] = edges from state with specified input.
				collections::Array<AstIns>			astInstructions;		// referenced by EdgeDesc::insBeforeInput and EdgeDesc::insAfterInput
				collections::Array<vint32_t>		returnIndices;			// referenced by ReturnIndexArray
				collections::Array<CompetitionDesc>	competitions;			// referenced by EdgeArray
				collections::Array<ReturnDesc>		returns;				// referenced by Executable::returnIndices
				collections::Array<EdgeDesc>		edges;					// referenced by EdgeArray
				collections::Array<StateDesc>		states;					// referenced by returnState/fromState/toState
				WString								stringLiteralBuffer;	// referenced by StringLiteral

				Executable() = default;
				Executable(stream::IStream& inputStream);

				void								Serialize(stream::IStream& outputStream);

				vint32_t GetTransitionIndex(vint32_t state, vint32_t input)
				{
					return state * (TokenBegin + tokenCount) + input;
				}
			};

			struct Metadata
			{
				collections::Array<WString>			ruleNames;
				collections::Array<WString>			stateLabels;
			};

/***********************************************************************
IExecutor
***********************************************************************/

			class UnableToResolveAmbiguityException : public Exception
			{
			public:
				vint32_t							class1 = -1;
				vint32_t							class2 = -1;
				vint32_t							tokenIndex1 = -1;
				vint32_t							tokenIndex2 = -1;

				UnableToResolveAmbiguityException(const WString& message, vint32_t _class1, vint32_t _class2, vint32_t _tokenIndex1, vint32_t _tokenIndex2)
					: Exception(message)
					, class1(_class1)
					, class2(_class2)
					, tokenIndex1(_tokenIndex1)
					, tokenIndex2(_tokenIndex2)
				{
				}
			};

			struct Trace;

			class IExecutor : public virtual Interface
			{
			public:
				class ITypeCallback : public virtual Interface
				{
				public:
					virtual WString					GetClassName(vint32_t classIndex) const = 0;
					virtual vint32_t				FindCommonBaseClass(vint32_t class1, vint32_t class2) const = 0;
				};

				virtual void						Initialize(vint32_t startState) = 0;
				virtual bool						Input(vint32_t currentTokenIndex, regex::RegexToken* token, regex::RegexToken* lookAhead) = 0;
				virtual bool						EndOfInput(bool& ambiguityInvolved) = 0;
				virtual void						PrepareTraceRoute() = 0;
				virtual void						ResolveAmbiguity() = 0;
				virtual Ptr<ParsingAstBase>			ExecuteTrace(IAstInsReceiver& receiver, collections::List<regex::RegexToken>& tokens) = 0;
			};

			extern Ptr<IExecutor>					CreateExecutor(Executable& executable, const IExecutor::ITypeCallback* typeCallback, vint _blockSize);
		}
	}
}

#endif

/***********************************************************************
.\SYNTAXBASE.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_SYNTAXBASE
#define VCZH_PARSER2_SYNTAXBASE


namespace vl
{
	namespace glr
	{
/***********************************************************************
ParserBase<TTokens, TStates, TReceiver, TStateTypes>
***********************************************************************/

		enum class ErrorType
		{
			UnrecognizedToken,		// (token)										the token is not recognizable to the tokenizer
			InvalidToken,			// (token, tokens, executable, traceManager)	the token cause the parser to stop
			InputIncomplete,		// (tokens, executable, traceManager)			all traces do not reach the end
			UnexpectedAstType,		// (tokens, executable, traceManager, ast)		unexpected type of the created AST
		};

		enum class TraceProcessingPhase
		{
			EndOfInput,
			PrepareTraceRoute,
			ResolveAmbiguity,
		};

		struct TraceProcessingArgs
		{
			collections::List<regex::RegexToken>&			tokens;
			automaton::Executable&							executable;
			automaton::IExecutor*							executor;
			bool											ambiguityInvolved;
			TraceProcessingPhase							phase;
		};

		struct ReadyToExecuteArgs
		{
			collections::List<regex::RegexToken>& tokens;
			automaton::Executable& executable;
			automaton::IExecutor* executor;
			bool											ambiguityInvolved;
		};

		struct ErrorArgs
		{
			bool											throwError;
			ErrorType										error;
			vint											codeIndex;
			regex::RegexToken&								token;
			collections::List<regex::RegexToken>&			tokens;
			automaton::Executable&							executable;
			automaton::IExecutor*							executor;
			Ptr<ParsingAstBase>								ast;

			static ErrorArgs								UnrecognizedToken	(const regex::RegexToken& token);
			static ErrorArgs								InvalidToken		(regex::RegexToken& token, collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::IExecutor* executor);
			static ErrorArgs								InputIncomplete		(vint codeIndex, collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::IExecutor* executor);
			static ErrorArgs								UnexpectedAstType	(collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::IExecutor* executor, Ptr<ParsingAstBase> ast);

			ParsingError									ToParsingError();
		};

		template<typename TParser>
		Ptr<EventHandler> InstallDefaultErrorMessageGenerator(TParser& parser, collections::List<ParsingError>& errors)
		{
			return parser.OnError.Add([&errors](ErrorArgs& args)
			{
				args.throwError = false;
				errors.Add(args.ToParsingError());
			});
		}

		template<
			typename TTokens,
			typename TStates,
			typename TReceiver
		>
		class ParserBase : public Object
		{
			static_assert(std::is_enum_v<TTokens>);
			static_assert(std::is_enum_v<TStates>);
			static_assert(std::is_convertible_v<TReceiver*, IAstInsReceiver*>);

			using Deleter = bool(*)(vint);
			using TokenList = collections::List<regex::RegexToken>;
			using TraceProcessingCallback = void(TraceProcessingArgs&);
			using ReadyToExecuteCallback = void(ReadyToExecuteArgs&);
			using ErrorCallback = void(ErrorArgs&);
		protected:
			Deleter									deleter;
			Ptr<regex::RegexLexer>					lexer;
			Ptr<automaton::Executable>				executable;

		public:
			Event<TraceProcessingCallback>			OnTraceProcessing;
			Event<ReadyToExecuteCallback>			OnReadyToExecute;
			Event<ErrorCallback>					OnError;

			ParserBase(
				Deleter _deleter,
				void(*_lexerData)(stream::IStream&),
				void(*_parserData)(stream::IStream&)
			) : deleter(_deleter)
			{
				{
					stream::MemoryStream data;
					_lexerData(data);
					data.SeekFromBegin(0);
					lexer = Ptr(new regex::RegexLexer(data));
				}
				{
					stream::MemoryStream data;
					_parserData(data);
					data.SeekFromBegin(0);
					executable = Ptr(new automaton::Executable(data));
				}
			}

			regex::RegexLexer& Lexer() const
			{
				return *lexer.Obj();
			}

			Deleter LexerDeleter() const
			{
				return deleter;
			}

			void Tokenize(const WString& input, TokenList& tokens, vint codeIndex = -1) const
			{
				input.Buffer();
				auto enumerable = lexer->Parse(input, {}, codeIndex);
				auto enumerator = Ptr(enumerable.CreateEnumerator());
				while (enumerator->Next())
				{
					auto&& token = enumerator->Current();
					if (token.token == -1 || !token.completeToken)
					{
						auto args = ErrorArgs::UnrecognizedToken(token);
						args.throwError = false;
						OnError(args);
						if (args.throwError)
						{
							CHECK_FAIL(L"vl::glr::ParserBase<...>::Tokenize(const WString&, List<RegexToken>&, vint)#Unrecognized token.");
						}
					}
					else if (!deleter(token.token))
					{
						tokens.Add(token);
					}
				}
			}

		protected:
			Ptr<ParsingAstBase> ParseInternal(TokenList& tokens, vint32_t state, automaton::IExecutor* executor, const automaton::IExecutor::ITypeCallback* typeCallback, vint codeIndex) const
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::ParserBase<...>::ParseInternal(List<RegexToken>&, vint32_t TraceManager::ITypeCallback*)#"
				if (codeIndex == -1 && tokens.Count() > 0)
				{
					codeIndex = tokens[0].codeIndex;
				}

				executor->Initialize(state);
				for (vint32_t i = 0; i < tokens.Count(); i++)
				{
					auto token = &tokens[i];
					auto lookAhead = i == tokens.Count() - 1 ? nullptr : &tokens[i + 1];

					if (!executor->Input(i, token, lookAhead))
					{
						auto args = ErrorArgs::InvalidToken(*token, tokens, *executable.Obj(), executor);
						OnError(args);
						if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Error happens during parsing.");
						return nullptr;
					}
				}

				bool ambiguityInvolved = false;
				if (!executor->EndOfInput(ambiguityInvolved))
				{
					auto args = ErrorArgs::InputIncomplete(codeIndex, tokens, *executable.Obj(), executor);
					OnError(args);
					if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Input is incomplete.");
					return nullptr;
				}

				{
					TraceProcessingArgs args = { tokens, *executable.Obj(), executor, ambiguityInvolved, TraceProcessingPhase::EndOfInput };
					OnTraceProcessing(args);
				}
				if (ambiguityInvolved)
				{
					{
						executor->PrepareTraceRoute();
						TraceProcessingArgs args = { tokens, *executable.Obj(), executor, ambiguityInvolved, TraceProcessingPhase::PrepareTraceRoute };
						OnTraceProcessing(args);
					}
					{
						executor->ResolveAmbiguity();
						TraceProcessingArgs args = { tokens, *executable.Obj(), executor, ambiguityInvolved, TraceProcessingPhase::ResolveAmbiguity };
						OnTraceProcessing(args);
					}
				}
				{
					ReadyToExecuteArgs args = { tokens, *executable.Obj(), executor, ambiguityInvolved };
					OnReadyToExecute(args);
				}

				TReceiver receiver;
				return executor->ExecuteTrace(receiver, tokens);

#undef ERROR_MESSAGE_PREFIX
			}

			template<typename TAst, TStates State>
			Ptr<TAst> ParseWithTokens(TokenList& tokens, const automaton::IExecutor::ITypeCallback* typeCallback, vint codeIndex, vint blockSize = 1024) const
			{
#define ERROR_MESSAGE_PREFIX L"vl::glr::ParserBase<...>::Parse<TAst, TStates>(List<RegexToken>& TraceManager::ITypeCallback*)#"
				auto executor = automaton::CreateExecutor(*executable.Obj(), typeCallback, blockSize);
				auto ast = ParseInternal(tokens, (vint32_t)State, executor.Obj(), typeCallback, codeIndex);
				auto typedAst = ast.template Cast<TAst>();

				if (ast && !typedAst)
				{
					auto args = ErrorArgs::UnexpectedAstType(tokens, *executable.Obj(), executor.Obj(), ast);
					OnError(args);
					if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unexpected type of the created AST.");
				}
				return typedAst;
#undef ERROR_MESSAGE_PREFIX
			}

			template<typename TAst, TStates State>
			Ptr<TAst> ParseWithString(const WString& input, const automaton::IExecutor::ITypeCallback* typeCallback, vint codeIndex, vint blockSize = 1024) const
			{
				TokenList tokens;
				Tokenize(input, tokens, codeIndex);
				return ParseWithTokens<TAst, State>(tokens, typeCallback, codeIndex, blockSize);
			}
		};
	}
}

#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST
#define VCZH_PARSER2_BUILTIN_JSON_AST_AST


namespace vl::glr::json
{
	class JsonArray;
	class JsonLiteral;
	class JsonNode;
	class JsonNumber;
	class JsonObject;
	class JsonObjectField;
	class JsonString;

	enum class JsonLiteralValue
	{
		UNDEFINED_ENUM_ITEM_VALUE = -1,
		True = 0,
		False = 1,
		Null = 2,
	};

	class JsonNode abstract : public vl::glr::ParsingAstBase, vl::reflection::Description<JsonNode>
	{
	public:
		class IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description<IVisitor>
		{
		public:
			virtual void Visit(JsonLiteral* node) = 0;
			virtual void Visit(JsonString* node) = 0;
			virtual void Visit(JsonNumber* node) = 0;
			virtual void Visit(JsonArray* node) = 0;
			virtual void Visit(JsonObject* node) = 0;
		};

		virtual void Accept(JsonNode::IVisitor* visitor) = 0;

	};

	class JsonLiteral : public JsonNode, vl::reflection::Description<JsonLiteral>
	{
	public:
		JsonLiteralValue value = JsonLiteralValue::UNDEFINED_ENUM_ITEM_VALUE;

		void Accept(JsonNode::IVisitor* visitor) override;
	};

	class JsonString : public JsonNode, vl::reflection::Description<JsonString>
	{
	public:
		vl::glr::ParsingToken content;

		void Accept(JsonNode::IVisitor* visitor) override;
	};

	class JsonNumber : public JsonNode, vl::reflection::Description<JsonNumber>
	{
	public:
		vl::glr::ParsingToken content;

		void Accept(JsonNode::IVisitor* visitor) override;
	};

	class JsonArray : public JsonNode, vl::reflection::Description<JsonArray>
	{
	public:
		vl::collections::List<vl::Ptr<JsonNode>> items;

		void Accept(JsonNode::IVisitor* visitor) override;
	};

	class JsonObjectField : public vl::glr::ParsingAstBase, vl::reflection::Description<JsonObjectField>
	{
	public:
		vl::glr::ParsingToken name;
		vl::Ptr<JsonNode> value;
	};

	class JsonObject : public JsonNode, vl::reflection::Description<JsonObject>
	{
	public:
		vl::collections::List<vl::Ptr<JsonObjectField>> fields;

		void Accept(JsonNode::IVisitor* visitor) override;
	};
}
namespace vl::reflection::description
{
#ifndef VCZH_DEBUG_NO_REFLECTION
	DECL_TYPE_INFO(vl::glr::json::JsonNode)
	DECL_TYPE_INFO(vl::glr::json::JsonNode::IVisitor)
	DECL_TYPE_INFO(vl::glr::json::JsonLiteralValue)
	DECL_TYPE_INFO(vl::glr::json::JsonLiteral)
	DECL_TYPE_INFO(vl::glr::json::JsonString)
	DECL_TYPE_INFO(vl::glr::json::JsonNumber)
	DECL_TYPE_INFO(vl::glr::json::JsonArray)
	DECL_TYPE_INFO(vl::glr::json::JsonObjectField)
	DECL_TYPE_INFO(vl::glr::json::JsonObject)

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

	BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::glr::json::JsonNode::IVisitor)
		void Visit(vl::glr::json::JsonLiteral* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::json::JsonString* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::json::JsonNumber* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::json::JsonArray* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::json::JsonObject* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

	END_INTERFACE_PROXY(vl::glr::json::JsonNode::IVisitor)

#endif
#endif
	/// <summary>Load all reflectable AST types, only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is off.</summary>
	/// <returns>Returns true if this operation succeeded.</returns>
	extern bool JsonAstLoadTypes();
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_BUILDER
#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_BUILDER


namespace vl::glr::json::builder
{
	class MakeArray : public vl::glr::ParsingAstBuilder<JsonArray>
	{
	public:
		MakeArray& items(const vl::Ptr<JsonNode>& value);
	};

	class MakeLiteral : public vl::glr::ParsingAstBuilder<JsonLiteral>
	{
	public:
		MakeLiteral& value(JsonLiteralValue value);
	};

	class MakeNumber : public vl::glr::ParsingAstBuilder<JsonNumber>
	{
	public:
		MakeNumber& content(const vl::WString& value);
	};

	class MakeObject : public vl::glr::ParsingAstBuilder<JsonObject>
	{
	public:
		MakeObject& fields(const vl::Ptr<JsonObjectField>& value);
	};

	class MakeObjectField : public vl::glr::ParsingAstBuilder<JsonObjectField>
	{
	public:
		MakeObjectField& name(const vl::WString& value);
		MakeObjectField& value(const vl::Ptr<JsonNode>& value);
	};

	class MakeString : public vl::glr::ParsingAstBuilder<JsonString>
	{
	public:
		MakeString& content(const vl::WString& value);
	};

}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_COPY_VISITOR
#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_COPY_VISITOR


namespace vl::glr::json::copy_visitor
{
	/// <summary>A copy visitor, overriding all abstract methods with AST copying code.</summary>
	class AstVisitor
		: public virtual vl::glr::CopyVisitorBase
		, protected virtual JsonNode::IVisitor
	{
	protected:
		void CopyFields(JsonArray* from, JsonArray* to);
		void CopyFields(JsonLiteral* from, JsonLiteral* to);
		void CopyFields(JsonNode* from, JsonNode* to);
		void CopyFields(JsonNumber* from, JsonNumber* to);
		void CopyFields(JsonObject* from, JsonObject* to);
		void CopyFields(JsonObjectField* from, JsonObjectField* to);
		void CopyFields(JsonString* from, JsonString* to);

	protected:
		virtual void Visit(JsonObjectField* node);

		void Visit(JsonLiteral* node) override;
		void Visit(JsonString* node) override;
		void Visit(JsonNumber* node) override;
		void Visit(JsonArray* node) override;
		void Visit(JsonObject* node) override;

	public:
		virtual vl::Ptr<JsonNode> CopyNode(JsonNode* node);
		virtual vl::Ptr<JsonObjectField> CopyNode(JsonObjectField* node);

		vl::Ptr<JsonArray> CopyNode(JsonArray* node);
		vl::Ptr<JsonLiteral> CopyNode(JsonLiteral* node);
		vl::Ptr<JsonNumber> CopyNode(JsonNumber* node);
		vl::Ptr<JsonObject> CopyNode(JsonObject* node);
		vl::Ptr<JsonString> CopyNode(JsonString* node);
	};
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_EMPTY_VISITOR
#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_EMPTY_VISITOR


namespace vl::glr::json::empty_visitor
{
	/// <summary>An empty visitor, overriding all abstract methods with empty implementations.</summary>
	class NodeVisitor : public vl::Object, public JsonNode::IVisitor
	{
	protected:
		// Dispatch (virtual) --------------------------------

	public:
		// Visitor Members -----------------------------------
		void Visit(JsonLiteral* node) override;
		void Visit(JsonString* node) override;
		void Visit(JsonNumber* node) override;
		void Visit(JsonArray* node) override;
		void Visit(JsonObject* node) override;
	};

}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_JSON_VISITOR
#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_JSON_VISITOR


namespace vl::glr::json::json_visitor
{
	/// <summary>A JSON visitor, overriding all abstract methods with AST to JSON serialization code.</summary>
	class AstVisitor
		: public vl::glr::JsonVisitorBase
		, protected virtual JsonNode::IVisitor
	{
	protected:
		virtual void PrintFields(JsonArray* node);
		virtual void PrintFields(JsonLiteral* node);
		virtual void PrintFields(JsonNode* node);
		virtual void PrintFields(JsonNumber* node);
		virtual void PrintFields(JsonObject* node);
		virtual void PrintFields(JsonObjectField* node);
		virtual void PrintFields(JsonString* node);

	protected:
		void Visit(JsonLiteral* node) override;
		void Visit(JsonString* node) override;
		void Visit(JsonNumber* node) override;
		void Visit(JsonArray* node) override;
		void Visit(JsonObject* node) override;

	public:
		AstVisitor(vl::stream::StreamWriter& _writer);

		void Print(JsonNode* node);
		void Print(JsonObjectField* node);
	};
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_AST_TRAVERSE_VISITOR
#define VCZH_PARSER2_BUILTIN_JSON_AST_AST_TRAVERSE_VISITOR


namespace vl::glr::json::traverse_visitor
{
	/// <summary>A traverse visitor, overriding all abstract methods with AST visiting code.</summary>
	class AstVisitor
		: public vl::Object
		, protected virtual JsonNode::IVisitor
	{
	protected:
		virtual void Traverse(vl::glr::ParsingToken& token);
		virtual void Traverse(vl::glr::ParsingAstBase* node);
		virtual void Traverse(JsonArray* node);
		virtual void Traverse(JsonLiteral* node);
		virtual void Traverse(JsonNode* node);
		virtual void Traverse(JsonNumber* node);
		virtual void Traverse(JsonObject* node);
		virtual void Traverse(JsonObjectField* node);
		virtual void Traverse(JsonString* node);

	protected:
		virtual void Finishing(vl::glr::ParsingAstBase* node);
		virtual void Finishing(JsonArray* node);
		virtual void Finishing(JsonLiteral* node);
		virtual void Finishing(JsonNode* node);
		virtual void Finishing(JsonNumber* node);
		virtual void Finishing(JsonObject* node);
		virtual void Finishing(JsonObjectField* node);
		virtual void Finishing(JsonString* node);

	protected:
		void Visit(JsonLiteral* node) override;
		void Visit(JsonString* node) override;
		void Visit(JsonNumber* node) override;
		void Visit(JsonArray* node) override;
		void Visit(JsonObject* node) override;

	public:
		void InspectInto(JsonNode* node);
		void InspectInto(JsonObjectField* node);
	};
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_AST_ASSEMBLER
#define VCZH_PARSER2_BUILTIN_JSON_AST_ASSEMBLER


namespace vl::glr::json
{
	enum class JsonClasses : vl::vint32_t
	{
		Array = 0,
		Literal = 1,
		Node = 2,
		Number = 3,
		Object = 4,
		ObjectField = 5,
		String = 6,
	};

	enum class JsonFields : vl::vint32_t
	{
		Array_items = 0,
		Literal_value = 1,
		Number_content = 2,
		Object_fields = 3,
		ObjectField_name = 4,
		ObjectField_value = 5,
		String_content = 6,
	};

	extern const wchar_t* JsonTypeName(JsonClasses type);
	extern const wchar_t* JsonCppTypeName(JsonClasses type);
	extern const wchar_t* JsonFieldName(JsonFields field);
	extern const wchar_t* JsonCppFieldName(JsonFields field);

	class JsonAstInsReceiver : public vl::glr::AstInsReceiverBase
	{
	protected:
		vl::Ptr<vl::glr::ParsingAstBase> CreateAstNode(vl::vint32_t type) override;
		void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr<vl::glr::ParsingAstBase> value) override;
		void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) override;
		void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem, bool weakAssignment) override;
		vl::Ptr<vl::glr::ParsingAstBase> ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& candidates) override;
	};
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_LEXER
#define VCZH_PARSER2_BUILTIN_JSON_LEXER


namespace vl::glr::json
{
	enum class JsonTokens : vl::vint32_t
	{
		TRUE_VALUE = 0,
		FALSE_VALUE = 1,
		NULL_VALUE = 2,
		OBJOPEN = 3,
		OBJCLOSE = 4,
		ARROPEN = 5,
		ARRCLOSE = 6,
		COMMA = 7,
		COLON = 8,
		NUMBER = 9,
		STRING = 10,
		SPACE = 11,
	};

	constexpr vl::vint JsonTokenCount = 12;
	extern bool JsonTokenDeleter(vl::vint token);
	extern const wchar_t* JsonTokenId(JsonTokens token);
	extern const wchar_t* JsonTokenDisplayText(JsonTokens token);
	extern const wchar_t* JsonTokenRegex(JsonTokens token);
	extern void JsonLexerData(vl::stream::IStream& outputStream);
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_JSON_PARSER_SYNTAX
#define VCZH_PARSER2_BUILTIN_JSON_PARSER_SYNTAX


namespace vl::glr::json
{
	enum class ParserStates
	{
		JLiteral = 0,
		JField = 7,
		JObject = 12,
		JArray = 18,
		JValue = 24,
		JRoot = 29,
	};

	const wchar_t* ParserRuleName(vl::vint index);
	const wchar_t* ParserStateLabel(vl::vint index);
	extern void JsonParserData(vl::stream::IStream& outputStream);

	class Parser
		: public vl::glr::ParserBase<JsonTokens, ParserStates, JsonAstInsReceiver>
		, protected vl::glr::automaton::IExecutor::ITypeCallback
	{
	protected:
		vl::WString GetClassName(vl::vint32_t classIndex) const override;
		vl::vint32_t FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const override;
	public:
		Parser();

		vl::Ptr<vl::glr::json::JsonNode> ParseJRoot(const vl::WString& input, vl::vint codeIndex = -1) const;
		vl::Ptr<vl::glr::json::JsonNode> ParseJRoot(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex = -1) const;
	};
}
#endif

/***********************************************************************
.\JSON\GLRJSON.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingJson_Parser

***********************************************************************/

#ifndef VCZH_PARSER2_BUILTIN_JSON
#define VCZH_PARSER2_BUILTIN_JSON


namespace vl
{
	namespace glr
	{
		namespace json
		{
			/// <summary>Deserialize JSON from string.</summary>
			/// <returns>The deserialized JSON node.</returns>
			/// <param name="input">The JSON code.</param>
			/// <param name="parser">The generated parser.</param>
			extern Ptr<JsonNode>			JsonParse(const WString& input, const Parser& parser);

			struct JsonFormatting
			{
				bool				spaceAfterColon = false;
				bool				spaceAfterComma = false;
				bool				crlf = false;
				bool				compact = false;		// available when crlf == true
				const wchar_t*		indentation = nullptr;	// available when crlf == true;

				JsonFormatting();
				JsonFormatting(const JsonFormatting&) = default;
				JsonFormatting(JsonFormatting&&) = default;
				JsonFormatting& operator=(const JsonFormatting&) = default;
				JsonFormatting& operator=(JsonFormatting&&) = default;
			};

			/// <summary>Serialize JSON to string.</summary>
			/// <param name="node">The JSON node to serialize.</param>
			/// <param name="writer">The text writer to receive the string.</param>
			extern void						JsonPrint(Ptr<JsonNode> node, stream::TextWriter& writer, JsonFormatting formatting = {});

			/// <summary>Serialize JSON to string.</summary>
			/// <returns>The serialized string.</returns>
			/// <param name="node">The JSON node to serialize.</param>
			extern WString					JsonToString(Ptr<JsonNode> node, JsonFormatting formatting = {});

			struct JsonNodeListSerializer
			{
				using SourceType = collections::List<Ptr<JsonNode>>;
				using DestType = WString;
				using ContextType = Ptr<Parser>;

				static void					Serialize(Ptr<Parser> parser, const SourceType& source, DestType& dest);
				static void					Deserialize(Ptr<Parser> parser, const DestType& source, SourceType& dest);
			};
		}
	}
}

#endif


/***********************************************************************
.\TRACEMANAGER\TRACEMANAGER.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_TRACEMANAGER_TRACEMANAGER
#define VCZH_PARSER2_TRACEMANAGER_TRACEMANAGER


namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
AllocateOnly<T>
***********************************************************************/

			struct WithMagicCounter
			{
				vuint64_t							mergeCounter = 0;		// a temporary counter for internal use
			};

			struct NullRef {};
			constexpr auto nullref = NullRef{};

			template<typename T>
			struct Ref
			{
				vint32_t		handle = -1;

				Ref() = default;
				Ref(NullRef) :handle(-1) {}
				Ref(T* obj) :handle(obj == nullptr ? -1 : obj->allocatedIndex) {}
				Ref(const Ref<T>& ref) :handle(ref.handle) {}
				explicit Ref(vint32_t _handle) :handle(_handle) {}

				__forceinline bool operator==(NullRef) const { return handle == -1; }
				__forceinline bool operator==(const Ref<T>& ref) const { return handle == ref.handle; }
				__forceinline std::strong_ordering operator<=>(const Ref<T>& ref) const = default;

				__forceinline Ref& operator=(const Ref<T>& ref) { handle = ref.handle; return *this; }
				__forceinline Ref& operator=(T* obj) { handle = obj == nullptr ? -1 : obj->allocatedIndex; return *this; }
				__forceinline Ref& operator=(NullRef) { handle = -1; return *this; }

				__forceinline std::strong_ordering operator<=>(vint32_t) = delete;
				__forceinline bool operator==(vint32_t) = delete;
				__forceinline Ref& operator=(vint32_t) = delete;
			};

			template<typename T>
			struct Allocatable
			{
				vint32_t		allocatedIndex = -1;
			};

			template<typename T>
			class AllocateOnly : public Object
			{
				static_assert(std::is_base_of_v<Allocatable<T>, T>, "T in AllocateOnly<T> does not inherit from Allocatable<T>.");
			protected:
				vint											blockSize;
				vint											remains;
				collections::List<Ptr<collections::Array<T>>>	buffers;

			public:
				AllocateOnly(vint _blockSize)
					: blockSize(_blockSize)
					, remains(0)
				{
				}

				T* Get(Ref<T> index)
				{
					vint row = index.handle / blockSize;
					vint column = index.handle % blockSize;
					CHECK_ERROR(0 <= row && row < buffers.Count(), L"vl::glr::automaton::AllocateOnly<T>::Get(vint)#Index out of range.");
					if (row == buffers.Count() - 1)
					{
						CHECK_ERROR(0 <= column && column < (blockSize - remains), L"vl::glr::automaton::AllocateOnly<T>::Get(vint)#Index out of range.");
					}
					else
					{
						CHECK_ERROR(0 <= column && column < blockSize, L"vl::glr::automaton::AllocateOnly<T>::Get(vint)#Index out of range.");
					}
					return &buffers[row]->operator[](column);
				}

				Ref<T> Allocate()
				{
					if (remains == 0)
					{
						buffers.Add(Ptr(new collections::Array<T>(blockSize)));
						remains = blockSize;
					}
					vint index = blockSize * (buffers.Count() - 1) + (blockSize - remains);
					buffers[buffers.Count() - 1]->operator[](blockSize - remains).allocatedIndex = (vint32_t)index;
					remains--;
					return Ref<T>((vint32_t)index);
				}

				void Clear()
				{
					remains = 0;
					buffers.Clear();
				}
			};

			struct ReturnStack;
			struct Trace;
			struct TraceExec;

/***********************************************************************
TraceManager (Data Structures)
***********************************************************************/

			struct ReturnStackSuccessors
			{
				vint32_t				tokenIndex = -1;			// index of the token when successors in this list are created
																	// the following members records all successors
																	// that is created at the token index

				Ref<ReturnStack>		first;						// first successor
				Ref<ReturnStack>		last;						// last successor
			};

			struct ReturnStackCache
			{
				ReturnStackSuccessors	lastSuccessors;				// the value of successors before the current one is changed
				ReturnStackSuccessors	successors;					// successors of ReturnStack for a token
				vint32_t				tokenIndex = -1;			// index of the token when this ReturnStack is created.
				Ref<ReturnStack>		prev;						// previous successor of ReturnStack::previous
				Ref<ReturnStack>		next;						// next successor of ReturnStack::previous
			};

			struct ReturnStack : Allocatable<ReturnStack>
			{
				Ref<ReturnStack>		previous;					// id of the previous ReturnStack
				vint32_t				returnIndex = -1;			// index of the ReturnDesc
				Ref<Trace>				fromTrace;					// id of the Trace which has a transition containing this ReturnStack
				ReturnStackCache		cache;
			};

			enum class CompetitionStatus
			{
				Holding,
				HighPriorityWin,
				LowPriorityWin,
			};

			struct Competition : Allocatable<Competition>
			{
				Ref<Competition>		nextActiveCompetition;					// next active Competition
				Ref<Competition>		nextHoldCompetition;					// next Competition hold by this trace

				CompetitionStatus		status = CompetitionStatus::Holding;	// if predecessors from this trace have different priority, the competition begins
																				// when the competition is over, it will be changed to HighPriorityWin or LowPriorityWin
																				// if all candidates fail, it could be Holding forever

				vint32_t				currentTokenIndex = -1;					// currentTokenIndex from the trace that creates this competition
				vint32_t				ruleId = -1;							// the rule id of state, when an edge starts this competition
				vint32_t				competitionId = -1;						// the unique competition id in a rule, when an edge starts this competition
																				// an state must be picked up and ensure that, the syntax creating the priority and the state belong to the same clause

				vint32_t				highCounter = 0;						// temporary counter for all existing high bets
																				// in the current step of input
				vint32_t				lowCounter = 0;							// temporary counter for all existing low bets
																				// in the current step of input
			};

			struct AttendingCompetitions : Allocatable<AttendingCompetitions>
			{
				Ref<AttendingCompetitions>	nextActiveAC;				// the next AttendingCompetitions for RuntimeRouting::attendingCompetitions
				Ref<AttendingCompetitions>	nextCarriedAC;				// the next AttendingCompetitions for RuntimeRouting::carriedCompetitions
				Ref<Competition>			competition;				// the id of the Competition
				bool						forHighPriority = false;	// bet of this competition

				Ref<ReturnStack>			returnStack;				// the ReturnStack object for the competition
																		// if the competition is attended by a ReturnDesc
																		// then the ReturnStack object is the one before a ReturnDesc transition happens

				bool						closed = false;				// true if the competition has been closed
																		// this flag is not always updated for discarded AttendingCompetitions objects
			};

/***********************************************************************
TraceManager (Data Structures -- Input/EndOfInput)

For a trace like:
  A
 / \
B   C
 \ /
  D

A.successors.(first .. last) = {B,C}
B.successors.siblingNext = C
C.successors.siblingPrev = B
(B, C).successors.(first .. last) = {D}

predecessors are for reverse relationships.
Such data structure makes many-to-many relationships impossible to represent.
***********************************************************************/

			struct TraceCollection
			{
				Ref<Trace>					first;						// first trace in the collection
				Ref<Trace>					last;						// last trace in the collection
				Ref<Trace>					siblingPrev;				// previous trace in the collection of the owned trace
				Ref<Trace>					siblingNext;				// next trace in the collection of the owned trace
			};

			struct CompetitionRouting
			{
				Ref<Competition>			holdingCompetitions;		// the id of the active Competition

				Ref<AttendingCompetitions>	attendingCompetitions;		// a linked list containing all AttendingCompetitions that this trace is attending
																		// predecessors could share and modify the same linked list
																		// if a competition is over, node could be removed from the linked list
																		// one competition only creates two AttendingCompetitions, traces with the same bet sharing the object

				Ref<AttendingCompetitions>	carriedCompetitions;		// all attended competitions regardless of the status of the competition
			};

			struct Trace : Allocatable<Trace>
			{
				TraceCollection			predecessors;				// ids of predecessor Trace

				// (filled by EndOfInput)
				TraceCollection			successors;					// ids of successor Trace
				vint32_t				predecessorCount = 0;
				vint32_t				successorCount = 0;

				// if state == -1
				// it means this is an ambiguity resolving trace
				// all merged traces are in predecessors

				vint32_t				state = -1;					// id of the current StateDesc
				Ref<ReturnStack>		returnStack;				// id of the current ReturnStack
				Ref<ReturnStack>		executedReturnStack;		// id of the executed ReturnStack that contains the ReturnDesc being executed
				vint32_t				byEdge = -1;				// id of the last EdgeDesc that make this trace
				vint32_t				byInput = -1;				// the last input that make this trace
				vint32_t				currentTokenIndex = -1;		// the index of the token that is byInput
				CompetitionRouting		competitionRouting;			// a data structure carrying priority and competition information

				// (filled by PrepareTraceRoute)
				Ref<TraceExec>			traceExecRef;				// the allocated TraceExec
				vint32_t				iterateCounter = 0;			// a temporary counter for IterateSurvivedTraces internal use
			};

/***********************************************************************
TraceManager (Data Structures -- PrepareTraceRoute)
***********************************************************************/

			struct InsExec_Stack;

			struct InsRef
			{
				Ref<Trace>							trace;
				vint32_t							ins = -1;

				__forceinline std::strong_ordering operator<=>(const InsRef& ref) const = default;
			};

			struct InsExec_InsRefLink : Allocatable<InsExec_InsRefLink>
			{
				Ref<InsExec_InsRefLink>				previous;
				InsRef								insRef;
			};

			struct InsExec_StackRefLink : Allocatable<InsExec_StackRefLink>
			{
				Ref<InsExec_StackRefLink>			previous;
				Ref<InsExec_Stack>					id;
			};

			struct InsExec_StackArrayRefLink : Allocatable<InsExec_StackArrayRefLink>, WithMagicCounter
			{
				Ref<InsExec_StackArrayRefLink>		previous;
				Ref<InsExec_StackRefLink>			ids;

				// The current depth of the link. The first one is 0.
				vint								currentDepth = -1;

				// Available when the link is in InsExec_Context::createStack
				// It records the InsExec_Context::objectStack depth when the link is created.
				vint								objectStackDepthForCreateStack = -1;
			};

			struct InsExec_StackSummarizing
			{
				// The earliest StackBegin instructions including in useFromStacks
				InsRef								earliestLocalInsRef;

				// The earliest StackBegin instructions including in useFromStacks and fieldStacks
				InsRef								earliestStackInsRef;

				// earliestStackInsRef but propogated back into useFromStacks
				InsRef								earliestInsRef;

				// StackEnd instructions mapping earliestInsRef.
				// Such StackBegin and StackEnd may not belong to the same stack.
				// But belong to the out-most stack.
				Ref<InsExec_InsRefLink>				bottomInsRefs;

				// All CreateObject instructions including in useFromStacks
				Ref<InsExec_InsRefLink>				indirectCreateObjectInsRefs;
			};

			struct InsExec_Stack : Allocatable<InsExec_Stack>, WithMagicCounter
			{
				// previous allocated object
				Ref<InsExec_Stack>					previous;

				// owner-field relationships
				Ref<InsExec_StackRefLink>			fieldStacks;

				// useFrom-useBy relationships
				Ref<InsExec_StackRefLink>			useFromStacks;

				// fieldStacks and useFromStacks
				Ref<InsExec_StackRefLink>			allDependentStacks;

				// Key instructions in this stack
				InsRef								beginInsRef;
				Ref<InsExec_InsRefLink>				createObjectInsRefs;
				Ref<InsExec_InsRefLink>				endWithCreateInsRefs;
				Ref<InsExec_InsRefLink>				endWithReuseInsRefs;

				InsExec_StackSummarizing			summarizing;
			};

			struct InsExec_Context
			{
				Ref<InsExec_StackArrayRefLink>		objectStack;			// Stack of created objects
				Ref<InsExec_StackArrayRefLink>		createStack;			// Stack of opening objects
			};

			struct InsExec : WithMagicCounter
			{
				// Stack operated by StackBegin/StackEnd/CreateObject
				Ref<InsExec_StackRefLink>			operatingStacks;

				// Context before executing this instruction
				InsExec_Context						contextBeforeExecution;
			};

/***********************************************************************
TraceManager (Data Structures -- ResolveAmbiguity)

A branch begins from:
  The initial trace
  Successors of a branch trace (a trace with multiple successors)
  A merge trace (a trace with multiple predecessors)
branchData.forwardTrace points to the nearest beginning of a trace.

Here a demos of which traces are beginnings:
  A*
  |
  B
 / \
C*  D*
|   |
E   F
 \ /
  G*(cfb->B)
  |
  H

For any merge trace, its branchData.commonForwardBranch points to the latest forwardTrace that all comming branches share.
It does not necessary equal to branchData.forwardTrace of all predecessors as their values might be different.

All branch traces can be found beginning from TraceManager::firstBranchTrace following nextBranchTrace.
All merge traces can be found beginning from TraceManager::firstMergeTrace following nextMergeTrace.
Traversing through branchData.forwardTrace and branchData.commonForwardBranch will skip all branches going forward.
***********************************************************************/

			// TraceAmbiguity describes where an ambiguity resolving begins and ends
			struct TraceAmbiguity : Allocatable<TraceAmbiguity>
			{
				// all objects to merge, they all have valid createObjectInsRef 
				Ref<InsExec_StackRefLink>			bottomCreateObjectStacks;

				// if multiple TraceAmbiguity are assigned to the same place
				// it records the one it overrides
				Ref<TraceAmbiguity>					overridedAmbiguity;

				// the trace where ambiguity resolution begins
				// prefix is the number of instructions before SB
				// if prefix + 1 is larger than instructions in firstTrace
				// then StackBegin is in all successors
				// these instructions create topObjectIds
				Ref<Trace>							firstTrace;
				vint32_t							prefix = -1;

				// the trace when ambiguity resolution ends
				// postfix is the number of instructions after SE
				// if lastTrace is a merge trace
				// then StackEnd is in all predecessors
				// these instructions end bottomObjectIds
				Ref<Trace>							lastTrace;
				vint32_t							postfix = -1;

				// The merge trace that creates this TraceAmbiguity, and its associated branch trace
				Ref<Trace>							branchTrace;
				Ref<Trace>							mergeTrace;
			};

			struct TraceAmbiguityLink : Allocatable<TraceAmbiguityLink>
			{
				Ref<TraceAmbiguityLink>				previous;
				Ref<TraceAmbiguity>					ambiguity;
			};

			struct TraceInsLists
			{
				InstructionArray					edgeInsAfterInput;
				InstructionArray					returnInsAfterInput;
				vint32_t							countAfterInput;
				vint32_t							countAll;
			};

			struct TraceBranchData : WithMagicCounter
			{
				// it stores the first trace of non branching path that this trace is in
				// such trace could be:
				//   the initial trace
				//   successors of a branch trace
				//   a merge trace
				Ref<Trace>							forwardTrace;

				// for merge trace, it stores the latest forwardTrace that all comming branches share
				Ref<Trace>							commonForwardBranch;
			};

			// TraceExec stores all ambiguity awared data for a trace
			struct TraceExec : Allocatable<TraceExec>
			{
				Ref<Trace>							traceId;
				TraceInsLists						insLists;				// instruction list of this trace
				InstructionArray					insExecRefs;			// allocated InsExec for instructions

				InsExec_Context						context;				// context after executing all instructions
				TraceBranchData						branchData;				// branch shapes

				// linked list of branch traces, in a global depth-first order, from TraceManager::firstBranchTrace
				Ref<Trace>							nextBranchTrace;

				// linked list of merge traces, in a global depth-first order, from TraceManager::firstMergeTrace
				Ref<Trace>							nextMergeTrace;

				// linked list of ambiguity critical trace
				// it is stored in a trace whose forwardTrace is itself
				// record all traces with the same forwardTrace value, order by trace id ascending
				//   a branch trace
				//   a predecessor of a merge trace
				//   a trace pointed by TraceAmbiguity::firstTrace
				Ref<Trace>							nextAmbiguityCriticalTrace;

				// TraceAmbiguity associated to the trace
				// it could be associated to
				//   TraceAmbiguity::firstTrace (order by prefix ascending)
				//   TraceAmbiguity::lastTrace  (order by postfix ascending)
				//   the merge trace that create this TraceAmbiguity
				// ambiguityBegins will contain multiple TraceAmbiguity when
				//   multiple ambiguity begins in different group of successors
				//   there is also a possibility when all ambiguities don't cover all successors

				Ref<TraceAmbiguity>					ambiguityDetected;		// The TraceAmbiguity whose lastTrace is this trace
																			// Referring to the last StackEnd of all predecessors
																			// Or the opening object at the end of the trace

				Ref<TraceAmbiguityLink>				ambiguityBegins;		// All TraceAmbiguity whose firstTrace is this trace
																			// All TraceAmbiguity in this list are grouped by lastTrace (using TraceAmbiguity::overridedAmbiguity)
																			// To traverse all of them, begins from each TraceAmbiguity in this list, and go through TraceAmbiguity::overridedAmbiguity
			};

/***********************************************************************
TraceManager (Data Structures -- BuildExecutionOrder)
***********************************************************************/

			enum class ExecutionType
			{
				Instruction,
				RA_Begin,
				RA_Branch,
				RA_End,
			};

			struct ExecutionStep : Allocatable<ExecutionStep>
			{
				struct ETI
				{
					vint32_t						startTrace;
					vint32_t						startIns;
					vint32_t						endTrace;
					vint32_t						endIns;
				};

				struct ETRA
				{
					vint32_t						type;
					vint32_t						trace;
				};

				ExecutionType						type = ExecutionType::Instruction;

				union
				{
					ETI								et_i;
					ETRA							et_ra;
				};

				// list (parent, next)
				// tree (parent, leafPrev, leafNext)
				Ref<ExecutionStep>					next, parent, leafNext;
				vint32_t							visitCount = 0;
				vint32_t							copyCount = 0;
			};

			struct ExecutionStepLinkedList
			{
				ExecutionStep*						first = nullptr;
				ExecutionStep*						last = nullptr;
			};

			struct ExecutionStepTree
			{
				ExecutionStep*						firstLeaf = nullptr;
				ExecutionStep*						lastLeaf = nullptr;
			};

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

			enum class TraceManagerState
			{
				Uninitialized,
				WaitingForInput,
				Finished,
				PreparedTraceRoute,
				ResolvedAmbiguity,
			};

			struct WalkingTrace
			{
				Trace*								currentTrace;
				Trace*								stateTrace;

				operator bool() const
				{
					return currentTrace && stateTrace;
				}
			};

			class TraceManager : public Object, public virtual IExecutor
			{
			protected:
				Executable&									executable;
				const ITypeCallback*						typeCallback = nullptr;

				TraceManagerState							state = TraceManagerState::Uninitialized;
				AllocateOnly<ReturnStack>					returnStacks;
				AllocateOnly<Trace>							traces;
				AllocateOnly<Competition>					competitions;
				AllocateOnly<AttendingCompetitions>			attendingCompetitions;

				collections::List<Trace*>					traces1;
				collections::List<Trace*>					traces2;

				Trace*										initialTrace = nullptr;
				Ref<Competition>							activeCompetitions;
				ReturnStackCache							initialReturnStackCache;

				collections::List<bool>						temporaryConditionStack;
				vint32_t									temporaryConditionStackSize = 0;

				void										BeginSwap();
				void										AddTrace(Trace* trace);
				void										EndSwap();
				void										AddTraceToCollection(Trace* owner, Trace* element, TraceCollection(Trace::* collection));

				// Ambiguity
				Trace*										EnsureTraceWithValidStates(Trace* trace);
				bool										AreTwoEndingInputTraceEqual(Trace* newTrace, Trace* candidate);
				Trace*										MergeTwoEndingInputTrace(Trace* newTrace, Trace* candidate);
				void										TryMergeSurvivingTraces();

				// Competition
				void										AttendCompetition(Trace* trace, Ref<AttendingCompetitions>& newAttendingCompetitions, Ref<AttendingCompetitions>& newCarriedCompetitions, Ref<ReturnStack> returnStack, vint32_t ruleId, CompetitionDesc comp);
				void										AttendCompetitionIfNecessary(Trace* trace, vint32_t currentTokenIndex, EdgeDesc& edgeDesc, Ref<AttendingCompetitions>& newAttendingCompetitions, Ref<AttendingCompetitions>& newCarriedCompetitions, Ref<ReturnStack>& newReturnStack);
				void										CheckAttendingCompetitionsOnEndingEdge(Trace* trace, EdgeDesc& edgeDesc, Ref<AttendingCompetitions> acId, Ref<ReturnStack> returnStack);
				bool										CheckBackupTracesBeforeSwapping(vint32_t currentTokenIndex);

				// ReturnStack
				ReturnStackSuccessors*						GetCurrentSuccessorInReturnStack(Ref<ReturnStack> base, vint32_t currentTokenIndex);
				ReturnStack*								PushReturnStack(Ref<ReturnStack> base, vint32_t returnIndex, Ref<Trace> fromTrace, vint32_t currentTokenIndex, bool allowReuse);

				// Walk
				bool										IsQualifiedTokenForCondition(regex::RegexToken* token, StringLiteral condition);
				bool										IsQualifiedTokenForEdgeArray(regex::RegexToken* token, EdgeArray& edgeArray);
				void										TestLeftrecEdgeQualification(EdgeDesc& edgeDesc, regex::RegexToken* lookAhead, bool& acceptLookAhead, bool& acceptEndingInput);
				WalkingTrace								WalkAlongSingleEdge(vint32_t currentTokenIndex, vint32_t input, WalkingTrace trace, vint32_t byEdge, EdgeDesc& edgeDesc);
				void										WalkAlongLeftrecEdges(vint32_t currentTokenIndex, regex::RegexToken* lookAhead, WalkingTrace trace, EdgeArray& edgeArray);
				void										WalkAlongEpsilonEdges(vint32_t currentTokenIndex, regex::RegexToken* lookAhead, WalkingTrace trace);
				void										WalkAlongTokenEdges(vint32_t currentTokenIndex, vint32_t input, regex::RegexToken* token, regex::RegexToken* lookAhead, WalkingTrace trace, EdgeArray& edgeArray);

				// EndOfInput
				void										FillSuccessorsAfterEndOfInput(bool& ambiguityInvolved);

			protected:
				// Common
				vuint64_t									MergeStack_MagicCounter = 0;

				template<typename TCallback>
				void										IterateSurvivedTraces(TCallback&& callback);

			public:
				void										ReadInstructionList(Trace* trace, TraceInsLists& insLists);
				AstIns&										ReadInstruction(vint32_t instruction, TraceInsLists& insLists);

			protected:
				// PrepareTraceRoute
				AllocateOnly<TraceExec>						traceExecs;
				collections::Array<InsExec>					insExecs;
				AllocateOnly<InsExec_Stack>					insExec_Stacks;
				AllocateOnly<InsExec_InsRefLink>			insExec_InsRefLinks;
				AllocateOnly<InsExec_StackRefLink>			insExec_StackRefLinks;
				AllocateOnly<InsExec_StackArrayRefLink>		insExec_StackArrayRefLinks;

				// phase: AllocateExecutionData
				void										AllocateExecutionData();

				// phase: BuildAmbiguityStructures
				Trace* StepForward(Trace* trace);
				void										BuildAmbiguityStructures();

				// phase: PartialExecuteTraces - PartialExecuteOrdinaryTrace
				InsExec_Stack*								NewStack();
				void										PushInsRefLink(Ref<InsExec_InsRefLink>& link, InsRef insRef);
				void										PushStackRefLink(Ref<InsExec_StackRefLink>& link, Ref<InsExec_Stack> id);
				void										PushStackArrayRefLink(Ref<InsExec_StackArrayRefLink>& arrayLink, Ref<InsExec_Stack> id);
				void										PushStackArrayRefLink(Ref<InsExec_StackArrayRefLink>& arrayLink, Ref<InsExec_StackRefLink> link);
				Ref<InsExec_InsRefLink>						JoinInsRefLink(Ref<InsExec_InsRefLink> first, Ref<InsExec_InsRefLink> second);
				Ref<InsExec_StackRefLink>					JoinStackRefLink(Ref<InsExec_StackRefLink> first, Ref<InsExec_StackRefLink> second);
				void										PartialExecuteOrdinaryTrace(Trace* trace);

				// phase: PartialExecuteTraces - EnsureInsExecContextCompatible
				void										EnsureInsExecContextCompatible(Trace* baselineTrace, Trace* commingTrace);

				// phase: PartialExecuteTraces - MergeInsExecContext
				template<Ref<InsExec_StackArrayRefLink> (InsExec_Context::*stack), typename TMerge>
				Ref<InsExec_StackArrayRefLink>				MergeStack(Trace* mergeTrace, TMerge&& merge);
				void										MergeInsExecContext(Trace* mergeTrace);

				// phase: PartialExecuteTraces
				void										PartialExecuteTraces();

				// phase: SummarizeInstructionRange
				template<typename TCallback>
				void										IterateStackWithDependency(Ref<InsExec_StackRefLink>(InsExec_Stack::* dependencies), TCallback&& callback);
				bool										UpdateTopTrace(InsRef& topInsRef, InsRef newInsRef);
				void										CollectInsRefs(collections::SortedList<InsRef>& insRefs, Ref<InsExec_InsRefLink> link);
				void										SummarizeEarilestLocalInsRefs();
				void										SummarizeEarilestStackInsRefs();
				void										SummarizeEarilestInsRefs();
				void										SummarizeInstructionRange();

			protected:
				// ResolveAmbiguity
				Ref<Trace>									firstBranchTrace;
				Ref<Trace>									firstMergeTrace;
				Ref<InsExec_Stack>							firstStack;
				Ref<ExecutionStep>							firstStep;
				AllocateOnly<TraceAmbiguity>				traceAmbiguities;
				AllocateOnly<TraceAmbiguityLink>			traceAmbiguityLinks;
				AllocateOnly<ExecutionStep>					executionSteps;

				// phase: CheckMergeTraces
				template<typename TCallback>
				bool										EnumerateObjects(Ref<InsExec_StackRefLink> stackRefLinkStartSet, bool withCounter, TCallback&& callback);
				template<typename TCallback>
				bool										EnumerateBottomInstructions(InsExec_Stack* ieObject, TCallback&& callback);
				bool										ComparePrefix(TraceExec* baselineTraceExec, TraceExec* commingTraceExec, vint32_t prefix);
				bool										ComparePostfix(TraceExec* baselineTraceExec, TraceExec* commingTraceExec, vint32_t postfix);
				template<typename TCallback>
				bool										CheckAmbiguityResolution(TraceAmbiguity* ta, collections::List<Ref<InsExec_StackRefLink>>& visitingIds, collections::List<WString>* failureReasons, TCallback&& callback);
				bool										CheckSingleMergeTrace(TraceAmbiguity* ta, Trace* trace, TraceExec* traceExec, collections::List<Ref<InsExec_StackRefLink>>& visitingIds, collections::List<WString>* failureReasons);
				void										LinkAmbiguityCriticalTrace(Ref<Trace> traceId);
				void										CheckTraceAmbiguity(TraceAmbiguity* ta);
				void										MarkAmbiguityCoveredForward(Trace* currentTrace, TraceAmbiguity* ta, Trace* firstTrace, TraceExec* firstTraceExec);
				void										CategorizeTraceAmbiguities(Trace* trace, TraceExec* traceExec);
				void										CheckMergeTraces();

				// phase: BuildExecutionOrder


				struct NestedAmbiguityInfo
				{
					collections::List<TraceAmbiguity*>					nestedAmbiguities;	// all nested ambiguities in order from outer to inner
					collections::Dictionary<Trace*, TraceAmbiguity*>	branchTraces;		// branchTrace to TraceAmbiguities
					collections::Group<TraceAmbiguity*, Trace*>			branchSelections;	// critial successors of each TraceAmbiguities' branchTrace from inner to outer
				};

				struct BSL_Guidance
				{
					const collections::List<Trace*>*					branchSelections = nullptr;
					const collections::List<TraceAmbiguity*>*			ambiguitiesToSkip = nullptr;

				};

				struct BSLA_Guidance
				{
					Ptr<NestedAmbiguityInfo>							nestedTas;
					vint												nextAmbiguityIndex = 0;
				};

				void										AppendStepsAfterList(ExecutionStepLinkedList steps, ExecutionStepLinkedList& current);
				void										AppendLeafToTree(ExecutionStep* leaf, ExecutionStepTree& tree);
				ExecutionStepLinkedList						ConvertStepTreeToList(ExecutionStepTree tree);

				ExecutionStep*								CreateResolveAmbiguityStep(TraceAmbiguity* ta);
				Ptr<NestedAmbiguityInfo>					CollectNestedAmbiguities(TraceAmbiguity* ta);
				
				void										BuildStepLeafsForAmbiguityBranch(
																TraceAmbiguity* ta,
																ExecutionStep* lastSharedStep,
																Trace* ambiguityBranchStartTrace,
																vint32_t* ambiguityBranchStartIns,
																ExecutionStepTree& ambiguityStepTree);
				void										BuildStepLeafsForNestedAmbiguityBranch(
																TraceAmbiguity* ta,
																ExecutionStep* lastSharedStep,
																BSLA_Guidance* guidance,
																ExecutionStepTree& ambiguityStepTree);
				ExecutionStepLinkedList						BuildStepListForAmbiguity(
																TraceAmbiguity* ta,
																BSLA_Guidance* guidance);
				ExecutionStepLinkedList						BuildStepListThroughAmbiguity(
																Trace*& currentTrace,
																vint32_t& currentIns,
																TraceAmbiguity* ta,
																BSLA_Guidance* guidance
																);
				ExecutionStepLinkedList						BuildStepListUntilFirstRawBranchTrace(
																Trace* startTrace,
																vint32_t startIns,
																Trace* endTrace,
																vint32_t endIns,
																BSL_Guidance* guidance,
																Trace** rawBranchTrace);
				ExecutionStepLinkedList						BuildStepList(
																Trace* startTrace,
																vint32_t startIns,
																Trace* endTrace,
																vint32_t endIns,
																BSL_Guidance* guidance);
				void										BuildExecutionOrder();

			public:
				TraceManager(Executable& _executable, const ITypeCallback* _typeCallback, vint blockSize);

				vint32_t						concurrentCount = 0;
				Nullable<vint32_t>				concurrentCountBeforeError;
				collections::List<Trace*>*		concurrentTraces = nullptr;
				collections::List<Trace*>*		backupTraces = nullptr;

				ReturnStack*					GetReturnStack(Ref<ReturnStack> index);
				ReturnStack*					AllocateReturnStack();
				Trace*							GetTrace(Ref<Trace> index);
				Trace*							AllocateTrace();
				Competition*					GetCompetition(Ref<Competition> index);
				Competition*					AllocateCompetition();
				AttendingCompetitions*			GetAttendingCompetitions(Ref<AttendingCompetitions> index);
				AttendingCompetitions*			AllocateAttendingCompetitions();

				InsExec*						GetInsExec(vint32_t index);
				InsExec_Stack*					GetInsExec_Stack(Ref<InsExec_Stack> index);
				InsExec_InsRefLink*				GetInsExec_InsRefLink(Ref<InsExec_InsRefLink> index);
				InsExec_StackRefLink*			GetInsExec_StackRefLink(Ref<InsExec_StackRefLink> index);
				InsExec_StackArrayRefLink*		GetInsExec_StackArrayRefLink(Ref<InsExec_StackArrayRefLink> index);
				TraceExec*						GetTraceExec(Ref<TraceExec> index);
				TraceAmbiguity*					GetTraceAmbiguity(Ref<TraceAmbiguity> index);
				TraceAmbiguityLink*				GetTraceAmbiguityLink(Ref<TraceAmbiguityLink> index);
				ExecutionStep*					GetExecutionStep(Ref<ExecutionStep> index);

				void							Initialize(vint32_t startState) override;
				Trace*							GetInitialTrace();
				ExecutionStep*					GetInitialExecutionStep();

				bool							Input(vint32_t currentTokenIndex, regex::RegexToken* token, regex::RegexToken* lookAhead) override;
				bool							EndOfInput(bool& ambiguityInvolved) override;

				void							PrepareTraceRoute() override;
				void							ResolveAmbiguity() override;

			protected:
				void							ExecuteSingleTrace(IAstInsReceiver& receiver, Trace* trace, vint32_t firstIns, vint32_t lastIns, TraceInsLists& insLists, collections::List<regex::RegexToken>& tokens);
				void							ExecuteSingleStep(IAstInsReceiver& receiver, ExecutionStep* step, collections::List<regex::RegexToken>& tokens);
			public:
				Ptr<ParsingAstBase>				ExecuteTrace(IAstInsReceiver& receiver, collections::List<regex::RegexToken>& tokens) override;
			};

			class TraceException : public Exception
			{
			public:
				TraceException(TraceManager& tm, InsRef insRef, const wchar_t* phrase, const wchar_t* message)
					: Exception(
						WString::Unmanaged(L"[") + 
						WString::Unmanaged(phrase) +
						WString::Unmanaged(L"] at ") +
						itow(insRef.trace.handle) + WString::Unmanaged(L"@") + itow(insRef.ins) +
						WString::Unmanaged(L" : ") +
						WString::Unmanaged(message)
					)
				{
				}

				TraceException(TraceManager& tm, Trace* trace1, Trace* trace2, const wchar_t* phrase, const WString& message)
					: Exception(
						WString::Unmanaged(L"[") +
						WString::Unmanaged(phrase) +
						WString::Unmanaged(L"] at trace ") +
						itow(trace1->allocatedIndex) +
						(trace2 == nullptr ? WString::Empty : WString::Unmanaged(L" and ") + itow(trace2->allocatedIndex)) +
						WString::Unmanaged(L" : ") +
						message
					)
				{
				}

				TraceException(TraceManager& tm, Trace* trace1, Trace* trace2, const wchar_t* phrase, const wchar_t* message)
					: TraceException(tm, trace1, trace2, phrase, WString::Unmanaged(message))
				{
				}

				TraceException(TraceManager& tm, TraceAmbiguity* ta1, TraceAmbiguity* ta2, const wchar_t* phrase, const wchar_t* message)
					: Exception(
						WString::Unmanaged(L"[") +
						WString::Unmanaged(phrase) +
						WString::Unmanaged(L"] at trace ambiguity ") +
						itow(ta1->firstTrace.handle) + WString::Unmanaged(L"@") + itow(ta1->prefix) + WString::Unmanaged(L"..") +
						itow(ta1->lastTrace.handle) + WString::Unmanaged(L"@-") + itow(ta1->postfix) +
						(ta2 == nullptr ? WString::Empty :
							WString::Unmanaged(L" and ") +
							itow(ta2->firstTrace.handle) + WString::Unmanaged(L"@") + itow(ta2->prefix) + WString::Unmanaged(L"..") +
							itow(ta2->lastTrace.handle) + WString::Unmanaged(L"@-") + itow(ta2->postfix)
							) +
						WString::Unmanaged(L" : ") +
						WString::Unmanaged(message)
					)
				{
				}

				TraceException(TraceManager& tm, InsExec_Stack* stack, const wchar_t* phrase, const wchar_t* message)
					: Exception(
						WString::Unmanaged(L"[") +
						WString::Unmanaged(phrase) +
						WString::Unmanaged(L"] at trace ") +
						itow(stack->allocatedIndex) +
						WString::Unmanaged(L" : ") +
						WString::Unmanaged(message)
					)
				{
				}

				TraceException(TraceManager& tm, const wchar_t* phrase, const wchar_t* message)
					: Exception(
						WString::Unmanaged(L"[") +
						WString::Unmanaged(phrase) +
						WString::Unmanaged(L"] : ") +
						WString::Unmanaged(message)
					)
				{
				}
			};
		}
	}
}

#endif

/***********************************************************************
.\TRACEMANAGER\TRACEMANAGER_COMMON.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_TRACEMANAGER_TRACEMANAGER_COMMON
#define VCZH_PARSER2_TRACEMANAGER_TRACEMANAGER_COMMON


namespace vl
{
	namespace glr
	{
		namespace automaton
		{
/***********************************************************************
IterateSurvivedTraces
***********************************************************************/

			template<typename TCallback>
			void TraceManager::IterateSurvivedTraces(TCallback&& callback)
			{
				Trace* lastTrace = nullptr;
				collections::List<Trace*> traces;
				traces.Add(initialTrace);

				while (traces.Count() > 0)
				{
					auto current = traces[traces.Count() - 1];
					traces.RemoveAt(traces.Count() - 1);

					if (current->iterateCounter == current->predecessorCount)
					{
						current->iterateCounter = 0;
					}

					current->iterateCounter++;
					callback(
						current,
						(
							current->predecessorCount == 0 ? nullptr :
							current->predecessorCount == 1 ? GetTrace(current->predecessors.first) :
							lastTrace
						),
						current->iterateCounter,
						current->predecessorCount
						);
					lastTrace = current;
					if (current->iterateCounter < current->predecessorCount) continue;

					auto successorId = current->successors.last;
					while (successorId != nullref)
					{
						auto successor = GetTrace(successorId);
						successorId = successor->successors.siblingPrev;
						traces.Add(successor);
					}
				}
			}
		}
	}
}

#endif

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

#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST
#define VCZH_PARSER2_BUILTIN_XML_AST_AST


namespace vl::glr::xml
{
	class XmlAttribute;
	class XmlCData;
	class XmlComment;
	class XmlDocument;
	class XmlElement;
	class XmlInstruction;
	class XmlNode;
	class XmlText;

	class XmlNode abstract : public vl::glr::ParsingAstBase, vl::reflection::Description<XmlNode>
	{
	public:
		class IVisitor : public virtual vl::reflection::IDescriptable, vl::reflection::Description<IVisitor>
		{
		public:
			virtual void Visit(XmlText* node) = 0;
			virtual void Visit(XmlCData* node) = 0;
			virtual void Visit(XmlComment* node) = 0;
			virtual void Visit(XmlElement* node) = 0;
			virtual void Visit(XmlInstruction* node) = 0;
			virtual void Visit(XmlDocument* node) = 0;
		};

		virtual void Accept(XmlNode::IVisitor* visitor) = 0;

	};

	class XmlText : public XmlNode, vl::reflection::Description<XmlText>
	{
	public:
		vl::glr::ParsingToken content;

		void Accept(XmlNode::IVisitor* visitor) override;
	};

	class XmlCData : public XmlNode, vl::reflection::Description<XmlCData>
	{
	public:
		vl::glr::ParsingToken content;

		void Accept(XmlNode::IVisitor* visitor) override;
	};

	class XmlAttribute : public vl::glr::ParsingAstBase, vl::reflection::Description<XmlAttribute>
	{
	public:
		vl::glr::ParsingToken name;
		vl::glr::ParsingToken value;
	};

	class XmlComment : public XmlNode, vl::reflection::Description<XmlComment>
	{
	public:
		vl::glr::ParsingToken content;

		void Accept(XmlNode::IVisitor* visitor) override;
	};

	class XmlElement : public XmlNode, vl::reflection::Description<XmlElement>
	{
	public:
		vl::glr::ParsingToken name;
		vl::glr::ParsingToken closingName;
		vl::collections::List<vl::Ptr<XmlAttribute>> attributes;
		vl::collections::List<vl::Ptr<XmlNode>> subNodes;

		void Accept(XmlNode::IVisitor* visitor) override;
	};

	class XmlInstruction : public XmlNode, vl::reflection::Description<XmlInstruction>
	{
	public:
		vl::glr::ParsingToken name;
		vl::collections::List<vl::Ptr<XmlAttribute>> attributes;

		void Accept(XmlNode::IVisitor* visitor) override;
	};

	class XmlDocument : public XmlNode, vl::reflection::Description<XmlDocument>
	{
	public:
		vl::collections::List<vl::Ptr<XmlNode>> prologs;
		vl::Ptr<XmlElement> rootElement;

		void Accept(XmlNode::IVisitor* visitor) override;
	};
}
namespace vl::reflection::description
{
#ifndef VCZH_DEBUG_NO_REFLECTION
	DECL_TYPE_INFO(vl::glr::xml::XmlNode)
	DECL_TYPE_INFO(vl::glr::xml::XmlNode::IVisitor)
	DECL_TYPE_INFO(vl::glr::xml::XmlText)
	DECL_TYPE_INFO(vl::glr::xml::XmlCData)
	DECL_TYPE_INFO(vl::glr::xml::XmlAttribute)
	DECL_TYPE_INFO(vl::glr::xml::XmlComment)
	DECL_TYPE_INFO(vl::glr::xml::XmlElement)
	DECL_TYPE_INFO(vl::glr::xml::XmlInstruction)
	DECL_TYPE_INFO(vl::glr::xml::XmlDocument)

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

	BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::glr::xml::XmlNode::IVisitor)
		void Visit(vl::glr::xml::XmlText* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::xml::XmlCData* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::xml::XmlComment* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::xml::XmlElement* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::xml::XmlInstruction* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

		void Visit(vl::glr::xml::XmlDocument* node) override
		{
			INVOKE_INTERFACE_PROXY(Visit, node);
		}

	END_INTERFACE_PROXY(vl::glr::xml::XmlNode::IVisitor)

#endif
#endif
	/// <summary>Load all reflectable AST types, only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is off.</summary>
	/// <returns>Returns true if this operation succeeded.</returns>
	extern bool XmlAstLoadTypes();
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_BUILDER
#define VCZH_PARSER2_BUILTIN_XML_AST_AST_BUILDER


namespace vl::glr::xml::builder
{
	class MakeAttribute : public vl::glr::ParsingAstBuilder<XmlAttribute>
	{
	public:
		MakeAttribute& name(const vl::WString& value);
		MakeAttribute& value(const vl::WString& value);
	};

	class MakeCData : public vl::glr::ParsingAstBuilder<XmlCData>
	{
	public:
		MakeCData& content(const vl::WString& value);
	};

	class MakeComment : public vl::glr::ParsingAstBuilder<XmlComment>
	{
	public:
		MakeComment& content(const vl::WString& value);
	};

	class MakeDocument : public vl::glr::ParsingAstBuilder<XmlDocument>
	{
	public:
		MakeDocument& prologs(const vl::Ptr<XmlNode>& value);
		MakeDocument& rootElement(const vl::Ptr<XmlElement>& value);
	};

	class MakeElement : public vl::glr::ParsingAstBuilder<XmlElement>
	{
	public:
		MakeElement& attributes(const vl::Ptr<XmlAttribute>& value);
		MakeElement& closingName(const vl::WString& value);
		MakeElement& name(const vl::WString& value);
		MakeElement& subNodes(const vl::Ptr<XmlNode>& value);
	};

	class MakeInstruction : public vl::glr::ParsingAstBuilder<XmlInstruction>
	{
	public:
		MakeInstruction& attributes(const vl::Ptr<XmlAttribute>& value);
		MakeInstruction& name(const vl::WString& value);
	};

	class MakeText : public vl::glr::ParsingAstBuilder<XmlText>
	{
	public:
		MakeText& content(const vl::WString& value);
	};

}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_COPY_VISITOR
#define VCZH_PARSER2_BUILTIN_XML_AST_AST_COPY_VISITOR


namespace vl::glr::xml::copy_visitor
{
	/// <summary>A copy visitor, overriding all abstract methods with AST copying code.</summary>
	class AstVisitor
		: public virtual vl::glr::CopyVisitorBase
		, protected virtual XmlNode::IVisitor
	{
	protected:
		void CopyFields(XmlAttribute* from, XmlAttribute* to);
		void CopyFields(XmlCData* from, XmlCData* to);
		void CopyFields(XmlComment* from, XmlComment* to);
		void CopyFields(XmlDocument* from, XmlDocument* to);
		void CopyFields(XmlElement* from, XmlElement* to);
		void CopyFields(XmlInstruction* from, XmlInstruction* to);
		void CopyFields(XmlNode* from, XmlNode* to);
		void CopyFields(XmlText* from, XmlText* to);

	protected:
		virtual void Visit(XmlAttribute* node);

		void Visit(XmlText* node) override;
		void Visit(XmlCData* node) override;
		void Visit(XmlComment* node) override;
		void Visit(XmlElement* node) override;
		void Visit(XmlInstruction* node) override;
		void Visit(XmlDocument* node) override;

	public:
		virtual vl::Ptr<XmlNode> CopyNode(XmlNode* node);
		virtual vl::Ptr<XmlAttribute> CopyNode(XmlAttribute* node);

		vl::Ptr<XmlCData> CopyNode(XmlCData* node);
		vl::Ptr<XmlComment> CopyNode(XmlComment* node);
		vl::Ptr<XmlDocument> CopyNode(XmlDocument* node);
		vl::Ptr<XmlElement> CopyNode(XmlElement* node);
		vl::Ptr<XmlInstruction> CopyNode(XmlInstruction* node);
		vl::Ptr<XmlText> CopyNode(XmlText* node);
	};
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_EMPTY_VISITOR
#define VCZH_PARSER2_BUILTIN_XML_AST_AST_EMPTY_VISITOR


namespace vl::glr::xml::empty_visitor
{
	/// <summary>An empty visitor, overriding all abstract methods with empty implementations.</summary>
	class NodeVisitor : public vl::Object, public XmlNode::IVisitor
	{
	protected:
		// Dispatch (virtual) --------------------------------

	public:
		// Visitor Members -----------------------------------
		void Visit(XmlText* node) override;
		void Visit(XmlCData* node) override;
		void Visit(XmlComment* node) override;
		void Visit(XmlElement* node) override;
		void Visit(XmlInstruction* node) override;
		void Visit(XmlDocument* node) override;
	};

}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_JSON_VISITOR
#define VCZH_PARSER2_BUILTIN_XML_AST_AST_JSON_VISITOR


namespace vl::glr::xml::json_visitor
{
	/// <summary>A JSON visitor, overriding all abstract methods with AST to JSON serialization code.</summary>
	class AstVisitor
		: public vl::glr::JsonVisitorBase
		, protected virtual XmlNode::IVisitor
	{
	protected:
		virtual void PrintFields(XmlAttribute* node);
		virtual void PrintFields(XmlCData* node);
		virtual void PrintFields(XmlComment* node);
		virtual void PrintFields(XmlDocument* node);
		virtual void PrintFields(XmlElement* node);
		virtual void PrintFields(XmlInstruction* node);
		virtual void PrintFields(XmlNode* node);
		virtual void PrintFields(XmlText* node);

	protected:
		void Visit(XmlText* node) override;
		void Visit(XmlCData* node) override;
		void Visit(XmlComment* node) override;
		void Visit(XmlElement* node) override;
		void Visit(XmlInstruction* node) override;
		void Visit(XmlDocument* node) override;

	public:
		AstVisitor(vl::stream::StreamWriter& _writer);

		void Print(XmlNode* node);
		void Print(XmlAttribute* node);
	};
}
#endif

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

#ifndef VCZH_PARSER2_BUILTIN_XML_AST_AST_TRAVERSE_VISITOR
#define VCZH_PARSER2_BUILTIN_XML_AST_AST_TRAVERSE_VISITOR


namespace vl::glr::xml::traverse_visitor
{
	/// <summary>A traverse visitor, overriding all abstract methods with AST visiting code.</summary>
	class AstVisitor
		: public vl::Object
		, protected virtual XmlNode::IVisitor
	{
	protected:
		virtual void Traverse(vl::glr::ParsingToken& token);
		virtual void Traverse(vl::glr::ParsingAstBase* node);
		virtual void Traverse(XmlAttribute* node);
		virtual void Traverse(XmlCData* node);
		virtual void Traverse(XmlComment* node);
		virtual void Traverse(XmlDocument* node);
		virtual void Traverse(XmlElement* node);
		virtual void Traverse(XmlInstruction* node);
		virtual void Traverse(XmlNode* node);
		virtual void Traverse(XmlText* node);

	protected:
		virtual void Finishing(vl::glr::ParsingAstBase* node);
		virtual void Finishing(XmlAttribute* node);
		virtual void Finishing(XmlCData* node);
		virtual void Finishing(XmlComment* node);
		virtual void Finishing(XmlDocument* node);
		virtual void Finishing(XmlElement* node);
		virtual void Finishing(XmlInstruction* node);
		virtual void Finishing(XmlNode* node);
		virtual void Finishing(XmlText* node);

	protected:
		void Visit(XmlText* node) override;
		void Visit(XmlCData* node) override;
		void Visit(XmlComment* node) override;
		void Visit(XmlElement* node) override;
		void Visit(XmlInstruction* node) override;
		void Visit(XmlDocument* node) override;

	public:
		void InspectInto(XmlNode* node);
		void InspectInto(XmlAttribute* node);
	};
}
#endif

/***********************************************************************
.\XML\GENERATED\XML_ASSEMBLER.H
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Xml
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_BUILTIN_XML_AST_ASSEMBLER
#define VCZH_PARSER2_BUILTIN_XML_AST_ASSEMBLER


namespace vl::glr::xml
{
	enum class XmlClasses : vl::vint32_t
	{
		Attribute = 0,
		CData = 1,
		Comment = 2,
		Document = 3,
		Element = 4,
		Instruction = 5,
		Node = 6,
		Text = 7,
	};

	enum class XmlFields : vl::vint32_t
	{
		Attribute_name = 0,
		Attribute_value = 1,
		CData_content = 2,
		Comment_content = 3,
		Document_prologs = 4,
		Document_rootElement = 5,
		Element_attributes = 6,
		Element_closingName = 7,
		Element_name = 8,
		Element_subNodes = 9,
		Instruction_attributes = 10,
		Instruction_name = 11,
		Text_content = 12,
	};

	extern const wchar_t* XmlTypeName(XmlClasses type);
	extern const wchar_t* XmlCppTypeName(XmlClasses type);
	extern const wchar_t* XmlFieldName(XmlFields field);
	extern const wchar_t* XmlCppFieldName(XmlFields field);

	class XmlAstInsReceiver : public vl::glr::AstInsReceiverBase
	{
	protected:
		vl::Ptr<vl::glr::ParsingAstBase> CreateAstNode(vl::vint32_t type) override;
		void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr<vl::glr::ParsingAstBase> value) override;
		void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex) override;
		void SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem, bool weakAssignment) override;
		vl::Ptr<vl::glr::ParsingAstBase> ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& candidates) override;
	};
}
#endif

/***********************************************************************
.\XML\GENERATED\XML_LEXER.H
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Xml
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_BUILTIN_XML_LEXER
#define VCZH_PARSER2_BUILTIN_XML_LEXER


namespace vl::glr::xml
{
	enum class XmlTokens : vl::vint32_t
	{
		INSTRUCTION_OPEN = 0,
		INSTRUCTION_CLOSE = 1,
		COMPLEX_ELEMENT_OPEN = 2,
		SINGLE_ELEMENT_CLOSE = 3,
		ELEMENT_OPEN = 4,
		ELEMENT_CLOSE = 5,
		EQUAL = 6,
		NAME = 7,
		ATTVALUE = 8,
		COMMENT = 9,
		CDATA = 10,
		TEXT = 11,
		SPACE = 12,
	};

	constexpr vl::vint XmlTokenCount = 13;
	extern bool XmlTokenDeleter(vl::vint token);
	extern const wchar_t* XmlTokenId(XmlTokens token);
	extern const wchar_t* XmlTokenDisplayText(XmlTokens token);
	extern const wchar_t* XmlTokenRegex(XmlTokens token);
	extern void XmlLexerData(vl::stream::IStream& outputStream);
}
#endif

/***********************************************************************
.\XML\GENERATED\XMLPARSER.H
***********************************************************************/
/***********************************************************************
This file is generated by: Vczh Parser Generator
From parser definition:Xml
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_PARSER2_BUILTIN_XML_PARSER_SYNTAX
#define VCZH_PARSER2_BUILTIN_XML_PARSER_SYNTAX


namespace vl::glr::xml
{
	enum class ParserStates
	{
		XAttribute = 0,
		XText = 5,
		XCData = 11,
		XComment = 14,
		XElement = 17,
		XSubNode = 28,
		XInstruction = 34,
		XDocument = 40,
	};

	const wchar_t* ParserRuleName(vl::vint index);
	const wchar_t* ParserStateLabel(vl::vint index);
	extern void XmlParserData(vl::stream::IStream& outputStream);

	class Parser
		: public vl::glr::ParserBase<XmlTokens, ParserStates, XmlAstInsReceiver>
		, protected vl::glr::automaton::IExecutor::ITypeCallback
	{
	protected:
		vl::WString GetClassName(vl::vint32_t classIndex) const override;
		vl::vint32_t FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const override;
	public:
		Parser();

		vl::Ptr<vl::glr::xml::XmlElement> ParseXElement(const vl::WString& input, vl::vint codeIndex = -1) const;
		vl::Ptr<vl::glr::xml::XmlElement> ParseXElement(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex = -1) const;
		vl::Ptr<vl::glr::xml::XmlDocument> ParseXDocument(const vl::WString& input, vl::vint codeIndex = -1) const;
		vl::Ptr<vl::glr::xml::XmlDocument> ParseXDocument(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex = -1) const;
	};
}
#endif

/***********************************************************************
.\XML\GLRXML.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingXml

***********************************************************************/

#ifndef VCZH_PARSER2_BUILTIN_XML
#define VCZH_PARSER2_BUILTIN_XML


namespace vl
{
	namespace glr
	{
		namespace xml
		{
			extern WString							XmlEscapeValue(const WString& value);
			extern WString							XmlUnescapeValue(const WString& value);
			extern WString							XmlEscapeCData(const WString& value);
			extern WString							XmlUnescapeCData(const WString& value);
			extern WString							XmlEscapeComment(const WString& value);
			extern WString							XmlUnescapeComment(const WString& value);

			/// <summary>Deserialize XML document from string.</summary>
			/// <returns>The deserialized XML node.</returns>
			/// <param name="input">The XML code.</param>
			/// <param name="parser">The generated parser.</param>
			extern Ptr<XmlDocument>								XmlParseDocument(const WString& input, const Parser& parser);

			/// <summary>Deserialize XML element from string.</summary>
			/// <returns>The deserialized XML node.</returns>
			/// <param name="input">The XML code.</param>
			/// <param name="parser">The generated parser.</param>
			extern Ptr<XmlElement>								XmlParseElement(const WString& input, const Parser& parser);

			/// <summary>Serialize XML to string.</summary>
			/// <param name="node">The XML node to serialize.</param>
			/// <param name="writer">The text writer to receive the string.</param>
			extern void											XmlPrint(Ptr<XmlNode> node, stream::TextWriter& writer);

			/// <summary>Serialize sub nodes in an XML element to string.</summary>
			/// <param name="element">The XML element in which sub nodes are to be serialized.</param>
			/// <param name="writer">The text writer to receive the string.</param>
			extern void											XmlPrintContent(Ptr<XmlElement> element, stream::TextWriter& writer);

			/// <summary>Serialize XML to string.</summary>
			/// <returns>The serialized string.</returns>
			/// <param name="node">The XML node to serialize.</param>
			extern WString										XmlToString(Ptr<XmlNode> node);

			/// <summary>Try to read an attribute in an XML element.</summary>
			/// <returns>The expected attribute. Returns null if it doesn't exist.</returns>
			/// <param name="element">The element to find the attribute.</param>
			/// <param name="name">The name of the attribute.</param>
			extern Ptr<XmlAttribute>							XmlGetAttribute(Ptr<XmlElement> element, const WString& name);

			/// <summary>Try to read a sub element in an XML element.</summary>
			/// <returns>The expected sub element. Returns null if it doesn't exist. If there are multiple elements of the expected name, returns the first one.</returns>
			/// <param name="element">The element to find the sub element.</param>
			/// <param name="name">The name of the sub element.</param>
			extern Ptr<XmlElement>								XmlGetElement(Ptr<XmlElement> element, const WString& name);

			/// <summary>Get all sub elements in an XML element.</summary>
			/// <returns>All sub elements in an XML element.</returns>
			/// <param name="element">The container XML element.</param>
			extern collections::LazyList<Ptr<XmlElement>>		XmlGetElements(Ptr<XmlElement> element);

			/// <summary>Try to read sub elements in an XML element.</summary>
			/// <returns>Expected sub elements. All sub elements of the expected name will be returned.</returns>
			/// <param name="element">The element to find sub elements.</param>
			/// <param name="name">The name of sub elements.</param>
			extern collections::LazyList<Ptr<XmlElement>>		XmlGetElements(Ptr<XmlElement> element, const WString& name);

			/// <summary>Serialize contents in an XML element.</summary>
			/// <returns>The serialized contents in an XML element.</returns>
			/// <param name="element">The XML element in which contents are to be serialized.</param>
			extern WString										XmlGetValue(Ptr<XmlElement> element);

			extern Ptr<XmlAttribute>							XmlGetAttribute(XmlElement* element, const WString& name);
			extern Ptr<XmlElement>								XmlGetElement(XmlElement* element, const WString& name);
			extern collections::LazyList<Ptr<XmlElement>>		XmlGetElements(XmlElement* element);
			extern collections::LazyList<Ptr<XmlElement>>		XmlGetElements(XmlElement* element, const WString& name);
			extern WString										XmlGetValue(XmlElement* element);

			struct XmlElementListSerializer
			{
				using SourceType = collections::List<Ptr<XmlElement>>;
				using DestType = WString;
				using ContextType = Ptr<Parser>;

				static void										Serialize(Ptr<Parser> parser, const SourceType& source, DestType& dest);
				static void										Deserialize(Ptr<Parser> parser, const DestType& source, SourceType& dest);
			};

			class XmlElementWriter : public Object
			{
			protected:
				Ptr<XmlElement>					element;
				const XmlElementWriter*			previousWriter;

			public:
				XmlElementWriter(Ptr<XmlElement> _element, const XmlElementWriter* _previousWriter=0);
				~XmlElementWriter();

				const XmlElementWriter&			Attribute(const WString& name, const WString& value)const;
				XmlElementWriter				Element(const WString& name)const;
				const XmlElementWriter&			End()const;
				const XmlElementWriter&			Text(const WString& value)const;
				const XmlElementWriter&			CData(const WString& value)const;
				const XmlElementWriter&			Comment(const WString& value)const;
			};
		}
	}
}

#endif

