@@ -63,37 +63,7 @@ extension TokenConsumer {
63
63
64
64
var subparser = self . lookahead ( )
65
65
66
- var hasAttribute = false
67
- var attributeProgress = LoopProgressCondition ( )
68
- while subparser. hasProgressed ( & attributeProgress) {
69
- if subparser. at ( . atSign) {
70
- _ = subparser. consumeAttributeList ( )
71
- hasAttribute = true
72
- } else if subparser. at ( . poundIf) && subparser. consumeIfConfigOfAttributes ( ) {
73
- subparser. skipSingle ( )
74
- hasAttribute = true
75
- } else {
76
- break
77
- }
78
- }
79
-
80
- var hasModifier = false
81
- if subparser. currentToken. isLexerClassifiedKeyword || subparser. currentToken. rawTokenKind == . identifier {
82
- var modifierProgress = LoopProgressCondition ( )
83
- while let ( modifierKind, handle) = subparser. at ( anyIn: DeclarationModifier . self) ,
84
- modifierKind != . class,
85
- subparser. hasProgressed ( & modifierProgress)
86
- {
87
- hasModifier = true
88
- subparser. eat ( handle)
89
- if modifierKind != . open && subparser. at ( . leftParen) && modifierKind. canHaveParenthesizedArgument {
90
- // When determining whether we are at a declaration, don't consume anything in parentheses after 'open'
91
- // so we don't consider a function call to open as a decl modifier. This matches the C++ parser.
92
- subparser. consumeAnyToken ( )
93
- subparser. consume ( to: . rightParen)
94
- }
95
- }
96
- }
66
+ let ( hasAttribute, hasModifier) = subparser. skipAttributesAndModifiers ( )
97
67
98
68
if hasAttribute {
99
69
if subparser. at ( . rightBrace) || subparser. at ( . endOfFile) || subparser. at ( . poundEndif) {
@@ -118,17 +88,7 @@ extension TokenConsumer {
118
88
switch declStartKeyword {
119
89
case . lhs( . actor ) :
120
90
// actor Foo {}
121
- if subparser. peek ( ) . rawTokenKind == . identifier {
122
- return true
123
- }
124
- // actor may be somewhere in the modifier list. Eat the tokens until we get
125
- // to something that isn't the start of a decl. If that is an identifier,
126
- // it's an actor declaration, otherwise, it isn't.
127
- var lookahead = subparser. lookahead ( )
128
- repeat {
129
- lookahead. consumeAnyToken ( )
130
- } while lookahead. atStartOfDeclaration ( isAtTopLevel: isAtTopLevel, allowInitDecl: allowInitDecl)
131
- return lookahead. at ( . identifier)
91
+ return subparser. atStartOfActor ( isAtTopLevel: isAtTopLevel, allowInitDecl: allowInitDecl)
132
92
case . lhs( . case) :
133
93
// When 'case' appears inside a function, it's probably a switch
134
94
// case, not an enum case declaration.
@@ -152,23 +112,7 @@ extension TokenConsumer {
152
112
return false
153
113
}
154
114
155
- var lookahead = subparser. lookahead ( )
156
-
157
- // Consume 'using'
158
- lookahead. consumeAnyToken ( )
159
-
160
- // Allow parsing 'using' as declaration only if
161
- // it's immediately followed by either `@` or
162
- // an identifier.
163
- if lookahead. atStartOfLine {
164
- return false
165
- }
166
-
167
- guard lookahead. at ( . atSign) || lookahead. at ( . identifier) else {
168
- return false
169
- }
170
-
171
- return true
115
+ return subparser. atStartOfUsing ( )
172
116
case . some( _) :
173
117
// All other decl start keywords unconditionally start a decl.
174
118
return true
@@ -190,6 +134,81 @@ extension TokenConsumer {
190
134
}
191
135
}
192
136
137
+ extension Parser . Lookahead {
138
+ fileprivate mutating func skipAttributesAndModifiers( ) -> ( hasAttribute: Bool , hasModifier: Bool ) {
139
+ var hasAttribute = false
140
+ var attributeProgress = LoopProgressCondition ( )
141
+ while self . hasProgressed ( & attributeProgress) {
142
+ if self . at ( . atSign) {
143
+ _ = self . consumeAttributeList ( )
144
+ hasAttribute = true
145
+ } else if self . at ( . poundIf) && self . consumeIfConfigOfAttributes ( ) {
146
+ self . skipSingle ( )
147
+ hasAttribute = true
148
+ } else {
149
+ break
150
+ }
151
+ }
152
+
153
+ var hasModifier = false
154
+ if self . currentToken. isLexerClassifiedKeyword || self . currentToken. rawTokenKind == . identifier {
155
+ var modifierProgress = LoopProgressCondition ( )
156
+ while let ( modifierKind, handle) = self . at ( anyIn: DeclarationModifier . self) ,
157
+ modifierKind != . class,
158
+ self . hasProgressed ( & modifierProgress)
159
+ {
160
+ hasModifier = true
161
+ self . eat ( handle)
162
+ if modifierKind != . open && self . at ( . leftParen) && modifierKind. canHaveParenthesizedArgument {
163
+ // When determining whether we are at a declaration, don't consume anything in parentheses after 'open'
164
+ // so we don't consider a function call to open as a decl modifier. This matches the C++ parser.
165
+ self . consumeAnyToken ( )
166
+ self . consume ( to: . rightParen)
167
+ }
168
+ }
169
+ }
170
+
171
+ return ( hasAttribute, hasModifier)
172
+ }
173
+
174
+ fileprivate mutating func atStartOfActor(
175
+ isAtTopLevel: Bool ,
176
+ allowInitDecl: Bool
177
+ ) -> Bool {
178
+ if self . peek ( ) . rawTokenKind == . identifier {
179
+ return true
180
+ }
181
+ // actor may be somewhere in the modifier list. Eat the tokens until we get
182
+ // to something that isn't the start of a decl. If that is an identifier,
183
+ // it's an actor declaration, otherwise, it isn't.
184
+ var lookahead = self . lookahead ( )
185
+ repeat {
186
+ lookahead. consumeAnyToken ( )
187
+ } while lookahead. atStartOfDeclaration ( isAtTopLevel: isAtTopLevel, allowInitDecl: allowInitDecl)
188
+ return lookahead. at ( . identifier)
189
+ }
190
+
191
+ fileprivate mutating func atStartOfUsing( ) -> Bool {
192
+ var lookahead = self . lookahead ( )
193
+
194
+ // Consume 'using'
195
+ lookahead. consumeAnyToken ( )
196
+
197
+ // Allow parsing 'using' as declaration only if
198
+ // it's immediately followed by either `@` or
199
+ // an identifier.
200
+ if lookahead. atStartOfLine {
201
+ return false
202
+ }
203
+
204
+ guard lookahead. at ( . atSign) || lookahead. at ( . identifier) else {
205
+ return false
206
+ }
207
+
208
+ return true
209
+ }
210
+ }
211
+
193
212
extension Parser {
194
213
struct DeclAttributes {
195
214
var attributes : RawAttributeListSyntax
0 commit comments