Skip to content

Commit 845a4e4

Browse files
committed
Formalize Labeled Syntax
This represents labeled statements as an explicit kind of statement and removes the Labeled trait. Any kind of statement is allowed to be labeled in the tree, but we specifically diagnose the syntax elements that aren't allowed to have labels. This homogenizes the way clients deal with statement labels and also makes parser recovery quite a bit easier in the case where we have a label but no actual statement following it.
1 parent 0b32290 commit 845a4e4

File tree

6 files changed

+33
-52
lines changed

6 files changed

+33
-52
lines changed

lib/Parse/ParseStmt.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -524,22 +524,24 @@ static ParserResult<Stmt> recoverFromInvalidCase(Parser &P) {
524524
ParserResult<Stmt> Parser::parseStmt() {
525525
AssertParserMadeProgressBeforeLeavingScopeRAII apmp(*this);
526526

527-
SyntaxParsingContext LocalContext(SyntaxContext, SyntaxContextKind::Stmt);
528-
529-
// Note that we're parsing a statement.
530-
StructureMarkerRAII ParsingStmt(*this, Tok.getLoc(),
531-
StructureMarkerKind::Statement);
532-
533-
LabeledStmtInfo LabelInfo;
534-
535527
// If this is a label on a loop/switch statement, consume it and pass it into
536528
// parsing logic below.
529+
SyntaxParsingContext LabelContext(SyntaxContext, SyntaxKind::LabeledStmt);
530+
LabeledStmtInfo LabelInfo;
537531
if (Tok.is(tok::identifier) && peekToken().is(tok::colon)) {
538532
LabelInfo.Loc = consumeIdentifier(LabelInfo.Name,
539533
/*diagnoseDollarPrefix=*/true);
540534
consumeToken(tok::colon);
535+
} else {
536+
LabelContext.setTransparent();
541537
}
542538

539+
SyntaxParsingContext LocalContext(SyntaxContext, SyntaxContextKind::Stmt);
540+
541+
// Note that we're parsing a statement.
542+
StructureMarkerRAII ParsingStmt(*this, Tok.getLoc(),
543+
StructureMarkerKind::Statement);
544+
543545
SourceLoc tryLoc;
544546
(void)consumeIf(tok::kw_try, tryLoc);
545547

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -345,19 +345,19 @@ func statementTests<FunctionSignature><ParameterClause>() </ParameterClause></Fu
345345
} </CodeBlock></CatchClause><CatchClause>catch <CatchItem><ExpressionPattern><FunctionCallExpr><MemberAccessExpr>.a</MemberAccessExpr>(<TupleExprElement><UnresolvedPatternExpr><ValueBindingPattern>let <IdentifierPattern>a</IdentifierPattern></ValueBindingPattern></UnresolvedPatternExpr></TupleExprElement>)</FunctionCallExpr></ExpressionPattern>, </CatchItem><CatchItem><ExpressionPattern><FunctionCallExpr><MemberAccessExpr>.b</MemberAccessExpr>(<TupleExprElement><UnresolvedPatternExpr><ValueBindingPattern>let <IdentifierPattern>b</IdentifierPattern></ValueBindingPattern></UnresolvedPatternExpr></TupleExprElement>) </FunctionCallExpr></ExpressionPattern><WhereClause>where <SequenceExpr><IdentifierExpr>b </IdentifierExpr><BinaryOperatorExpr>== </BinaryOperatorExpr><StringLiteralExpr>"<StringSegment></StringSegment>" </StringLiteralExpr></SequenceExpr></WhereClause></CatchItem><CodeBlock>{
346346
} </CodeBlock></CatchClause><CatchClause>catch <CatchItem></CatchItem><CodeBlock>{
347347
}</CodeBlock></CatchClause></DoStmt><RepeatWhileStmt>
348-
repeat <CodeBlock>{ } </CodeBlock>while <BooleanLiteralExpr>true</BooleanLiteralExpr></RepeatWhileStmt><RepeatWhileStmt>
349-
LABEL: repeat <CodeBlock>{ } </CodeBlock>while <BooleanLiteralExpr>false</BooleanLiteralExpr></RepeatWhileStmt><WhileStmt>
350-
while <ConditionElement><BooleanLiteralExpr>true </BooleanLiteralExpr></ConditionElement><CodeBlock>{ }</CodeBlock></WhileStmt><WhileStmt>
351-
LABEL: while <ConditionElement><BooleanLiteralExpr>true </BooleanLiteralExpr></ConditionElement><CodeBlock>{ }</CodeBlock></WhileStmt><DoStmt>
352-
LABEL: do <CodeBlock>{}</CodeBlock></DoStmt><SwitchStmt>
353-
LABEL: switch <IdentifierExpr>foo </IdentifierExpr>{<SwitchCase><SwitchCaseLabel>
348+
repeat <CodeBlock>{ } </CodeBlock>while <BooleanLiteralExpr>true</BooleanLiteralExpr></RepeatWhileStmt><LabeledStmt>
349+
LABEL: <RepeatWhileStmt>repeat <CodeBlock>{ } </CodeBlock>while <BooleanLiteralExpr>false</BooleanLiteralExpr></RepeatWhileStmt></LabeledStmt><WhileStmt>
350+
while <ConditionElement><BooleanLiteralExpr>true </BooleanLiteralExpr></ConditionElement><CodeBlock>{ }</CodeBlock></WhileStmt><LabeledStmt>
351+
LABEL: <WhileStmt>while <ConditionElement><BooleanLiteralExpr>true </BooleanLiteralExpr></ConditionElement><CodeBlock>{ }</CodeBlock></WhileStmt></LabeledStmt><LabeledStmt>
352+
LABEL: <DoStmt>do <CodeBlock>{}</CodeBlock></DoStmt></LabeledStmt><LabeledStmt>
353+
LABEL: <SwitchStmt>switch <IdentifierExpr>foo </IdentifierExpr>{<SwitchCase><SwitchCaseLabel>
354354
case <CaseItem><ExpressionPattern><IntegerLiteralExpr>1</IntegerLiteralExpr></ExpressionPattern></CaseItem>:</SwitchCaseLabel><FallthroughStmt>
355355
fallthrough</FallthroughStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
356356
case <CaseItem><ExpressionPattern><IntegerLiteralExpr>2</IntegerLiteralExpr></ExpressionPattern></CaseItem>:</SwitchCaseLabel><BreakStmt>
357357
break LABEL</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
358358
case <CaseItem><ExpressionPattern><IntegerLiteralExpr>3</IntegerLiteralExpr></ExpressionPattern></CaseItem>:</SwitchCaseLabel><BreakStmt>
359359
break</BreakStmt></SwitchCase>
360-
}</SwitchStmt><ForInStmt>
360+
}</SwitchStmt></LabeledStmt><ForInStmt>
361361

362362
for <IdentifierPattern>a </IdentifierPattern>in <IdentifierExpr>b </IdentifierExpr><CodeBlock>{<DeferStmt>
363363
defer <CodeBlock>{ <TupleExpr>() </TupleExpr>}</CodeBlock></DeferStmt><IfStmt>

utils/gyb_syntax_support/NodeSerializationCodes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@
268268
'MissingType': 264,
269269
'MissingPattern': 265,
270270
'GarbageNodes' : 266,
271+
'LabeledStmt': 267,
271272
}
272273

273274

utils/gyb_syntax_support/PatternNodes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373

7474
# tuple-pattern-element -> identifier? ':' pattern ','?
7575
Node('TuplePatternElement', kind='Syntax',
76-
traits=['WithTrailingComma', 'Labeled'],
76+
traits=['WithTrailingComma'],
7777
children=[
7878
Child('LabelName', kind='IdentifierToken',
7979
is_optional=True),

utils/gyb_syntax_support/StmtNodes.py

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
from .Node import Node # noqa: I201
33

44
STMT_NODES = [
5+
# labeled-stmt -> label ':' stmt
6+
Node('LabeledStmt', kind='Stmt',
7+
children=[
8+
Child('LabelName', kind='IdentifierToken'),
9+
Child('LabelColon', kind='ColonToken'),
10+
Child('Statement', kind='Stmt'),
11+
]),
12+
513
# continue-stmt -> 'continue' label? ';'?
614
Node('ContinueStmt', kind='Stmt',
715
children=[
@@ -12,12 +20,8 @@
1220

1321
# while-stmt -> label? ':'? 'while' condition-list code-block ';'?
1422
Node('WhileStmt', kind='Stmt',
15-
traits=['WithCodeBlock', 'Labeled'],
23+
traits=['WithCodeBlock'],
1624
children=[
17-
Child('LabelName', kind='IdentifierToken',
18-
is_optional=True),
19-
Child('LabelColon', kind='ColonToken',
20-
is_optional=True),
2125
Child('WhileKeyword', kind='WhileToken'),
2226
Child('Conditions', kind='ConditionElementList',
2327
collection_element_name='Condition'),
@@ -46,12 +50,8 @@
4650

4751
# repeat-while-stmt -> label? ':'? 'repeat' code-block 'while' expr ';'?
4852
Node('RepeatWhileStmt', kind='Stmt',
49-
traits=['WithCodeBlock', 'Labeled'],
53+
traits=['WithCodeBlock'],
5054
children=[
51-
Child('LabelName', kind='IdentifierToken',
52-
is_optional=True),
53-
Child('LabelColon', kind='ColonToken',
54-
is_optional=True),
5555
Child('RepeatKeyword', kind='RepeatToken'),
5656
Child('Body', kind='CodeBlock'),
5757
Child('WhileKeyword', kind='WhileToken'),
@@ -79,12 +79,8 @@
7979
# 'for' 'try'? 'await'? 'case'? pattern 'in' expr 'where'?
8080
# expr code-block ';'?
8181
Node('ForInStmt', kind='Stmt',
82-
traits=['WithCodeBlock', 'Labeled'],
82+
traits=['WithCodeBlock'],
8383
children=[
84-
Child('LabelName', kind='IdentifierToken',
85-
is_optional=True),
86-
Child('LabelColon', kind='ColonToken',
87-
is_optional=True),
8884
Child('ForKeyword', kind='ForToken'),
8985
Child('TryKeyword', kind='TryToken',
9086
is_optional=True),
@@ -106,12 +102,8 @@
106102
# switch-stmt -> identifier? ':'? 'switch' expr '{'
107103
# switch-case-list '}' ';'?
108104
Node('SwitchStmt', kind='Stmt',
109-
traits=['Braced', 'Labeled'],
105+
traits=['Braced'],
110106
children=[
111-
Child('LabelName', kind='IdentifierToken',
112-
is_optional=True),
113-
Child('LabelColon', kind='ColonToken',
114-
is_optional=True),
115107
Child('SwitchKeyword', kind='SwitchToken'),
116108
Child('Expression', kind='Expr'),
117109
Child('LeftBrace', kind='LeftBraceToken'),
@@ -127,12 +119,8 @@
127119

128120
# do-stmt -> identifier? ':'? 'do' code-block catch-clause-list ';'?
129121
Node('DoStmt', kind='Stmt',
130-
traits=['WithCodeBlock', 'Labeled'],
122+
traits=['WithCodeBlock'],
131123
children=[
132-
Child('LabelName', kind='IdentifierToken',
133-
is_optional=True),
134-
Child('LabelColon', kind='ColonToken',
135-
is_optional=True),
136124
Child('DoKeyword', kind='DoToken'),
137125
Child('Body', kind='CodeBlock'),
138126
Child('CatchClauses', kind='CatchClauseList',
@@ -272,12 +260,8 @@
272260
# if-stmt -> identifier? ':'? 'if' condition-list code-block
273261
# else-clause ';'?
274262
Node('IfStmt', kind='Stmt',
275-
traits=['WithCodeBlock', 'Labeled'],
263+
traits=['WithCodeBlock'],
276264
children=[
277-
Child('LabelName', kind='IdentifierToken',
278-
is_optional=True),
279-
Child('LabelColon', kind='ColonToken',
280-
is_optional=True),
281265
Child('IfKeyword', kind='IfToken'),
282266
Child('Conditions', kind='ConditionElementList',
283267
collection_element_name='Condition'),

utils/gyb_syntax_support/Traits.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ def __init__(self, trait_name, description=None, children=None):
4343
Child('TrailingComma', kind='CommaToken', is_optional=True),
4444
]),
4545

46-
Trait('Labeled',
47-
children=[
48-
Child('LabelName', kind='IdentifierToken', is_optional=True),
49-
Child('LabelColon', kind='ColonToken', is_optional=True),
50-
]),
51-
5246
Trait('WithStatements',
5347
children=[
5448
Child('Statements', kind='CodeBlockItemList'),

0 commit comments

Comments
 (0)