mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-03-24 00:13:48 +08:00
3205 lines
114 KiB
C++
3205 lines
114 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"
|
|
|
|
/***********************************************************************
|
|
.\PARSINGTREE.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parsing::Parsing Tree
|
|
|
|
Classes:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_PARSINGTREE
|
|
#define VCZH_PARSING_PARSINGTREE
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
|
|
/***********************************************************************
|
|
Location
|
|
***********************************************************************/
|
|
|
|
/// <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 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;}
|
|
};
|
|
|
|
/// <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;
|
|
|
|
ParsingTextRange()
|
|
:codeIndex(-1)
|
|
{
|
|
end.index=-1;
|
|
end.column=-1;
|
|
}
|
|
|
|
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)
|
|
:codeIndex(startToken->codeIndex)
|
|
{
|
|
start.index=startToken->start;
|
|
start.row=startToken->rowStart;
|
|
start.column=startToken->columnStart;
|
|
end.index=endToken->start+endToken->length-1;
|
|
end.row=endToken->rowEnd;
|
|
end.column=endToken->columnEnd;
|
|
}
|
|
|
|
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;}
|
|
};
|
|
}
|
|
|
|
namespace stream
|
|
{
|
|
namespace internal
|
|
{
|
|
BEGIN_SERIALIZATION(parsing::ParsingTextPos)
|
|
SERIALIZE(index)
|
|
SERIALIZE(row)
|
|
SERIALIZE(column)
|
|
END_SERIALIZATION
|
|
|
|
BEGIN_SERIALIZATION(parsing::ParsingTextRange)
|
|
SERIALIZE(start)
|
|
SERIALIZE(end)
|
|
SERIALIZE(codeIndex)
|
|
END_SERIALIZATION
|
|
}
|
|
}
|
|
|
|
namespace parsing
|
|
{
|
|
/***********************************************************************
|
|
General Syntax Tree
|
|
***********************************************************************/
|
|
|
|
class ParsingTreeNode;
|
|
class ParsingTreeToken;
|
|
class ParsingTreeObject;
|
|
class ParsingTreeArray;
|
|
|
|
/// <summary>Abstract syntax tree.</summary>
|
|
class ParsingTreeNode : public Object, public reflection::Description<ParsingTreeNode>
|
|
{
|
|
public:
|
|
class IVisitor : public Interface
|
|
{
|
|
public:
|
|
virtual void Visit(ParsingTreeToken* node)=0;
|
|
virtual void Visit(ParsingTreeObject* node)=0;
|
|
virtual void Visit(ParsingTreeArray* node)=0;
|
|
};
|
|
|
|
class TraversalVisitor : public Object, public IVisitor
|
|
{
|
|
public:
|
|
enum TraverseDirection
|
|
{
|
|
ByTextPosition,
|
|
ByStorePosition
|
|
};
|
|
protected:
|
|
TraverseDirection direction;
|
|
public:
|
|
TraversalVisitor(TraverseDirection _direction);
|
|
|
|
virtual void BeforeVisit(ParsingTreeToken* node);
|
|
virtual void AfterVisit(ParsingTreeToken* node);
|
|
virtual void BeforeVisit(ParsingTreeObject* node);
|
|
virtual void AfterVisit(ParsingTreeObject* node);
|
|
virtual void BeforeVisit(ParsingTreeArray* node);
|
|
virtual void AfterVisit(ParsingTreeArray* node);
|
|
|
|
virtual void Visit(ParsingTreeToken* node)override;
|
|
virtual void Visit(ParsingTreeObject* node)override;
|
|
virtual void Visit(ParsingTreeArray* node)override;
|
|
};
|
|
protected:
|
|
typedef collections::List<Ptr<ParsingTreeNode>> NodeList;
|
|
|
|
ParsingTextRange codeRange;
|
|
ParsingTreeNode* parent;
|
|
NodeList cachedOrderedSubNodes;
|
|
|
|
virtual const NodeList& GetSubNodesInternal()=0;
|
|
bool BeforeAddChild(Ptr<ParsingTreeNode> node);
|
|
void AfterAddChild(Ptr<ParsingTreeNode> node);
|
|
bool BeforeRemoveChild(Ptr<ParsingTreeNode> node);
|
|
void AfterRemoveChild(Ptr<ParsingTreeNode> node);
|
|
public:
|
|
ParsingTreeNode(const ParsingTextRange& _codeRange);
|
|
~ParsingTreeNode();
|
|
|
|
virtual void Accept(IVisitor* visitor)=0;
|
|
virtual Ptr<ParsingTreeNode> Clone()=0;
|
|
ParsingTextRange GetCodeRange();
|
|
void SetCodeRange(const ParsingTextRange& range);
|
|
|
|
/// <summary>Precalculate for enhance searching performance for this node and all child nodes.</summary>
|
|
void InitializeQueryCache();
|
|
/// <summary>Clear all cache made by <see cref="InitializeQueryCache"/>.</summary>
|
|
void ClearQueryCache();
|
|
/// <summary>Get the parent node. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
|
|
/// <returns>The parent node.</returns>
|
|
ParsingTreeNode* GetParent();
|
|
/// <summary>Get the child nodes. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
|
|
/// <returns>The child nodes.</returns>
|
|
const NodeList& GetSubNodes();
|
|
|
|
/// <summary>Find a direct child node at the position. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
|
|
/// <returns>The found node.</returns>
|
|
/// <param name="position">The position.</param>
|
|
ParsingTreeNode* FindSubNode(const ParsingTextPos& position);
|
|
/// <summary>Find a direct child node at the range. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
|
|
/// <returns>The found node.</returns>
|
|
/// <param name="range">The range.</param>
|
|
ParsingTreeNode* FindSubNode(const ParsingTextRange& range);
|
|
/// <summary>Find a most deepest indirect child node at the position. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
|
|
/// <returns>The found node.</returns>
|
|
/// <param name="position">The position.</param>
|
|
ParsingTreeNode* FindDeepestNode(const ParsingTextPos& position);
|
|
/// <summary>Find a most deepest indirect child node at the range. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
|
|
/// <returns>The found node.</returns>
|
|
/// <param name="range">The range.</param>
|
|
ParsingTreeNode* FindDeepestNode(const ParsingTextRange& range);
|
|
};
|
|
|
|
/// <summary>Representing a token node in a abstract syntax tree.</summary>
|
|
class ParsingTreeToken : public ParsingTreeNode, public reflection::Description<ParsingTreeToken>
|
|
{
|
|
protected:
|
|
WString value;
|
|
vint tokenIndex;
|
|
|
|
const NodeList& GetSubNodesInternal()override;
|
|
public:
|
|
ParsingTreeToken(const WString& _value, vint _tokenIndex=-1, const ParsingTextRange& _codeRange=ParsingTextRange());
|
|
~ParsingTreeToken();
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
Ptr<ParsingTreeNode> Clone()override;
|
|
vint GetTokenIndex();
|
|
void SetTokenIndex(vint _tokenIndex);
|
|
/// <summary>Get the content of the token.</summary>
|
|
/// <returns>The content of the token.</returns>
|
|
const WString& GetValue();
|
|
void SetValue(const WString& _value);
|
|
};
|
|
|
|
/// <summary>Representing an object node in a abstract syntax tree.</summary>
|
|
class ParsingTreeObject : public ParsingTreeNode, public reflection::Description<ParsingTreeObject>
|
|
{
|
|
protected:
|
|
typedef collections::Dictionary<WString, Ptr<ParsingTreeNode>> NodeMap;
|
|
typedef collections::SortedList<WString> NameList;
|
|
typedef collections::List<WString> RuleList;
|
|
|
|
WString type;
|
|
NodeMap members;
|
|
RuleList rules;
|
|
|
|
const NodeList& GetSubNodesInternal()override;
|
|
public:
|
|
ParsingTreeObject(const WString& _type=L"", const ParsingTextRange& _codeRange=ParsingTextRange());
|
|
~ParsingTreeObject();
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
Ptr<ParsingTreeNode> Clone()override;
|
|
/// <summary>Get the type name of the object.</summary>
|
|
/// <returns>The type name of the object.</returns>
|
|
const WString& GetType();
|
|
void SetType(const WString& _type);
|
|
/// <summary>Get all fields of the object.</summary>
|
|
/// <returns>All fields of the object.</returns>
|
|
NodeMap& GetMembers();
|
|
/// <summary>Get a field of the object by the field name.</summary>
|
|
/// <returns>The field of the object.</returns>
|
|
/// <param name="name">The field name.</param>
|
|
Ptr<ParsingTreeNode> GetMember(const WString& name);
|
|
bool SetMember(const WString& name, Ptr<ParsingTreeNode> node);
|
|
bool RemoveMember(const WString& name);
|
|
/// <summary>Get all field names.</summary>
|
|
/// <returns>All field names of the object.</returns>
|
|
const NameList& GetMemberNames();
|
|
/// <summary>Get names of all rules that return this object.</summary>
|
|
/// <returns>Names of all rules.</returns>
|
|
RuleList& GetCreatorRules();
|
|
};
|
|
|
|
/// <summary>Representing an array node in a abstract syntax tree.</summary>
|
|
class ParsingTreeArray : public ParsingTreeNode, public reflection::Description<ParsingTreeArray>
|
|
{
|
|
protected:
|
|
typedef collections::List<Ptr<ParsingTreeNode>> NodeArray;
|
|
|
|
WString elementType;
|
|
NodeArray items;
|
|
|
|
const NodeList& GetSubNodesInternal()override;
|
|
public:
|
|
ParsingTreeArray(const WString& _elementType=L"", const ParsingTextRange& _codeRange=ParsingTextRange());
|
|
~ParsingTreeArray();
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
Ptr<ParsingTreeNode> Clone()override;
|
|
/// <summary>Get the type of all elements. It could be different from any actual element's type, but it should at least be the base types of them.</summary>
|
|
/// <returns>The type of all elements.</returns>
|
|
const WString& GetElementType();
|
|
void SetElementType(const WString& _elementType);
|
|
/// <summary>Get all elements in this array.</summary>
|
|
/// <returns>All elements in this array.</returns>
|
|
NodeArray& GetItems();
|
|
/// <summary>Get a specified element in this array by the index.</summary>
|
|
/// <returns>The element.</returns>
|
|
/// <param name="index">The index of the element.</param>
|
|
Ptr<ParsingTreeNode> GetItem(vint index);
|
|
bool SetItem(vint index, Ptr<ParsingTreeNode> node);
|
|
bool AddItem(Ptr<ParsingTreeNode> node);
|
|
bool InsertItem(vint index, Ptr<ParsingTreeNode> node);
|
|
bool RemoveItem(vint index);
|
|
bool RemoveItem(ParsingTreeNode* node);
|
|
vint IndexOfItem(ParsingTreeNode* node);
|
|
bool ContainsItem(ParsingTreeNode* node);
|
|
vint Count();
|
|
bool Clear();
|
|
};
|
|
|
|
/***********************************************************************
|
|
AST Building Block
|
|
***********************************************************************/
|
|
|
|
/// <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. See [T:vl.parsing.tabling.ParsingTable] for details.</summary>
|
|
class ParsingTreeCustomBase : public Object, public reflection::Description<ParsingTreeCustomBase>
|
|
{
|
|
public:
|
|
/// <summary>Range of all tokens that form this object.</summary>
|
|
ParsingTextRange codeRange;
|
|
/// <summary>Names of all rules that return this object.</summary>
|
|
collections::List<WString> creatorRules;
|
|
};
|
|
|
|
/// <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>
|
|
class ParsingToken : public ParsingTreeCustomBase, public reflection::Description<ParsingToken>
|
|
{
|
|
public:
|
|
/// <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 tokenIndex;
|
|
/// <summary>Content of the token.</summary>
|
|
WString value;
|
|
|
|
ParsingToken():tokenIndex(-1){}
|
|
};
|
|
|
|
/// <summary>Error.</summary>
|
|
class ParsingError : public Object, public reflection::Description<ParsingError>
|
|
{
|
|
public:
|
|
/// <summary>Range where the error happens.</summary>
|
|
ParsingTextRange codeRange;
|
|
/// <summary>Token at which the error happens.</summary>
|
|
const regex::RegexToken* token;
|
|
/// <summary>A syntax tree that contains this error.</summary>
|
|
ParsingTreeCustomBase* parsingTree;
|
|
/// <summary>The error message.</summary>
|
|
WString errorMessage;
|
|
|
|
ParsingError();
|
|
ParsingError(const WString& _errorMessage);
|
|
ParsingError(const regex::RegexToken* _token, const WString& _errorMessage);
|
|
ParsingError(ParsingTreeCustomBase* _parsingTree, const WString& _errorMessage);
|
|
~ParsingError();
|
|
};
|
|
|
|
/***********************************************************************
|
|
Syntax Tree Serialization Helper
|
|
***********************************************************************/
|
|
|
|
class ParsingTreeConverter : public Object
|
|
{
|
|
public:
|
|
typedef collections::List<regex::RegexToken> TokenList;
|
|
|
|
virtual Ptr<ParsingTreeCustomBase> ConvertClass(Ptr<ParsingTreeObject> obj, const TokenList& tokens)=0;
|
|
|
|
bool SetMember(ParsingToken& member, Ptr<ParsingTreeNode> node, const TokenList& tokens)
|
|
{
|
|
Ptr<ParsingTreeToken> token=node.Cast<ParsingTreeToken>();
|
|
if(token)
|
|
{
|
|
member.tokenIndex=token->GetTokenIndex();
|
|
member.value=token->GetValue();
|
|
member.codeRange=token->GetCodeRange();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template<typename T>
|
|
bool SetMember(collections::List<T>& member, Ptr<ParsingTreeNode> node, const TokenList& tokens)
|
|
{
|
|
Ptr<ParsingTreeArray> arr=node.Cast<ParsingTreeArray>();
|
|
if(arr)
|
|
{
|
|
member.Clear();
|
|
vint count=arr->Count();
|
|
for(vint i=0;i<count;i++)
|
|
{
|
|
T t;
|
|
SetMember(t, arr->GetItem(i), tokens);
|
|
member.Add(t);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template<typename T>
|
|
bool SetMember(Ptr<T>& member, Ptr<ParsingTreeNode> node, const TokenList& tokens)
|
|
{
|
|
Ptr<ParsingTreeObject> obj=node.Cast<ParsingTreeObject>();
|
|
if(obj)
|
|
{
|
|
Ptr<ParsingTreeCustomBase> tree=ConvertClass(obj, tokens);
|
|
if(tree)
|
|
{
|
|
tree->codeRange=node->GetCodeRange();
|
|
member=tree.Cast<T>();
|
|
return member;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Logging
|
|
***********************************************************************/
|
|
|
|
class IParsingPrintNodeRecorder : public virtual Interface
|
|
{
|
|
public:
|
|
virtual void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range) = 0;
|
|
};
|
|
|
|
class ParsingEmptyPrintNodeRecorder : public Object, public virtual IParsingPrintNodeRecorder
|
|
{
|
|
public:
|
|
ParsingEmptyPrintNodeRecorder();
|
|
~ParsingEmptyPrintNodeRecorder();
|
|
|
|
void Record(ParsingTreeCustomBase* 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(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
|
|
};
|
|
|
|
class ParsingOriginalLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
|
|
{
|
|
protected:
|
|
Ptr<IParsingPrintNodeRecorder> recorder;
|
|
|
|
public:
|
|
ParsingOriginalLocationRecorder(Ptr<IParsingPrintNodeRecorder> _recorder);
|
|
~ParsingOriginalLocationRecorder();
|
|
|
|
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
|
|
};
|
|
|
|
class ParsingGeneratedLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
|
|
{
|
|
typedef collections::Dictionary<ParsingTreeCustomBase*, ParsingTextRange> RangeMap;
|
|
protected:
|
|
RangeMap& rangeMap;
|
|
|
|
public:
|
|
ParsingGeneratedLocationRecorder(RangeMap& _rangeMap);
|
|
~ParsingGeneratedLocationRecorder();
|
|
|
|
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
|
|
};
|
|
|
|
class ParsingUpdateLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
|
|
{
|
|
public:
|
|
ParsingUpdateLocationRecorder();
|
|
~ParsingUpdateLocationRecorder();
|
|
|
|
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
|
|
};
|
|
|
|
class ParsingWriter : public stream::TextWriter
|
|
{
|
|
typedef collections::Pair<ParsingTreeCustomBase*, 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(ParsingTreeCustomBase* node);
|
|
void AfterPrint(ParsingTreeCustomBase* node);
|
|
};
|
|
|
|
extern void Log(ParsingTreeNode* node, const WString& originalInput, stream::TextWriter& writer, const WString& prefix=L"");
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\PARSINGDEFINITIONS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parsing::Definitions
|
|
|
|
Classes:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_PARSINGDEFINITIONS
|
|
#define VCZH_PARSING_PARSINGDEFINITIONS
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace definitions
|
|
{
|
|
|
|
/***********************************************************************
|
|
Attributes
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionAttribute : public ParsingTreeCustomBase
|
|
{
|
|
public:
|
|
WString name;
|
|
collections::List<WString> arguments;
|
|
};
|
|
|
|
class ParsingDefinitionBase : public ParsingTreeCustomBase
|
|
{
|
|
typedef collections::List<Ptr<ParsingDefinitionAttribute>> AttributeList;
|
|
public:
|
|
AttributeList attributes;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Type
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionPrimitiveType;
|
|
class ParsingDefinitionTokenType;
|
|
class ParsingDefinitionSubType;
|
|
class ParsingDefinitionArrayType;
|
|
|
|
class ParsingDefinitionType : public ParsingTreeCustomBase
|
|
{
|
|
public:
|
|
class IVisitor : public Interface
|
|
{
|
|
public:
|
|
virtual void Visit(ParsingDefinitionPrimitiveType* node)=0;
|
|
virtual void Visit(ParsingDefinitionTokenType* node)=0;
|
|
virtual void Visit(ParsingDefinitionSubType* node)=0;
|
|
virtual void Visit(ParsingDefinitionArrayType* node)=0;
|
|
};
|
|
|
|
virtual void Accept(IVisitor* visitor)=0;
|
|
};
|
|
|
|
class ParsingDefinitionPrimitiveType : public ParsingDefinitionType
|
|
{
|
|
public:
|
|
WString name;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionTokenType : public ParsingDefinitionType
|
|
{
|
|
public:
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionSubType : public ParsingDefinitionType
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionType> parentType;
|
|
WString subTypeName;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionArrayType : public ParsingDefinitionType
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionType> elementType;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Type Definition
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionClassMemberDefinition;
|
|
class ParsingDefinitionClassDefinition;
|
|
class ParsingDefinitionEnumMemberDefinition;
|
|
class ParsingDefinitionEnumDefinition;
|
|
|
|
class ParsingDefinitionTypeDefinition : public ParsingDefinitionBase
|
|
{
|
|
public:
|
|
class IVisitor : public Interface
|
|
{
|
|
public:
|
|
virtual void Visit(ParsingDefinitionClassMemberDefinition* node)=0;
|
|
virtual void Visit(ParsingDefinitionClassDefinition* node)=0;
|
|
virtual void Visit(ParsingDefinitionEnumMemberDefinition* node)=0;
|
|
virtual void Visit(ParsingDefinitionEnumDefinition* node)=0;
|
|
};
|
|
|
|
virtual void Accept(IVisitor* visitor)=0;
|
|
public:
|
|
WString name;
|
|
};
|
|
|
|
class ParsingDefinitionClassMemberDefinition : public ParsingDefinitionTypeDefinition
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionType> type;
|
|
WString unescapingFunction;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionClassDefinition : public ParsingDefinitionTypeDefinition
|
|
{
|
|
public:
|
|
typedef collections::List<Ptr<ParsingDefinitionClassMemberDefinition>> MemberList;
|
|
typedef collections::List<Ptr<ParsingDefinitionTypeDefinition>> TypeList;
|
|
|
|
Ptr<ParsingDefinitionType> ambiguousType;
|
|
Ptr<ParsingDefinitionType> parentType;
|
|
MemberList members;
|
|
TypeList subTypes;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionEnumMemberDefinition : public ParsingDefinitionTypeDefinition
|
|
{
|
|
public:
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionEnumDefinition : public ParsingDefinitionTypeDefinition
|
|
{
|
|
public:
|
|
typedef collections::List<Ptr<ParsingDefinitionEnumMemberDefinition>> MemberList;
|
|
|
|
MemberList members;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Grammar
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionPrimitiveGrammar;
|
|
class ParsingDefinitionTextGrammar;
|
|
class ParsingDefinitionSequenceGrammar;
|
|
class ParsingDefinitionAlternativeGrammar;
|
|
class ParsingDefinitionLoopGrammar;
|
|
class ParsingDefinitionOptionalGrammar;
|
|
class ParsingDefinitionCreateGrammar;
|
|
class ParsingDefinitionAssignGrammar;
|
|
class ParsingDefinitionUseGrammar;
|
|
class ParsingDefinitionSetterGrammar;
|
|
|
|
class ParsingDefinitionGrammar : public ParsingTreeCustomBase
|
|
{
|
|
public:
|
|
class IVisitor : public Interface
|
|
{
|
|
public:
|
|
virtual void Visit(ParsingDefinitionPrimitiveGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionTextGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionSequenceGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionAlternativeGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionLoopGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionOptionalGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionCreateGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionAssignGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionUseGrammar* node)=0;
|
|
virtual void Visit(ParsingDefinitionSetterGrammar* node)=0;
|
|
};
|
|
|
|
virtual void Accept(IVisitor* visitor)=0;
|
|
};
|
|
|
|
class ParsingDefinitionPrimitiveGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
WString name;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionTextGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
WString text;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionSequenceGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> first;
|
|
Ptr<ParsingDefinitionGrammar> second;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionAlternativeGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> first;
|
|
Ptr<ParsingDefinitionGrammar> second;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionLoopGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> grammar;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionOptionalGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> grammar;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionCreateGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> grammar;
|
|
Ptr<ParsingDefinitionType> type;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionAssignGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> grammar;
|
|
WString memberName;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionUseGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> grammar;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
class ParsingDefinitionSetterGrammar : public ParsingDefinitionGrammar
|
|
{
|
|
public:
|
|
Ptr<ParsingDefinitionGrammar> grammar;
|
|
WString memberName;
|
|
WString value;
|
|
|
|
void Accept(IVisitor* visitor)override;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Token and Rule
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionTokenDefinition : public ParsingDefinitionBase
|
|
{
|
|
public:
|
|
WString name;
|
|
WString regex;
|
|
bool discard;
|
|
};
|
|
|
|
class ParsingDefinitionRuleDefinition : public ParsingDefinitionBase
|
|
{
|
|
public:
|
|
WString name;
|
|
Ptr<ParsingDefinitionType> type;
|
|
collections::List<Ptr<ParsingDefinitionGrammar>> grammars;
|
|
};
|
|
|
|
class ParsingDefinition : public ParsingTreeCustomBase
|
|
{
|
|
public:
|
|
collections::List<Ptr<ParsingDefinitionTypeDefinition>> types;
|
|
collections::List<Ptr<ParsingDefinitionTokenDefinition>> tokens;
|
|
collections::List<Ptr<ParsingDefinitionRuleDefinition>> rules;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Attribute Writer
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionAttributeWriter : public Object
|
|
{
|
|
friend ParsingDefinitionAttributeWriter Attribute(const WString& name);
|
|
protected:
|
|
Ptr<ParsingDefinitionAttribute> attribute;
|
|
|
|
ParsingDefinitionAttributeWriter(const WString& name);
|
|
public:
|
|
ParsingDefinitionAttributeWriter(const ParsingDefinitionAttributeWriter& attributeWriter);
|
|
|
|
ParsingDefinitionAttributeWriter& Argument(const WString& argument);
|
|
Ptr<ParsingDefinitionAttribute> Attribute()const;
|
|
};
|
|
|
|
extern ParsingDefinitionAttributeWriter Attribute(const WString& name);
|
|
|
|
/***********************************************************************
|
|
Type Writer
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionTypeWriter : public Object
|
|
{
|
|
friend ParsingDefinitionTypeWriter Type(const WString& name);
|
|
friend ParsingDefinitionTypeWriter TokenType();
|
|
protected:
|
|
Ptr<ParsingDefinitionType> type;
|
|
|
|
ParsingDefinitionTypeWriter(Ptr<ParsingDefinitionType> internalType);
|
|
ParsingDefinitionTypeWriter(const WString& name);
|
|
public:
|
|
ParsingDefinitionTypeWriter(const ParsingDefinitionTypeWriter& typeWriter);
|
|
|
|
ParsingDefinitionTypeWriter Sub(const WString& subTypeName)const;
|
|
ParsingDefinitionTypeWriter Array()const;
|
|
Ptr<ParsingDefinitionType> Type()const;
|
|
};
|
|
|
|
extern ParsingDefinitionTypeWriter Type(const WString& name);
|
|
extern ParsingDefinitionTypeWriter TokenType();
|
|
|
|
/***********************************************************************
|
|
Type Definition Writer
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionTypeDefinitionWriter : public Object
|
|
{
|
|
public:
|
|
virtual Ptr<ParsingDefinitionTypeDefinition> Definition()const=0;
|
|
};
|
|
|
|
class ParsingDefinitionClassDefinitionWriter : public ParsingDefinitionTypeDefinitionWriter
|
|
{
|
|
protected:
|
|
Ptr<ParsingDefinitionBase> currentDefinition;
|
|
Ptr<ParsingDefinitionClassDefinition> definition;
|
|
|
|
public:
|
|
ParsingDefinitionClassDefinitionWriter(const WString& name);
|
|
ParsingDefinitionClassDefinitionWriter(const WString& name, const ParsingDefinitionTypeWriter& parentType);
|
|
|
|
ParsingDefinitionClassDefinitionWriter& AmbiguousType(const ParsingDefinitionTypeWriter& ambiguousType);
|
|
ParsingDefinitionClassDefinitionWriter& Member(const WString& name, const ParsingDefinitionTypeWriter& type, const WString& unescapingFunction=L"");
|
|
ParsingDefinitionClassDefinitionWriter& SubType(const ParsingDefinitionTypeDefinitionWriter& type);
|
|
ParsingDefinitionClassDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
|
|
|
|
Ptr<ParsingDefinitionTypeDefinition> Definition()const override;
|
|
};
|
|
|
|
extern ParsingDefinitionClassDefinitionWriter Class(const WString& name);
|
|
extern ParsingDefinitionClassDefinitionWriter Class(const WString& name, const ParsingDefinitionTypeWriter& parentType);
|
|
|
|
class ParsingDefinitionEnumDefinitionWriter : public ParsingDefinitionTypeDefinitionWriter
|
|
{
|
|
protected:
|
|
Ptr<ParsingDefinitionBase> currentDefinition;
|
|
Ptr<ParsingDefinitionEnumDefinition> definition;
|
|
|
|
public:
|
|
ParsingDefinitionEnumDefinitionWriter(const WString& name);
|
|
|
|
ParsingDefinitionEnumDefinitionWriter& Member(const WString& name);
|
|
ParsingDefinitionEnumDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
|
|
|
|
Ptr<ParsingDefinitionTypeDefinition> Definition()const override;
|
|
};
|
|
|
|
extern ParsingDefinitionEnumDefinitionWriter Enum(const WString& name);
|
|
|
|
/***********************************************************************
|
|
Grammar Writer
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionGrammarWriter : public Object
|
|
{
|
|
friend ParsingDefinitionGrammarWriter Rule(const WString& name);
|
|
friend ParsingDefinitionGrammarWriter Text(const WString& name);
|
|
friend ParsingDefinitionGrammarWriter Opt(const ParsingDefinitionGrammarWriter& writer);
|
|
protected:
|
|
Ptr<ParsingDefinitionGrammar> grammar;
|
|
|
|
ParsingDefinitionGrammarWriter(Ptr<ParsingDefinitionGrammar> internalGrammar);
|
|
public:
|
|
ParsingDefinitionGrammarWriter(const ParsingDefinitionGrammarWriter& grammarWriter);
|
|
|
|
ParsingDefinitionGrammarWriter operator+(const ParsingDefinitionGrammarWriter& next)const;
|
|
ParsingDefinitionGrammarWriter operator|(const ParsingDefinitionGrammarWriter& next)const;
|
|
ParsingDefinitionGrammarWriter operator*()const;
|
|
ParsingDefinitionGrammarWriter As(const ParsingDefinitionTypeWriter& type)const;
|
|
ParsingDefinitionGrammarWriter operator[](const WString& memberName)const;
|
|
ParsingDefinitionGrammarWriter operator!()const;
|
|
ParsingDefinitionGrammarWriter Set(const WString& memberName, const WString& value)const;
|
|
|
|
Ptr<ParsingDefinitionGrammar> Grammar()const;
|
|
};
|
|
|
|
extern ParsingDefinitionGrammarWriter Rule(const WString& name);
|
|
extern ParsingDefinitionGrammarWriter Text(const WString& text);
|
|
extern ParsingDefinitionGrammarWriter Opt(const ParsingDefinitionGrammarWriter& writer);
|
|
|
|
/***********************************************************************
|
|
Token and Rule Writer
|
|
***********************************************************************/
|
|
|
|
class ParsingDefinitionWriter;
|
|
|
|
class ParsingDefinitionTokenDefinitionWriter : public Object
|
|
{
|
|
protected:
|
|
Ptr<ParsingDefinitionTokenDefinition> token;
|
|
ParsingDefinitionWriter& owner;
|
|
public:
|
|
ParsingDefinitionTokenDefinitionWriter(ParsingDefinitionWriter& _owner, Ptr<ParsingDefinitionTokenDefinition> _token);
|
|
|
|
ParsingDefinitionTokenDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
|
|
ParsingDefinitionWriter& EndToken();
|
|
};
|
|
|
|
class ParsingDefinitionRuleDefinitionWriter : public Object
|
|
{
|
|
protected:
|
|
Ptr<ParsingDefinitionRuleDefinition> rule;
|
|
ParsingDefinitionWriter& owner;
|
|
public:
|
|
ParsingDefinitionRuleDefinitionWriter(ParsingDefinitionWriter& _owner, Ptr<ParsingDefinitionRuleDefinition> _rule);
|
|
|
|
ParsingDefinitionRuleDefinitionWriter& Imply(const ParsingDefinitionGrammarWriter& grammar);
|
|
ParsingDefinitionRuleDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
|
|
ParsingDefinitionWriter& EndRule();
|
|
};
|
|
|
|
class ParsingDefinitionWriter : public Object
|
|
{
|
|
protected:
|
|
Ptr<ParsingDefinition> definition;
|
|
|
|
public:
|
|
ParsingDefinitionWriter();
|
|
|
|
ParsingDefinitionWriter& Type(const ParsingDefinitionTypeDefinitionWriter& type);
|
|
ParsingDefinitionWriter& Token(const WString& name, const WString& regex);
|
|
ParsingDefinitionTokenDefinitionWriter TokenAtt(const WString& name, const WString& regex);
|
|
ParsingDefinitionWriter& Discard(const WString& name, const WString& regex);
|
|
ParsingDefinitionRuleDefinitionWriter Rule(const WString& name, const ParsingDefinitionTypeWriter& type);
|
|
|
|
Ptr<ParsingDefinition> Definition()const;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Helper Functions
|
|
***********************************************************************/
|
|
|
|
extern WString TypeToString(ParsingDefinitionType* type);
|
|
extern WString GrammarToString(ParsingDefinitionGrammar* grammar);
|
|
extern WString GrammarStateToString(ParsingDefinitionGrammar* grammar, ParsingDefinitionGrammar* stateNode, bool beforeNode);
|
|
extern ParsingDefinitionGrammar* FindAppropriateGrammarState(ParsingDefinitionGrammar* grammar, ParsingDefinitionGrammar* stateNode, bool beforeNode);
|
|
extern void Log(Ptr<ParsingDefinition> definition, stream::TextWriter& writer);
|
|
extern WString DeserializeString(const WString& value);
|
|
extern WString SerializeString(const WString& value);
|
|
|
|
/***********************************************************************
|
|
Bootstrap
|
|
***********************************************************************/
|
|
|
|
extern Ptr<ParsingDefinition> CreateParserDefinition();
|
|
extern Ptr<ParsingDefinition> DeserializeDefinition(Ptr<ParsingTreeNode> node);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\PARSINGANALYZER.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parsing::Analyzing
|
|
|
|
Classes:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_PARSINGANALYZER
|
|
#define VCZH_PARSING_PARSINGANALYZER
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace analyzing
|
|
{
|
|
|
|
/***********************************************************************
|
|
DefinitionTypeScopePair
|
|
***********************************************************************/
|
|
|
|
class ParsingSymbol;
|
|
class ParsingSymbolManager;
|
|
|
|
struct DefinitionTypeScopePair
|
|
{
|
|
definitions::ParsingDefinitionType* type;
|
|
ParsingSymbol* scope;
|
|
|
|
DefinitionTypeScopePair()
|
|
{
|
|
}
|
|
|
|
DefinitionTypeScopePair(definitions::ParsingDefinitionType* _type, ParsingSymbol* _scope)
|
|
:type(_type)
|
|
,scope(_scope)
|
|
{
|
|
}
|
|
|
|
vint Compare(const DefinitionTypeScopePair& pair)const
|
|
{
|
|
if(type<pair.type) return -1;
|
|
if(type>pair.type) return 1;
|
|
if(scope<pair.scope) return -1;
|
|
if(scope>pair.scope) return 1;
|
|
return 0;
|
|
}
|
|
|
|
bool operator== (const DefinitionTypeScopePair& pair)const {return Compare(pair)==0;}
|
|
bool operator!= (const DefinitionTypeScopePair& pair)const {return Compare(pair)!=0;}
|
|
bool operator> (const DefinitionTypeScopePair& pair)const {return Compare(pair)>0;}
|
|
bool operator>= (const DefinitionTypeScopePair& pair)const {return Compare(pair)>=0;}
|
|
bool operator< (const DefinitionTypeScopePair& pair)const {return Compare(pair)<0;}
|
|
bool operator<= (const DefinitionTypeScopePair& pair)const {return Compare(pair)<=0;}
|
|
};
|
|
|
|
/***********************************************************************
|
|
ParsingSymbol Management
|
|
***********************************************************************/
|
|
|
|
class ParsingSymbol : public Object
|
|
{
|
|
friend class ParsingSymbolManager;
|
|
|
|
typedef collections::Dictionary<WString, ParsingSymbol*> ParsingSymbolMap;
|
|
typedef collections::List<ParsingSymbol*> ParsingSymbolList;
|
|
public:
|
|
enum SymbolType
|
|
{
|
|
Global,
|
|
EnumType,
|
|
ClassType, // descriptor == base type
|
|
ArrayType, // descriptor == element type
|
|
TokenType,
|
|
EnumItem, // descriptor == parent
|
|
ClassField, // descriptor == field type
|
|
TokenDef, // descriptor == token type
|
|
RuleDef, // descriptor == rule type
|
|
};
|
|
|
|
protected:
|
|
ParsingSymbolManager* manager;
|
|
SymbolType type;
|
|
WString name;
|
|
ParsingSymbol* descriptorSymbol;
|
|
WString descriptorString;
|
|
ParsingSymbol* parentSymbol;
|
|
ParsingSymbol* arrayTypeSymbol;
|
|
ParsingSymbolList subSymbolList;
|
|
ParsingSymbolMap subSymbolMap;
|
|
|
|
bool AddSubSymbol(ParsingSymbol* subSymbol);
|
|
|
|
ParsingSymbol(ParsingSymbolManager* _manager, SymbolType _type, const WString& _name, ParsingSymbol* _descriptorSymbol, const WString& _descriptorString);
|
|
public:
|
|
~ParsingSymbol();
|
|
|
|
ParsingSymbolManager* GetManager();
|
|
SymbolType GetType();
|
|
const WString& GetName();
|
|
vint GetSubSymbolCount();
|
|
ParsingSymbol* GetSubSymbol(vint index);
|
|
ParsingSymbol* GetSubSymbolByName(const WString& name);
|
|
ParsingSymbol* GetDescriptorSymbol();
|
|
WString GetDescriptorString();
|
|
ParsingSymbol* GetParentSymbol();
|
|
bool IsType();
|
|
ParsingSymbol* SearchClassSubSymbol(const WString& name);
|
|
ParsingSymbol* SearchCommonBaseClass(ParsingSymbol* classType);
|
|
};
|
|
|
|
class ParsingSymbolManager : public Object
|
|
{
|
|
typedef definitions::ParsingDefinitionClassDefinition ClassDefinition;
|
|
typedef collections::List<Ptr<ParsingSymbol>> ParsingSymbolList;
|
|
typedef collections::Dictionary<DefinitionTypeScopePair, ParsingSymbol*> DefinitionTypeSymbolMap;
|
|
typedef collections::Dictionary<definitions::ParsingDefinitionGrammar*, ParsingSymbol*> DefinitionGrammarSymbolMap;
|
|
typedef collections::Dictionary<ParsingSymbol*, ClassDefinition*> SymbolClassDefinitionMap;
|
|
typedef collections::Dictionary<ClassDefinition*, ParsingSymbol*> ClassDefinitionSymbolMap;
|
|
protected:
|
|
ParsingSymbol* globalSymbol;
|
|
ParsingSymbol* tokenTypeSymbol;
|
|
ParsingSymbolList createdSymbols;
|
|
DefinitionTypeSymbolMap definitionTypeSymbolCache;
|
|
DefinitionGrammarSymbolMap definitionGrammarSymbolCache;
|
|
DefinitionGrammarSymbolMap definitionGrammarTypeCache;
|
|
SymbolClassDefinitionMap symbolClassDefinitionCache;
|
|
ClassDefinitionSymbolMap classDefinitionSymbolCache;
|
|
|
|
bool TryAddSubSymbol(Ptr<ParsingSymbol> subSymbol, ParsingSymbol* parentSymbol);
|
|
public:
|
|
ParsingSymbolManager();
|
|
~ParsingSymbolManager();
|
|
|
|
ParsingSymbol* GetGlobal();
|
|
ParsingSymbol* GetTokenType();
|
|
ParsingSymbol* GetArrayType(ParsingSymbol* elementType);
|
|
|
|
ParsingSymbol* AddClass(definitions::ParsingDefinitionClassDefinition* classDef, ParsingSymbol* baseType, ParsingSymbol* parentType=0);
|
|
ParsingSymbol* AddField(const WString& name, ParsingSymbol* classType, ParsingSymbol* fieldType);
|
|
ParsingSymbol* AddEnum(const WString& name, ParsingSymbol* parentType=0);
|
|
ParsingSymbol* AddEnumItem(const WString& name, ParsingSymbol* enumType);
|
|
ParsingSymbol* AddTokenDefinition(const WString& name, const WString& regex);
|
|
ParsingSymbol* AddRuleDefinition(const WString& name, ParsingSymbol* ruleType);
|
|
|
|
ClassDefinition* CacheGetClassDefinition(ParsingSymbol* type);
|
|
ParsingSymbol* CacheGetClassType(ClassDefinition* type);
|
|
ParsingSymbol* CacheGetType(definitions::ParsingDefinitionType* type, ParsingSymbol* scope);
|
|
bool CacheSetType(definitions::ParsingDefinitionType* type, ParsingSymbol* scope, ParsingSymbol* symbol);
|
|
ParsingSymbol* CacheGetSymbol(definitions::ParsingDefinitionGrammar* grammar);
|
|
bool CacheSetSymbol(definitions::ParsingDefinitionGrammar* grammar, ParsingSymbol* symbol);
|
|
ParsingSymbol* CacheGetType(definitions::ParsingDefinitionGrammar* grammar);
|
|
bool CacheSetType(definitions::ParsingDefinitionGrammar* grammar, ParsingSymbol* type);
|
|
};
|
|
|
|
/***********************************************************************
|
|
Semantic Analyzer
|
|
***********************************************************************/
|
|
|
|
extern WString GetTypeFullName(ParsingSymbol* type);
|
|
extern ParsingSymbol* FindType(definitions::ParsingDefinitionType* type, ParsingSymbolManager* manager, ParsingSymbol* scope, collections::List<Ptr<ParsingError>>& errors);
|
|
extern void PrepareSymbols(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
|
|
extern void ValidateRuleStructure(Ptr<definitions::ParsingDefinition> definition, Ptr<definitions::ParsingDefinitionRuleDefinition> rule, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
|
|
extern void ResolveRuleSymbols(Ptr<definitions::ParsingDefinitionRuleDefinition> rule, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
|
|
extern void ResolveSymbols(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
|
|
extern void ValidateDefinition(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\PARSINGTABLE.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parsing::Table
|
|
|
|
Classes:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_PARSINGTABLE
|
|
#define VCZH_PARSING_PARSINGTABLE
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace tabling
|
|
{
|
|
|
|
/***********************************************************************
|
|
Parsing Table
|
|
***********************************************************************/
|
|
|
|
/// <summary><![CDATA[
|
|
/// The parsing table. When you complete a grammar file, ParserGen.exe which is in the Tools project will generate the C++ code for you to create a parsing table.
|
|
///
|
|
/// Here is a brief description of the grammar file format:
|
|
///
|
|
/// include:"<releative path to the Vlpp.h>" // (multiple) e.g. "../Import/Vlpp.h"
|
|
/// classPrefix:<class prefix> // (single) A prefix that will be add before all generated types and function. e.g. Xml
|
|
/// guard:<C++ header guard> // (single) The C++ header guard pattern macro name. e.g. VCZH_PARSING_XML_PARSINGXML_PARSER
|
|
/// namespace:<C++ namespaces> // (single) Namespaces separated by "." to contain the generated code. e.g. vl.parsing.xml
|
|
/// reflection:<namespace> // (single) Namespaces separated by "." to contain the name of reflectable types. In most of the cases this should be the same as namespace. e.g. vl.parsing.xml
|
|
/// parser:<name>(<rule>) // (multiple) Pair a function name to a rule name. ParserGen.exe will generate a function called "<prefix><name>" to parse the input using rule named "<rule>". e.g. ParseDocument(XDocument)
|
|
/// ambiguity:(enabled|disabled) // (single) Set to "enabled" indicating that the grammar is by design to have ambiguity.
|
|
/// serialization:(enabled|disabled) // (single) Set to "enabled" to serialize the parsing table as binary in the generated C++ code, so that when the "<prefix>LoadTable" function is called to load the table, it can deserialize from the binary data directly, instead of parsing the grammar again. But the grammar text will always be contained in the generated C++ code regardless of the value of "serialization", it can always be retrived using the "<prefix>GetParserTextBuffer" function.
|
|
/// grammar: // (single) Configuration ends here. All content after "grammar:" will be treated as the grammar to define the input.
|
|
///
|
|
/// Here is the brief description of the grammar.
|
|
/// The grammar is formed by 3 parts: types, token definitions and rule definitions. There is only one character escaping in strings: "", which means the " character.
|
|
///
|
|
/// 1) Types:
|
|
/// You can write attributes like @AttributeName("argument1", "argument2", ...) in the middle of types. But attributes don't affect the parsing. All attribute definitions will be stored in the generated parsing table, and who uses the table defines how attributes work. Multiple attributes are separated by ",".
|
|
///
|
|
/// a) Enum:
|
|
/// enum EnumName <attributes>
|
|
/// {
|
|
/// Item1 <attributes>,
|
|
/// Item2 <attributes>,
|
|
/// ... // cannot skip the last ","
|
|
/// }
|
|
///
|
|
/// b) Class:
|
|
/// class Name [ambiguous(AmbiguousType)] [: ParentType] <attributes>
|
|
/// {
|
|
/// Type name [(UnescapingFunction)] <attributes> ;
|
|
/// }
|
|
///
|
|
/// UnescapingFunction is a callback, which will be called when the contained type is fully constructed. The generated C++ code will define forward declarations of all unescaping functions in the cpp file. You should implement them in other places, or you will get linking errors.
|
|
///
|
|
/// If the grammar enables ambiguity, then the parsing result may contain ambiguous results for the same part of the input. For example, in C++:
|
|
/// A*B;
|
|
/// has two meaning (if we only consider context-free parsing): multiplication expression and pointer variable definition.
|
|
/// So if the grammar doesn't enable ambiguity, ParserGen.exe will refuce to generate C++ codes because the grammar is wrong.
|
|
/// If the grammar enables ambiguity, than the syntax tree should be defined like this:
|
|
///
|
|
/// class Statement ambiguous(AmbiguousStatement)
|
|
/// {
|
|
/// }
|
|
///
|
|
/// class AmbiguousStatement : Statement // due to the definition of "Statement" class, "AmbiguousStatement" should inherit from "Statement"
|
|
/// {
|
|
/// Statement[] items; // required by naming convention
|
|
/// }
|
|
///
|
|
/// class ExpressionStatement : Statement
|
|
/// {
|
|
/// Expression expression;
|
|
/// }
|
|
///
|
|
/// class VariableDefinitionStatement : Statement
|
|
/// {
|
|
/// Type type;
|
|
/// token name;
|
|
/// }
|
|
///
|
|
/// So for the "A*B;" part in the whole input, it will becomes an AmbiguousStatement, in which the "items" field contains 2 instance of "ExpressionStatement" and "VariableDefinitionStatement".
|
|
/// And you can write C++ code to resolve the ambiguity in later passes.
|
|
///
|
|
/// c) Type references:
|
|
/// Types can be defined globally or inside classes. Generic type is not supported. When you want to refer to a specific type, it could be:
|
|
/// token: Store a token, which will becomes [T:vl.parsing.ParsingToken].
|
|
/// Type[]: Array, which will becomes [T:vl.collections.List`2] to the element type. Token cannot be the element of arrays.
|
|
/// ClassName: Instance of a specified type, which will becomes [T:vl.Ptr`1] to that type.
|
|
/// OuterClass.InnerClass: Refer to the "InnerClass" defined inside the "OuterClass".
|
|
///
|
|
/// 2) Token definitions:
|
|
/// token TokenName = "regular expression" <attributes>;
|
|
/// discardtoken TokenName = "regular expression";
|
|
///
|
|
/// "discardtoken" means if such a token is identified, it will not appear in the lexical analyzing result. And you cannot refer to names of "discardtoken" in the grammar.
|
|
///
|
|
/// 3) Rule definitions:
|
|
/// rule RuleType RuleName <attributes>
|
|
/// = Grammar1
|
|
/// = Grammar2
|
|
/// ...
|
|
/// ;
|
|
///
|
|
/// It means rule "RuleName" is defined by those grammars, and matching this rule will create an instance of "RuleType" or its whatever types that inheriting "RuleType".
|
|
///
|
|
/// 4) Grammars:
|
|
/// RuleName: Defines an input that matches a rule.
|
|
/// TokenName: Defines an input that formed by the specified token.
|
|
/// "StringConstant": Defins an input that formed by exactly the string constant. This constant should define a token in the token list.
|
|
/// Grammar : FieldName: Defines an input that matches Grammar (should be either a rule name or a token name), and the result will be stored in field "FieldName" of a class, whose type will appear later.
|
|
/// !Grammar: Defines an input that matches Grammar, and the rule will return the result from this grammar. The input should still match other part of the rule, but result of other parts are ignored.
|
|
/// [Grammar]: Defines an input that, if match Grammar, will returns the result from that grammar; if not, the result is null.
|
|
/// {Grammar}: Defines an input that matches 0, 1 or more Grammar.
|
|
/// (Grammar): Defins an input that matches the the grammar. Brackets is only for changing operator associations.
|
|
/// Grammar1 Grammar2: Defines an input that should match Grammar1 right before Grammar2.
|
|
/// Grammar1 | Grammar2: Defines an input that match either Grammar1 or Grammar2.
|
|
/// Grammar as Type: Defines an input that matches the Grammar, and the whole branch of the rule creates an instance of type "Type"
|
|
/// Grammar with { FieldName = Value }: Defins an input that matches the Grammar, and will assign "Value", which should be an enum item, to the field "FieldName" of the created instance.
|
|
///
|
|
/// 5) Example
|
|
/// Here is an example to parse expression containing +, -, *, /, () and numbers:\
|
|
///
|
|
/// include:"Vlpp.h"
|
|
/// classPrefix:Calc
|
|
/// guard:VCZH_CALCULATOR_PARSER
|
|
/// namespace:vl.calculator
|
|
/// reflection:vl.calculator
|
|
/// parser:ParseExpression(Expr)
|
|
/// ambiguity:disabled
|
|
/// serialization:enabled
|
|
/// grammar:
|
|
///
|
|
/// class Expression
|
|
/// {
|
|
/// }
|
|
///
|
|
/// enum BinaryOperator
|
|
/// {
|
|
/// Add, Sub, Mul, Div,
|
|
/// }
|
|
///
|
|
/// class NumberExpression : Expression
|
|
/// {
|
|
/// token number;
|
|
/// }
|
|
///
|
|
/// class BinaryExpression : Expression
|
|
/// {
|
|
/// BinaryOperator op;
|
|
/// Expression left;
|
|
/// Expression right;
|
|
/// }
|
|
///
|
|
/// token ADD "\+"
|
|
/// token SUB "-"
|
|
/// token MUL "\*"
|
|
/// token DIV "\/"
|
|
/// token NUMBER "\d+(.\d+)?"
|
|
/// token OPEN "("
|
|
/// token CLOSE ")"
|
|
///
|
|
/// rule Expression Factor
|
|
/// = NUMBER : number as NumberExpression
|
|
/// = "(" !Expr ")"
|
|
/// ;
|
|
/// rule Expression Term
|
|
/// = !Factor
|
|
/// = Term : left "*" Factor : right as BinaryExpression with {op = "Mul"}
|
|
/// = Term : left "/" Factor : right as BinaryExpression with {op = "Div"}
|
|
/// ;
|
|
/// rule Expression Expr
|
|
/// = !Term
|
|
/// = Expr : left "+" Term : right as BinaryExpression with {op = "Add"}
|
|
/// = Expr : left "-" Term : right as BinaryExpression with {op = "Sub"}
|
|
/// ;
|
|
///
|
|
/// After using ParserGen.exe to generate C++ codes, you can do this:
|
|
/// auto table = CalcLoadTable(); // this table can be used several times, don't load each type for each parsing, it will have a big performance overhead.
|
|
/// List<Ptr<ParsingError>> errors;
|
|
/// auto expression = CalcParseExpression(L"(1+2) * (3+4)", table, errors); // it should be a Ptr<CalcExpression>, will returns nullptr if the input is wrong, with all errors filled into the "errors" variable.
|
|
/// You don't need to define the "errors" if you don't actually care how the input is wrong. There will be a overloaded version of CalcParseExpression that doesn't need the error list.
|
|
///
|
|
/// If you want to parse a wrong input and do automatic error recovering, which means if the input is not too wrong, you can still get a syntax tree, but some fields are null, with errors filled into the "error" variable. It will be a little complex:
|
|
/// auto table = CalcLoadTable(); // Load the table.
|
|
/// ParsingState state(L"(1+2) * (3+4)", table); // Initialize a state with the input and the table.
|
|
/// state.Reset(L"Expr"); // Set the rule to parse.
|
|
/// auto parser = CreateAutoRecoverParser(table); // Create an appropriate automatic error recoverable parser.
|
|
/// List<Ptr<ParsingError>> errors; // Define an error list.
|
|
/// auto node = parser->Parse(state, errors); // Parse to get an abstract syntax tree, which is a Ptr<ParsingTreeNode>.
|
|
/// if (node)
|
|
/// {
|
|
/// auto expression = CalcConvertParsingTreeNode(node, state.GetTokens()).Cast<CalcExpression>();
|
|
/// }
|
|
///
|
|
/// After you get a strong typed syntax tree, you can use the generated visitor interface to do something, like evaluate the results of the expression:
|
|
/// class Evaluator : public Object, public virtual CalcExpression::IVisitor
|
|
/// {
|
|
/// private:
|
|
/// double result;
|
|
///
|
|
/// double Call(CalcExpression* node)
|
|
/// {
|
|
/// node->Accept(this);
|
|
/// return result;
|
|
/// }
|
|
///
|
|
/// public:
|
|
///
|
|
/// static double Evaluate(CalcExpression* node)
|
|
/// {
|
|
/// return Evaluator().Call(node);
|
|
/// }
|
|
///
|
|
/// void Visit(CalcNumberExpression* node)override
|
|
/// {
|
|
/// return wtof(node->number.value);
|
|
/// }
|
|
///
|
|
/// void Visit(CalcBinaryExpression* node)override
|
|
/// {
|
|
/// auto left = Calc(node->left.Obj());
|
|
/// auto right = Calc(node->right.Obj());
|
|
/// switch (node->op)
|
|
/// {
|
|
/// case CalcBinaryOperator::Add:
|
|
/// result = left + right;
|
|
/// break;
|
|
/// case CalcBinaryOperator::Sub:
|
|
/// result = left 0 right;
|
|
/// break;
|
|
/// case CalcBinaryOperator::Mul:
|
|
/// result = left * right;
|
|
/// break;
|
|
/// case CalcBinaryOperator::Div:
|
|
/// result = left / right;
|
|
/// break;
|
|
/// }
|
|
/// }
|
|
/// };
|
|
///
|
|
/// Nullable<double> EvaluateExpression(const WString& input)
|
|
/// {
|
|
/// static auto table = CalcLoadTable();
|
|
/// auto expression = CalcParseExpression(input, table);
|
|
/// Nulllable<double> result;
|
|
/// if (expression)
|
|
/// {
|
|
/// result = Evaluator::Evaulate(expression.Obj());
|
|
/// }
|
|
/// return result;
|
|
/// }
|
|
///
|
|
/// ]]></summary>
|
|
class ParsingTable : public Object
|
|
{
|
|
public:
|
|
static const vint TokenBegin=0;
|
|
static const vint TokenFinish=1;
|
|
static const vint NormalReduce=2;
|
|
static const vint LeftRecursiveReduce=3;
|
|
static const vint UserTokenStart=4;
|
|
|
|
class AttributeInfo : public Object
|
|
{
|
|
public:
|
|
WString name;
|
|
collections::List<WString> arguments;
|
|
|
|
AttributeInfo(const WString& _name = L"")
|
|
:name(_name)
|
|
{
|
|
}
|
|
|
|
AttributeInfo* Argument(const WString& argument)
|
|
{
|
|
arguments.Add(argument);
|
|
return this;
|
|
}
|
|
};
|
|
|
|
class AttributeInfoList : public Object
|
|
{
|
|
public:
|
|
collections::List<Ptr<AttributeInfo>> attributes;
|
|
|
|
Ptr<AttributeInfo> FindFirst(const WString& name);
|
|
};
|
|
|
|
class TreeTypeInfo
|
|
{
|
|
public:
|
|
WString type;
|
|
vint attributeIndex;
|
|
|
|
TreeTypeInfo()
|
|
:attributeIndex(-1)
|
|
{
|
|
}
|
|
|
|
TreeTypeInfo(const WString& _type, vint _attributeIndex)
|
|
:type(_type)
|
|
,attributeIndex(_attributeIndex)
|
|
{
|
|
}
|
|
};
|
|
|
|
class TreeFieldInfo
|
|
{
|
|
public:
|
|
WString type;
|
|
WString field;
|
|
vint attributeIndex;
|
|
|
|
TreeFieldInfo()
|
|
:attributeIndex(-1)
|
|
{
|
|
}
|
|
|
|
TreeFieldInfo(const WString& _type, const WString& _field, vint _attributeIndex)
|
|
:type(_type)
|
|
,field(_field)
|
|
,attributeIndex(_attributeIndex)
|
|
{
|
|
}
|
|
};
|
|
|
|
class TokenInfo
|
|
{
|
|
public:
|
|
WString name;
|
|
WString regex;
|
|
vint regexTokenIndex;
|
|
vint attributeIndex;
|
|
|
|
TokenInfo()
|
|
:regexTokenIndex(-1)
|
|
,attributeIndex(-1)
|
|
{
|
|
}
|
|
|
|
TokenInfo(const WString& _name, const WString& _regex, vint _attributeIndex)
|
|
:name(_name)
|
|
,regex(_regex)
|
|
,regexTokenIndex(-1)
|
|
,attributeIndex(_attributeIndex)
|
|
{
|
|
}
|
|
};
|
|
|
|
class StateInfo
|
|
{
|
|
public:
|
|
WString ruleName;
|
|
WString stateName;
|
|
WString stateExpression;
|
|
|
|
WString ruleAmbiguousType; // filled in Initialize()
|
|
|
|
StateInfo()
|
|
{
|
|
}
|
|
|
|
StateInfo(const WString& _ruleName, const WString& _stateName, const WString& _stateExpression)
|
|
:ruleName(_ruleName)
|
|
,stateName(_stateName)
|
|
,stateExpression(_stateExpression)
|
|
{
|
|
}
|
|
};
|
|
|
|
class RuleInfo
|
|
{
|
|
public:
|
|
WString name;
|
|
WString type;
|
|
WString ambiguousType;
|
|
vint rootStartState;
|
|
vint attributeIndex;
|
|
|
|
RuleInfo()
|
|
:rootStartState(-1)
|
|
,attributeIndex(-1)
|
|
{
|
|
}
|
|
|
|
RuleInfo(const WString& _name, const WString& _type, const WString& _ambiguousType, vint _rootStartState, vint _attributeIndex)
|
|
:name(_name)
|
|
,type(_type)
|
|
,ambiguousType(_ambiguousType)
|
|
,rootStartState(_rootStartState)
|
|
,attributeIndex(_attributeIndex)
|
|
{
|
|
}
|
|
};
|
|
|
|
class Instruction
|
|
{
|
|
public:
|
|
enum InstructionType
|
|
{
|
|
Create,
|
|
Assign,
|
|
Item,
|
|
Using,
|
|
Setter,
|
|
Shift,
|
|
Reduce,
|
|
LeftRecursiveReduce,
|
|
};
|
|
|
|
InstructionType instructionType;
|
|
vint stateParameter;
|
|
WString nameParameter;
|
|
WString value;
|
|
WString creatorRule;
|
|
|
|
Instruction()
|
|
:instructionType(Create)
|
|
,stateParameter(0)
|
|
{
|
|
}
|
|
|
|
Instruction(InstructionType _instructionType, vint _stateParameter, const WString& _nameParameter, const WString& _value, const WString& _creatorRule)
|
|
:instructionType(_instructionType)
|
|
,stateParameter(_stateParameter)
|
|
,nameParameter(_nameParameter)
|
|
,value(_value)
|
|
,creatorRule(_creatorRule)
|
|
{
|
|
}
|
|
};
|
|
|
|
class LookAheadInfo
|
|
{
|
|
public:
|
|
collections::List<vint> tokens;
|
|
vint state;
|
|
|
|
LookAheadInfo()
|
|
:state(-1)
|
|
{
|
|
}
|
|
|
|
enum PrefixResult
|
|
{
|
|
Prefix,
|
|
Equal,
|
|
NotPrefix,
|
|
};
|
|
|
|
static PrefixResult TestPrefix(Ptr<LookAheadInfo> a, Ptr<LookAheadInfo> b);
|
|
static void WalkInternal(Ptr<ParsingTable> table, Ptr<LookAheadInfo> previous, vint state, collections::SortedList<vint>& walkedStates, collections::List<Ptr<LookAheadInfo>>& newInfos);
|
|
static void Walk(Ptr<ParsingTable> table, Ptr<LookAheadInfo> previous, vint state, collections::List<Ptr<LookAheadInfo>>& newInfos);
|
|
};
|
|
|
|
class TransitionItem
|
|
{
|
|
public:
|
|
vint token;
|
|
vint targetState;
|
|
collections::List<Ptr<LookAheadInfo>> lookAheads;
|
|
collections::List<vint> stackPattern;
|
|
collections::List<Instruction> instructions;
|
|
|
|
enum OrderResult
|
|
{
|
|
CorrectOrder,
|
|
WrongOrder,
|
|
SameOrder,
|
|
UnknownOrder,
|
|
};
|
|
|
|
TransitionItem(){}
|
|
|
|
TransitionItem(vint _token, vint _targetState)
|
|
:token(_token)
|
|
,targetState(_targetState)
|
|
{
|
|
}
|
|
|
|
static OrderResult CheckOrder(Ptr<TransitionItem> t1, Ptr<TransitionItem> t2, OrderResult defaultResult = UnknownOrder);
|
|
static vint Compare(Ptr<TransitionItem> t1, Ptr<TransitionItem> t2, OrderResult defaultResult);
|
|
};
|
|
|
|
class TransitionBag
|
|
{
|
|
public:
|
|
collections::List<Ptr<TransitionItem>> transitionItems;
|
|
};
|
|
|
|
protected:
|
|
// metadata
|
|
bool ambiguity;
|
|
collections::Array<Ptr<AttributeInfoList>> attributeInfos;
|
|
collections::Array<TreeTypeInfo> treeTypeInfos;
|
|
collections::Array<TreeFieldInfo> treeFieldInfos;
|
|
|
|
// LALR table
|
|
vint tokenCount; // tokenInfos.Count() + discardTokenInfos.Count()
|
|
vint stateCount; // stateInfos.Count()
|
|
collections::Array<TokenInfo> tokenInfos;
|
|
collections::Array<TokenInfo> discardTokenInfos;
|
|
collections::Array<StateInfo> stateInfos;
|
|
collections::Array<RuleInfo> ruleInfos;
|
|
collections::Array<Ptr<TransitionBag>> transitionBags;
|
|
|
|
// generated data
|
|
Ptr<regex::RegexLexer> lexer;
|
|
collections::Dictionary<WString, vint> ruleMap;
|
|
collections::Dictionary<WString, vint> treeTypeInfoMap;
|
|
collections::Dictionary<collections::Pair<WString, WString>, vint> treeFieldInfoMap;
|
|
|
|
template<typename TIO>
|
|
void IO(TIO& io);
|
|
|
|
public:
|
|
ParsingTable(vint _attributeInfoCount, vint _treeTypeInfoCount, vint _treeFieldInfoCount, vint _tokenCount, vint _discardTokenCount, vint _stateCount, vint _ruleCount);
|
|
/// <summary>Deserialize the parsing table from a stream. <see cref="Initialize"/> should be before using this table.</summary>
|
|
/// <param name="input">The stream.</param>
|
|
ParsingTable(stream::IStream& input);
|
|
~ParsingTable();
|
|
|
|
/// <summary>Serialize the parsing table to a stream.</summary>
|
|
/// <param name="output">The stream.</param>
|
|
void Serialize(stream::IStream& output);
|
|
|
|
bool GetAmbiguity();
|
|
void SetAmbiguity(bool value);
|
|
|
|
vint GetAttributeInfoCount();
|
|
Ptr<AttributeInfoList> GetAttributeInfo(vint index);
|
|
void SetAttributeInfo(vint index, Ptr<AttributeInfoList> info);
|
|
|
|
vint GetTreeTypeInfoCount();
|
|
const TreeTypeInfo& GetTreeTypeInfo(vint index);
|
|
const TreeTypeInfo& GetTreeTypeInfo(const WString& type);
|
|
void SetTreeTypeInfo(vint index, const TreeTypeInfo& info);
|
|
|
|
vint GetTreeFieldInfoCount();
|
|
const TreeFieldInfo& GetTreeFieldInfo(vint index);
|
|
const TreeFieldInfo& GetTreeFieldInfo(const WString& type, const WString& field);
|
|
void SetTreeFieldInfo(vint index, const TreeFieldInfo& info);
|
|
|
|
vint GetTokenCount();
|
|
const TokenInfo& GetTokenInfo(vint token);
|
|
void SetTokenInfo(vint token, const TokenInfo& info);
|
|
|
|
vint GetDiscardTokenCount();
|
|
const TokenInfo& GetDiscardTokenInfo(vint token);
|
|
void SetDiscardTokenInfo(vint token, const TokenInfo& info);
|
|
|
|
vint GetStateCount();
|
|
const StateInfo& GetStateInfo(vint state);
|
|
void SetStateInfo(vint state, const StateInfo& info);
|
|
|
|
vint GetRuleCount();
|
|
const RuleInfo& GetRuleInfo(const WString& ruleName);
|
|
const RuleInfo& GetRuleInfo(vint rule);
|
|
void SetRuleInfo(vint rule, const RuleInfo& info);
|
|
|
|
const regex::RegexLexer& GetLexer();
|
|
Ptr<TransitionBag> GetTransitionBag(vint state, vint token);
|
|
void SetTransitionBag(vint state, vint token, Ptr<TransitionBag> bag);
|
|
/// <summary>Initialize the parsing table. This function should be called after deserializing the table from a string.</summary>
|
|
void Initialize();
|
|
bool IsInputToken(vint regexTokenIndex);
|
|
vint GetTableTokenIndex(vint regexTokenIndex);
|
|
vint GetTableDiscardTokenIndex(vint regexTokenIndex);
|
|
};
|
|
|
|
/***********************************************************************
|
|
Helper Functions
|
|
***********************************************************************/
|
|
|
|
extern void Log(Ptr<ParsingTable> table, stream::TextWriter& writer);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\PARSINGAUTOMATON.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parsing::Automaton
|
|
|
|
Classes:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_PARSINGAUTOMATON
|
|
#define VCZH_PARSING_PARSINGAUTOMATON
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace analyzing
|
|
{
|
|
|
|
/***********************************************************************
|
|
Automaton
|
|
***********************************************************************/
|
|
|
|
class Action;
|
|
class Transition;
|
|
class State;
|
|
|
|
class Action : public Object
|
|
{
|
|
public:
|
|
enum ActionType
|
|
{
|
|
Create, // new source
|
|
Assign, // source ::= <created symbol>
|
|
Using, // use <created symbol>
|
|
Setter, // source ::= target
|
|
Shift,
|
|
Reduce,
|
|
LeftRecursiveReduce,
|
|
};
|
|
|
|
ActionType actionType;
|
|
ParsingSymbol* actionTarget;
|
|
ParsingSymbol* actionSource;
|
|
definitions::ParsingDefinitionRuleDefinition* creatorRule;
|
|
|
|
// the following two fields record which rule symbol transition generate this shift/reduce action
|
|
State* shiftReduceSource;
|
|
State* shiftReduceTarget;
|
|
|
|
Action();
|
|
~Action();
|
|
};
|
|
|
|
class Transition : public Object
|
|
{
|
|
public:
|
|
enum TransitionType
|
|
{
|
|
TokenBegin, // token stream start
|
|
TokenFinish, // token stream end
|
|
NormalReduce, // rule end
|
|
LeftRecursiveReduce, // rule end with left recursive
|
|
Epsilon, // an epsilon transition
|
|
Symbol, // a syntax symbol
|
|
};
|
|
|
|
enum StackOperationType
|
|
{
|
|
None,
|
|
ShiftReduceCompacted,
|
|
LeftRecursive,
|
|
};
|
|
|
|
State* source;
|
|
State* target;
|
|
collections::List<Ptr<Action>> actions;
|
|
|
|
TransitionType transitionType;
|
|
StackOperationType stackOperationType;
|
|
ParsingSymbol* transitionSymbol;
|
|
|
|
Transition();
|
|
~Transition();
|
|
|
|
static bool IsEquivalent(Transition* t1, Transition* t2, bool careSourceAndTarget);
|
|
};
|
|
|
|
class State : public Object
|
|
{
|
|
public:
|
|
enum StatePosition
|
|
{
|
|
BeforeNode,
|
|
AfterNode,
|
|
};
|
|
|
|
collections::List<Transition*> transitions;
|
|
collections::List<Transition*> inputs;
|
|
bool endState;
|
|
|
|
ParsingSymbol* ownerRuleSymbol;
|
|
definitions::ParsingDefinitionRuleDefinition* ownerRule;
|
|
definitions::ParsingDefinitionGrammar* grammarNode;
|
|
definitions::ParsingDefinitionGrammar* stateNode;
|
|
StatePosition statePosition;
|
|
WString stateName;
|
|
WString stateExpression;
|
|
|
|
State();
|
|
~State();
|
|
};
|
|
|
|
class RuleInfo : public Object
|
|
{
|
|
public:
|
|
State* rootRuleStartState;
|
|
State* rootRuleEndState;
|
|
State* startState;
|
|
collections::List<State*> endStates;
|
|
int stateNameCount;
|
|
|
|
RuleInfo();
|
|
~RuleInfo();
|
|
};
|
|
|
|
class Automaton : public Object
|
|
{
|
|
typedef collections::List<definitions::ParsingDefinitionRuleDefinition*> RuleDefList;
|
|
typedef collections::Dictionary<definitions::ParsingDefinitionRuleDefinition*, Ptr<RuleInfo>> RuleInfoMap;
|
|
public:
|
|
ParsingSymbolManager* symbolManager;
|
|
collections::List<Ptr<Transition>> transitions;
|
|
collections::List<Ptr<State>> states;
|
|
collections::List<Ptr<RuleInfo>> ruleInfos;
|
|
|
|
RuleDefList orderedRulesDefs;
|
|
RuleInfoMap ruleDefToInfoMap;
|
|
|
|
Automaton(ParsingSymbolManager* _symbolManager);
|
|
~Automaton();
|
|
|
|
void AddRuleInfo(definitions::ParsingDefinitionRuleDefinition* rule, Ptr<RuleInfo> ruleInfo);
|
|
|
|
State* RuleStartState(definitions::ParsingDefinitionRuleDefinition* ownerRule);
|
|
State* RootRuleStartState(definitions::ParsingDefinitionRuleDefinition* ownerRule);
|
|
State* RootRuleEndState(definitions::ParsingDefinitionRuleDefinition* ownerRule);
|
|
State* StartState(definitions::ParsingDefinitionRuleDefinition* ownerRule, definitions::ParsingDefinitionGrammar* grammarNode, definitions::ParsingDefinitionGrammar* stateNode);
|
|
State* EndState(definitions::ParsingDefinitionRuleDefinition* ownerRule, definitions::ParsingDefinitionGrammar* grammarNode, definitions::ParsingDefinitionGrammar* stateNode);
|
|
State* CopyState(State* oldState);
|
|
|
|
Transition* CreateTransition(State* start, State* end);
|
|
Transition* TokenBegin(State* start, State* end);
|
|
Transition* TokenFinish(State* start, State* end);
|
|
Transition* NormalReduce(State* start, State* end);
|
|
Transition* LeftRecursiveReduce(State* start, State* end);
|
|
Transition* Epsilon(State* start, State* end);
|
|
Transition* Symbol(State* start, State* end, ParsingSymbol* transitionSymbol);
|
|
Transition* CopyTransition(State* start, State* end, Transition* oldTransition);
|
|
|
|
void DeleteTransition(Transition* transition);
|
|
void DeleteState(State* state);
|
|
};
|
|
|
|
/***********************************************************************
|
|
Helper: Closuer Searching
|
|
***********************************************************************/
|
|
|
|
struct ClosureItem
|
|
{
|
|
enum SearchResult
|
|
{
|
|
Continue,
|
|
Hit,
|
|
Blocked,
|
|
};
|
|
|
|
State* state; // target state of one path of a closure
|
|
Ptr<collections::List<Transition*>> transitions; // path
|
|
bool cycle; // true: invalid closure because there are cycles, and in the middle of the path there will be a transition that targets to the state field.
|
|
|
|
ClosureItem()
|
|
:state(0)
|
|
,cycle(false)
|
|
{
|
|
}
|
|
|
|
ClosureItem(State* _state, Ptr<collections::List<Transition*>> _transitions, bool _cycle)
|
|
:state(_state)
|
|
,transitions(_transitions)
|
|
,cycle(_cycle)
|
|
{
|
|
}
|
|
};
|
|
|
|
extern void SearchClosure(ClosureItem::SearchResult(*closurePredicate)(Transition*), State* startState, collections::List<ClosureItem>& closure);
|
|
extern void RemoveEpsilonTransitions(collections::Dictionary<State*, State*>& oldNewStateMap, collections::List<State*>& scanningStates, Ptr<Automaton> automaton);
|
|
|
|
/***********************************************************************
|
|
Helper: State Merging
|
|
***********************************************************************/
|
|
|
|
extern void DeleteUnnecessaryStates(Ptr<Automaton> automaton, Ptr<RuleInfo> ruleInfo, collections::List<State*>& newStates);
|
|
extern void MergeStates(Ptr<Automaton> automaton, Ptr<RuleInfo> ruleInfo, collections::List<State*>& newStates);
|
|
|
|
/***********************************************************************
|
|
Helper: Automaton Building
|
|
***********************************************************************/
|
|
|
|
extern Ptr<Automaton> CreateEpsilonPDA(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager);
|
|
extern Ptr<Automaton> CreateNondeterministicPDAFromEpsilonPDA(Ptr<Automaton> epsilonPDA);
|
|
extern Ptr<Automaton> CreateJointPDAFromNondeterministicPDA(Ptr<Automaton> nondeterministicPDA);
|
|
extern void CompactJointPDA(Ptr<Automaton> jointPDA);
|
|
extern void MarkLeftRecursiveInJointPDA(Ptr<Automaton> jointPDA, collections::List<Ptr<ParsingError>>& errors);
|
|
|
|
/***********************************************************************
|
|
Helper: Parsing Table Generating
|
|
***********************************************************************/
|
|
|
|
extern WString GetTypeNameForCreateInstruction(ParsingSymbol* type);
|
|
extern Ptr<tabling::ParsingTable> GenerateTableFromPDA(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, Ptr<Automaton> jointPDA, bool enableAmbiguity, collections::List<Ptr<ParsingError>>& errors);
|
|
extern Ptr<tabling::ParsingTable> GenerateTable(Ptr<definitions::ParsingDefinition> definition, bool enableAmbiguity, collections::List<Ptr<ParsingError>>& errors);
|
|
extern void Log(Ptr<Automaton> automaton, stream::TextWriter& writer);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\PARSINGSTATE.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parsing::State
|
|
|
|
Classes:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_PARSINGSTATE
|
|
#define VCZH_PARSING_PARSINGSTATE
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace tabling
|
|
{
|
|
|
|
/***********************************************************************
|
|
Syntax Analyzer
|
|
***********************************************************************/
|
|
|
|
class ParsingTokenWalker : public Object
|
|
{
|
|
protected:
|
|
class LookAheadEnumerator : public Object, public collections::IEnumerator<vint>
|
|
{
|
|
protected:
|
|
const ParsingTokenWalker* walker;
|
|
vint firstToken;
|
|
vint currentToken;
|
|
vint currentValue;
|
|
vint index;
|
|
|
|
public:
|
|
LookAheadEnumerator(const ParsingTokenWalker* _walker, vint _currentToken);
|
|
LookAheadEnumerator(const LookAheadEnumerator& _enumerator);
|
|
|
|
collections::IEnumerator<vint>* Clone()const override;
|
|
const vint& Current()const override;
|
|
vint Index()const override;
|
|
bool Next()override;
|
|
void Reset()override;
|
|
};
|
|
|
|
class TokenLookAhead : public Object, public collections::IEnumerable<vint>
|
|
{
|
|
protected:
|
|
const ParsingTokenWalker* walker;
|
|
public:
|
|
TokenLookAhead(const ParsingTokenWalker* _talker);
|
|
|
|
collections::IEnumerator<vint>* CreateEnumerator()const override;
|
|
};
|
|
|
|
class ReduceLookAhead : public Object, public collections::IEnumerable<vint>
|
|
{
|
|
protected:
|
|
const ParsingTokenWalker* walker;
|
|
public:
|
|
ReduceLookAhead(const ParsingTokenWalker* _walker);
|
|
|
|
collections::IEnumerator<vint>* CreateEnumerator()const override;
|
|
};
|
|
|
|
protected:
|
|
collections::List<regex::RegexToken>& tokens;
|
|
Ptr<ParsingTable> table;
|
|
vint currentToken;
|
|
TokenLookAhead tokenLookAhead;
|
|
ReduceLookAhead reduceLookAhead;
|
|
|
|
vint GetNextIndex(vint index)const;
|
|
vint GetTableTokenIndex(vint index)const;
|
|
public:
|
|
ParsingTokenWalker(collections::List<regex::RegexToken>& _tokens, Ptr<ParsingTable> _table);
|
|
~ParsingTokenWalker();
|
|
|
|
const collections::IEnumerable<vint>& GetTokenLookahead()const;
|
|
const collections::IEnumerable<vint>& GetReduceLookahead()const;
|
|
void Reset();
|
|
bool Move();
|
|
vint GetTableTokenIndex()const;
|
|
regex::RegexToken* GetRegexToken()const;
|
|
vint GetTokenIndexInStream()const;
|
|
};
|
|
|
|
class ParsingState : public Object
|
|
{
|
|
public:
|
|
struct ShiftReduceRange
|
|
{
|
|
regex::RegexToken* shiftToken;
|
|
regex::RegexToken* reduceToken;
|
|
|
|
ShiftReduceRange()
|
|
:shiftToken(0)
|
|
,reduceToken(0)
|
|
{
|
|
}
|
|
};
|
|
|
|
struct TransitionResult
|
|
{
|
|
enum TransitionType
|
|
{
|
|
ExecuteInstructions,
|
|
AmbiguityBegin,
|
|
AmbiguityBranch,
|
|
AmbiguityEnd,
|
|
SkipToken,
|
|
};
|
|
|
|
TransitionType transitionType;
|
|
vint ambiguityAffectedStackNodeCount;
|
|
WString ambiguityNodeType;
|
|
|
|
vint tableTokenIndex;
|
|
vint tableStateSource;
|
|
vint tableStateTarget;
|
|
vint tokenIndexInStream;
|
|
regex::RegexToken* token;
|
|
|
|
ParsingTable::TransitionItem* transition;
|
|
vint instructionBegin;
|
|
vint instructionCount;
|
|
Ptr<collections::List<ShiftReduceRange>> shiftReduceRanges;
|
|
|
|
TransitionResult(TransitionType _transitionType=ExecuteInstructions)
|
|
:transitionType(_transitionType)
|
|
,ambiguityAffectedStackNodeCount(0)
|
|
,tableTokenIndex(-1)
|
|
,tableStateSource(-1)
|
|
,tableStateTarget(-1)
|
|
,tokenIndexInStream(-1)
|
|
,token(0)
|
|
,transition(0)
|
|
,instructionBegin(-1)
|
|
,instructionCount(-1)
|
|
{
|
|
}
|
|
|
|
operator bool()const
|
|
{
|
|
return transitionType!=ExecuteInstructions || transition!=0;
|
|
}
|
|
|
|
void AddShiftReduceRange(regex::RegexToken* shiftToken, regex::RegexToken* reduceToken)
|
|
{
|
|
ShiftReduceRange range;
|
|
range.shiftToken=shiftToken;
|
|
range.reduceToken=reduceToken;
|
|
if(!shiftReduceRanges)
|
|
{
|
|
shiftReduceRanges=new collections::List<ShiftReduceRange>();
|
|
}
|
|
shiftReduceRanges->Add(range);
|
|
}
|
|
};
|
|
|
|
struct Future
|
|
{
|
|
vint currentState;
|
|
vint reduceStateCount;
|
|
collections::List<vint> shiftStates;
|
|
regex::RegexToken* selectedRegexToken;
|
|
vint selectedToken;
|
|
ParsingTable::TransitionItem* selectedItem;
|
|
Future* previous;
|
|
Future* next;
|
|
|
|
Future()
|
|
:currentState(-1)
|
|
,reduceStateCount(0)
|
|
,selectedRegexToken(0)
|
|
,selectedToken(-1)
|
|
,selectedItem(0)
|
|
,previous(0)
|
|
,next(0)
|
|
{
|
|
}
|
|
|
|
Future* Clone()
|
|
{
|
|
Future* future = new Future;
|
|
future->currentState = currentState;
|
|
future->reduceStateCount = reduceStateCount;
|
|
CopyFrom(future->shiftStates, shiftStates);
|
|
future->selectedRegexToken = selectedRegexToken;
|
|
future->selectedToken = selectedToken;
|
|
future->selectedItem = selectedItem;
|
|
future->previous = previous;
|
|
return future;
|
|
}
|
|
};
|
|
|
|
struct StateGroup
|
|
{
|
|
collections::List<vint> stateStack;
|
|
vint currentState;
|
|
vint tokenSequenceIndex;
|
|
|
|
collections::List<regex::RegexToken*> shiftTokenStack;
|
|
regex::RegexToken* shiftToken;
|
|
regex::RegexToken* reduceToken;
|
|
|
|
StateGroup();
|
|
StateGroup(const ParsingTable::RuleInfo& info);
|
|
StateGroup(const StateGroup& group);
|
|
};
|
|
private:
|
|
WString input;
|
|
Ptr<ParsingTable> table;
|
|
collections::List<regex::RegexToken> tokens;
|
|
Ptr<ParsingTokenWalker> walker;
|
|
|
|
WString parsingRule;
|
|
vint parsingRuleStartState;
|
|
Ptr<StateGroup> stateGroup;
|
|
public:
|
|
ParsingState(const WString& _input, Ptr<ParsingTable> _table, vint codeIndex=-1);
|
|
~ParsingState();
|
|
|
|
const WString& GetInput();
|
|
Ptr<ParsingTable> GetTable();
|
|
const collections::List<regex::RegexToken>& GetTokens();
|
|
regex::RegexToken* GetToken(vint index);
|
|
|
|
vint Reset(const WString& rule);
|
|
WString GetParsingRule();
|
|
vint GetParsingRuleStartState();
|
|
vint GetCurrentToken();
|
|
vint GetCurrentTableTokenIndex();
|
|
const collections::List<vint>& GetStateStack();
|
|
vint GetCurrentState();
|
|
void SkipCurrentToken();
|
|
|
|
bool TestTransitionItemInFuture(vint tableTokenIndex, Future* future, ParsingTable::TransitionItem* item, const collections::IEnumerable<vint>* lookAheadTokens);
|
|
ParsingTable::TransitionItem* MatchTokenInFuture(vint tableTokenIndex, Future* future, const collections::IEnumerable<vint>* lookAheadTokens);
|
|
ParsingTable::TransitionItem* MatchToken(vint tableTokenIndex, const collections::IEnumerable<vint>* lookAheadTokens);
|
|
void RunTransitionInFuture(ParsingTable::TransitionItem* transition, Future* previous, Future* now);
|
|
ParsingState::TransitionResult RunTransition(ParsingTable::TransitionItem* transition, regex::RegexToken* regexToken, vint instructionBegin, vint instructionCount, bool lastPart);
|
|
ParsingState::TransitionResult RunTransition(ParsingTable::TransitionItem* transition, regex::RegexToken* regexToken);
|
|
|
|
bool ReadTokenInFuture(vint tableTokenIndex, Future* previous, Future* now, const collections::IEnumerable<vint>* lookAheadTokens);
|
|
TransitionResult ReadToken(vint tableTokenIndex, regex::RegexToken* regexToken, const collections::IEnumerable<vint>* lookAheadTokens);
|
|
TransitionResult ReadToken();
|
|
|
|
bool TestExplore(vint tableTokenIndex, Future* previous);
|
|
bool Explore(vint tableTokenIndex, Future* previous, collections::List<Future*>& possibilities);
|
|
bool ExploreStep(collections::List<Future*>& previousFutures, vint start, vint count, collections::List<Future*>& possibilities);
|
|
bool ExploreNormalReduce(collections::List<Future*>& previousFutures, vint start, vint count, collections::List<Future*>& possibilities);
|
|
bool ExploreLeftRecursiveReduce(collections::List<Future*>& previousFutures, vint start, vint count, collections::List<Future*>& possibilities);
|
|
Future* ExploreCreateRootFuture();
|
|
|
|
Ptr<StateGroup> TakeSnapshot();
|
|
void RestoreSnapshot(Ptr<StateGroup> group);
|
|
};
|
|
|
|
/***********************************************************************
|
|
AST Generating
|
|
***********************************************************************/
|
|
|
|
class ParsingTransitionProcessor : public Object
|
|
{
|
|
public:
|
|
virtual void Reset()=0;
|
|
virtual bool Run(const ParsingState::TransitionResult& result)=0;
|
|
virtual bool GetProcessingAmbiguityBranch()=0;
|
|
};
|
|
|
|
class ParsingTreeBuilder : public ParsingTransitionProcessor
|
|
{
|
|
protected:
|
|
Ptr<ParsingTreeNode> createdObject;
|
|
Ptr<ParsingTreeObject> operationTarget;
|
|
collections::List<Ptr<ParsingTreeObject>> nodeStack;
|
|
|
|
bool processingAmbiguityBranch;
|
|
Ptr<ParsingTreeNode> ambiguityBranchCreatedObject;
|
|
Ptr<ParsingTreeNode> ambiguityBranchOperationTarget;
|
|
vint ambiguityBranchSharedNodeCount;
|
|
collections::List<Ptr<ParsingTreeObject>> ambiguityBranchNodeStack;
|
|
collections::List<Ptr<ParsingTreeObject>> ambiguityNodes;
|
|
public:
|
|
ParsingTreeBuilder();
|
|
~ParsingTreeBuilder();
|
|
|
|
void Reset()override;
|
|
bool Run(const ParsingState::TransitionResult& result)override;
|
|
bool GetProcessingAmbiguityBranch()override;
|
|
Ptr<ParsingTreeObject> GetNode()const;
|
|
};
|
|
|
|
class ParsingTransitionCollector : public ParsingTransitionProcessor
|
|
{
|
|
typedef collections::List<ParsingState::TransitionResult> TransitionResultList;
|
|
protected:
|
|
vint ambiguityBegin;
|
|
TransitionResultList transitions;
|
|
|
|
collections::Dictionary<vint, vint> ambiguityBeginToEnds;
|
|
collections::Group<vint, vint> ambiguityBeginToBranches;
|
|
collections::Dictionary<vint, vint> ambiguityBranchToBegins;
|
|
public:
|
|
ParsingTransitionCollector();
|
|
~ParsingTransitionCollector();
|
|
|
|
void Reset()override;
|
|
bool Run(const ParsingState::TransitionResult& result)override;
|
|
bool GetProcessingAmbiguityBranch()override;
|
|
|
|
const TransitionResultList& GetTransitions()const;
|
|
vint GetAmbiguityEndFromBegin(vint transitionIndex)const;
|
|
const collections::List<vint>& GetAmbiguityBranchesFromBegin(vint transitionIndex)const;
|
|
vint GetAmbiguityBeginFromBranch(vint transitionIndex)const;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\PARSING.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parsing::Parser
|
|
|
|
Classes:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_PARSING
|
|
#define VCZH_PARSING_PARSING
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace tabling
|
|
{
|
|
|
|
/***********************************************************************
|
|
Parser
|
|
***********************************************************************/
|
|
|
|
/// <summary>Base type of all parser strategy.</summary>
|
|
class ParsingGeneralParser : public Object
|
|
{
|
|
protected:
|
|
Ptr<ParsingTable> table;
|
|
|
|
public:
|
|
ParsingGeneralParser(Ptr<ParsingTable> _table);
|
|
~ParsingGeneralParser();
|
|
|
|
/// <summary>Get the parser table that used to do the parsing.</summary>
|
|
/// <returns>The parser table that used to do the parsing.</returns>
|
|
Ptr<ParsingTable> GetTable();
|
|
/// <summary>Initialization. It should be called before each time of parsing.</summary>
|
|
virtual void BeginParse();
|
|
virtual ParsingState::TransitionResult ParseStep(ParsingState& state, collections::List<Ptr<ParsingError>>& errors)=0;
|
|
bool Parse(ParsingState& state, ParsingTransitionProcessor& processor, collections::List<Ptr<ParsingError>>& errors);
|
|
Ptr<ParsingTreeNode> Parse(ParsingState& state, collections::List<Ptr<ParsingError>>& errors);
|
|
/// <summary>Parse an input and get an abstract syntax tree if no error happens or all errors are recovered.</summary>
|
|
/// <returns>The abstract syntax tree.</returns>
|
|
/// <param name="input">The input to parse.</param>
|
|
/// <param name="rule">The name of the rule that used to parse the input.</param>
|
|
/// <param name="errors">Returns all errors.</param>
|
|
/// <param name="codeIndex">The code index to differentiate each input. This value will be stored in every tokens and abstract syntax nodes.</param>
|
|
Ptr<ParsingTreeNode> Parse(const WString& input, const WString& rule, collections::List<Ptr<ParsingError>>& errors, vint codeIndex = -1);
|
|
};
|
|
|
|
/***********************************************************************
|
|
Parser with different strategies
|
|
***********************************************************************/
|
|
|
|
/// <summary>A strict parse. It doesn't allow ambiguity and error recovery.</summary>
|
|
class ParsingStrictParser : public ParsingGeneralParser
|
|
{
|
|
protected:
|
|
|
|
virtual bool OnTestErrorRecoverExists();
|
|
virtual void OnClearErrorRecover();
|
|
virtual ParsingState::TransitionResult OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<Ptr<ParsingError>>& errors);
|
|
public:
|
|
/// <summary>Create the parse using a parsing table.</summary>
|
|
/// <param name="_table">The parsing table.</param>
|
|
ParsingStrictParser(Ptr<ParsingTable> _table=0);
|
|
~ParsingStrictParser();
|
|
|
|
ParsingState::TransitionResult ParseStep(ParsingState& state, collections::List<Ptr<ParsingError>>& errors)override;
|
|
};
|
|
|
|
/// <summary>A strict parse. It doesn't allow ambiguity but allows error recovery.</summary>
|
|
class ParsingAutoRecoverParser : public ParsingStrictParser
|
|
{
|
|
public:
|
|
struct RecoverFuture
|
|
{
|
|
ParsingState::Future* future;
|
|
vint insertedTokenCount;
|
|
vint index;
|
|
vint previousIndex;
|
|
vint nextIndex;
|
|
|
|
RecoverFuture()
|
|
:future(0)
|
|
, insertedTokenCount(0)
|
|
, index(-1)
|
|
, previousIndex(-1)
|
|
, nextIndex(-1)
|
|
{
|
|
}
|
|
};
|
|
protected:
|
|
vint maxInsertedTokenCount;
|
|
collections::List<RecoverFuture> recoverFutures;
|
|
vint recoveringFutureIndex;
|
|
|
|
RecoverFuture& GetRecoverFuture(vint index);
|
|
RecoverFuture& CreateRecoverFuture(vint index, vint previousIndex);
|
|
bool OnTestErrorRecoverExists()override;
|
|
void OnClearErrorRecover()override;
|
|
ParsingState::TransitionResult OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<Ptr<ParsingError>>& errors)override;
|
|
public:
|
|
/// <summary>Create the parse using a parsing table.</summary>
|
|
/// <param name="_table">The parsing table.</param>
|
|
/// <param name="_maxInsertedTokenCount">The maximum number of tokens that allow to insert to recover an error.</param>
|
|
ParsingAutoRecoverParser(Ptr<ParsingTable> _table = 0, vint _maxInsertedTokenCount = -1);
|
|
~ParsingAutoRecoverParser();
|
|
|
|
void BeginParse()override;
|
|
};
|
|
|
|
/// <summary>A strict parse. It allows ambiguity but doesn't allow error recovery.</summary>
|
|
class ParsingAmbiguousParser : public ParsingGeneralParser
|
|
{
|
|
typedef collections::List<ParsingState::TransitionResult> DecisionList;
|
|
protected:
|
|
|
|
DecisionList decisions;
|
|
vint consumedDecisionCount;
|
|
|
|
virtual void OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<ParsingState::Future*>& futures, vint& begin, vint& end, collections::List<Ptr<ParsingError>>& errors);
|
|
vint GetResolvableFutureLevels(collections::List<ParsingState::Future*>& futures, vint begin, vint end);
|
|
vint SearchPathForOneStep(ParsingState& state, collections::List<ParsingState::Future*>& futures, vint& begin, vint& end, collections::List<Ptr<ParsingError>>& errors);
|
|
vint GetConflictReduceCount(collections::List<ParsingState::Future*>& futures);
|
|
void GetConflictReduceIndices(collections::List<ParsingState::Future*>& futures, vint conflictReduceCount, collections::Array<vint>& conflictReduceIndices);
|
|
vint GetAffectedStackNodeCount(collections::List<ParsingState::Future*>& futures, collections::Array<vint>& conflictReduceIndices);
|
|
void BuildSingleDecisionPath(ParsingState& state, ParsingState::Future* future, vint lastAvailableInstructionCount);
|
|
void BuildAmbiguousDecisions(ParsingState& state, collections::List<ParsingState::Future*>& futures, vint begin, vint end, vint resolvableFutureLevels, collections::List<Ptr<ParsingError>>& errors);
|
|
void BuildDecisions(ParsingState& state, collections::List<ParsingState::Future*>& futures, vint begin, vint end, vint resolvableFutureLevels, collections::List<Ptr<ParsingError>>& errors);
|
|
public:
|
|
/// <summary>Create the parse using a parsing table.</summary>
|
|
/// <param name="_table">The parsing table.</param>
|
|
ParsingAmbiguousParser(Ptr<ParsingTable> _table=0);
|
|
~ParsingAmbiguousParser();
|
|
|
|
ParsingState::TransitionResult ParseStep(ParsingState& state, collections::List<Ptr<ParsingError>>& errors)override;
|
|
void BeginParse()override;
|
|
};
|
|
|
|
/// <summary>A strict parse. It allow both ambiguity and error recovery.</summary>
|
|
class ParsingAutoRecoverAmbiguousParser : public ParsingAmbiguousParser
|
|
{
|
|
protected:
|
|
vint maxInsertedTokenCount;
|
|
|
|
void OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<ParsingState::Future*>& futures, vint& begin, vint& end, collections::List<Ptr<ParsingError>>& errors)override;
|
|
public:
|
|
/// <summary>Create the parse using a parsing table.</summary>
|
|
/// <param name="_table">The parsing table.</param>
|
|
/// <param name="_maxInsertedTokenCount">The maximum number of tokens that allow to insert to recover an error.</param>
|
|
ParsingAutoRecoverAmbiguousParser(Ptr<ParsingTable> _table = 0, vint _maxInsertedTokenCount = -1);
|
|
~ParsingAutoRecoverAmbiguousParser();
|
|
};
|
|
|
|
/***********************************************************************
|
|
Helper Functions
|
|
***********************************************************************/
|
|
|
|
/// <summary>Create the correct strict parser from a parsing table.</summary>
|
|
/// <returns>The created parse.</returns>
|
|
/// <param name="table">The table to create a parser.</param>
|
|
extern Ptr<ParsingGeneralParser> CreateStrictParser(Ptr<ParsingTable> table);
|
|
/// <summary>Create the correct error recoverable parser from a parsing table.</summary>
|
|
/// <returns>The created parse.</returns>
|
|
/// <param name="table">The table to create a parser.</param>
|
|
extern Ptr<ParsingGeneralParser> CreateAutoRecoverParser(Ptr<ParsingTable> table);
|
|
/// <summary>Create the correct strict parser to parse the grammar itself.</summary>
|
|
/// <returns>The created parse.</returns>
|
|
extern Ptr<ParsingGeneralParser> CreateBootstrapStrictParser();
|
|
/// <summary>Create the correct error recoverable to parse the grammar itself.</summary>
|
|
/// <returns>The created parse.</returns>
|
|
extern Ptr<ParsingGeneralParser> CreateBootstrapAutoRecoverParser();
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
Reflection for AST
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
#define PARSINGREFLECTION_TYPELIST(F)\
|
|
F(parsing::ParsingTextPos)\
|
|
F(parsing::ParsingTextRange)\
|
|
F(parsing::ParsingTreeNode)\
|
|
F(parsing::ParsingTreeToken)\
|
|
F(parsing::ParsingTreeObject)\
|
|
F(parsing::ParsingTreeArray)\
|
|
F(parsing::ParsingTreeCustomBase)\
|
|
F(parsing::ParsingToken)\
|
|
F(parsing::ParsingError)\
|
|
|
|
PARSINGREFLECTION_TYPELIST(DECL_TYPE_INFO)
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
extern bool LoadParsingTypes();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\JSON\PARSINGJSON_AST.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parser::ParsingJson.parser.txt
|
|
|
|
This file is generated by: Vczh Parser Generator
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_JSON_PARSINGJSON_PARSER_AST
|
|
#define VCZH_PARSING_JSON_PARSINGJSON_PARSER_AST
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace json
|
|
{
|
|
enum class JsonParserTokenIndex
|
|
{
|
|
TRUEVALUE = 0,
|
|
FALSEVALUE = 1,
|
|
NULLVALUE = 2,
|
|
OBJOPEN = 3,
|
|
OBJCLOSE = 4,
|
|
ARROPEN = 5,
|
|
ARRCLOSE = 6,
|
|
COMMA = 7,
|
|
COLON = 8,
|
|
NUMBER = 9,
|
|
STRING = 10,
|
|
SPACE = 11,
|
|
};
|
|
class JsonNode;
|
|
class JsonLiteral;
|
|
class JsonString;
|
|
class JsonNumber;
|
|
class JsonArray;
|
|
class JsonObjectField;
|
|
class JsonObject;
|
|
|
|
class JsonNode abstract : public vl::parsing::ParsingTreeCustomBase, vl::reflection::Description<JsonNode>
|
|
{
|
|
public:
|
|
class IVisitor : public 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(JsonObjectField* node)=0;
|
|
virtual void Visit(JsonObject* node)=0;
|
|
};
|
|
|
|
virtual void Accept(JsonNode::IVisitor* visitor)=0;
|
|
|
|
};
|
|
|
|
class JsonLiteral : public JsonNode, vl::reflection::Description<JsonLiteral>
|
|
{
|
|
public:
|
|
enum class JsonValue
|
|
{
|
|
True,
|
|
False,
|
|
Null,
|
|
};
|
|
|
|
JsonValue value;
|
|
|
|
void Accept(JsonNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<JsonLiteral> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class JsonString : public JsonNode, vl::reflection::Description<JsonString>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken content;
|
|
|
|
void Accept(JsonNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<JsonString> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class JsonNumber : public JsonNode, vl::reflection::Description<JsonNumber>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken content;
|
|
|
|
void Accept(JsonNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<JsonNumber> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class JsonArray : public JsonNode, vl::reflection::Description<JsonArray>
|
|
{
|
|
public:
|
|
vl::collections::List<vl::Ptr<JsonNode>> items;
|
|
|
|
void Accept(JsonNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<JsonArray> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class JsonObjectField : public JsonNode, vl::reflection::Description<JsonObjectField>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken name;
|
|
vl::Ptr<JsonNode> value;
|
|
|
|
void Accept(JsonNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<JsonObjectField> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class JsonObject : public JsonNode, vl::reflection::Description<JsonObject>
|
|
{
|
|
public:
|
|
vl::collections::List<vl::Ptr<JsonObjectField>> fields;
|
|
|
|
void Accept(JsonNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<JsonObject> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
}
|
|
}
|
|
}
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonNode)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonLiteral)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonLiteral::JsonValue)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonString)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonNumber)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonArray)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonObjectField)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonObject)
|
|
DECL_TYPE_INFO(vl::parsing::json::JsonNode::IVisitor)
|
|
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::parsing::json::JsonNode::IVisitor)
|
|
void Visit(vl::parsing::json::JsonLiteral* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::json::JsonString* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::json::JsonNumber* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::json::JsonArray* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::json::JsonObjectField* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::json::JsonObject* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
END_INTERFACE_PROXY(vl::parsing::json::JsonNode::IVisitor)
|
|
|
|
#endif
|
|
extern bool JsonLoadTypes();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\JSON\PARSINGJSON_PARSER.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parser::ParsingJson.parser.txt
|
|
|
|
This file is generated by: Vczh Parser Generator
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_JSON_PARSINGJSON_PARSER_PARSER
|
|
#define VCZH_PARSING_JSON_PARSINGJSON_PARSER_PARSER
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace json
|
|
{
|
|
extern vl::WString JsonGetParserTextBuffer();
|
|
extern vl::Ptr<vl::parsing::ParsingTreeCustomBase> JsonConvertParsingTreeNode(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
extern vl::Ptr<vl::parsing::tabling::ParsingTable> JsonLoadTable();
|
|
|
|
extern vl::Ptr<vl::parsing::ParsingTreeNode> JsonParseAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<vl::parsing::ParsingTreeNode> JsonParseAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<JsonNode> JsonParse(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<JsonNode> JsonParse(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\JSON\PARSINGJSON.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parser::ParsingJson_Parser
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_JSON_PARSINGJSON
|
|
#define VCZH_PARSING_JSON_PARSINGJSON
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace json
|
|
{
|
|
extern void JsonEscapeString(const WString& text, stream::TextWriter& writer);
|
|
extern void JsonUnescapeString(const WString& text, stream::TextWriter& writer);
|
|
extern void JsonPrint(Ptr<JsonNode> node, stream::TextWriter& writer);
|
|
extern WString JsonToString(Ptr<JsonNode> node);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\XML\PARSINGXML_AST.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parser::ParsingXml.parser.txt
|
|
|
|
This file is generated by: Vczh Parser Generator
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_XML_PARSINGXML_PARSER_AST
|
|
#define VCZH_PARSING_XML_PARSINGXML_PARSER_AST
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace xml
|
|
{
|
|
enum class XmlParserTokenIndex
|
|
{
|
|
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,
|
|
};
|
|
class XmlNode;
|
|
class XmlText;
|
|
class XmlCData;
|
|
class XmlAttribute;
|
|
class XmlComment;
|
|
class XmlElement;
|
|
class XmlInstruction;
|
|
class XmlDocument;
|
|
|
|
class XmlNode abstract : public vl::parsing::ParsingTreeCustomBase, vl::reflection::Description<XmlNode>
|
|
{
|
|
public:
|
|
class IVisitor : public vl::reflection::IDescriptable, vl::reflection::Description<IVisitor>
|
|
{
|
|
public:
|
|
virtual void Visit(XmlText* node)=0;
|
|
virtual void Visit(XmlCData* node)=0;
|
|
virtual void Visit(XmlAttribute* 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::parsing::ParsingToken content;
|
|
|
|
void Accept(XmlNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<XmlText> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class XmlCData : public XmlNode, vl::reflection::Description<XmlCData>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken content;
|
|
|
|
void Accept(XmlNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<XmlCData> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class XmlAttribute : public XmlNode, vl::reflection::Description<XmlAttribute>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken name;
|
|
vl::parsing::ParsingToken value;
|
|
|
|
void Accept(XmlNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<XmlAttribute> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class XmlComment : public XmlNode, vl::reflection::Description<XmlComment>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken content;
|
|
|
|
void Accept(XmlNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<XmlComment> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class XmlElement : public XmlNode, vl::reflection::Description<XmlElement>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken name;
|
|
vl::parsing::ParsingToken closingName;
|
|
vl::collections::List<vl::Ptr<XmlAttribute>> attributes;
|
|
vl::collections::List<vl::Ptr<XmlNode>> subNodes;
|
|
|
|
void Accept(XmlNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<XmlElement> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
class XmlInstruction : public XmlNode, vl::reflection::Description<XmlInstruction>
|
|
{
|
|
public:
|
|
vl::parsing::ParsingToken name;
|
|
vl::collections::List<vl::Ptr<XmlAttribute>> attributes;
|
|
|
|
void Accept(XmlNode::IVisitor* visitor)override;
|
|
|
|
static vl::Ptr<XmlInstruction> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
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;
|
|
|
|
static vl::Ptr<XmlDocument> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
};
|
|
|
|
}
|
|
}
|
|
}
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlNode)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlText)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlCData)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlAttribute)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlComment)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlElement)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlInstruction)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlDocument)
|
|
DECL_TYPE_INFO(vl::parsing::xml::XmlNode::IVisitor)
|
|
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::parsing::xml::XmlNode::IVisitor)
|
|
void Visit(vl::parsing::xml::XmlText* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::xml::XmlCData* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::xml::XmlAttribute* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::xml::XmlComment* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::xml::XmlElement* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::xml::XmlInstruction* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
void Visit(vl::parsing::xml::XmlDocument* node)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Visit, node);
|
|
}
|
|
|
|
END_INTERFACE_PROXY(vl::parsing::xml::XmlNode::IVisitor)
|
|
|
|
#endif
|
|
extern bool XmlLoadTypes();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\XML\PARSINGXML_PARSER.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parser::ParsingXml.parser.txt
|
|
|
|
This file is generated by: Vczh Parser Generator
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_XML_PARSINGXML_PARSER_PARSER
|
|
#define VCZH_PARSING_XML_PARSINGXML_PARSER_PARSER
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
namespace xml
|
|
{
|
|
extern vl::WString XmlGetParserTextBuffer();
|
|
extern vl::Ptr<vl::parsing::ParsingTreeCustomBase> XmlConvertParsingTreeNode(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
|
|
extern vl::Ptr<vl::parsing::tabling::ParsingTable> XmlLoadTable();
|
|
|
|
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseDocumentAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseDocumentAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<XmlDocument> XmlParseDocument(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<XmlDocument> XmlParseDocument(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
|
|
|
|
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseElementAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseElementAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<XmlElement> XmlParseElement(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
|
|
extern vl::Ptr<XmlElement> XmlParseElement(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\XML\PARSINGXML.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
Parser::ParsingXml
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_PARSING_XML_PARSINGXML
|
|
#define VCZH_PARSING_XML_PARSINGXML
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace parsing
|
|
{
|
|
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);
|
|
extern void XmlPrint(Ptr<XmlNode> node, stream::TextWriter& writer);
|
|
extern void XmlPrintContent(Ptr<XmlElement> element, stream::TextWriter& writer);
|
|
extern WString XmlToString(Ptr<XmlNode> node);
|
|
|
|
extern Ptr<XmlAttribute> XmlGetAttribute(Ptr<XmlElement> element, const WString& name);
|
|
extern Ptr<XmlElement> XmlGetElement(Ptr<XmlElement> element, const WString& name);
|
|
extern collections::LazyList<Ptr<XmlElement>> XmlGetElements(Ptr<XmlElement> element);
|
|
extern collections::LazyList<Ptr<XmlElement>> XmlGetElements(Ptr<XmlElement> element, const WString& name);
|
|
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
|