Skip to content

Don’t use arrays in consume functions #1314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 39 additions & 10 deletions Sources/SwiftParser/Attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

extension Parser {
mutating func parseAttributeList() -> RawAttributeListSyntax? {
guard self.at(any: [.atSign, .poundIfKeyword]) else {
guard self.at(.atSign, .poundIfKeyword) else {
return nil
}

Expand All @@ -23,7 +23,7 @@ extension Parser {
repeat {
let attribute = self.parseAttribute()
elements.append(attribute)
} while self.at(any: [.atSign, .poundIfKeyword]) && loopProgress.evaluate(currentToken)
} while self.at(.atSign, .poundIfKeyword) && loopProgress.evaluate(currentToken)
return RawAttributeListSyntax(elements: elements, arena: self.arena)
}
}
Expand Down Expand Up @@ -282,7 +282,7 @@ extension Parser {
// The contents of the @_effects attribute are parsed in SIL, we just
// represent the contents as a list of tokens in SwiftSyntax.
var tokens: [RawTokenSyntax] = []
while !parser.at(any: [.rightParen, .eof]) {
while !parser.at(.rightParen, .eof) {
tokens.append(parser.consumeAnyToken())
}
return .effectsArguments(RawEffectsArgumentsSyntax(elements: tokens, arena: parser.arena))
Expand Down Expand Up @@ -443,7 +443,7 @@ extension Parser {

var elements = [RawDifferentiabilityParamSyntax]()
var loopProgress = LoopProgressCondition()
while !self.at(any: [.eof, .rightParen]) && loopProgress.evaluate(currentToken) {
while !self.at(.eof, .rightParen) && loopProgress.evaluate(currentToken) {
guard let param = self.parseDifferentiabilityParameter() else {
break
}
Expand Down Expand Up @@ -605,7 +605,7 @@ extension Parser {
mutating func parseObjectiveCSelector() -> RawObjCSelectorSyntax {
var elements = [RawObjCSelectorPieceSyntax]()
var loopProgress = LoopProgressCondition()
while !self.at(any: [.eof, .rightParen]) && loopProgress.evaluate(currentToken) {
while !self.at(.eof, .rightParen) && loopProgress.evaluate(currentToken) {
// Empty selector piece.
if let colon = self.consume(if: .colon) {
elements.append(
Expand Down Expand Up @@ -687,7 +687,7 @@ extension Parser {
var elements = [RawSpecializeAttributeSpecListSyntax.Element]()
// Parse optional "exported" and "kind" labeled parameters.
var loopProgress = LoopProgressCondition()
while !self.at(any: [.eof, .rightParen, .keyword(.where)]) && loopProgress.evaluate(currentToken) {
while !self.at(.eof, .rightParen, .keyword(.where)) && loopProgress.evaluate(currentToken) {
switch self.at(anyIn: SpecializeParameter.self) {
case (.target, let handle)?:
let ident = self.eat(handle)
Expand Down Expand Up @@ -751,7 +751,7 @@ extension Parser {
case (.exported, let handle)?:
let ident = self.eat(handle)
let (unexpectedBeforeColon, colon) = self.expect(.colon)
let (unexpectedBeforeValue, value) = self.expectAny([.keyword(.true), .keyword(.false)], default: .keyword(.false))
let (unexpectedBeforeValue, value) = self.expect(.keyword(.true), .keyword(.false), default: .keyword(.false))
let comma = self.consume(if: .comma)
elements.append(
.labeledSpecializeEntry(
Expand Down Expand Up @@ -951,7 +951,7 @@ extension Parser {
extension Parser {
mutating func parseExposeArguments() -> RawExposeAttributeArgumentsSyntax {
let language: RawTokenSyntax
if !self.at(any: [.rightParen, .comma]) {
if !self.at(.rightParen, .comma) {
language = self.consumeAnyToken()
} else {
language = missingToken(.identifier)
Expand Down Expand Up @@ -1076,13 +1076,42 @@ extension Parser {

var keepGoing: RawTokenSyntax? = nil
repeat {
let (unexpectedBeforeLabel, label) = self.expectAny([.keyword(.visibility), .keyword(.metadata)], default: .keyword(.visibility))
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.visibility), .keyword(.metadata), default: .keyword(.visibility))
let (unexpectedBeforeColon, colon) = self.expect(.colon)
let unexpectedBeforeValue: RawUnexpectedNodesSyntax?
let value: RawDocumentationAttributeArgumentSyntax.Value
switch label.tokenText {
case "visibility":
let (unexpected, token) = self.expectAny([.keyword(.open), .keyword(.public), .keyword(.internal), .keyword(.fileprivate), .keyword(.private)], default: .keyword(.internal))
enum AccessLevelModifier: RawTokenKindSubset {
case `private`
case `fileprivate`
case `internal`
case `public`
case `open`

var rawTokenKind: RawTokenKind {
switch self {
case .private: return .keyword(.private)
case .fileprivate: return .keyword(.fileprivate)
case .internal: return .keyword(.internal)
case .public: return .keyword(.public)
case .open: return .keyword(.open)
}
}

init?(lexeme: Lexer.Lexeme) {
switch lexeme {
case RawTokenKindMatch(.private): self = .private
case RawTokenKindMatch(.fileprivate): self = .fileprivate
case RawTokenKindMatch(.internal): self = .internal
case RawTokenKindMatch(.public): self = .public
case RawTokenKindMatch(.open): self = .open
default: return nil
}
}
}

let (unexpected, token) = self.expect(anyIn: AccessLevelModifier.self, default: .internal)
unexpectedBeforeValue = unexpected
value = .token(token)
case "metadata":
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftParser/Availability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ extension Parser {
}

let version: RawVersionTupleSyntax?
if self.at(any: [.integerLiteral, .floatingLiteral]) {
if self.at(.integerLiteral, .floatingLiteral) {
version = self.parseVersionTuple()
} else {
version = nil
Expand All @@ -242,7 +242,7 @@ extension Parser {
/// platform-version → decimal-digits '.' decimal-digits
/// platform-version → decimal-digits '.' decimal-digits '.' decimal-digits
mutating func parseVersionTuple() -> RawVersionTupleSyntax {
let (unexpectedBeforeMajorMinor, majorMinor) = self.expectAny([.integerLiteral, .floatingLiteral], default: .integerLiteral)
let (unexpectedBeforeMajorMinor, majorMinor) = self.expect(.integerLiteral, .floatingLiteral, default: .integerLiteral)
let patchPeriod: RawTokenSyntax?
let unexpectedBeforePatch: RawUnexpectedNodesSyntax?
let patch: RawTokenSyntax?
Expand Down
72 changes: 55 additions & 17 deletions Sources/SwiftParser/Declarations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ extension Parser {
return RawDeclSyntax(self.parseMacroDeclaration(attrs: attrs, introducerHandle: handle))
case nil:
if inMemberDeclList {
let isProbablyVarDecl = self.at(any: [.identifier, .wildcard]) && self.peek().rawTokenKind.is(any: [.colon, .equal, .comma])
let isProbablyTupleDecl = self.at(.leftParen) && self.peek().rawTokenKind.is(any: [.identifier, .wildcard])
let isProbablyVarDecl = self.at(.identifier, .wildcard) && self.peek().rawTokenKind.is(.colon, .equal, .comma)
let isProbablyTupleDecl = self.at(.leftParen) && self.peek().rawTokenKind.is(.identifier, .wildcard)

if isProbablyVarDecl || isProbablyTupleDecl {
return RawDeclSyntax(self.parseLetOrVarDeclaration(attrs, .missing(.keyword(.var))))
Expand All @@ -274,7 +274,7 @@ extension Parser {
)
}

let isProbablyFuncDecl = self.at(any: [.identifier, .wildcard]) || self.at(anyIn: Operator.self) != nil
let isProbablyFuncDecl = self.at(.identifier, .wildcard) || self.at(anyIn: Operator.self) != nil

if isProbablyFuncDecl {
return RawDeclSyntax(self.parseFuncDeclaration(attrs, .missing(.keyword(.func))))
Expand Down Expand Up @@ -321,7 +321,45 @@ extension Parser {

@_spi(RawSyntax)
public mutating func parseImportKind() -> RawTokenSyntax? {
return self.consume(ifAny: [.keyword(.typealias), .keyword(.struct), .keyword(.class), .keyword(.enum), .keyword(.protocol), .keyword(.var), .keyword(.let), .keyword(.func)])
enum ImportKind: RawTokenKindSubset {
case `typealias`
case `struct`
case `class`
case `enum`
case `protocol`
case `var`
case `let`
case `func`

var rawTokenKind: RawTokenKind {
switch self {
case .typealias: return .keyword(.typealias)
case .struct: return .keyword(.struct)
case .class: return .keyword(.class)
case .enum: return .keyword(.enum)
case .protocol: return .keyword(.protocol)
case .var: return .keyword(.var)
case .let: return .keyword(.let)
case .func: return .keyword(.func)
}
}

init?(lexeme: Lexer.Lexeme) {
switch lexeme {
case RawTokenKindMatch(.typealias): self = .typealias
case RawTokenKindMatch(.struct): self = .struct
case RawTokenKindMatch(.class): self = .class
case RawTokenKindMatch(.enum): self = .enum
case RawTokenKindMatch(.protocol): self = .protocol
case RawTokenKindMatch(.var): self = .var
case RawTokenKindMatch(.let): self = .let
case RawTokenKindMatch(.func): self = .func
default: return nil
}
}
}

return self.consume(ifAnyIn: ImportKind.self)
}

@_spi(RawSyntax)
Expand Down Expand Up @@ -442,7 +480,7 @@ extension Parser {
let unexpectedBeforeInherited: RawUnexpectedNodesSyntax?
let inherited: RawTypeSyntax?
if colon != nil {
if self.at(any: [.identifier, .keyword(.protocol), .keyword(.Any)]) {
if self.at(.identifier, .keyword(.protocol), .keyword(.Any)) {
unexpectedBeforeInherited = nil
inherited = self.parseType()
} else if let classKeyword = self.consume(if: .keyword(.class)) {
Expand Down Expand Up @@ -769,7 +807,7 @@ extension Parser {
let (unexpectedBeforeLBrace, lbrace) = self.expect(.leftBrace)
do {
var loopProgress = LoopProgressCondition()
while !self.at(any: [.eof, .rightBrace]) && loopProgress.evaluate(currentToken) {
while !self.at(.eof, .rightBrace) && loopProgress.evaluate(currentToken) {
let newItemAtStartOfLine = self.currentToken.isAtStartOfLine
guard let newElement = self.parseMemberDeclListItem() else {
break
Expand Down Expand Up @@ -979,7 +1017,7 @@ extension Parser {

// Parse the '!' or '?' for a failable initializer.
let failable: RawTokenSyntax?
if let parsedFailable = self.consume(ifAny: [.exclamationMark, .postfixQuestionMark, .infixQuestionMark]) {
if let parsedFailable = self.consume(if: .exclamationMark, .postfixQuestionMark, .infixQuestionMark) {
failable = parsedFailable
} else if let parsedFailable = self.consumeIfContextualPunctuator("!", remapping: .exclamationMark) {
failable = parsedFailable
Expand Down Expand Up @@ -1195,7 +1233,7 @@ extension Parser {
if !shouldSkipParameterParsing {
var keepGoing = true
var loopProgress = LoopProgressCondition()
while !self.at(any: [.eof, .rightParen])
while !self.at(.eof, .rightParen)
&& keepGoing
&& loopProgress.evaluate(currentToken)
{
Expand Down Expand Up @@ -1277,7 +1315,7 @@ extension Parser {
let (unexpectedBeforeFuncKeyword, funcKeyword) = self.eat(handle)
let unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?
let identifier: RawTokenSyntax
if self.at(anyIn: Operator.self) != nil || self.at(any: [.exclamationMark, .prefixAmpersand]) || self.atRegexLiteralThatCouldBeAnOperator() {
if self.at(anyIn: Operator.self) != nil || self.at(.exclamationMark, .prefixAmpersand) || self.atRegexLiteralThatCouldBeAnOperator() {
var name = self.currentToken.tokenText
if name.count > 1 && name.hasSuffix("<") && self.peek().rawTokenKind == .identifier {
name = SyntaxText(rebasing: name.dropLast())
Expand Down Expand Up @@ -1552,7 +1590,7 @@ extension Parser {
// Check there is an identifier before consuming
var look = self.lookahead()
let _ = look.consumeAttributeList()
let hasModifier = look.consume(ifAny: [.keyword(.mutating), .keyword(.nonmutating), .keyword(.__consuming)]) != nil
let hasModifier = look.consume(if: .keyword(.mutating), .keyword(.nonmutating), .keyword(.__consuming)) != nil
guard let (kind, handle) = look.at(anyIn: AccessorKind.self) ?? forcedKind else {
return nil
}
Expand All @@ -1563,7 +1601,7 @@ extension Parser {
// get and set.
let modifier: RawDeclModifierSyntax?
if hasModifier {
let (unexpectedBeforeName, name) = self.expectAny([.keyword(.mutating), .keyword(.nonmutating), .keyword(.__consuming)], default: .keyword(.mutating))
let (unexpectedBeforeName, name) = self.expect(.keyword(.mutating), .keyword(.nonmutating), .keyword(.__consuming), default: .keyword(.mutating))
modifier = RawDeclModifierSyntax(
unexpectedBeforeName,
name: name,
Expand Down Expand Up @@ -1667,7 +1705,7 @@ extension Parser {
var elements = [RawAccessorDeclSyntax]()
do {
var loopProgress = LoopProgressCondition()
while !self.at(any: [.eof, .rightBrace]) && loopProgress.evaluate(currentToken) {
while !self.at(.eof, .rightBrace) && loopProgress.evaluate(currentToken) {
guard let introducer = self.parseAccessorIntroducer() else {
// There can only be an implicit getter if no other accessors were
// seen before this one.
Expand Down Expand Up @@ -1812,7 +1850,7 @@ extension Parser {
case (_, let handle)?:
(unexpectedBeforeName, name) = self.eat(handle)
default:
if let identifier = self.consume(ifAny: [.identifier, .dollarIdentifier], allowTokenAtStartOfLine: false) {
if let identifier = self.consume(if: .identifier, .dollarIdentifier, allowTokenAtStartOfLine: false) {
// Recover if the developer tried to use an identifier as the operator name
unexpectedBeforeName = RawUnexpectedNodesSyntax([identifier], arena: self.arena)
} else {
Expand All @@ -1827,7 +1865,7 @@ extension Parser {
var loopProgress = LoopProgressCondition()
while (identifiersAfterOperatorName.last ?? name).trailingTriviaByteLength == 0,
self.currentToken.leadingTriviaByteLength == 0,
!self.at(any: [.colon, .leftBrace, .eof]),
!self.at(.colon, .leftBrace, .eof),
loopProgress.evaluate(self.currentToken)
{
identifiersAfterOperatorName.append(consumeAnyToken())
Expand Down Expand Up @@ -1977,12 +2015,12 @@ extension Parser {
var elements = [RawPrecedenceGroupAttributeListSyntax.Element]()
do {
var attributesProgress = LoopProgressCondition()
LOOP: while !self.at(any: [.eof, .rightBrace]) && attributesProgress.evaluate(currentToken) {
LOOP: while !self.at(.eof, .rightBrace) && attributesProgress.evaluate(currentToken) {
switch self.at(anyIn: LabelText.self) {
case (.associativity, let handle)?:
let associativity = self.eat(handle)
let (unexpectedBeforeColon, colon) = self.expect(.colon)
var (unexpectedBeforeValue, value) = self.expectAny([.keyword(.left), .keyword(.right), .keyword(.none)], default: .keyword(.none))
var (unexpectedBeforeValue, value) = self.expect(.keyword(.left), .keyword(.right), .keyword(.none), default: .keyword(.none))
if value.isMissing, let identifier = self.consume(if: .identifier) {
unexpectedBeforeValue = RawUnexpectedNodesSyntax(combining: unexpectedBeforeValue, identifier, arena: self.arena)
}
Expand All @@ -2001,7 +2039,7 @@ extension Parser {
case (.assignment, let handle)?:
let assignmentKeyword = self.eat(handle)
let (unexpectedBeforeColon, colon) = self.expect(.colon)
let (unexpectedBeforeFlag, flag) = self.expectAny([.keyword(.true), .keyword(.false)], default: .keyword(.true))
let (unexpectedBeforeFlag, flag) = self.expect(.keyword(.true), .keyword(.false), default: .keyword(.true))
let unexpectedAfterFlag: RawUnexpectedNodesSyntax?
if flag.isMissing, let unexpectedIdentifier = self.consume(if: .identifier, allowTokenAtStartOfLine: false) {
unexpectedAfterFlag = RawUnexpectedNodesSyntax([unexpectedIdentifier], arena: self.arena)
Expand Down
27 changes: 25 additions & 2 deletions Sources/SwiftParser/Directives.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,29 @@
@_spi(RawSyntax) import SwiftSyntax

extension Parser {
private enum IfConfigClauseStartKeyword: RawTokenKindSubset {
case poundIfKeyword
case poundElseifKeyword
case poundElseKeyword

var rawTokenKind: RawTokenKind {
switch self {
case .poundIfKeyword: return .poundIfKeyword
case .poundElseifKeyword: return .poundElseifKeyword
case .poundElseKeyword: return .poundElseKeyword
}
}

init?(lexeme: Lexer.Lexeme) {
switch lexeme {
case RawTokenKindMatch(.poundIfKeyword): self = .poundIfKeyword
case RawTokenKindMatch(.poundElseifKeyword): self = .poundElseifKeyword
case RawTokenKindMatch(.poundElseKeyword): self = .poundElseKeyword
default: return nil
}
}
}

/// Parse a conditional compilation block.
///
/// This function should be used to parse conditional compilation statements,
Expand Down Expand Up @@ -83,7 +106,7 @@ extension Parser {
do {
var firstIteration = true
var loopProgress = LoopProgressCondition()
while let poundIfHandle = self.canRecoverTo(any: firstIteration ? [.poundIfKeyword] : [.poundIfKeyword, .poundElseifKeyword, .poundElseKeyword]),
while let poundIfHandle = firstIteration ? self.canRecoverTo(.poundIfKeyword) : self.canRecoverTo(anyIn: IfConfigClauseStartKeyword.self)?.handle,
loopProgress.evaluate(self.currentToken)
{
let (unexpectedBeforePoundIf, poundIf) = self.eat(poundIfHandle)
Expand All @@ -102,7 +125,7 @@ extension Parser {
var elements = [Element]()
do {
var elementsProgress = LoopProgressCondition()
while !self.at(any: [.eof, .poundElseKeyword, .poundElseifKeyword, .poundEndifKeyword]) && elementsProgress.evaluate(currentToken) {
while !self.at(.eof) && !self.at(.poundElseKeyword, .poundElseifKeyword, .poundEndifKeyword) && elementsProgress.evaluate(currentToken) {
let newItemAtStartOfLine = self.currentToken.isAtStartOfLine
guard let element = parseElement(&self), !element.isEmpty else {
break
Expand Down
Loading