Skip to content

Commit 0d98c4c

Browse files
authored
libSyntax: Ensure round-trip printing when we build syntax tree from parser incrementally. (#12709)
1 parent 094395b commit 0d98c4c

File tree

11 files changed

+261
-124
lines changed

11 files changed

+261
-124
lines changed

include/swift/AST/Module.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ namespace syntax {
8383
class SourceFileSyntax;
8484
class SyntaxParsingContext;
8585
class SyntaxParsingContextRoot;
86-
struct RawTokenInfo;
86+
struct RawSyntaxInfo;
8787
}
8888

8989
/// Discriminator for file-units.
@@ -1092,7 +1092,7 @@ class SourceFile final : public FileUnit {
10921092
Optional<std::vector<Token>> AllCorrectedTokens;
10931093

10941094
/// All of the raw token syntax nodes in the underlying source.
1095-
std::vector<syntax::RawTokenInfo> AllRawTokenSyntax;
1095+
std::vector<syntax::RawSyntaxInfo> AllRawTokenSyntax;
10961096

10971097
SourceFileSyntaxInfo &SyntaxInfo;
10981098

include/swift/Parse/Lexer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class Lexer {
246246
}
247247

248248
/// Lex a full token including leading and trailing trivia.
249-
syntax::RawTokenInfo fullLex();
249+
syntax::RawSyntaxInfo fullLex();
250250

251251
bool isKeepingComments() const {
252252
return RetainComments == CommentRetentionMode::ReturnAsTokens;

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1429,7 +1429,7 @@ tokenizeWithTrivia(const LangOptions &LangOpts,
14291429
void populateTokenSyntaxMap(const LangOptions &LangOpts,
14301430
const SourceManager &SM,
14311431
unsigned BufferID,
1432-
std::vector<syntax::RawTokenInfo> &Result);
1432+
std::vector<syntax::RawSyntaxInfo> &Result);
14331433
} // end namespace swift
14341434

14351435
#endif

include/swift/Syntax/SyntaxParsingContext.h

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,30 @@
2323

2424
namespace swift {
2525
class SourceFile;
26+
class Token;
2627

2728
namespace syntax {
2829

29-
struct RawTokenInfo {
30-
SourceLoc Loc;
31-
RC<RawTokenSyntax> Token;
30+
/// The handler for parser to generate libSyntax entities.
31+
struct RawSyntaxInfo {
32+
/// Start location of this syntax node.
33+
SourceLoc StartLoc;
34+
35+
/// The number of tokens belong to the syntax node.
36+
unsigned TokCount;
37+
38+
/// The raw node.
39+
RC<RawSyntax> RawNode;
40+
RawSyntaxInfo(SourceLoc StartLoc, RC<RawSyntax> RawNode):
41+
RawSyntaxInfo(StartLoc, 1, RawNode) {}
42+
RawSyntaxInfo(SourceLoc StartLoc, unsigned TokCount, RC<RawSyntax> RawNode);
43+
template <typename SyntaxNode>
44+
SyntaxNode makeSyntax() const { return make<SyntaxNode>(RawNode); }
45+
46+
template <typename RawSyntaxNode>
47+
RC<RawSyntaxNode> getRaw() const {
48+
return RC<RawSyntaxNode>(cast<RawSyntaxNode>(RawNode));
49+
}
3250
};
3351

3452
enum class SyntaxParsingContextKind: uint8_t {
@@ -40,7 +58,7 @@ enum class SyntaxParsingContextKind: uint8_t {
4058
/// create syntax nodes.
4159
class SyntaxParsingContext {
4260
protected:
43-
SyntaxParsingContext(bool Enabled);
61+
SyntaxParsingContext(SourceFile &SF, unsigned BufferID);
4462
SyntaxParsingContext(SyntaxParsingContext &Another);
4563
public:
4664
struct ContextInfo;
@@ -66,12 +84,10 @@ class SyntaxParsingContext {
6684
// of all other entity-specific contexts. This is the context Parser
6785
// has when the parser instance is firstly created.
6886
class SyntaxParsingContextRoot: public SyntaxParsingContext {
87+
SourceFile &File;
6988
public:
70-
struct GlobalInfo;
71-
72-
// Contains global information of the source file under parsing.
73-
GlobalInfo &GlobalData;
74-
SyntaxParsingContextRoot(SourceFile &SF, unsigned BufferID);
89+
SyntaxParsingContextRoot(SourceFile &File, unsigned BufferID):
90+
SyntaxParsingContext(File, BufferID), File(File) {}
7591
~SyntaxParsingContextRoot();
7692
void addTokenSyntax(SourceLoc Loc) override {};
7793
void makeNode(SyntaxKind Kind) override {};
@@ -80,21 +96,23 @@ class SyntaxParsingContextRoot: public SyntaxParsingContext {
8096
};
8197
};
8298

99+
enum class SyntaxContextKind: uint8_t{
100+
Expr,
101+
Decl,
102+
};
103+
83104
// The base class for contexts that are created from a parent context.
84105
// The stack instance will set the context holder when the context
85106
// is firstly created and reset the context holder to the parent when
86107
// it's destructed.
87108
class SyntaxParsingContextChild: public SyntaxParsingContext {
88109
SyntaxParsingContext *Parent;
89110
SyntaxParsingContext *&ContextHolder;
90-
const SyntaxKind FinalKind;
111+
const SyntaxContextKind Kind;
112+
Token &Tok;
91113
public:
92114
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
93-
SyntaxKind FinalKind):
94-
SyntaxParsingContext(*ContextHolder), Parent(ContextHolder),
95-
ContextHolder(ContextHolder), FinalKind(FinalKind) {
96-
ContextHolder = this;
97-
}
115+
SyntaxContextKind Kind, Token &Tok);
98116
~SyntaxParsingContextChild();
99117
void makeNode(SyntaxKind Kind) override;
100118
void addTokenSyntax(SourceLoc Loc) override;

lib/Parse/Lexer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ static bool rangeContainsPlaceholderEnd(const char *CurPtr,
737737
return false;
738738
}
739739

740-
syntax::RawTokenInfo Lexer::fullLex() {
740+
syntax::RawSyntaxInfo Lexer::fullLex() {
741741
if (NextToken.isEscapedIdentifier()) {
742742
LeadingTrivia.push_back(syntax::TriviaPiece::backtick());
743743
TrailingTrivia.insert(TrailingTrivia.begin(),

lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <algorithm>
3838

3939
using namespace swift;
40+
using namespace syntax;
4041

4142
namespace {
4243
/// A RAII object for deciding whether this DeclKind needs special
@@ -2146,7 +2147,8 @@ void Parser::delayParseFromBeginningToHere(ParserPosition BeginParserPosition,
21462147
ParserResult<Decl>
21472148
Parser::parseDecl(ParseDeclOptions Flags,
21482149
llvm::function_ref<void(Decl*)> Handler) {
2149-
2150+
SyntaxParsingContextChild DeclParsingContext(SyntaxContext,
2151+
SyntaxContextKind::Decl, Tok);
21502152
if (Tok.is(tok::pound_if)) {
21512153
auto IfConfigResult = parseIfConfig(
21522154
[&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {

lib/Parse/ParseExpr.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ using namespace swift::syntax;
4040
/// \param isExprBasic Whether we're only parsing an expr-basic.
4141
ParserResult<Expr> Parser::parseExprImpl(Diag<> Message, bool isExprBasic) {
4242
// Start a context for creating expression syntax.
43-
SyntaxParsingContextChild ExprParsingContext(SyntaxContext, SyntaxKind::Expr);
43+
SyntaxParsingContextChild ExprParsingContext(SyntaxContext,
44+
SyntaxContextKind::Expr, Tok);
4445

4546
// If we are parsing a refutable pattern, check to see if this is the start
4647
// of a let/var/is pattern. If so, parse it to an UnresolvedPatternExpr and
@@ -1804,7 +1805,8 @@ ParserResult<Expr> Parser::parseExprStringLiteral() {
18041805
// Create a syntax node for string literal.
18051806
SyntaxContext->addTokenSyntax(Tok.getLoc());
18061807
SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr);
1807-
SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::Expr);
1808+
SyntaxParsingContextChild LocalContext(SyntaxContext,
1809+
SyntaxContextKind::Expr, Tok);
18081810

18091811
// FIXME: Avoid creating syntax nodes for string interpolation.
18101812
LocalContext.disable();

lib/Parse/Parser.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ swift::tokenizeWithTrivia(const LangOptions &LangOpts,
268268
syntax::AbsolutePosition>> Tokens;
269269
syntax::AbsolutePosition RunningPos;
270270
do {
271-
auto ThisToken = L.fullLex().Token;
271+
auto ThisToken = L.fullLex().getRaw<syntax::RawTokenSyntax>();
272272
auto ThisTokenPos = ThisToken->accumulateAbsolutePosition(RunningPos);
273273
Tokens.push_back({ThisToken, ThisTokenPos});
274274
} while (Tokens.back().first->isNot(tok::eof));
@@ -279,15 +279,15 @@ swift::tokenizeWithTrivia(const LangOptions &LangOpts,
279279
void swift::populateTokenSyntaxMap(const LangOptions &LangOpts,
280280
const SourceManager &SM,
281281
unsigned BufferID,
282-
std::vector<syntax::RawTokenInfo> &Result) {
282+
std::vector<syntax::RawSyntaxInfo> &Result) {
283283
if (!Result.empty())
284284
return;
285285
Lexer L(LangOpts, SM, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
286286
CommentRetentionMode::AttachToNextToken,
287287
TriviaRetentionMode::WithTrivia);
288288
do {
289289
Result.emplace_back(L.fullLex());
290-
if (Result.back().Token->is(tok::eof))
290+
if (Result.back().getRaw<syntax::RawTokenSyntax>()->is(tok::eof))
291291
return;
292292
} while (true);
293293
}

0 commit comments

Comments
 (0)