mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-03-23 15:52:56 +08:00
2820 lines
95 KiB
C++
2820 lines
95 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 };
|
|
}
|
|
|
|
static vint Compare(const ParsingTextPos& a, const ParsingTextPos& b)
|
|
{
|
|
if (a.IsInvalid() && b.IsInvalid())
|
|
{
|
|
return 0;
|
|
}
|
|
else if (a.IsInvalid())
|
|
{
|
|
return -1;
|
|
}
|
|
else if (b.IsInvalid())
|
|
{
|
|
return 1;
|
|
}
|
|
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 0;
|
|
}
|
|
}
|
|
|
|
bool operator==(const ParsingTextPos& pos)const { return Compare(*this, pos) == 0; }
|
|
bool operator!=(const ParsingTextPos& pos)const { return Compare(*this, pos) != 0; }
|
|
bool operator<(const ParsingTextPos& pos)const { return Compare(*this, pos) < 0; }
|
|
bool operator<=(const ParsingTextPos& pos)const { return Compare(*this, pos) <= 0; }
|
|
bool operator>(const ParsingTextPos& pos)const { return Compare(*this, pos) > 0; }
|
|
bool operator>=(const ParsingTextPos& pos)const { return Compare(*this, pos) >= 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 = MakePtr<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.
|
|
BeginObjectLeftRecursive, // BeginObjectLeftRecursive(Type) : Begin creating an AST node, taking the ownership of the last pushed object.
|
|
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.
|
|
Field, // Field(Field) : Associate a field name with the top object.
|
|
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;
|
|
|
|
vint Compare(const AstIns& ins) const
|
|
{
|
|
auto result = (vint)type - (vint)ins.type;
|
|
if (result != 0) return result;
|
|
result = (vint)param - (vint)ins.param;
|
|
if (result != 0) return result;
|
|
return count - ins.count;
|
|
}
|
|
|
|
bool operator==(const AstIns& ins) const { return Compare(ins) == 0; }
|
|
bool operator!=(const AstIns& ins) const { return Compare(ins) != 0; }
|
|
bool operator< (const AstIns& ins) const { return Compare(ins) < 0; }
|
|
bool operator<=(const AstIns& ins) const { return Compare(ins) <= 0; }
|
|
bool operator> (const AstIns& ins) const { return Compare(ins) > 0; }
|
|
bool operator>=(const AstIns& ins) const { return Compare(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.
|
|
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.
|
|
MissingLeftRecursiveValue, // MissingLeftRecursiveValue() : There is no pushed value to create left recursive object.
|
|
LeftRecursiveValueIsNotObject, // LeftRecursiveValueIsNotObject() : The pushed value to create left recursive object is not an object.
|
|
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.
|
|
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;
|
|
};
|
|
|
|
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;
|
|
bool finished = false;
|
|
bool corrupted = false;
|
|
|
|
void EnsureContinuable();
|
|
void SetField(ParsingAstBase* object, vint32_t field, const ObjectOrToken& value);
|
|
|
|
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) = 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, 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)
|
|
{
|
|
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)
|
|
{
|
|
Ptr<TAmbiguity> ast = 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 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,
|
|
};
|
|
|
|
struct ReturnDesc
|
|
{
|
|
vint32_t consumedRule = -1;
|
|
vint32_t returnState = -1;
|
|
EdgePriority priority = EdgePriority::NoCompetition;
|
|
InstructionArray insAfterInput;
|
|
};
|
|
|
|
struct EdgeDesc
|
|
{
|
|
vint32_t fromState = -1;
|
|
vint32_t toState = -1;
|
|
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> instructions; // referenced by InstructionArray
|
|
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; // refereced by returnState/fromState/toState
|
|
|
|
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;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#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>
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
class AllocateOnly : public Object
|
|
{
|
|
protected:
|
|
vint blockSize;
|
|
vint remains;
|
|
collections::List<Ptr<collections::Array<T>>> buffers;
|
|
|
|
public:
|
|
AllocateOnly(vint _blockSize = 65536)
|
|
: blockSize(_blockSize)
|
|
, remains(0)
|
|
{
|
|
}
|
|
|
|
T* Get(vint32_t index)
|
|
{
|
|
vint row = index / blockSize;
|
|
vint column = index % 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);
|
|
}
|
|
|
|
vint32_t Allocate()
|
|
{
|
|
if (remains == 0)
|
|
{
|
|
buffers.Add(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 (vint32_t)index;
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
remains = 0;
|
|
buffers.Clear();
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
TraceManager (Data Structures)
|
|
***********************************************************************/
|
|
|
|
struct ReturnStackSuccessors
|
|
{
|
|
vint32_t createdTokenIndex = -1; // index of the token when this ReturnStack is created
|
|
vint32_t successorTokenIndex = -1; // index of the token when this ReturnStack has its first successor
|
|
// the following members records all successors
|
|
// that is created at the token index
|
|
|
|
vint32_t first = -1; // first successor
|
|
vint32_t last = -1; // last successor
|
|
vint32_t prev = -1; // previous successor of ReturnStack::previous
|
|
vint32_t next = -1; // next successor of ReturnStack::previous
|
|
};
|
|
|
|
struct ReturnStack
|
|
{
|
|
vint32_t allocatedIndex = -1; // id of this ReturnStack
|
|
vint32_t previous = -1; // id of the previous ReturnStack
|
|
vint32_t returnIndex = -1; // index of ReturnDesc
|
|
ReturnStackSuccessors successors;
|
|
};
|
|
|
|
struct TraceCollection
|
|
{
|
|
vint32_t first = -1; // first trace in the collection
|
|
vint32_t last = -1; // last trace in the collection
|
|
vint32_t siblingPrev = -1; // previous trace in the collection of the owned trace
|
|
vint32_t siblingNext = -1; // next trace in the collection of the owned trace
|
|
};
|
|
|
|
struct TraceAmbiguity
|
|
{
|
|
vint32_t insEndObject = -1; // the index of the first EndObject instruction
|
|
// in {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined
|
|
// when this member is valid, the trace should satisfies:
|
|
// trace.ambiguity.insEndObject == trace.byEdge.insBeforeInput.count - trace.ambiguityInsPostfix
|
|
|
|
vint32_t traceBeginObject = -1; // id of the trace containing BeginObject or DelayFieldAssignment
|
|
// that ends by the above EndObject
|
|
|
|
vint32_t insBeginObject = -1; // the index of the BeginObject instruction
|
|
// from traceBeginObject
|
|
// in {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined
|
|
// if insBeginObject is larger than the number of instructions in traceBeginObject
|
|
// then the branches begin from the (insBeginObject - instruction-count(traceBeginObject))-th instruction (starting from 0) in all successors
|
|
|
|
vint32_t ambiguityType = -1; // when the BeginObject creates an object that later be consumed by BeginObjectLeftRecursive
|
|
// than the correct type is the type in BeginObjectLeftRecursive
|
|
};
|
|
|
|
enum class CompetitionStatus
|
|
{
|
|
Holding,
|
|
HighPriorityWin,
|
|
LowPriorityWin,
|
|
};
|
|
|
|
struct Competition
|
|
{
|
|
vint32_t allocatedIndex = -1;
|
|
vint32_t nextActiveCompetition = -1; // next active Competition
|
|
vint32_t nextHoldCompetition = -1; // 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
|
|
{
|
|
vint32_t allocatedIndex = -1; // id of this AttendingCompetitions
|
|
vint32_t nextActiveAC = -1; // the next AttendingCompetitions for RuntimeRouting::attendingCompetitions
|
|
vint32_t nextCarriedAC = -1; // the next AttendingCompetitions for RuntimeRouting::carriedCompetitions
|
|
vint32_t competition = -1; // the id of the Competition
|
|
bool forHighPriority = false; // bet of this competition
|
|
|
|
vint32_t returnStack = -1; // 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
|
|
};
|
|
|
|
struct CompetitionRouting
|
|
{
|
|
vint32_t holdingCompetitions = -1; // the id of the active Competition
|
|
|
|
vint32_t attendingCompetitions = -1; // 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
|
|
|
|
vint32_t carriedCompetitions = -1; // all attended competitions regardless of the status of the competition
|
|
};
|
|
|
|
struct AmbiguityRouting
|
|
{
|
|
vint32_t predecessorCount = -1; // the number of predecessors
|
|
// (filled by ExecuteTrace)
|
|
|
|
vint32_t branchVisited = 0; // the number of visited branches in the current loop.
|
|
// if these branches are contained in a larger ambiguity resolving loop, all branches could be visited multiple times
|
|
// (filled by ExecuteTrace)
|
|
};
|
|
|
|
struct Trace
|
|
{
|
|
vint32_t allocatedIndex = -1; // id of this Trace
|
|
TraceCollection predecessors; // id of the predecessor Trace
|
|
TraceCollection successors; // successors (filled by PrepareTraceRoute)
|
|
|
|
vint32_t state = -1; // id of the current StateDesc
|
|
vint32_t returnStack = -1; // id of the current ReturnStack
|
|
vint32_t executedReturnStack = -1; // 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
|
|
|
|
TraceAmbiguity ambiguity; // where to end resolving ambiguity in instructions from this trace
|
|
// this member is useful when it has multiple predecessors
|
|
// (filled by PrepareTraceRoute)
|
|
|
|
vint32_t ambiguityBranchInsPostfix = -1; // this member is useful when it is not -1 and the trace has multiple successors
|
|
// specifying the length of the postfix
|
|
// of {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined
|
|
// only execute the specified prefix of instructions
|
|
// usually EndObject is the last instruction in the prefix
|
|
|
|
vint32_t ambiguityMergeInsPostfix = -1; // this member is useful when it is not -1 and the trace has multiple predecessors
|
|
// specifying the length of the postfix
|
|
// of {byEdge.insBeforeInput, byEdge.insAfterInput, executedReturnStack.returnIndex.insAfterInput} combined
|
|
// only execute the specified postfix of instructions
|
|
// usually EndObject is the last instruction in the prefix
|
|
|
|
CompetitionRouting competitionRouting; // a data structure carrying priority and competition information
|
|
|
|
AmbiguityRouting ambiguityRouting; // a data structure guiding instruction execution when a trace need to be executed multiple times
|
|
// this member is useful when it has multiple predecessors or successors
|
|
};
|
|
|
|
enum class TraceManagerState
|
|
{
|
|
Uninitialized,
|
|
WaitingForInput,
|
|
Finished,
|
|
PreparedTraceRoute,
|
|
};
|
|
|
|
struct TraceInsLists
|
|
{
|
|
InstructionArray edgeInsBeforeInput;
|
|
InstructionArray edgeInsAfterInput;
|
|
InstructionArray returnInsAfterInput;
|
|
vint32_t c1;
|
|
vint32_t c2;
|
|
vint32_t c3;
|
|
};
|
|
|
|
/***********************************************************************
|
|
TraceManager
|
|
***********************************************************************/
|
|
|
|
class TraceManager : public Object
|
|
{
|
|
public:
|
|
class ITypeCallback : public virtual Interface
|
|
{
|
|
public:
|
|
virtual vint32_t FindCommonBaseClass(vint32_t class1, vint32_t class2) const= 0;
|
|
};
|
|
|
|
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;
|
|
vint32_t activeCompetitions = -1;
|
|
ReturnStackSuccessors initialReturnStackSuccessors;
|
|
|
|
void BeginSwap();
|
|
void AddTrace(Trace* trace);
|
|
void EndSwap();
|
|
void AddTraceToCollection(Trace* owner, Trace* element, TraceCollection(Trace::* collection));
|
|
|
|
// Ambiguity
|
|
bool AreTwoEndingInputTraceEqual(vint32_t state, vint32_t returnStack, vint32_t executedReturnStack, vint32_t acId, Trace* candidate);
|
|
vint32_t GetInstructionPostfix(EdgeDesc& oldEdge, EdgeDesc& newEdge);
|
|
void MergeTwoEndingInputTrace(
|
|
Trace* trace,
|
|
Trace* ambiguityTraceToMerge,
|
|
vint32_t currentTokenIndex,
|
|
vint32_t input,
|
|
vint32_t byEdge,
|
|
EdgeDesc& edgeDesc,
|
|
vint32_t state,
|
|
vint32_t returnStack,
|
|
vint32_t attendingCompetitions,
|
|
vint32_t carriedCompetitions,
|
|
vint32_t executedReturnStack);
|
|
|
|
// Competition
|
|
void AttendCompetition(Trace* trace, vint32_t& newAttendingCompetitions, vint32_t& newCarriedCompetitions, vint32_t returnStack, vint32_t ruleId, vint32_t clauseId, bool forHighPriority);
|
|
ReturnStack* PushReturnStack(vint32_t base, vint32_t returnIndex, vint32_t currentTokenIndex);
|
|
void AttendCompetitionIfNecessary(Trace* trace, vint32_t currentTokenIndex, EdgeDesc& edgeDesc, vint32_t& newAttendingCompetitions, vint32_t& newCarriedCompetitions, vint32_t& newReturnStack);
|
|
void CheckAttendingCompetitionsOnEndingEdge(Trace* trace, EdgeDesc& edgeDesc, vint32_t acId, vint32_t returnStack);
|
|
void CheckBackupTracesBeforeSwapping(vint32_t currentTokenIndex);
|
|
|
|
// Walk
|
|
Trace* WalkAlongSingleEdge(vint32_t currentTokenIndex, vint32_t input, Trace* trace, vint32_t byEdge, EdgeDesc& edgeDesc);
|
|
void WalkAlongLeftrecEdges(vint32_t currentTokenIndex, vint32_t lookAhead, Trace* trace, EdgeArray& edgeArray);
|
|
void WalkAlongEpsilonEdges(vint32_t currentTokenIndex, vint32_t lookAhead, Trace* trace);
|
|
void WalkAlongTokenEdges(vint32_t currentTokenIndex, vint32_t input, vint32_t lookAhead, Trace* trace, EdgeArray& edgeArray);
|
|
|
|
// PrepareTraceRoute
|
|
struct SharedBeginObject
|
|
{
|
|
Trace* traceBeginObject = nullptr;
|
|
vint32_t insBeginObject = -1;
|
|
vint32_t type = -1;
|
|
};
|
|
|
|
void ReadInstructionList(Trace* trace, TraceInsLists& insLists);
|
|
AstIns& ReadInstruction(vint32_t instruction, TraceInsLists& insLists);
|
|
bool RunInstruction(vint32_t instruction, TraceInsLists& insLists, vint32_t& objectCount, vint32_t& reopenCount);
|
|
void AdjustToRealTrace(SharedBeginObject& shared);
|
|
|
|
void FindBalancedBoOrBolr(SharedBeginObject& balanced, vint32_t& objectCount, vint32_t& reopenCount);
|
|
void FindBalancedBoOrDfa(Trace* trace, vint32_t objectCount, SharedBeginObject& branch);
|
|
|
|
void MergeAmbiguityType(vint32_t& ambiguityType, vint32_t branchType);
|
|
SharedBeginObject MergeSharedBeginObjectsSingleRoot(Trace* trace, collections::Dictionary<Trace*, SharedBeginObject>& predecessorToBranches);
|
|
SharedBeginObject MergeSharedBeginObjectsMultipleRoot(Trace* trace, collections::Dictionary<Trace*, SharedBeginObject>& predecessorToBranches);
|
|
SharedBeginObject MergeSharedBeginObjectsPartialMultipleRoot(Trace* trace, vint32_t ambiguityType, collections::Group<Trace*, Trace*>& beginToPredecessors, collections::Dictionary<Trace*, SharedBeginObject>& predecessorToBranches);
|
|
|
|
SharedBeginObject FillAmbiguityInfoForMergingTrace(Trace* trace);
|
|
void FillAmbiguityInfoForPredecessorTraces(Trace* trace);
|
|
void CreateLastMergingTrace(Trace* rootTraceCandidate);
|
|
public:
|
|
TraceManager(Executable& _executable, const ITypeCallback* _typeCallback = nullptr);
|
|
|
|
vint32_t concurrentCount = 0;
|
|
collections::List<Trace*>* concurrentTraces = nullptr;
|
|
collections::List<Trace*>* backupTraces = nullptr;
|
|
|
|
ReturnStack* GetReturnStack(vint32_t index);
|
|
ReturnStack* AllocateReturnStack();
|
|
Trace* GetTrace(vint32_t index);
|
|
Trace* AllocateTrace();
|
|
Competition* GetCompetition(vint32_t index);
|
|
Competition* AllocateCompetition();
|
|
AttendingCompetitions* GetAttendingCompetitions(vint32_t index);
|
|
AttendingCompetitions* AllocateAttendingCompetitions();
|
|
|
|
void Initialize(vint32_t startState);
|
|
void Input(vint32_t currentTokenIndex, vint32_t token, vint32_t lookAhead);
|
|
void EndOfInput();
|
|
Trace* PrepareTraceRoute();
|
|
Ptr<ParsingAstBase> ExecuteTrace(Trace* trace, IAstInsReceiver& receiver, collections::List<regex::RegexToken>& tokens);
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#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
|
|
};
|
|
|
|
struct EndOfInputArgs
|
|
{
|
|
collections::List<regex::RegexToken>& tokens;
|
|
automaton::Executable& executable;
|
|
automaton::TraceManager& traceManager;
|
|
automaton::Trace* rootTrace;
|
|
};
|
|
|
|
struct ErrorArgs
|
|
{
|
|
bool throwError;
|
|
ErrorType error;
|
|
vint codeIndex;
|
|
regex::RegexToken& token;
|
|
collections::List<regex::RegexToken>& tokens;
|
|
automaton::Executable& executable;
|
|
automaton::TraceManager& traceManager;
|
|
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::TraceManager& traceManager);
|
|
static ErrorArgs InputIncomplete (vint codeIndex, collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager);
|
|
static ErrorArgs UnexpectedAstType (collections::List<regex::RegexToken>& tokens, automaton::Executable& executable, automaton::TraceManager& traceManager, 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 EndOfInputCallback = void(EndOfInputArgs&);
|
|
using ErrorCallback = void(ErrorArgs&);
|
|
protected:
|
|
Deleter deleter;
|
|
Ptr<regex::RegexLexer> lexer;
|
|
Ptr<automaton::Executable> executable;
|
|
|
|
public:
|
|
Event<EndOfInputCallback> OnEndOfInput;
|
|
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 = new regex::RegexLexer(data);
|
|
}
|
|
{
|
|
stream::MemoryStream data;
|
|
_parserData(data);
|
|
data.SeekFromBegin(0);
|
|
executable = 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);
|
|
Ptr<collections::IEnumerator<regex::RegexToken>> enumerator = 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::TraceManager& tm, const automaton::TraceManager::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;
|
|
}
|
|
|
|
tm.Initialize(state);
|
|
for (vint32_t i = 0; i < tokens.Count(); i++)
|
|
{
|
|
auto&& token = tokens[i];
|
|
auto lookAhead = i == tokens.Count() - 1 ? -1 : tokens[i + 1].token;
|
|
tm.Input(i, (vint32_t)token.token, (vint32_t)lookAhead);
|
|
|
|
if (tm.concurrentCount == 0)
|
|
{
|
|
auto args = ErrorArgs::InvalidToken(token, tokens, *executable.Obj(), tm);
|
|
OnError(args);
|
|
if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Error happens during parsing.");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
tm.EndOfInput();
|
|
if (tm.concurrentCount == 0)
|
|
{
|
|
auto args = ErrorArgs::InputIncomplete(codeIndex, tokens, *executable.Obj(), tm);
|
|
OnError(args);
|
|
if (args.throwError) CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Input is incomplete.");
|
|
return nullptr;
|
|
}
|
|
|
|
auto rootTrace = tm.PrepareTraceRoute();
|
|
{
|
|
EndOfInputArgs args = { tokens, *executable.Obj(), tm, rootTrace };
|
|
OnEndOfInput(args);
|
|
}
|
|
|
|
TReceiver receiver;
|
|
return tm.ExecuteTrace(rootTrace, receiver, tokens);
|
|
|
|
#undef ERROR_MESSAGE_PREFIX
|
|
}
|
|
|
|
template<typename TAst, TStates State>
|
|
Ptr<TAst> ParseWithTokens(TokenList& tokens, const automaton::TraceManager::ITypeCallback* typeCallback, vint codeIndex) const
|
|
{
|
|
#define ERROR_MESSAGE_PREFIX L"vl::glr::ParserBase<...>::Parse<TAst, TStates>(List<RegexToken>& TraceManager::ITypeCallback*)#"
|
|
automaton::TraceManager tm(*executable.Obj(), typeCallback);
|
|
auto ast = ParseInternal(tokens, (vint32_t)State, tm, typeCallback, codeIndex);
|
|
auto typedAst = ast.Cast<TAst>();
|
|
|
|
if (!typedAst)
|
|
{
|
|
auto args = ErrorArgs::UnexpectedAstType(tokens, *executable.Obj(), tm, 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::TraceManager::ITypeCallback* typeCallback, vint codeIndex) const
|
|
{
|
|
TokenList tokens;
|
|
Tokenize(input, tokens, codeIndex);
|
|
return ParseWithTokens<TAst, State>(tokens, typeCallback, codeIndex);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
#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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace json
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace json
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace json
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace json
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace json
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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) 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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::TraceManager::ITypeCallback
|
|
{
|
|
protected:
|
|
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
|
|
|
|
/***********************************************************************
|
|
.\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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace xml
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace xml
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace xml
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace xml
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace xml
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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) 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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
|
|
{
|
|
namespace glr
|
|
{
|
|
namespace 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::TraceManager::ITypeCallback
|
|
{
|
|
protected:
|
|
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
|