Skip to content

Commit c7ac859

Browse files
committed
[Parse] Optimize syntax parsing: Speed-up Lexer::lexTrivia()
Introduce ParsedTrivia which is a more efficient structure to use during lexing than syntax::Trivia.
1 parent 9fa91e9 commit c7ac859

24 files changed

+285
-108
lines changed

include/swift/Parse/Lexer.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
#include "swift/Basic/SourceManager.h"
2323
#include "swift/Parse/LexerState.h"
2424
#include "swift/Parse/Token.h"
25-
#include "swift/Syntax/References.h"
26-
#include "swift/Syntax/Trivia.h"
25+
#include "swift/Parse/ParsedTrivia.h"
2726
#include "llvm/ADT/SmallVector.h"
2827
#include "llvm/Support/SaveAndRestore.h"
2928

@@ -118,13 +117,13 @@ class Lexer {
118117
///
119118
/// This is only preserved if this Lexer was constructed with
120119
/// `TriviaRetentionMode::WithTrivia`.
121-
syntax::Trivia LeadingTrivia;
120+
ParsedTrivia LeadingTrivia;
122121

123122
/// The current trailing trivia for the next token.
124123
///
125124
/// This is only preserved if this Lexer was constructed with
126125
/// `TriviaRetentionMode::WithTrivia`.
127-
syntax::Trivia TrailingTrivia;
126+
ParsedTrivia TrailingTrivia;
128127

129128
Lexer(const Lexer&) = delete;
130129
void operator=(const Lexer&) = delete;
@@ -185,8 +184,8 @@ class Lexer {
185184

186185
/// Lex a token. If \c TriviaRetentionMode is \c WithTrivia, passed pointers
187186
/// to trivias are populated.
188-
void lex(Token &Result, syntax::Trivia &LeadingTriviaResult,
189-
syntax::Trivia &TrailingTriviaResult) {
187+
void lex(Token &Result, ParsedTrivia &LeadingTriviaResult,
188+
ParsedTrivia &TrailingTriviaResult) {
190189
Result = NextToken;
191190
if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
192191
LeadingTriviaResult = {LeadingTrivia};
@@ -197,7 +196,7 @@ class Lexer {
197196
}
198197

199198
void lex(Token &Result) {
200-
syntax::Trivia LeadingTrivia, TrailingTrivia;
199+
ParsedTrivia LeadingTrivia, TrailingTrivia;
201200
lex(Result, LeadingTrivia, TrailingTrivia);
202201
}
203202

@@ -229,7 +228,7 @@ class Lexer {
229228
/// After restoring the state, lexer will return this token and continue from
230229
/// there.
231230
State getStateForBeginningOfToken(const Token &Tok,
232-
const syntax::Trivia &LeadingTrivia = {}) const {
231+
const ParsedTrivia &LeadingTrivia = {}) const {
233232

234233
// If the token has a comment attached to it, rewind to before the comment,
235234
// not just the start of the token. This ensures that we will re-lex and
@@ -529,7 +528,7 @@ class Lexer {
529528
void lexOperatorIdentifier();
530529
void lexHexNumber();
531530
void lexNumber();
532-
void lexTrivia(syntax::Trivia &T, bool IsForTrailingTrivia);
531+
void lexTrivia(ParsedTrivia &T, bool IsForTrailingTrivia);
533532
static unsigned lexUnicodeEscape(const char *&CurPtr, Lexer *Diags);
534533

535534
unsigned lexCharacter(const char *&CurPtr, char StopQuote,

include/swift/Parse/LexerState.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "llvm/ADT/Optional.h"
2121
#include "swift/Basic/SourceLoc.h"
22-
#include "swift/Syntax/Trivia.h"
22+
#include "swift/Parse/ParsedTrivia.h"
2323

2424
namespace swift {
2525
class Lexer;
@@ -39,7 +39,7 @@ class LexerState {
3939
private:
4040
explicit LexerState(SourceLoc Loc) : Loc(Loc) {}
4141
SourceLoc Loc;
42-
llvm::Optional<syntax::Trivia> LeadingTrivia;
42+
llvm::Optional<ParsedTrivia> LeadingTrivia;
4343
friend class Lexer;
4444
};
4545

include/swift/Parse/ParsedRawSyntaxNode.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
#define SWIFT_PARSE_PARSEDRAWSYNTAXNODE_H
1515

1616
#include "swift/Basic/SourceLoc.h"
17+
#include "swift/Parse/ParsedTrivia.h"
1718
#include "swift/Parse/Token.h"
1819
#include "swift/Syntax/SyntaxKind.h"
19-
#include "swift/Syntax/Trivia.h"
2020
#include <vector>
2121

2222
namespace swift {
@@ -54,8 +54,8 @@ class ParsedRawSyntaxNode {
5454
};
5555
struct DeferredTokenNode {
5656
Token Tok;
57-
syntax::Trivia LeadingTrivia;
58-
syntax::Trivia TrailingTrivia;
57+
ParsedTrivia LeadingTrivia;
58+
ParsedTrivia TrailingTrivia;
5959
};
6060

6161
union {
@@ -78,8 +78,8 @@ class ParsedRawSyntaxNode {
7878
}
7979

8080
ParsedRawSyntaxNode(Token tok,
81-
syntax::Trivia leadingTrivia,
82-
syntax::Trivia trailingTrivia)
81+
ParsedTrivia leadingTrivia,
82+
ParsedTrivia trailingTrivia)
8383
: DeferredToken{std::move(tok),
8484
std::move(leadingTrivia),
8585
std::move(trailingTrivia)},
@@ -212,11 +212,11 @@ class ParsedRawSyntaxNode {
212212
assert(DK == DataKind::DeferredToken);
213213
return DeferredToken.Tok;
214214
}
215-
const syntax::Trivia &getLeadingTrivia() const {
215+
const ParsedTrivia &getLeadingTrivia() const {
216216
assert(DK == DataKind::DeferredToken);
217217
return DeferredToken.LeadingTrivia;
218218
}
219-
const syntax::Trivia &getTrailingTrivia() const {
219+
const ParsedTrivia &getTrailingTrivia() const {
220220
assert(DK == DataKind::DeferredToken);
221221
return DeferredToken.TrailingTrivia;
222222
}
@@ -231,8 +231,8 @@ class ParsedRawSyntaxNode {
231231

232232
/// Form a deferred token node.
233233
static ParsedRawSyntaxNode makeDeferred(Token tok,
234-
syntax::Trivia leadingTrivia,
235-
syntax::Trivia trailingTrivia) {
234+
ParsedTrivia leadingTrivia,
235+
ParsedTrivia trailingTrivia) {
236236
return ParsedRawSyntaxNode{std::move(tok), std::move(leadingTrivia),
237237
std::move(trailingTrivia)};
238238
}

include/swift/Parse/ParsedRawSyntaxRecorder.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
namespace swift {
2626

2727
class ParsedRawSyntaxNode;
28+
struct ParsedTrivia;
2829
class SyntaxParseActions;
2930
class SourceLoc;
3031
class Token;
3132
enum class tok;
3233

3334
namespace syntax {
3435
enum class SyntaxKind;
35-
struct Trivia;
3636
}
3737

3838
class ParsedRawSyntaxRecorder {
@@ -43,8 +43,8 @@ class ParsedRawSyntaxRecorder {
4343
: SPActions(std::move(spActions)) {}
4444

4545
ParsedRawSyntaxNode recordToken(const Token &tok,
46-
const syntax::Trivia &leadingTrivia,
47-
const syntax::Trivia &trailingTrivia);
46+
const ParsedTrivia &leadingTrivia,
47+
const ParsedTrivia &trailingTrivia);
4848

4949
/// Record a missing token. \p loc can be invalid or an approximate location
5050
/// of where the token would be if not missing.

include/swift/Parse/ParsedTrivia.h

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//===--- ParsedTrivia.h - ParsedTrivia API ----------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_PARSE_PARSEDTRIVIA_H
14+
#define SWIFT_PARSE_PARSEDTRIVIA_H
15+
16+
#include "swift/Basic/LLVM.h"
17+
#include "llvm/ADT/SmallVector.h"
18+
19+
namespace swift {
20+
class SourceLoc;
21+
class SourceManager;
22+
23+
namespace syntax {
24+
enum class TriviaKind;
25+
struct Trivia;
26+
}
27+
28+
class ParsedTriviaPiece {
29+
syntax::TriviaKind Kind;
30+
unsigned Length;
31+
32+
public:
33+
ParsedTriviaPiece(syntax::TriviaKind kind, unsigned length)
34+
: Kind(kind), Length(length) {}
35+
36+
syntax::TriviaKind getKind() const { return Kind; }
37+
38+
/// Return the text of the trivia.
39+
unsigned getLength() const { return Length; }
40+
41+
void extendLength(unsigned len) {
42+
Length += len;
43+
}
44+
};
45+
46+
using ParsedTriviaList = SmallVector<ParsedTriviaPiece, 3>;
47+
48+
struct ParsedTrivia {
49+
ParsedTriviaList Pieces;
50+
51+
/// Get the begin iterator of the pieces.
52+
ParsedTriviaList::const_iterator begin() const {
53+
return Pieces.begin();
54+
}
55+
56+
/// Get the end iterator of the pieces.
57+
ParsedTriviaList::const_iterator end() const {
58+
return Pieces.end();
59+
}
60+
61+
/// Clear pieces.
62+
void clear() {
63+
Pieces.clear();
64+
}
65+
66+
/// Returns true if there are no pieces in this Trivia collection.
67+
bool empty() const {
68+
return Pieces.empty();
69+
}
70+
71+
size_t getLength() const {
72+
size_t Len = 0;
73+
for (auto &P : Pieces)
74+
Len += P.getLength();
75+
return Len;
76+
}
77+
78+
void push_back(syntax::TriviaKind kind, unsigned length) {
79+
Pieces.emplace_back(kind, length);
80+
}
81+
82+
void appendOrSquash(syntax::TriviaKind kind, unsigned length) {
83+
if (empty() || Pieces.back().getKind() != kind) {
84+
push_back(kind, length);
85+
} else {
86+
Pieces.back().extendLength(length);
87+
}
88+
}
89+
90+
syntax::Trivia convertToSyntaxTrivia(SourceLoc loc, const SourceManager &SM,
91+
unsigned bufferID) const;
92+
};
93+
94+
} // end namespace swift
95+
96+
#endif

include/swift/Parse/Parser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "swift/Parse/ParserResult.h"
3434
#include "swift/Parse/SyntaxParserResult.h"
3535
#include "swift/Parse/SyntaxParsingContext.h"
36+
#include "swift/Syntax/References.h"
3637
#include "swift/Config.h"
3738
#include "llvm/ADT/SetVector.h"
3839

@@ -200,11 +201,11 @@ class Parser {
200201

201202
/// leading trivias for \c Tok.
202203
/// Always empty if !SF.shouldBuildSyntaxTree().
203-
syntax::Trivia LeadingTrivia;
204+
ParsedTrivia LeadingTrivia;
204205

205206
/// trailing trivias for \c Tok.
206207
/// Always empty if !SF.shouldBuildSyntaxTree().
207-
syntax::Trivia TrailingTrivia;
208+
ParsedTrivia TrailingTrivia;
208209

209210
/// Whether we should disable delayed parsing.
210211
bool DisableDelayedParsing;

include/swift/Parse/SyntaxParseActions.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323
namespace swift {
2424

2525
class CharSourceRange;
26+
struct ParsedTrivia;
2627
class SourceLoc;
2728
class Token;
2829
enum class tok;
2930

3031
namespace syntax {
3132
enum class SyntaxKind;
32-
struct Trivia;
3333
}
3434

3535
typedef void *OpaqueSyntaxNode;
@@ -41,8 +41,8 @@ class SyntaxParseActions {
4141
virtual ~SyntaxParseActions() = default;
4242

4343
virtual OpaqueSyntaxNode recordToken(const Token &tok,
44-
const syntax::Trivia &leadingTrivia,
45-
const syntax::Trivia &trailingTrivia,
44+
const ParsedTrivia &leadingTrivia,
45+
const ParsedTrivia &trailingTrivia,
4646
CharSourceRange range) = 0;
4747

4848
/// Record a missing token. \c loc can be invalid or an approximate location

include/swift/Parse/SyntaxParsingContext.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ using namespace swift::syntax;
2424

2525
class ParsedSyntax;
2626
class ParsedTokenSyntax;
27+
struct ParsedTrivia;
2728
class SourceFile;
2829
enum class tok;
2930
class Token;
@@ -245,8 +246,8 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
245246
void addRawSyntax(ParsedRawSyntaxNode Raw);
246247

247248
/// Add Token with Trivia to the parts.
248-
void addToken(Token &Tok, Trivia &LeadingTrivia,
249-
Trivia &TrailingTrivia);
249+
void addToken(Token &Tok, ParsedTrivia &LeadingTrivia,
250+
ParsedTrivia &TrailingTrivia);
250251

251252
/// Add Syntax to the parts.
252253
void addSyntax(ParsedSyntax Node);

include/swift/Parse/Token.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,17 @@ class Token {
248248
return CharSourceRange(getLoc(), getLength());
249249
}
250250

251+
CharSourceRange getRangeWithoutBackticks() const {
252+
SourceLoc TokLoc = getLoc();
253+
unsigned TokLength = getLength();
254+
if (isEscapedIdentifier()) {
255+
// Adjust to account for the backticks.
256+
TokLoc = TokLoc.getAdvancedLoc(1);
257+
TokLength -= 2;
258+
}
259+
return CharSourceRange(TokLoc, TokLength);
260+
}
261+
251262
bool hasComment() const {
252263
return CommentLength != 0;
253264
}

include/swift/Syntax/Trivia.h.gyb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ enum class TriviaKind {
109109
% end
110110
};
111111

112+
bool isCommentTriviaKind(TriviaKind kind);
113+
112114
/// A contiguous stretch of a single kind of trivia. The constituent part of
113115
/// a `Trivia` collection.
114116
///
@@ -150,6 +152,8 @@ public:
150152
% end
151153
% end
152154

155+
static TriviaPiece fromText(TriviaKind kind, StringRef text);
156+
153157
/// Return kind of the trivia.
154158
TriviaKind getKind() const { return Kind; }
155159

@@ -174,7 +178,9 @@ public:
174178
llvm_unreachable("unhandled kind");
175179
}
176180

177-
bool isComment() const;
181+
bool isComment() const {
182+
return isCommentTriviaKind(getKind());
183+
}
178184

179185
void accumulateAbsolutePosition(AbsolutePosition &Pos) const;
180186

0 commit comments

Comments
 (0)