Files
GacUI/Import/VlppGlrParser.h
2026-02-01 00:01:55 -08:00

3446 lines
117 KiB
C++

/***********************************************************************
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 = {});
}
}
}
#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);
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