| //===--- ParsedRawSyntaxNode.h - Parsed Raw Syntax Node ---------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_PARSE_PARSEDRAWSYNTAXNODE_H |
| #define SWIFT_PARSE_PARSEDRAWSYNTAXNODE_H |
| |
| #include "swift/Basic/SourceLoc.h" |
| #include "swift/Parse/ParsedTrivia.h" |
| #include "swift/Parse/Token.h" |
| #include "swift/Syntax/SyntaxKind.h" |
| #include <vector> |
| |
| namespace swift { |
| |
| typedef void *OpaqueSyntaxNode; |
| class SyntaxParsingContext; |
| |
| /// Represents a raw syntax node formed by the parser. |
| /// |
| /// It can be either 'recorded', in which case it encapsulates an |
| /// \c OpaqueSyntaxNode that was returned from a \c SyntaxParseActions |
| /// invocation, or 'deferred' which captures the data for a |
| /// \c SyntaxParseActions invocation to occur later. |
| /// |
| /// An \c OpaqueSyntaxNode can represent both the result of 'recording' a token |
| /// as well as 'recording' a syntax layout, so there's only one |
| /// \c RecordedSyntaxNode structure that can represent both. |
| /// |
| /// The 'deferred' form is used for when the parser is backtracking and when |
| /// there are instances that it's not clear what will be the final syntax node |
| /// in the current parsing context. |
| class ParsedRawSyntaxNode { |
| enum class DataKind: uint8_t { |
| Null, |
| Recorded, |
| DeferredLayout, |
| DeferredToken, |
| }; |
| |
| struct RecordedSyntaxNode { |
| OpaqueSyntaxNode OpaqueNode; |
| CharSourceRange Range; |
| }; |
| struct DeferredLayoutNode { |
| ArrayRef<ParsedRawSyntaxNode> Children; |
| }; |
| struct DeferredTokenNode { |
| const ParsedTriviaPiece *TriviaPieces; |
| SourceLoc TokLoc; |
| unsigned TokLength; |
| uint16_t NumLeadingTrivia; |
| uint16_t NumTrailingTrivia; |
| }; |
| |
| union { |
| RecordedSyntaxNode RecordedData; |
| DeferredLayoutNode DeferredLayout; |
| DeferredTokenNode DeferredToken; |
| }; |
| uint16_t SynKind; |
| uint16_t TokKind; |
| DataKind DK; |
| /// Primary used for capturing a deferred missing token. |
| bool IsMissing = false; |
| |
| ParsedRawSyntaxNode(syntax::SyntaxKind k, |
| ArrayRef<ParsedRawSyntaxNode> deferredNodes) |
| : DeferredLayout{deferredNodes}, |
| SynKind(uint16_t(k)), TokKind(uint16_t(tok::unknown)), |
| DK(DataKind::DeferredLayout) { |
| assert(getKind() == k && "Syntax kind with too large value!"); |
| } |
| |
| ParsedRawSyntaxNode(tok tokKind, SourceLoc tokLoc, unsigned tokLength, |
| const ParsedTriviaPiece *triviaPieces, |
| unsigned numLeadingTrivia, |
| unsigned numTrailingTrivia) |
| : DeferredToken{triviaPieces, |
| tokLoc, tokLength, |
| uint16_t(numLeadingTrivia), |
| uint16_t(numTrailingTrivia)}, |
| SynKind(uint16_t(syntax::SyntaxKind::Token)), |
| TokKind(uint16_t(tokKind)), |
| DK(DataKind::DeferredToken) { |
| assert(getTokenKind() == tokKind && "Token kind is too large value!"); |
| assert(DeferredToken.NumLeadingTrivia == numLeadingTrivia && |
| "numLeadingTrivia is too large value!"); |
| assert(DeferredToken.NumTrailingTrivia == numTrailingTrivia && |
| "numLeadingTrivia is too large value!"); |
| } |
| |
| public: |
| ParsedRawSyntaxNode() |
| : RecordedData{}, |
| SynKind(uint16_t(syntax::SyntaxKind::Unknown)), |
| TokKind(uint16_t(tok::unknown)), |
| DK(DataKind::Null) { |
| } |
| |
| ParsedRawSyntaxNode(syntax::SyntaxKind k, tok tokKind, |
| CharSourceRange r, OpaqueSyntaxNode n) |
| : RecordedData{n, r}, |
| SynKind(uint16_t(k)), TokKind(uint16_t(tokKind)), |
| DK(DataKind::Recorded) { |
| assert(getKind() == k && "Syntax kind with too large value!"); |
| assert(getTokenKind() == tokKind && "Token kind with too large value!"); |
| } |
| |
| syntax::SyntaxKind getKind() const { return syntax::SyntaxKind(SynKind); } |
| tok getTokenKind() const { return tok(TokKind); } |
| |
| bool isToken() const { |
| return getKind() == syntax::SyntaxKind::Token; |
| } |
| bool isToken(tok tokKind) const { |
| return getTokenKind() == tokKind; |
| } |
| |
| bool isNull() const { |
| return DK == DataKind::Null; |
| } |
| |
| bool isRecorded() const { return DK == DataKind::Recorded; } |
| bool isDeferredLayout() const { return DK == DataKind::DeferredLayout; } |
| bool isDeferredToken() const { return DK == DataKind::DeferredToken; } |
| |
| /// Primary used for a deferred missing token. |
| bool isMissing() const { return IsMissing; } |
| |
| // Recorded Data ===========================================================// |
| |
| CharSourceRange getRange() const { |
| assert(isRecorded()); |
| return RecordedData.Range; |
| } |
| OpaqueSyntaxNode getOpaqueNode() const { |
| assert(isRecorded()); |
| return RecordedData.OpaqueNode; |
| } |
| |
| // Deferred Layout Data ====================================================// |
| |
| ArrayRef<ParsedRawSyntaxNode> getDeferredChildren() const { |
| assert(DK == DataKind::DeferredLayout); |
| return DeferredLayout.Children; |
| } |
| |
| // Deferred Token Data =====================================================// |
| |
| CharSourceRange getDeferredTokenRangeWithoutBackticks() const { |
| assert(DK == DataKind::DeferredToken); |
| return CharSourceRange{DeferredToken.TokLoc, DeferredToken.TokLength}; |
| } |
| ArrayRef<ParsedTriviaPiece> getDeferredLeadingTriviaPieces() const { |
| assert(DK == DataKind::DeferredToken); |
| return ArrayRef<ParsedTriviaPiece>(DeferredToken.TriviaPieces, |
| DeferredToken.NumLeadingTrivia); |
| } |
| ArrayRef<ParsedTriviaPiece> getDeferredTrailingTriviaPieces() const { |
| assert(DK == DataKind::DeferredToken); |
| return ArrayRef<ParsedTriviaPiece>( |
| DeferredToken.TriviaPieces + DeferredToken.NumLeadingTrivia, |
| DeferredToken.NumTrailingTrivia); |
| } |
| |
| //==========================================================================// |
| |
| /// Form a deferred syntax layout node. |
| static ParsedRawSyntaxNode makeDeferred(syntax::SyntaxKind k, |
| ArrayRef<ParsedRawSyntaxNode> deferredNodes, |
| SyntaxParsingContext &ctx); |
| |
| /// Form a deferred token node. |
| static ParsedRawSyntaxNode makeDeferred(Token tok, |
| const ParsedTrivia &leadingTrivia, |
| const ParsedTrivia &trailingTrivia, |
| SyntaxParsingContext &ctx); |
| |
| /// Form a deferred missing token node. |
| static ParsedRawSyntaxNode makeDeferredMissing(tok tokKind, SourceLoc loc) { |
| auto raw = ParsedRawSyntaxNode(tokKind, loc, 0, nullptr, 0, 0); |
| raw.IsMissing = true; |
| return raw; |
| } |
| |
| /// Dump this piece of syntax recursively for debugging or testing. |
| LLVM_ATTRIBUTE_DEPRECATED( |
| void dump() const LLVM_ATTRIBUTE_USED, |
| "only for use within the debugger"); |
| |
| /// Dump this piece of syntax recursively. |
| void dump(raw_ostream &OS, unsigned Indent = 0) const; |
| |
| static ParsedRawSyntaxNode null() { |
| return ParsedRawSyntaxNode{}; |
| } |
| }; |
| |
| } // end namespace swift |
| |
| #endif |