Skip to content

Commit 6a07ac5

Browse files
committed
Migrate isStartOfStatement to RawTokenKindSubset
1 parent f27de16 commit 6a07ac5

File tree

6 files changed

+86
-104
lines changed

6 files changed

+86
-104
lines changed

Sources/SwiftParser/Expressions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,7 @@ extension Parser {
16731673
// If The next token is at the beginning of a new line and can never start
16741674
// an element, break.
16751675
if self.currentToken.isAtStartOfLine
1676-
&& (self.at(any: [.rightBrace, .poundEndifKeyword]) || self.lookahead().isStartOfDeclaration() || self.lookahead().isStartOfStatement()) {
1676+
&& (self.at(any: [.rightBrace, .poundEndifKeyword]) || self.lookahead().isStartOfDeclaration() || self.atStartOfStatement()) {
16771677
break
16781678
}
16791679
}

Sources/SwiftParser/Lookahead.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ extension Parser {
4242

4343
/// Initiates a lookahead session from the current point in this
4444
/// lookahead session.
45-
func lookahead() -> Lookahead {
45+
public func lookahead() -> Lookahead {
4646
return Lookahead(lexemes: self.lexemes, currentToken: self.currentToken)
4747
}
4848
}

Sources/SwiftParser/RawTokenKindSubset.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,53 @@ enum CanBeDeclaratinStart: RawTokenKindSubset {
170170
}
171171
}
172172

173+
enum CanBeStatementStart: RawTokenKindSubset {
174+
case breakKeyword
175+
case continueKeyword
176+
case deferKeyword
177+
case doKeyword
178+
case fallthroughKeyword
179+
case forKeyword
180+
case guardKeyword
181+
case ifKeyword
182+
case poundAssertKeyword
183+
case repeatKeyword
184+
case returnKeyword
185+
case switchKeyword
186+
case throwKeyword
187+
case whileKeyword
188+
case yield
189+
case yieldAsIdentifier
190+
191+
var rawTokenKind: RawTokenKind {
192+
switch self {
193+
case .breakKeyword: return .breakKeyword
194+
case .continueKeyword: return .continueKeyword
195+
case .deferKeyword: return .deferKeyword
196+
case .doKeyword: return .doKeyword
197+
case .fallthroughKeyword: return .fallthroughKeyword
198+
case .forKeyword: return .forKeyword
199+
case .guardKeyword: return .guardKeyword
200+
case .ifKeyword: return .ifKeyword
201+
case .poundAssertKeyword: return .poundAssertKeyword
202+
case .repeatKeyword: return .repeatKeyword
203+
case .returnKeyword: return .returnKeyword
204+
case .switchKeyword: return .switchKeyword
205+
case .throwKeyword: return .throwKeyword
206+
case .whileKeyword: return .whileKeyword
207+
case .yield: return .yield
208+
case .yieldAsIdentifier: return .identifier
209+
}
210+
}
211+
212+
var contextualKeyword: SyntaxText? {
213+
switch self {
214+
case .yieldAsIdentifier: return "yield"
215+
default: return nil
216+
}
217+
}
218+
}
219+
173220
enum ContextualDeclKeyword: SyntaxText, ContextualKeywords {
174221
case __consuming = "__consuming"
175222
case _compilerInitialized = "_compilerInitialized"

Sources/SwiftParser/Statements.swift

Lines changed: 33 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,26 @@
1212

1313
@_spi(RawSyntax) import SwiftSyntax
1414

15+
extension TokenConsumer {
16+
/// Returns `true` if the current token represents the start of a statement
17+
/// item.
18+
///
19+
/// - Note: This function must be kept in sync with `parseStatement()`.
20+
/// - Seealso: ``Parser/parseStatement()``
21+
func atStartOfStatement() -> Bool {
22+
var lookahead = self.lookahead()
23+
_ = lookahead.consume(if: .identifier, followedBy: .colon)
24+
return lookahead.at(anyIn: CanBeStatementStart.self) != nil
25+
}
26+
}
27+
1528
extension Parser {
1629
/// Parse a statement.
1730
///
1831
/// This function is meant to be invoked as part of parsing an item. As such
1932
/// it does not deal with parsing expressions, declarations, or consuming
2033
/// any trailing semicolons.
2134
///
22-
/// - Note: This function must be kept in sync with ``Parser/Lookahead/isStartOfStatement()``
23-
/// - Seealso: ``Parser/Lookahead/isStartOfStatement()``
24-
///
2535
/// Grammar
2636
/// =======
2737
///
@@ -67,45 +77,44 @@ extension Parser {
6777
}
6878

6979
let optLabel = self.parseOptionalStatementLabel()
70-
switch self.currentToken.tokenKind {
71-
case .forKeyword:
80+
switch self.at(anyIn: CanBeStatementStart.self) {
81+
case (.forKeyword, _)?:
7282
return label(self.parseForEachStatement(), with: optLabel)
73-
case .whileKeyword:
83+
case (.whileKeyword, _)?:
7484
return label(self.parseWhileStatement(), with: optLabel)
75-
case .repeatKeyword:
85+
case (.repeatKeyword, _)?:
7686
return label(self.parseRepeatWhileStatement(), with: optLabel)
7787

78-
case .ifKeyword:
88+
case (.ifKeyword, _)?:
7989
return label(self.parseIfStatement(), with: optLabel)
80-
case .guardKeyword:
90+
case (.guardKeyword, _)?:
8191
return label(self.parseGuardStatement(), with: optLabel)
82-
case .switchKeyword:
92+
case (.switchKeyword, _)?:
8393
return label(self.parseSwitchStatement(), with: optLabel)
8494

85-
case .breakKeyword:
95+
case (.breakKeyword, _)?:
8696
return label(self.parseBreakStatement(), with: optLabel)
87-
case .continueKeyword:
97+
case (.continueKeyword, _)?:
8898
return label(self.parseContinueStatement(), with: optLabel)
89-
case .fallthroughKeyword:
99+
case (.fallthroughKeyword, _)?:
90100
return label(self.parseFallthroughStatement(), with: optLabel)
91-
case .returnKeyword:
101+
case (.returnKeyword, _)?:
92102
return label(self.parseReturnStatement(), with: optLabel)
93-
case .throwKeyword:
103+
case (.throwKeyword, _)?:
94104
return label(self.parseThrowStatement(), with: optLabel)
95-
case .deferKeyword:
105+
case (.deferKeyword, _)?:
96106
return label(self.parseDeferStatement(), with: optLabel)
97-
case .doKeyword:
107+
case (.doKeyword, _)?:
98108
return label(self.parseDoStatement(), with: optLabel)
99109

100-
case .poundAssertKeyword:
110+
case (.poundAssertKeyword, _)?:
101111
// FIXME: This drops `optLabel`.
102112
return RawStmtSyntax(self.parsePoundAssertStatement())
103-
case _ where self.atContextualKeyword("yield"):
104-
fallthrough
105-
case .yield:
113+
case (.yieldAsIdentifier, _)?,
114+
(.yield, _)?:
106115
// FIXME: This drops `optLabel`.
107116
return RawStmtSyntax(self.parseYieldStatement())
108-
default:
117+
case nil:
109118
let missingStmt = RawStmtSyntax(RawMissingStmtSyntax(arena: self.arena))
110119
return label(missingStmt, with: optLabel)
111120
}
@@ -824,7 +833,7 @@ extension Parser {
824833
.poundIfKeyword, .poundErrorKeyword, .poundWarningKeyword,
825834
.poundEndifKeyword, .poundElseKeyword, .poundElseifKeyword
826835
])
827-
&& !self.lookahead().isStartOfStatement() && !self.lookahead().isStartOfDeclaration() {
836+
&& !self.atStartOfStatement() && !self.lookahead().isStartOfDeclaration() {
828837
expr = self.parseExpression()
829838
} else {
830839
expr = nil
@@ -982,7 +991,7 @@ extension Parser {
982991

983992
guard
984993
self.at(.identifier) &&
985-
!self.lookahead().isStartOfStatement() &&
994+
!self.atStartOfStatement() &&
986995
!self.lookahead().isStartOfDeclaration()
987996
else {
988997
return nil
@@ -1023,82 +1032,6 @@ extension Parser {
10231032
// MARK: Lookahead
10241033

10251034
extension Parser.Lookahead {
1026-
/// Returns `true` if the current token represents the start of a statement
1027-
/// item.
1028-
///
1029-
/// - Note: This function must be kept in sync with `parseStatement()`.
1030-
/// - Seealso: ``Parser/parseStatement()``
1031-
public func isStartOfStatement() -> Bool {
1032-
switch self.currentToken.tokenKind {
1033-
case .returnKeyword,
1034-
.throwKeyword,
1035-
.deferKeyword,
1036-
.ifKeyword,
1037-
.guardKeyword,
1038-
.whileKeyword,
1039-
.doKeyword,
1040-
.repeatKeyword,
1041-
.forKeyword,
1042-
.breakKeyword,
1043-
.continueKeyword,
1044-
.fallthroughKeyword,
1045-
.switchKeyword,
1046-
.caseKeyword,
1047-
.defaultKeyword,
1048-
.yield,
1049-
.poundAssertKeyword,
1050-
.poundIfKeyword,
1051-
.poundWarningKeyword,
1052-
.poundErrorKeyword,
1053-
.poundSourceLocationKeyword:
1054-
return true
1055-
1056-
case .poundLineKeyword:
1057-
// #line at the start of a line is a directive, when within, it is an expr.
1058-
return self.currentToken.isAtStartOfLine
1059-
1060-
case .identifier:
1061-
// "identifier ':' for/while/do/switch" is a label on a loop/switch.
1062-
guard self.peek().tokenKind == .colon else {
1063-
// "yield" in the right context begins a yield statement.
1064-
if self.atContextualKeyword("yield") {
1065-
return true
1066-
}
1067-
return false
1068-
}
1069-
1070-
// To disambiguate other cases of "identifier :", which might be part of a
1071-
// question colon expression or something else, we look ahead to the second
1072-
// token.
1073-
var backtrack = self.lookahead()
1074-
backtrack.expectIdentifierWithoutRecovery()
1075-
backtrack.eat(.colon)
1076-
1077-
// We treating IDENTIFIER: { as start of statement to provide missed 'do'
1078-
// diagnostics. This case will be handled in parseStmt().
1079-
if self.at(.leftBrace) {
1080-
return true
1081-
}
1082-
// For better recovery, we just accept a label on any statement. We reject
1083-
// putting a label on something inappropriate in parseStmt().
1084-
return backtrack.isStartOfStatement()
1085-
1086-
case .atSign:
1087-
// Might be a statement or case attribute. The only one of these we have
1088-
// right now is `@unknown default`, so hardcode a check for an attribute
1089-
// without any parens.
1090-
guard self.peek().tokenKind == .identifier else {
1091-
return false
1092-
}
1093-
var backtrack = self.lookahead()
1094-
backtrack.eat(.atSign)
1095-
backtrack.expectIdentifierWithoutRecovery()
1096-
return backtrack.isStartOfStatement()
1097-
default:
1098-
return false
1099-
}
1100-
}
1101-
11021035
func isBooleanExpr() -> Bool {
11031036
var lookahead = self.lookahead()
11041037
return !lookahead.canParseTypedPattern() || !lookahead.at(.equal)

Sources/SwiftParser/TokenConsumer.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ public protocol TokenConsumer {
3030
mutating func missingToken(_ kind: RawTokenKind, text: SyntaxText?) -> Token
3131

3232
/// Return the lexeme that will be parsed next.
33-
mutating func peek() -> Lexer.Lexeme
33+
func peek() -> Lexer.Lexeme
34+
35+
func lookahead() -> Parser.Lookahead
3436
}
3537

3638
// MARK: Checking if we are at one specific token (`at`)

Sources/SwiftParser/TopLevel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ extension Parser {
138138
return RawSyntax(self.parsePoundSourceLocationDirective())
139139
} else if self.lookahead().isStartOfDeclaration() {
140140
return RawSyntax(self.parseDeclaration())
141-
} else if self.lookahead().isStartOfStatement() {
141+
} else if self.atStartOfStatement() {
142142
return RawSyntax(self.parseStatement())
143143
} else {
144144
return RawSyntax(self.parseExpression())

0 commit comments

Comments
 (0)