| //===--- ParsedRawSyntaxRecorder.cpp - Raw Syntax Parsing Recorder --------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the ParsedRawSyntaxRecorder, which is the interface the |
| // parser is using to pass parsed syntactic elements to a SyntaxParseActions |
| // receiver and get a ParsedRawSyntaxNode object back. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/Parse/ParsedRawSyntaxRecorder.h" |
| #include "swift/Parse/ParsedRawSyntaxNode.h" |
| #include "swift/Parse/ParsedTrivia.h" |
| #include "swift/Parse/SyntaxParseActions.h" |
| #include "swift/Parse/Token.h" |
| #include "swift/Syntax/SyntaxKind.h" |
| |
| using namespace swift; |
| using namespace swift::syntax; |
| |
| ParsedRawSyntaxNode |
| ParsedRawSyntaxRecorder::recordToken(const Token &tok, |
| const ParsedTrivia &leadingTrivia, |
| const ParsedTrivia &trailingTrivia) { |
| return recordToken(tok.getKind(), tok.getRangeWithoutBackticks(), |
| leadingTrivia.Pieces, trailingTrivia.Pieces); |
| } |
| |
| ParsedRawSyntaxNode |
| ParsedRawSyntaxRecorder::recordToken(tok tokKind, CharSourceRange tokRange, |
| ArrayRef<ParsedTriviaPiece> leadingTrivia, |
| ArrayRef<ParsedTriviaPiece> trailingTrivia) { |
| size_t leadingTriviaLen = ParsedTriviaPiece::getTotalLength(leadingTrivia); |
| size_t trailingTriviaLen = ParsedTriviaPiece::getTotalLength(trailingTrivia); |
| SourceLoc offset = tokRange.getStart().getAdvancedLoc(-leadingTriviaLen); |
| unsigned length = leadingTriviaLen + tokRange.getByteLength() + |
| trailingTriviaLen; |
| CharSourceRange range{offset, length}; |
| OpaqueSyntaxNode n = SPActions->recordToken(tokKind, leadingTrivia, |
| trailingTrivia, range); |
| return ParsedRawSyntaxNode{SyntaxKind::Token, tokKind, range, n}; |
| } |
| |
| ParsedRawSyntaxNode |
| ParsedRawSyntaxRecorder::recordMissingToken(tok tokenKind, SourceLoc loc) { |
| CharSourceRange range{loc, 0}; |
| OpaqueSyntaxNode n = SPActions->recordMissingToken(tokenKind, loc); |
| return ParsedRawSyntaxNode{SyntaxKind::Token, tokenKind, range, n}; |
| } |
| |
| static ParsedRawSyntaxNode |
| getRecordedNode(const ParsedRawSyntaxNode &node, ParsedRawSyntaxRecorder &rec) { |
| if (node.isNull() || node.isRecorded()) |
| return node; |
| if (node.isDeferredLayout()) |
| return rec.recordRawSyntax(node.getKind(), node.getDeferredChildren()); |
| assert(node.isDeferredToken()); |
| CharSourceRange tokRange = node.getDeferredTokenRangeWithoutBackticks(); |
| tok tokKind = node.getTokenKind(); |
| if (node.isMissing()) |
| return rec.recordMissingToken(tokKind, tokRange.getStart()); |
| return rec.recordToken(tokKind,tokRange, |
| node.getDeferredLeadingTriviaPieces(), |
| node.getDeferredTrailingTriviaPieces()); |
| } |
| |
| ParsedRawSyntaxNode |
| ParsedRawSyntaxRecorder::recordRawSyntax(SyntaxKind kind, |
| ArrayRef<ParsedRawSyntaxNode> elements) { |
| CharSourceRange range; |
| SmallVector<OpaqueSyntaxNode, 16> subnodes; |
| if (!elements.empty()) { |
| SourceLoc offset; |
| unsigned length = 0; |
| for (const auto &elem : elements) { |
| auto subnode = getRecordedNode(elem, *this); |
| if (subnode.isNull()) { |
| subnodes.push_back(nullptr); |
| } else { |
| subnodes.push_back(subnode.getOpaqueNode()); |
| auto range = subnode.getRange(); |
| if (range.isValid()) { |
| if (offset.isInvalid()) |
| offset = range.getStart(); |
| length += subnode.getRange().getByteLength(); |
| } |
| } |
| } |
| range = CharSourceRange{offset, length}; |
| } |
| OpaqueSyntaxNode n = SPActions->recordRawSyntax(kind, subnodes, range); |
| return ParsedRawSyntaxNode{kind, tok::unknown, range, n}; |
| } |
| |
| ParsedRawSyntaxNode |
| ParsedRawSyntaxRecorder::recordEmptyRawSyntaxCollection(SyntaxKind kind, |
| SourceLoc loc) { |
| CharSourceRange range{loc, 0}; |
| OpaqueSyntaxNode n = SPActions->recordRawSyntax(kind, {}, range); |
| return ParsedRawSyntaxNode{kind, tok::unknown, range, n}; |
| } |
| |
| ParsedRawSyntaxNode |
| ParsedRawSyntaxRecorder::lookupNode(size_t lexerOffset, SourceLoc loc, |
| SyntaxKind kind) { |
| size_t length; |
| OpaqueSyntaxNode n; |
| std::tie(length, n) = SPActions->lookupNode(lexerOffset, kind); |
| if (length == 0) { |
| return ParsedRawSyntaxNode::null(); |
| } |
| CharSourceRange range{loc, unsigned(length)}; |
| return ParsedRawSyntaxNode{kind, tok::unknown, range, n}; |
| } |