Files
GacUI/Import/VlppGlrParser.h
T
2023-04-09 03:49:54 -07:00

3208 lines
111 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 operator==(const ParsingTextRange& range)const { return start == range.start && end == range.end; }
bool operator!=(const ParsingTextRange& range)const { return start != range.start || end != range.end; }
bool Contains(const ParsingTextPos& pos)const { return start <= pos && pos <= end; }
bool Contains(const ParsingTextRange& range)const { return start <= range.start && range.end <= end; }
};
/***********************************************************************
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
***********************************************************************/
enum class AstInsType
{
Token, // Token() : Push the current token as a value.
EnumItem, // EnumItem(Value) : Push an enum item.
BeginObject, // BeginObject(Type) : Begin creating an AST node.
DelayFieldAssignment, // DelayFieldAssignment() : An object will be created later by ReopenObject, delay future field assignments to this object before ReopenObject.
ReopenObject, // ReopenObject() : Move the last pushed object back to creating status.
EndObject, // EndObject() : Finish creating an AST node, all objects pushed after BeginObject are supposed to be its fields.
DiscardValue, // DiscardValue() : Remove a pushed value.
LriStore, // LriStore() : Take the top object away and store to a register temporarily.
LriFetch, // LriFetch() : Clear the register and put it back as a top object.
Field, // Field(Field) : Associate a field name with the top object.
FieldIfUnassigned, // FieldIfUnassigned(Field) : Like Field(Field) but only take effect if such field has never been assigned.
ResolveAmbiguity, // ResolveAmbiguity(Type, Count) : Combine several top objects to one using an ambiguity node. Type is the type of each top object.
AccumulatedDfa, // AccumulatedDfa(Count) : Multiple DelayFieldAssignment
AccumulatedEoRo, // AccumulatedEoRo(Count) : Multiple EndObject + ReopenObject
};
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.
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.
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.
NoRootObject, // NoRootObject() : There is no created objects.
NoRootObjectAfterDfa, // NoRootObjectAfterDfa() : There is no created objects after DelayFieldAssignment.
TooManyUnassignedValues, // LeavingUnassignedValues() : The value to reopen is not the only unassigned value.
MissingDfaBeforeReopen, // MissingDfaBeforeReopen() : DelayFieldAssignment is not submitted before ReopenObject.
MissingValueToReopen, // MissingValueToReopen() : There is no pushed value to reopen.
ReopenedValueIsNotObject, // ReopenedValueIsNotObject() : The pushed value to reopen is not an object.
MissingValueToDiscard, // MissingValueToDiscard() : There is no pushed value to discard.
MissingValueToLriStore, // MissingValueToLriStore() : There is no pushed value to run LriStore.
LriStoredValueIsNotObject, // LriStoredValueIsNotObject() : The value to run LriStore is not an object.
LriStoredValueNotCleared, // LriStoredValueNotCleared() : LriFetch is not executed before the next LriStore.
LriStoredValueNotExists, // LriStoredValueNotExists() : LriStore is not executed before the next LriFetch.
LeavingUnassignedValues, // LeavingUnassignedValues() : There are still values to assign to fields before finishing an object.
MissingFieldValue, // MissingFieldValue() : There is no pushed value to be assigned to a field.
MissingAmbiguityCandidate, // MissingAmbiguityCandidate() : There are not enough candidates to create an ambiguity node.
AmbiguityCandidateIsNotObject, // AmbiguityCandidateIsNotObject() : Tokens or enum items cannot be ambiguity candidates.
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;
};
class AstInsReceiverBase : public Object, public virtual IAstInsReceiver
{
private:
struct ObjectOrToken
{
Ptr<ParsingAstBase> object;
vint32_t enumItem = -1;
regex::RegexToken token = {};
vint32_t tokenIndex = -1;
explicit ObjectOrToken(Ptr<ParsingAstBase> _object) : object(_object) {}
explicit ObjectOrToken(vint32_t _enumItem) : enumItem(_enumItem) {}
explicit ObjectOrToken(const regex::RegexToken& _token, vint32_t _tokenIndex) : token(_token), tokenIndex(_tokenIndex) {}
};
struct FieldAssignment
{
ObjectOrToken value;
vint32_t field = -1;
bool weakAssignment = false;
};
struct CreatedObject
{
Ptr<ParsingAstBase> object;
vint pushedCount;
regex::RegexToken delayedToken;
collections::List<FieldAssignment> delayedFieldAssignments;
vint extraEmptyDfaBelow = 0;
CreatedObject(Ptr<ParsingAstBase> _object, vint _pushedCount)
: object(_object)
, pushedCount(_pushedCount)
{
}
CreatedObject(Ptr<ParsingAstBase> _object, vint _pushedCount, const regex::RegexToken& _delayedToken)
: object(_object)
, pushedCount(_pushedCount)
, delayedToken(_delayedToken)
{
}
};
collections::List<CreatedObject> created;
collections::List<ObjectOrToken> pushed;
Ptr<ParsingAstBase> lriStoredObject;
bool finished = false;
bool corrupted = false;
void EnsureContinuable();
void SetField(ParsingAstBase* object, vint32_t field, const ObjectOrToken& value, bool weakAssignment);
CreatedObject& PushCreated(CreatedObject&& createdObject);
const CreatedObject& TopCreated();
void PopCreated();
void DelayAssign(FieldAssignment&& fa);
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());
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 ReturnIndexArray
{
vint32_t start = -1;
vint32_t count = -1;
};
struct EdgeArray
{
vint32_t start = -1;
vint32_t count = 0;
};
enum class EdgePriority
{
NoCompetition,
HighPriority,
LowPriority,
};
enum class ReturnRuleType
{
Field,
Partial,
Discard,
Reuse,
};
struct ReturnDesc
{
vint32_t consumedRule = -1;
vint32_t returnState = -1;
EdgePriority priority = EdgePriority::NoCompetition;
ReturnRuleType ruleType = ReturnRuleType::Field;
InstructionArray insAfterInput;
};
struct EdgeDesc
{
vint32_t fromState = -1;
vint32_t toState = -1;
StringLiteral condition;
EdgePriority priority = EdgePriority::NoCompetition;
InstructionArray insBeforeInput;
InstructionArray insAfterInput;
ReturnIndexArray returnIndices;
};
struct StateDesc
{
vint32_t rule = -1;
vint32_t clause = -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<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);
/// <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);
/// <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);
}
}
}
#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 std::strong_ordering operator<=>(const Ref<T>& ref) const { return handle <=> ref.handle; }
__forceinline bool operator==(const Ref<T>& ref) const { return handle == ref.handle; }
__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;
struct InsExec_Object;
/***********************************************************************
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 clauseId = -1; // the clause id of the state, 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)
***********************************************************************/
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 share 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/ResolveAmbiguity)
***********************************************************************/
struct InsRef
{
Ref<Trace> trace;
vint32_t ins = -1;
};
struct InsExec_InsRefLink : Allocatable<InsExec_InsRefLink>
{
Ref<InsExec_InsRefLink> previous;
InsRef insRef;
};
struct InsExec_ObjRefLink : Allocatable<InsExec_ObjRefLink>
{
Ref<InsExec_ObjRefLink> previous;
Ref<InsExec_Object> id;
};
struct InsExec_Object : Allocatable<InsExec_Object>, WithMagicCounter
{
static const vint32_t TokenOrEnumItemObjectId = -2;
// previous allocated object
Ref<InsExec_Object> previous;
// fieldObjectIds are object fields of this object
Ref<InsExec_ObjRefLink> fieldObjectIds;
// assignedToObjectIds are objects who has at least one field that is this object
Ref<InsExec_ObjRefLink> assignedToObjectIds;
// instruction that creates this object
InsRef createInsRef;
// DelayFieldAssignment instructions that associates to the current object
Ref<InsExec_InsRefLink> dfaInsRefs;
// first instruction that creates this object
InsRef topLocalInsRef;
// first instruction that creates this object or its fields
InsRef topInsRef;
// last instructions that closes this object
Ref<InsExec_InsRefLink> bottomInsRefs;
};
struct InsExec_ObjectStack : Allocatable<InsExec_ObjectStack>, WithMagicCounter
{
Ref<InsExec_ObjectStack> previous;
Ref<InsExec_ObjRefLink> objectIds;
vint32_t pushedCount = -1; // number for InsExec_CreateStack::stackBase
};
struct InsExec_CreateStack : Allocatable<InsExec_CreateStack>, WithMagicCounter
{
Ref<InsExec_CreateStack> previous;
vint32_t stackBase = -1; // the number of objects in the object stack that is frozen
// All InsExec_InsRefLink that create the current InsExec_CreateStack
Ref<InsExec_InsRefLink> createInsRefs;
// InsExec_ObjRefLink assigned by BO/BOLA/RO
Ref<InsExec_ObjRefLink> objectIds;
// objectIds will be added to reverseAssignedToObjectIds::assignedToObjectIds when ReopenObject happens
// it happens when a field is assigned to a DFA created object, the objectIds are unknown yet
Ref<InsExec_ObjRefLink> reverseAssignedToObjectIds;
};
struct InsExec_Context
{
Ref<InsExec_ObjectStack> objectStack; // InsExec_ObjectStack after executing instructions
Ref<InsExec_CreateStack> createStack; // InsExec_CreateStack after executing instructions
Ref<InsExec_ObjRefLink> lriStoredObjects; // LriStore stored InsExec_ObjRefLink after executing instructions
};
struct InsExec : WithMagicCounter
{
// BO:
// the created object
Ref<InsExec_Object> createdObjectId;
// DFA:
// all associated objects
// EO:
// all ended objects
Ref<InsExec_ObjRefLink> objRefs;
// InsExec_InsRefLink
// BO/DFA:
// EndingObject instructions that close objects or create stack created by the current instruction
Ref<InsExec_InsRefLink> eoInsRefs;
// context before executing the current instruction
InsExec_Context contextBeforeExecution;
};
struct TraceAmbiguity : Allocatable<TraceAmbiguity>
{
// all objects to merge
Ref<InsExec_ObjRefLink> bottomObjectIds;
// 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 BO/DFA
// if prefix + 1 is larger than instructions in firstTrace
// then BO/DFA 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 EO
// if lastTrace is a merge trace
// then EO is in all predecessors
// these instructions end bottomObjectIds
Ref<Trace> lastTrace;
vint32_t postfix = -1;
};
struct TraceAmbiguityLink : Allocatable<TraceAmbiguityLink>
{
Ref<TraceAmbiguityLink> previous;
Ref<TraceAmbiguity> ambiguity;
};
struct TraceInsLists
{
InstructionArray edgeInsBeforeInput;
InstructionArray edgeInsAfterInput;
InstructionArray returnInsAfterInput;
vint32_t c1;
vint32_t c2;
vint32_t c3;
};
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;
};
struct TraceExec : Allocatable<TraceExec>
{
Ref<Trace> traceId;
TraceInsLists insLists; // instruction list of this trace
InstructionArray insExecRefs; // allocated InsExec for instructions
InsExec_Context context;
TraceBranchData branchData;
// linked list of branch traces
Ref<Trace> nextBranchTrace;
// linked list of merge traces
Ref<Trace> nextMergeTrace;
// linked list of ambiguity critical trace (order by trace id ascending)
// the linked list begins from a trace whose forwardTrace is itself
// record all traces that is
// 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
// firstTrace (order by prefix ascending)
// 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;
Ref<TraceAmbiguityLink> ambiguityBegins;
// when this trace is a successor of a branch trace
// and such branch trace has non-empty ambiguityBegins
// ambiguityCoveredInForward points to the ambiguity which begins in the current trace
Ref<TraceAmbiguity> ambiguityCoveredInForward;
};
/***********************************************************************
TraceManager (Data Structures -- BuildExecutionOrder)
***********************************************************************/
struct ExecutionStep;
enum class ExecutionType
{
Empty,
Instruction,
ResolveAmbiguity,
};
struct ExecutionStep : Allocatable<ExecutionStep>
{
struct ETI
{
vint32_t startTrace;
vint32_t startIns;
vint32_t endTrace;
vint32_t endIns;
};
struct ETRA
{
vint32_t count;
vint32_t type;
vint32_t trace;
};
ExecutionType type = ExecutionType::Instruction;
// for steps that ready to execute
// "next" means the next step to execute
// for steps that returns from BuildStepTree
// "next" in a leaf step points to the next leaf step
Ref<ExecutionStep> next;
// for steps that returns from BuildStepTree
// "next" is the parent step in the tree
Ref<ExecutionStep> parent;
vint32_t copyCount = 0;
vint32_t visitCount = 0;
union
{
ETI et_i;
ETRA et_ra;
};
};
/***********************************************************************
TraceManager
***********************************************************************/
enum class TraceManagerState
{
Uninitialized,
WaitingForInput,
Finished,
PreparedTraceRoute,
ResolvedAmbiguity,
};
struct WalkingTrace
{
Trace* currentTrace;
Trace* stateTrace;
operator bool() const
{
return currentTrace && stateTrace;
}
};
struct TraceManagerSubmitter;
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);
void MergeTwoEndingInputTrace(Trace* newTrace, Trace* candidate);
// Competition
void AttendCompetition(Trace* trace, Ref<AttendingCompetitions>& newAttendingCompetitions, Ref<AttendingCompetitions>& newCarriedCompetitions, Ref<ReturnStack> returnStack, vint32_t ruleId, vint32_t clauseId, bool forHighPriority);
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);
void 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);
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);
void ReadInstructionList(Trace* trace, TraceInsLists& insLists);
AstIns& ReadInstruction(vint32_t instruction, TraceInsLists& insLists);
protected:
// PrepareTraceRoute
AllocateOnly<TraceExec> traceExecs;
collections::Array<InsExec> insExecs;
AllocateOnly<InsExec_Object> insExec_Objects;
AllocateOnly<InsExec_InsRefLink> insExec_InsRefLinks;
AllocateOnly<InsExec_ObjRefLink> insExec_ObjRefLinks;
AllocateOnly<InsExec_ObjectStack> insExec_ObjectStacks;
AllocateOnly<InsExec_CreateStack> insExec_CreateStacks;
// phase: AllocateExecutionData
void AllocateExecutionData();
// phase: PartialExecuteTraces - PartialExecuteOrdinaryTrace
InsExec_Object* NewObject();
vint32_t GetStackBase(InsExec_Context& context);
vint32_t GetStackTop(InsExec_Context& context);
void PushInsRefLink(Ref<InsExec_InsRefLink>& link, InsRef insRef);
void PushObjRefLink(Ref<InsExec_ObjRefLink>& link, Ref<InsExec_Object> id);
Ref<InsExec_InsRefLink> JoinInsRefLink(Ref<InsExec_InsRefLink> first, Ref<InsExec_InsRefLink> second);
Ref<InsExec_ObjRefLink> JoinObjRefLink(Ref<InsExec_ObjRefLink> first, Ref<InsExec_ObjRefLink> second);
void PushAssignedToObjectIdsSingleWithMagic(Ref<InsExec_ObjRefLink> fieldObjectIds, Ref<InsExec_Object> assignedToTarget);
void PushAssignedToObjectIdsMultipleWithMagic(Ref<InsExec_ObjRefLink> fieldObjectIds, Ref<InsExec_ObjRefLink> assignedToTargets);
InsExec_ObjectStack* PushObjectStackSingle(InsExec_Context& context, Ref<InsExec_Object> objectId);
InsExec_ObjectStack* PushObjectStackMultiple(InsExec_Context& context, Ref<InsExec_ObjRefLink> linkId);
InsExec_CreateStack* PushCreateStack(InsExec_Context& context);
void PartialExecuteOrdinaryTrace(Trace* trace);
// phase: PartialExecuteTraces - EnsureInsExecContextCompatible
void EnsureInsExecContextCompatible(Trace* baselineTrace, Trace* commingTrace);
// phase: PartialExecuteTraces - MergeInsExecContext
void PushInsRefLinkWithCounter(Ref<InsExec_InsRefLink>& link, Ref<InsExec_InsRefLink> comming);
void PushObjRefLinkWithCounter(Ref<InsExec_ObjRefLink>& link, Ref<InsExec_ObjRefLink> comming);
template<typename T, T* (TraceManager::*get)(Ref<T>), Ref<T> (InsExec_Context::*stack), typename TMerge>
Ref<T> MergeStack(Trace* mergeTrace, AllocateOnly<T>& allocator, TMerge&& merge);
void MergeInsExecContext(Trace* mergeTrace);
// phase: PartialExecuteTraces - CalculateObjectFirstInstruction
bool UpdateTopTrace(InsRef& topInsRef, InsRef newInsRef);
void InjectFirstInstruction(InsRef insRef, Ref<InsExec_ObjRefLink> injectTargets, vuint64_t magicInjection);
void CalculateObjectFirstInstruction();
// phase: PartialExecuteTraces - CalculateObjectLastInstruction
bool IsInTheSameBranch(Trace* forward, Trace* targetForwardAtFront);
void CalculateObjectLastInstruction();
// phase: PartialExecuteTraces
void PartialExecuteTraces();
// phase: BuildAmbiguityStructures
Trace* StepForward(Trace* trace);
void BuildAmbiguityStructures();
#if defined VCZH_MSVC && defined _DEBUG
// phase: DebugCheckTraceExecData
void DebugCheckTraceExecData();
#endif
protected:
// ResolveAmbiguity
Ref<Trace> firstBranchTrace;
Ref<Trace> firstMergeTrace;
Ref<InsExec_Object> firstObject;
Ref<ExecutionStep> firstStep;
AllocateOnly<TraceAmbiguity> traceAmbiguities;
AllocateOnly<TraceAmbiguityLink> traceAmbiguityLinks;
AllocateOnly<ExecutionStep> executionSteps;
// phase: CheckMergeTraces
template<typename TCallback>
bool EnumerateObjects(Ref<InsExec_ObjRefLink> objRefLinkStartSet, bool withCounter, TCallback&& callback);
template<typename TCallback>
bool EnumerateBottomInstructions(InsExec_Object* 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_ObjRefLink>>& visitingIds, TCallback&& callback);
bool CheckMergeTrace(TraceAmbiguity* ta, Trace* trace, TraceExec* traceExec, collections::List<Ref<InsExec_ObjRefLink>>& visitingIds);
void LinkAmbiguityCriticalTrace(Ref<Trace> traceId);
void CheckTraceAmbiguity(TraceAmbiguity* ta);
#if defined VCZH_MSVC && defined _DEBUG
void DebugCheckTraceAmbiguitiesInSameTrace(Trace* trace, TraceExec* traceExec);
#endif
void MarkAmbiguityCoveredForward(Trace* currentTrace, TraceAmbiguity* ta, Trace* firstTrace, TraceExec* firstTraceExec);
void CategorizeTraceAmbiguities(Trace* trace, TraceExec* traceExec);
void CheckMergeTraces();
// phase: BuildExecutionOrder
#define DEFINE_EXECUTION_STEP_CONTEXT ExecutionStep*& root, ExecutionStep*& firstLeaf, ExecutionStep*& currentStep, ExecutionStep*& currentLeaf
void MarkNewLeafStep(ExecutionStep* step, ExecutionStep*& firstLeaf, ExecutionStep*& currentLeaf);
void AppendStepLink(ExecutionStep* first, ExecutionStep* last, bool leapNode, DEFINE_EXECUTION_STEP_CONTEXT);
void AppendStepsBeforeAmbiguity(Trace* startTrace, vint32_t startIns, TraceAmbiguity* ta, DEFINE_EXECUTION_STEP_CONTEXT);
void AppendStepsAfterAmbiguity(Trace*& startTrace, vint32_t& startIns, TraceAmbiguity* ta, DEFINE_EXECUTION_STEP_CONTEXT);
void AppendStepsForAmbiguity(TraceAmbiguity* ta, bool checkCoveredMark, DEFINE_EXECUTION_STEP_CONTEXT);
void AppendStepsBeforeBranch(Trace* startTrace, vint32_t startIns, Trace* branchTrace, TraceExec* branchTraceExec, DEFINE_EXECUTION_STEP_CONTEXT);
void BuildStepTree(Trace* startTrace, vint32_t startIns, Trace* endTrace, vint32_t endIns, ExecutionStep*& root, ExecutionStep*& firstLeaf, ExecutionStep* currentStep, ExecutionStep*& currentLeaf);
void ConvertStepTreeToLink(ExecutionStep* root, ExecutionStep* firstLeaf, ExecutionStep*& first, ExecutionStep*& last);
void BuildAmbiguousStepLink(TraceAmbiguity* ta, bool checkCoveredMark, ExecutionStep*& first, ExecutionStep*& last);
void BuildExecutionOrder();
#undef DEFINE_EXECUTION_STEP_CONTEXT
public:
TraceManager(Executable& _executable, const ITypeCallback* _typeCallback, vint blockSize);
vint32_t concurrentCount = 0;
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_Object* GetInsExec_Object(Ref<InsExec_Object> index);
InsExec_InsRefLink* GetInsExec_InsRefLink(Ref<InsExec_InsRefLink> index);
InsExec_ObjRefLink* GetInsExec_ObjRefLink(Ref<InsExec_ObjRefLink> index);
InsExec_ObjectStack* GetInsExec_ObjectStack(Ref<InsExec_ObjectStack> index);
InsExec_CreateStack* GetInsExec_CreateStack(Ref<InsExec_CreateStack> 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(TraceManagerSubmitter& submitter, Trace* trace, vint32_t firstIns, vint32_t lastIns, TraceInsLists& insLists, collections::List<regex::RegexToken>& tokens);
void ExecuteSingleStep(TraceManagerSubmitter& submitter, ExecutionStep* step, collections::List<regex::RegexToken>& tokens);
public:
Ptr<ParsingAstBase> ExecuteTrace(IAstInsReceiver& receiver, collections::List<regex::RegexToken>& tokens) override;
};
}
}
}
#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