//===--- AST.h - ReST AST nodes -------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef LLVM_REST_AST_H #define LLVM_REST_AST_H #include "swift/ReST/LineList.h" #include "llvm/Support/Casting.h" #include "llvm/ADT/ArrayRef.h" namespace llvm { namespace rest { class ReSTContext; #define REST_AST_NODE(Id, Parent) class Id; #include "swift/ReST/ASTNodes.def" enum class ASTNodeKind : uint8_t { #define REST_AST_NODE(Id, Parent) Id, #include "swift/ReST/ASTNodes.def" }; class alignas(void *) ReSTASTNode { ReSTASTNode(const ReSTASTNode &) = delete; void operator=(const ReSTASTNode &) = delete; ASTNodeKind Kind; public: ReSTASTNode(ASTNodeKind Kind) : Kind(Kind) {} ASTNodeKind getKind() const { return Kind; } bool isStructuralElement() const { return isa(this) || isa
(this) || isa(this) || isa(this) || isStructuralSubelement(); } bool isStructuralSubelement() const { return false; // FIXME } bool isBibliographicElement() const { return false; // FIXME } bool isDecorativeElement() const { return false; // FIXME } bool isBodyElement() const { return false; // FIXME } LLVM_ATTRIBUTE_DEPRECATED( void dump() const LLVM_ATTRIBUTE_USED, "only for use within the debugger"); // Only allow allocation using the allocator in ReSTContext or by placement // new. void *operator new(size_t Bytes, ReSTContext &C, unsigned Alignment = alignof(ReSTASTNode)); void *operator new(size_t Bytes, void *Mem) { assert(Mem); return Mem; } // Make vanilla new/delete illegal for ReST AST nodes. void *operator new(size_t Bytes) = delete; void operator delete(void *Data) = delete; }; // Structural element. class Document final : public ReSTASTNode { /// Non-null. // Title *TheTitle; /// Might be null. // Subtitle *TheSubtitle; // Decoration -- not implemented. // Docinfo -- not implemented. unsigned NumChildren; const ReSTASTNode *const *getChildrenBuffer() const { return reinterpret_cast(this + 1); } ReSTASTNode **getChildrenBuffer() { return reinterpret_cast(this + 1); } Document(ArrayRef Children); public: static Document *create(ReSTContext &C, ArrayRef Children); /// Content model: /// \code /// %structure.model; /// \endcode ArrayRef getChildren() const { return ArrayRef(getChildrenBuffer(), NumChildren); } ArrayRef getChildren() { return ArrayRef(getChildrenBuffer(), NumChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Document; } }; // Structural element. class Section : public ReSTASTNode { /// Non-null. // Title *TheTitle; /// Content model: /// \code /// %structure.model; /// \endcode ArrayRef Children; public: Section() : ReSTASTNode(ASTNodeKind::Section) {} static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Section; } }; // Structural element. class Topic : public ReSTASTNode { public: Topic() : ReSTASTNode(ASTNodeKind::Topic) {} static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Topic; } }; // Structural element. class Sidebar : public ReSTASTNode { /// Non-null. // Title *TheTitle; /// Might be null. // Subtitle *TheSubtitle; /// Content model: /// \code /// (%body.elements; | topic)+ /// \endcode ArrayRef Children; public: Sidebar() : ReSTASTNode(ASTNodeKind::Sidebar) {} static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Sidebar; } }; // Structural subelement. class Title final : public ReSTASTNode { // TextAndInline *Content; public: Title() : ReSTASTNode(ASTNodeKind::Title) {} static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Title; } }; // Structural subelement. class Subtitle final : public ReSTASTNode { // TextAndInline *Content; public: Subtitle() : ReSTASTNode(ASTNodeKind::Subtitle) {} static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Subtitle; } }; // Structural subelement. // class Decoration {}; // Structural subelement. // class Docinfo {}; // Structural subelement. class Transition final : public ReSTASTNode { // Just the source location. public: Transition() : ReSTASTNode(ASTNodeKind::Transition) {} static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Transition; } }; // Simple body element. class Paragraph final : public ReSTASTNode { TextAndInline *Content; public: Paragraph(TextAndInline *Content) : ReSTASTNode(ASTNodeKind::Paragraph), Content(Content) {} const TextAndInline *getContent() const { return Content; } TextAndInline *getMutableContent() { return Content; } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Paragraph; } }; // Compound body element. class BulletList final : public ReSTASTNode { unsigned NumItems; public: struct ListItemInfo { unsigned FirstChildIndex; unsigned NumChildren; }; private: const ListItemInfo *getItemInfoBuffer() const { return reinterpret_cast(this + 1); } ListItemInfo *getItemInfoBuffer() { return reinterpret_cast(this + 1); } ReSTASTNode *const *getItemChildrenBuffer() const { return reinterpret_cast(getItemInfoBuffer() + NumItems); } ReSTASTNode **getItemChildrenBuffer() { return reinterpret_cast(getItemInfoBuffer() + NumItems); } BulletList(ArrayRef ItemInfos, ArrayRef ItemChildren); public: static BulletList *create(ReSTContext &C, ArrayRef ItemInfos, ArrayRef ItemChildren); unsigned getNumItems() const { return NumItems; } const ListItemInfo &getItemInfo(unsigned i) const { assert(i < NumItems); return *(getItemInfoBuffer() + i); } ArrayRef getItemChildren(unsigned i) const { assert(i < NumItems); const auto &ItemInfo = getItemInfo(i); return ArrayRef(getItemChildrenBuffer() + ItemInfo.FirstChildIndex, ItemInfo.NumChildren); } ArrayRef getItemChildren(unsigned i) { assert(i < NumItems); const auto &ItemInfo = getItemInfo(i); return ArrayRef(getItemChildrenBuffer() + ItemInfo.FirstChildIndex, ItemInfo.NumChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::BulletList; } }; // Compound body element. class EnumeratedList final : public ReSTASTNode { unsigned NumItems; public: struct ListItemInfo { unsigned FirstChildIndex; unsigned NumChildren; }; private: const ListItemInfo *getItemInfoBuffer() const { return reinterpret_cast(this + 1); } ListItemInfo *getItemInfoBuffer() { return reinterpret_cast(this + 1); } ReSTASTNode *const *getItemChildrenBuffer() const { return reinterpret_cast(getItemInfoBuffer() + NumItems); } ReSTASTNode **getItemChildrenBuffer() { return reinterpret_cast(getItemInfoBuffer() + NumItems); } EnumeratedList(ArrayRef ItemInfos, ArrayRef ItemChildren); public: static EnumeratedList *create(ReSTContext &C, ArrayRef ItemInfos, ArrayRef ItemChildren); unsigned getNumItems() const { return NumItems; } const ListItemInfo &getItemInfo(unsigned i) const { assert(i < NumItems); return *(getItemInfoBuffer() + i); } ArrayRef getItemChildren(unsigned i) const { assert(i < NumItems); const auto &ItemInfo = getItemInfo(i); return ArrayRef(getItemChildrenBuffer() + ItemInfo.FirstChildIndex, ItemInfo.NumChildren); } ArrayRef getItemChildren(unsigned i) { assert(i < NumItems); const auto &ItemInfo = getItemInfo(i); return ArrayRef(getItemChildrenBuffer() + ItemInfo.FirstChildIndex, ItemInfo.NumChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::EnumeratedList; } }; // Body subelement, compound. class DefinitionListItem final : public ReSTASTNode { TextAndInline *Term; unsigned NumClassifiers : 16; unsigned NumDefinitionChildren : 16; TextAndInline *const *getClassifiersBuffer() const { return reinterpret_cast(this + 1); } TextAndInline **getClassifiersBuffer() { return reinterpret_cast(this + 1); } ReSTASTNode *const *getDefinitionChildrenBuffer() const { return reinterpret_cast(getClassifiersBuffer() + NumClassifiers); } ReSTASTNode **getDefinitionChildrenBuffer() { return reinterpret_cast(getClassifiersBuffer() + NumClassifiers); } DefinitionListItem(TextAndInline *Term, ArrayRef Classifiers, ArrayRef DefinitionChildren); public: static DefinitionListItem *create(ReSTContext &C, TextAndInline *Term, ArrayRef Classifiers, ArrayRef DefinitionChildren); const TextAndInline *getTerm() const { return Term; } TextAndInline *getTerm() { return Term; } ArrayRef getClassifiers() const { return ArrayRef(getClassifiersBuffer(), NumClassifiers); } ArrayRef getClassifiers() { return ArrayRef(getClassifiersBuffer(), NumClassifiers); } ArrayRef getDefinitionChildren() const { return ArrayRef(getDefinitionChildrenBuffer(), NumDefinitionChildren); } ArrayRef getDefinitionChildren() { return ArrayRef(getDefinitionChildrenBuffer(), NumDefinitionChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::DefinitionListItem; } }; // Compound body element. class DefinitionList final : public ReSTASTNode { unsigned NumChildren; const DefinitionListItem *const *getChildrenBuffer() const { return reinterpret_cast(this + 1); } DefinitionListItem **getChildrenBuffer() { return reinterpret_cast(this + 1); } DefinitionList(ArrayRef Children); public: static DefinitionList *create(ReSTContext &C, ArrayRef Children); ArrayRef getChildren() const { return ArrayRef(getChildrenBuffer(), NumChildren); } ArrayRef getChildren() { return ArrayRef(getChildrenBuffer(), NumChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::DefinitionList; } }; // Body subelement, compound. class Field final : public ReSTASTNode { TextAndInline *Name; unsigned NumBodyChildren; ReSTASTNode *const *getBodyChildrenBuffer() const { return reinterpret_cast(this + 1); } ReSTASTNode **getBodyChildrenBuffer() { return reinterpret_cast(this + 1); } Field(TextAndInline *Name, ArrayRef BodyChildren); public: static Field *create(ReSTContext &C, TextAndInline *Name, ArrayRef BodyChildren); const TextAndInline *getName() const { return Name; } TextAndInline *getName() { return Name; } ArrayRef getBodyChildren() const { return ArrayRef(getBodyChildrenBuffer(), NumBodyChildren); } ArrayRef getBodyChildren() { return ArrayRef(getBodyChildrenBuffer(), NumBodyChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::Field; } }; // Compound body element. class FieldList final : public ReSTASTNode { unsigned NumChildren; const Field *const *getChildrenBuffer() const { return reinterpret_cast(this + 1); } Field **getChildrenBuffer() { return reinterpret_cast(this + 1); } FieldList(ArrayRef Children); public: static FieldList *create(ReSTContext &C, ArrayRef Children); ArrayRef getChildren() const { return ArrayRef(getChildrenBuffer(), NumChildren); } MutableArrayRef getChildren() { return MutableArrayRef(getChildrenBuffer(), NumChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::FieldList; } }; // Compound body element. class BlockQuote final : public ReSTASTNode { unsigned NumChildren; ReSTASTNode **getChildrenBuffer() { return reinterpret_cast(this + 1); } const ReSTASTNode *const *getChildrenBuffer() const { return reinterpret_cast(this + 1); } BlockQuote(ArrayRef Children); public: static BlockQuote *create(ReSTContext &C, ArrayRef Children); ArrayRef getChildren() { return ArrayRef(getChildrenBuffer(), NumChildren); } ArrayRef getChildren() const { return ArrayRef(getChildrenBuffer(), NumChildren); } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::BlockQuote; } }; class TextAndInline final : public ReSTASTNode { // FIXME: use a more specific AST node here? ArrayRef Children; // FIXME: temporary while we don't parse inline markup. union { LineListRef LL; LinePart LP; }; bool IsLinePart; public: TextAndInline(LineListRef LL) : ReSTASTNode(ASTNodeKind::TextAndInline), LL(LL), IsLinePart(false) {} TextAndInline(LinePart LP) : ReSTASTNode(ASTNodeKind::TextAndInline), LP(LP), IsLinePart(true) {} bool isLinePart() const { return IsLinePart; } LineListRef getLines() const { assert(!IsLinePart); return LL; } void setLines(LineListRef LL) { assert(!IsLinePart); this->LL = LL; } LinePart getLinePart() const { assert(IsLinePart); return LP; } void setLinePart(LinePart LP) { assert(IsLinePart); this->LP = LP; } static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::TextAndInline; } }; class PrivateExtension : public ReSTASTNode { public: PrivateExtension() : ReSTASTNode(ASTNodeKind::PrivateExtension) {} static bool classof(const ReSTASTNode *N) { return N->getKind() == ASTNodeKind::PrivateExtension; } }; } // namespace rest } // namespace llvm #endif // LLVM_REST_AST_H