Skip to content

Commit f7dafa1

Browse files
committed
libSyntax: parse codeblock syntax node.
1 parent b246cf4 commit f7dafa1

File tree

5 files changed

+135
-61
lines changed

5 files changed

+135
-61
lines changed

include/swift/Syntax/SyntaxParsingContext.h

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
#ifndef SWIFT_SYNTAX_PARSING_CONTEXT_H
1414
#define SWIFT_SYNTAX_PARSING_CONTEXT_H
1515

16-
#include "swift/Syntax/Syntax.h"
16+
#include "swift/Basic/SourceLoc.h"
17+
#include "swift/Syntax/Syntax.h"
1718

1819
namespace swift {
1920
class SourceLoc;
@@ -25,19 +26,28 @@ namespace syntax {
2526
struct RawSyntax;
2627
enum class SyntaxKind;
2728

29+
enum class SyntaxContextKind: uint8_t{
30+
Expr,
31+
Decl,
32+
Stmt,
33+
};
34+
2835
/// The handler for parser to generate libSyntax entities.
2936
struct RawSyntaxInfo {
3037
/// Start location of this syntax node.
3138
SourceLoc StartLoc;
3239

33-
/// The number of tokens belong to the syntax node.
34-
unsigned TokCount;
40+
/// The end location of this syntax node.
41+
SourceLoc EndLoc;
3542

3643
/// The raw node.
3744
RC<RawSyntax> RawNode;
45+
RawSyntaxInfo(RC<RawSyntax> RawNode): RawSyntaxInfo(SourceLoc(), RawNode) {}
3846
RawSyntaxInfo(SourceLoc StartLoc, RC<RawSyntax> RawNode):
39-
RawSyntaxInfo(StartLoc, 1, RawNode) {}
40-
RawSyntaxInfo(SourceLoc StartLoc, unsigned TokCount, RC<RawSyntax> RawNode);
47+
RawSyntaxInfo(StartLoc, StartLoc, RawNode) {}
48+
RawSyntaxInfo(SourceLoc StartLoc, SourceLoc EndLoc, RC<RawSyntax> RawNode);
49+
50+
bool isImplicit() const { return StartLoc.isInvalid(); }
4151

4252
template <typename SyntaxNode>
4353
SyntaxNode makeSyntax() const { return make<SyntaxNode>(RawNode); }
@@ -46,6 +56,7 @@ struct RawSyntaxInfo {
4656
RC<RawSyntaxNode> getRaw() const {
4757
return RC<RawSyntaxNode>(cast<RawSyntaxNode>(RawNode));
4858
}
59+
void brigeWithContext(SyntaxContextKind Kind);
4960
};
5061

5162
enum class SyntaxParsingContextKind: uint8_t {
@@ -96,22 +107,28 @@ class SyntaxParsingContextRoot: public SyntaxParsingContext {
96107
};
97108
};
98109

99-
enum class SyntaxContextKind: uint8_t{
100-
Expr,
101-
Decl,
102-
};
103-
104110
// The base class for contexts that are created from a parent context.
105111
// The stack instance will set the context holder when the context
106112
// is firstly created and reset the context holder to the parent when
107113
// it's destructed.
108114
class SyntaxParsingContextChild: public SyntaxParsingContext {
109115
SyntaxParsingContext *Parent;
110116
SyntaxParsingContext *&ContextHolder;
111-
const SyntaxContextKind Kind;
117+
Optional<SyntaxContextKind> Kind;
118+
Optional<SyntaxKind> KnownSyntax;
119+
void makeNodeWhole(SyntaxKind Kind);
120+
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
121+
Optional<SyntaxContextKind> Kind,
122+
Optional<SyntaxKind> KnownSyntax);
112123
public:
113124
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
114-
SyntaxContextKind Kind);
125+
SyntaxContextKind Kind): SyntaxParsingContextChild(ContextHolder,
126+
Kind, None) {}
127+
128+
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
129+
SyntaxKind KnownSyntax): SyntaxParsingContextChild(ContextHolder,
130+
None, KnownSyntax) {};
131+
115132
~SyntaxParsingContextChild();
116133
void makeNode(SyntaxKind Kind) override;
117134
void addTokenSyntax(SourceLoc Loc) override;

lib/Parse/ParseStmt.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@
2222
#include "swift/Parse/Lexer.h"
2323
#include "swift/Parse/CodeCompletionCallbacks.h"
2424
#include "swift/Subsystems.h"
25+
#include "swift/Syntax/TokenSyntax.h"
26+
#include "swift/Syntax/SyntaxParsingContext.h"
2527
#include "llvm/ADT/PointerUnion.h"
2628
#include "llvm/ADT/Twine.h"
2729
#include "llvm/Support/Compiler.h"
2830
#include "llvm/Support/SaveAndRestore.h"
2931

3032
using namespace swift;
33+
using namespace swift::syntax;
3134

3235
/// isStartOfStmt - Return true if the current token starts a statement.
3336
///
@@ -223,7 +226,7 @@ void Parser::consumeTopLevelDecl(ParserPosition BeginParserPosition,
223226
ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
224227
BraceItemListKind Kind,
225228
BraceItemListKind ConditionalBlockKind) {
226-
229+
SyntaxParsingContextChild StmtListContext(SyntaxContext, SyntaxKind::StmtList);
227230
bool IsTopLevel = (Kind == BraceItemListKind::TopLevelCode) ||
228231
(Kind == BraceItemListKind::TopLevelLibrary);
229232
bool isActiveConditionalBlock =
@@ -259,6 +262,7 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
259262
Tok.isNot(tok::kw_sil_default_witness_table) &&
260263
(isConditionalBlock ||
261264
!isTerminatorForBraceItemListKind(Kind, Entries))) {
265+
SyntaxParsingContextChild StmtContext(SyntaxContext, SyntaxContextKind::Stmt);
262266
if (Kind == BraceItemListKind::TopLevelLibrary &&
263267
skipExtraTopLevelRBraces())
264268
continue;
@@ -489,7 +493,7 @@ static ParserResult<Stmt> recoverFromInvalidCase(Parser &P) {
489493
}
490494

491495
ParserResult<Stmt> Parser::parseStmt() {
492-
496+
SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxContextKind::Stmt);
493497
// Note that we're parsing a statement.
494498
StructureMarkerRAII ParsingStmt(*this, Tok.getLoc(),
495499
StructureMarkerKind::Statement);
@@ -586,15 +590,19 @@ ParserResult<BraceStmt> Parser::parseBraceItemList(Diag<> ID) {
586590
if (Tok.isNot(tok::l_brace))
587591
return nullptr;
588592
}
593+
SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::CodeBlock);
589594
SourceLoc LBLoc = consumeToken(tok::l_brace);
595+
LocalContext.addTokenSyntax(LBLoc);
590596

591597
SmallVector<ASTNode, 16> Entries;
592598
SourceLoc RBLoc;
593599

594600
ParserStatus Status = parseBraceItems(Entries, BraceItemListKind::Brace,
595601
BraceItemListKind::Brace);
596-
parseMatchingToken(tok::r_brace, RBLoc,
597-
diag::expected_rbrace_in_brace_stmt, LBLoc);
602+
if (!parseMatchingToken(tok::r_brace, RBLoc,
603+
diag::expected_rbrace_in_brace_stmt, LBLoc)) {
604+
LocalContext.addTokenSyntax(RBLoc);
605+
}
598606

599607
return makeParserResult(Status,
600608
BraceStmt::create(Context, LBLoc, Entries, RBLoc));

lib/Syntax/RawSyntax.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static bool isTrivialSyntaxKind(SyntaxKind Kind) {
2929
case SyntaxKind::SourceFile:
3030
case SyntaxKind::TopLevelCodeDecl:
3131
case SyntaxKind::ExpressionStmt:
32+
case SyntaxKind::DeclarationStmt:
3233
return true;
3334
default:
3435
return false;

lib/Syntax/SyntaxParsingContext.cpp

Lines changed: 87 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,11 @@ static ArrayRef<Syntax> getSyntaxNodes(ArrayRef<RawSyntaxInfo> RawNodes,
4343
return Scratch;
4444
}
4545

46-
static unsigned countTokens(ArrayRef<RawSyntaxInfo> AllNodes) {
47-
return std::accumulate(AllNodes.begin(), AllNodes.end(), 0,
48-
[](unsigned Sum, const RawSyntaxInfo &Info) { return Sum + Info.TokCount; });
49-
}
5046
} // End of anonymous namespace
5147

52-
RawSyntaxInfo::RawSyntaxInfo(SourceLoc StartLoc, unsigned TokCount,
53-
RC<RawSyntax> RawNode): StartLoc(StartLoc), TokCount(TokCount), RawNode(RawNode) {
54-
assert(StartLoc.isValid());
48+
RawSyntaxInfo::RawSyntaxInfo(SourceLoc StartLoc, SourceLoc EndLoc,
49+
RC<RawSyntax> RawNode): StartLoc(StartLoc), EndLoc(EndLoc), RawNode(RawNode) {
50+
assert(StartLoc.isValid() == EndLoc.isValid());
5551
}
5652

5753
struct SyntaxParsingContext::ContextInfo {
@@ -66,7 +62,7 @@ struct SyntaxParsingContext::ContextInfo {
6662

6763
ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) {
6864
for (auto It = Tokens.begin(); It != Tokens.end(); It ++) {
69-
assert(It->TokCount == 1);
65+
assert(It->StartLoc == It->EndLoc);
7066
if (It->StartLoc == Loc)
7167
return It;
7268
}
@@ -98,8 +94,9 @@ struct SyntaxParsingContext::ContextInfo {
9894
ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; };
9995

10096
void addPendingSyntax(RawSyntaxInfo Info) {
101-
assert(PendingSyntax.empty() || PendingSyntax.back().StartLoc.
102-
getOpaquePointerValue() < Info.StartLoc.getOpaquePointerValue());
97+
assert(Info.isImplicit() || PendingSyntax.empty() ||
98+
PendingSyntax.back().StartLoc.getOpaquePointerValue() <
99+
Info.StartLoc.getOpaquePointerValue());
103100
PendingSyntax.push_back(Info);
104101
}
105102

@@ -139,10 +136,15 @@ SyntaxParsingContext::ContextInfo::collectAllSyntax() {
139136
// If no remaining syntax nodes, add the token.
140137
Results.emplace_back(Tok);
141138
It ++;
139+
} else if (CurSyntax->isImplicit()) {
140+
// Skip implicit syntax node.
141+
CurSyntax ++;
142142
} else if (CurSyntax->StartLoc == Tok.StartLoc) {
143143
// Prefer syntax nodes to tokens.
144144
Results.emplace_back(*CurSyntax);
145-
It += CurSyntax->TokCount;
145+
while(It->EndLoc != CurSyntax->EndLoc) It++;
146+
assert(It < Tokens.end() && It->EndLoc == CurSyntax->EndLoc);
147+
It ++;
146148
CurSyntax ++;
147149
} else {
148150
// We have to add token in this case since the next syntax node has not
@@ -178,7 +180,7 @@ SyntaxParsingContext::ContextInfo::createFromBack(SyntaxKind Kind, unsigned N) {
178180
Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
179181
SyntaxParts));
180182
}
181-
RawSyntaxInfo NewSyntaxNode(Parts.front().StartLoc, countTokens(Parts),
183+
RawSyntaxInfo NewSyntaxNode(Parts.front().StartLoc, Parts.back().EndLoc,
182184
Result->getRaw());
183185
// Remove the building bricks and re-append the result.
184186
for (unsigned I = 0; I < N; I ++)
@@ -209,26 +211,9 @@ SyntaxParsingContextRoot::~SyntaxParsingContextRoot() {
209211
}
210212
}
211213
for (auto Info: ContextData.getPendingSyntax()) {
212-
std::vector<StmtSyntax> AllStmts;
213-
auto S = Info.makeSyntax<Syntax>();
214-
if (S.isDecl()) {
215-
AllStmts.push_back(SyntaxFactory::makeDeclarationStmt(
216-
S.getAs<DeclSyntax>().getValue(), None));
217-
} else if (S.isExpr()) {
218-
AllStmts.push_back(SyntaxFactory::makeExpressionStmt(
219-
S.getAs<ExprSyntax>().getValue(), None));
220-
} else if (S.isStmt()) {
221-
AllStmts.push_back(S.getAs<StmtSyntax>().getValue());
222-
} else {
223-
// If this is a standalone token, we create an unknown expression wrapper
224-
// for it.
225-
AllStmts.push_back(SyntaxFactory::makeExpressionStmt(
226-
*makeUnknownSyntax(SyntaxKind::UnknownExpr,
227-
{ *S.getAs<TokenSyntax>() }).getAs<ExprSyntax>(),
228-
None));
229-
}
214+
assert(Info.RawNode->Kind == SyntaxKind::StmtList);
230215
AllTopLevel.push_back(SyntaxFactory::makeTopLevelCodeDecl(
231-
SyntaxFactory::makeStmtList(AllStmts)));
216+
Info.makeSyntax<StmtListSyntax>()));
232217
}
233218

234219
File.setSyntaxRoot(
@@ -248,14 +233,16 @@ SyntaxParsingContextRoot &SyntaxParsingContextChild::getRoot() {
248233

249234
SyntaxParsingContextChild::
250235
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
251-
SyntaxContextKind Kind):
236+
Optional<SyntaxContextKind> Kind, Optional<SyntaxKind> KnownSyntax):
252237
SyntaxParsingContext(*ContextHolder), Parent(ContextHolder),
253-
ContextHolder(ContextHolder), Kind(Kind) {
238+
ContextHolder(ContextHolder), Kind(Kind), KnownSyntax(KnownSyntax) {
239+
assert(Kind.hasValue() != KnownSyntax.hasValue());
254240
ContextHolder = this;
255241
if (ContextData.Enabled)
256242
ContextData.setContextStart(Tok.getLoc());
257243
}
258244

245+
259246
void SyntaxParsingContextChild::addTokenSyntax(SourceLoc Loc) {
260247
if (ContextData.Enabled)
261248
ContextData.promoteTokenAt(Loc);
@@ -281,6 +268,48 @@ void SyntaxParsingContextChild::makeNode(SyntaxKind Kind) {
281268
}
282269

283270
default:
271+
llvm_unreachable("Unrecognized node kind.");
272+
}
273+
}
274+
275+
void SyntaxParsingContextChild::makeNodeWhole(SyntaxKind Kind) {
276+
assert(ContextData.Enabled);
277+
switch (Kind) {
278+
case SyntaxKind::CodeBlock: {
279+
ContextData.createFromBack(Kind);
280+
break;
281+
}
282+
case SyntaxKind::StmtList: {
283+
if (ContextData.getPendingSyntax().empty()) {
284+
// Create an empty statement list if no statement is in the context.
285+
ContextData.addPendingSyntax({SyntaxFactory::makeBlankStmtList().getRaw()});
286+
} else {
287+
ContextData.createFromBack(Kind);
288+
}
289+
break;
290+
}
291+
default:
292+
llvm_unreachable("Unrecognized node kind.");
293+
}
294+
}
295+
296+
void RawSyntaxInfo::brigeWithContext(SyntaxContextKind Kind) {
297+
switch (Kind) {
298+
case SyntaxContextKind::Stmt: {
299+
if (RawNode->isDecl()) {
300+
// Wrap a declaration with a declaration statement
301+
RawNode = SyntaxFactory::createSyntax(SyntaxKind::DeclarationStmt,
302+
{ makeSyntax<Syntax>() })->getRaw();
303+
} else if (RawNode->isExpr()) {
304+
// Wrap an expression with an expression statement
305+
RawNode = SyntaxFactory::createSyntax(SyntaxKind::ExpressionStmt,
306+
{ makeSyntax<Syntax>() })->getRaw();
307+
}
308+
assert(RawNode->isStmt());
309+
break;
310+
}
311+
case SyntaxContextKind::Decl:
312+
case SyntaxContextKind::Expr:
284313
break;
285314
}
286315
}
@@ -295,32 +324,51 @@ SyntaxParsingContextChild::~SyntaxParsingContextChild() {
295324

296325
// Set the end of the context.
297326
ContextData.setContextEnd(Tok.getLoc());
327+
if (KnownSyntax) {
328+
// If the entire context should be created to a known syntax kind, create
329+
// all pending syntax nodes into that node.
330+
makeNodeWhole(*KnownSyntax);
331+
assert(ContextData.getPendingSyntax().size() == 1);
332+
auto AllNodes = ContextData.collectAllSyntax();
333+
assert(AllNodes.size() == 1);
334+
Parent->ContextData.addPendingSyntax(AllNodes.front());
335+
return;
336+
}
298337
auto AllNodes = ContextData.collectAllSyntax();
299-
assert(countTokens(AllNodes) == ContextData.allTokens().size());
300338
RC<RawSyntax> FinalResult;
301339
if (AllNodes.empty())
302340
return;
303341

342+
// Make sure we used all tokens.
343+
assert(AllNodes.front().StartLoc == ContextData.allTokens().front().StartLoc);
344+
assert(AllNodes.back().EndLoc == ContextData.allTokens().back().StartLoc);
345+
304346
if (AllNodes.size() == 1) {
305-
// FIXME: Check kind
306-
Parent->ContextData.addPendingSyntax(AllNodes.front());
347+
// If we have only one syntax node remaining, we are done.
348+
auto Result = AllNodes.front();
349+
// Bridge the syntax node to the expected context kind.
350+
Result.brigeWithContext(*Kind);
351+
Parent->ContextData.addPendingSyntax(Result);
307352
return;
308353
}
309354

310355
llvm::SmallVector<Syntax, 8> Scratch;
311356
auto SyntaxNodes = getSyntaxNodes(AllNodes, Scratch);
312357
SourceLoc Start = AllNodes.front().StartLoc;
313-
unsigned TokCount = countTokens(AllNodes);
358+
SourceLoc End = AllNodes.back().EndLoc;
314359
SyntaxKind UnknownKind;
315-
switch (Kind) {
360+
switch (*Kind) {
316361
case SyntaxContextKind::Expr:
317362
UnknownKind = SyntaxKind::UnknownExpr;
318363
break;
319364
case SyntaxContextKind::Decl:
320365
UnknownKind = SyntaxKind::UnknownDecl;
321366
break;
367+
case SyntaxContextKind::Stmt:
368+
UnknownKind = SyntaxKind::UnknownStmt;
369+
break;
322370
}
323371
// Create an unknown node and give it to the parent context.
324-
Parent->ContextData.addPendingSyntax({Start, TokCount,
372+
Parent->ContextData.addPendingSyntax({Start, End,
325373
makeUnknownSyntax(UnknownKind, SyntaxNodes).getRaw()});
326374
}

0 commit comments

Comments
 (0)