@@ -68,36 +68,7 @@ extension TokenConsumer {
6868 ) -> Bool {
6969 var subparser = self . lookahead ( )
7070
71- var hasAttribute = false
72- var attributeProgress = LoopProgressCondition ( )
73- while subparser. hasProgressed ( & attributeProgress) {
74- if subparser. at ( . atSign) {
75- _ = subparser. consumeAttributeList ( )
76- hasAttribute = true
77- } else if subparser. at ( . poundIf) && subparser. consumeIfConfigOfAttributes ( ) {
78- hasAttribute = true
79- } else {
80- break
81- }
82- }
83-
84- var hasModifier = false
85- if subparser. currentToken. isLexerClassifiedKeyword || subparser. currentToken. rawTokenKind == . identifier {
86- var modifierProgress = LoopProgressCondition ( )
87- while let ( modifierKind, handle) = subparser. at ( anyIn: DeclarationModifier . self) ,
88- modifierKind != . class,
89- subparser. hasProgressed ( & modifierProgress)
90- {
91- hasModifier = true
92- subparser. eat ( handle)
93- if modifierKind != . open && subparser. at ( . leftParen) && modifierKind. canHaveParenthesizedArgument {
94- // When determining whether we are at a declaration, don't consume anything in parentheses after 'open'
95- // so we don't consider a function call to open as a decl modifier. This matches the C++ parser.
96- subparser. consumeAnyToken ( )
97- subparser. consume ( to: . rightParen)
98- }
99- }
100- }
71+ let ( hasAttribute, hasModifier) = subparser. skipAttributesAndModifiers ( )
10172
10273 if hasAttribute {
10374 if subparser. at ( . rightBrace) || subparser. at ( . endOfFile) || subparser. at ( . poundEndif) {
@@ -112,17 +83,7 @@ extension TokenConsumer {
11283 switch subparser. at ( anyIn: DeclarationKeyword . self) ? . 0 {
11384 case . lhs( . actor ) :
11485 // actor Foo {}
115- if subparser. peek ( ) . rawTokenKind == . identifier {
116- return true
117- }
118- // actor may be somewhere in the modifier list. Eat the tokens until we get
119- // to something that isn't the start of a decl. If that is an identifier,
120- // it's an actor declaration, otherwise, it isn't.
121- var lookahead = subparser. lookahead ( )
122- repeat {
123- lookahead. consumeAnyToken ( )
124- } while lookahead. atStartOfDeclaration ( allowInitDecl: allowInitDecl, requiresDecl: requiresDecl)
125- return lookahead. at ( . identifier)
86+ return subparser. atStartOfActor ( allowInitDecl: allowInitDecl, requiresDecl: requiresDecl)
12687 case . lhs( . case) :
12788 // When 'case' appears inside a function, it's probably a switch
12889 // case, not an enum case declaration.
@@ -146,23 +107,7 @@ extension TokenConsumer {
146107 return false
147108 }
148109
149- var lookahead = subparser. lookahead ( )
150-
151- // Consume 'using'
152- lookahead. consumeAnyToken ( )
153-
154- // Allow parsing 'using' as declaration only if
155- // it's immediately followed by either `@` or
156- // an identifier.
157- if lookahead. atStartOfLine {
158- return false
159- }
160-
161- guard lookahead. at ( . atSign) || lookahead. at ( . identifier) else {
162- return false
163- }
164-
165- return true
110+ return subparser. atStartOfUsing ( )
166111 case . some( _) :
167112 // All other decl start keywords unconditionally start a decl.
168113 return true
@@ -200,6 +145,80 @@ extension TokenConsumer {
200145 }
201146}
202147
148+ extension Parser . Lookahead {
149+ fileprivate mutating func skipAttributesAndModifiers( ) -> ( hasAttribute: Bool , hasModifier: Bool ) {
150+ var hasAttribute = false
151+ var attributeProgress = LoopProgressCondition ( )
152+ while self . hasProgressed ( & attributeProgress) {
153+ if self . at ( . atSign) {
154+ _ = self . consumeAttributeList ( )
155+ hasAttribute = true
156+ } else if self . at ( . poundIf) && self . consumeIfConfigOfAttributes ( ) {
157+ hasAttribute = true
158+ } else {
159+ break
160+ }
161+ }
162+
163+ var hasModifier = false
164+ if self . currentToken. isLexerClassifiedKeyword || self . currentToken. rawTokenKind == . identifier {
165+ var modifierProgress = LoopProgressCondition ( )
166+ while let ( modifierKind, handle) = self . at ( anyIn: DeclarationModifier . self) ,
167+ modifierKind != . class,
168+ self . hasProgressed ( & modifierProgress)
169+ {
170+ hasModifier = true
171+ self . eat ( handle)
172+ if modifierKind != . open && self . at ( . leftParen) && modifierKind. canHaveParenthesizedArgument {
173+ // When determining whether we are at a declaration, don't consume anything in parentheses after 'open'
174+ // so we don't consider a function call to open as a decl modifier. This matches the C++ parser.
175+ self . consumeAnyToken ( )
176+ self . consume ( to: . rightParen)
177+ }
178+ }
179+ }
180+
181+ return ( hasAttribute, hasModifier)
182+ }
183+
184+ fileprivate mutating func atStartOfActor(
185+ allowInitDecl: Bool ,
186+ requiresDecl: Bool
187+ ) -> Bool {
188+ if self . peek ( ) . rawTokenKind == . identifier {
189+ return true
190+ }
191+ // actor may be somewhere in the modifier list. Eat the tokens until we get
192+ // to something that isn't the start of a decl. If that is an identifier,
193+ // it's an actor declaration, otherwise, it isn't.
194+ var lookahead = self . lookahead ( )
195+ repeat {
196+ lookahead. consumeAnyToken ( )
197+ } while lookahead. atStartOfDeclaration ( allowInitDecl: allowInitDecl, requiresDecl: requiresDecl)
198+ return lookahead. at ( . identifier)
199+ }
200+
201+ fileprivate mutating func atStartOfUsing( ) -> Bool {
202+ var lookahead = self . lookahead ( )
203+
204+ // Consume 'using'
205+ lookahead. consumeAnyToken ( )
206+
207+ // Allow parsing 'using' as declaration only if
208+ // it's immediately followed by either `@` or
209+ // an identifier.
210+ if lookahead. atStartOfLine {
211+ return false
212+ }
213+
214+ guard lookahead. at ( . atSign) || lookahead. at ( . identifier) else {
215+ return false
216+ }
217+
218+ return true
219+ }
220+ }
221+
203222extension Parser {
204223 struct DeclAttributes {
205224 var attributes : RawAttributeListSyntax
0 commit comments