@@ -63,37 +63,7 @@ extension TokenConsumer {
6363
6464 var subparser = self . lookahead ( )
6565
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 ( )
9767
9868 if hasAttribute {
9969 if subparser. at ( . rightBrace) || subparser. at ( . endOfFile) || subparser. at ( . poundEndif) {
@@ -118,17 +88,7 @@ extension TokenConsumer {
11888 switch declStartKeyword {
11989 case . lhs( . actor ) :
12090 // 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)
13292 case . lhs( . case) :
13393 // When 'case' appears inside a function, it's probably a switch
13494 // case, not an enum case declaration.
@@ -152,23 +112,7 @@ extension TokenConsumer {
152112 return false
153113 }
154114
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 ( )
172116 case . some( _) :
173117 // All other decl start keywords unconditionally start a decl.
174118 return true
@@ -190,6 +134,81 @@ extension TokenConsumer {
190134 }
191135}
192136
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+
193212extension Parser {
194213 struct DeclAttributes {
195214 var attributes : RawAttributeListSyntax
0 commit comments