diff --git a/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift b/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift index 65e54c99fbe..d80270c42d9 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift @@ -89,7 +89,7 @@ struct GenerateSwiftSyntax: ParsableCommand { var fileSpecs: [GeneratedFileSpec] = [ // SwiftParser GeneratedFileSpec(swiftParserGeneratedDir + ["IsLexerClassified.swift"], isLexerClassifiedFile), - GeneratedFileSpec(swiftParserGeneratedDir + ["LayoutNodes+Parsable.swift"], parserEntryFile), + GeneratedFileSpec(swiftParserGeneratedDir + ["LayoutNodes+Parsable.swift"], layoutNodesParsableFile), GeneratedFileSpec(swiftParserGeneratedDir + ["Parser+TokenSpecSet.swift"], parserTokenSpecSetFile), GeneratedFileSpec(swiftParserGeneratedDir + ["TokenSpecStaticMembers.swift"], tokenSpecStaticMembersFile), diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ParserEntryFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/LayoutNodesParsableFile.swift similarity index 91% rename from CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ParserEntryFile.swift rename to CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/LayoutNodesParsableFile.swift index 5dd1b7533b7..19d4e3b90bf 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ParserEntryFile.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/LayoutNodesParsableFile.swift @@ -15,7 +15,7 @@ import SwiftSyntaxBuilder import SyntaxSupport import Utils -let parserEntryFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { +let layoutNodesParsableFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { DeclSyntax("@_spi(RawSyntax) import SwiftSyntax") DeclSyntax( @@ -74,5 +74,13 @@ let parserEntryFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { } """ ) + + DeclSyntax( + """ + mutating func parseExpression() -> RawExprSyntax { + return self.parseExpression(flavor: .basic, pattern: .none) + } + """ + ) } } diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 792a48399f9..cf41df2a91d 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -799,7 +799,7 @@ extension Parser { // See if there's a raw value expression. let rawValue: RawInitializerClauseSyntax? if let eq = self.consume(if: .equal) { - let value = self.parseExpression() + let value = self.parseExpression(flavor: .basic, pattern: .none) rawValue = RawInitializerClauseSyntax( equal: eq, value: value, @@ -1219,7 +1219,7 @@ extension Parser { // Parse an initializer if present. let initializer: RawInitializerClauseSyntax? if let equal = self.consume(if: .equal) { - var value = self.parseExpression() + var value = self.parseExpression(flavor: .basic, pattern: .none) if hasTryBeforeIntroducer && !value.is(RawTryExprSyntax.self) { value = RawExprSyntax( RawTryExprSyntax( @@ -1250,8 +1250,7 @@ extension Parser { arena: self.arena ) ), - .basic, - forDirective: false, + flavor: .basic, pattern: .none ) initializer = RawInitializerClauseSyntax( @@ -1268,7 +1267,7 @@ extension Parser { ) } else if self.atStartOfExpression(), !self.at(.leftBrace), !self.atStartOfLine { let missingEqual = RawTokenSyntax(missing: .equal, arena: self.arena) - let expr = self.parseExpression() + let expr = self.parseExpression(flavor: .basic, pattern: .none) initializer = RawInitializerClauseSyntax( equal: missingEqual, value: expr, @@ -1849,7 +1848,7 @@ extension Parser { // Initializer, if any. let definition: RawInitializerClauseSyntax? if let equal = self.consume(if: .equal) { - let expr = self.parseExpression() + let expr = self.parseExpression(flavor: .basic, pattern: .none) definition = RawInitializerClauseSyntax( equal: equal, value: expr, @@ -1933,10 +1932,10 @@ extension Parser { let trailingClosure: RawClosureExprSyntax? let additionalTrailingClosures: RawMultipleTrailingClosureElementListSyntax if self.at(.leftBrace), - self.withLookahead({ $0.atValidTrailingClosure(.trailingClosure) }) + self.withLookahead({ $0.atValidTrailingClosure(flavor: .basic) }) { (trailingClosure, additionalTrailingClosures) = - self.parseTrailingClosures(.trailingClosure) + self.parseTrailingClosures(flavor: .basic) } else { trailingClosure = nil additionalTrailingClosures = self.emptyCollection(RawMultipleTrailingClosureElementListSyntax.self) diff --git a/Sources/SwiftParser/Directives.swift b/Sources/SwiftParser/Directives.swift index b3fd95f58cf..eb4c6e1b577 100644 --- a/Sources/SwiftParser/Directives.swift +++ b/Sources/SwiftParser/Directives.swift @@ -70,7 +70,7 @@ extension Parser { // Parse #if let (unexpectedBeforePoundIf, poundIf) = self.expect(.poundIf) - let condition = RawExprSyntax(self.parseSequenceExpression(.basic, forDirective: true)) + let condition = RawExprSyntax(self.parseSequenceExpression(flavor: .poundIfDirective)) let unexpectedBetweenConditionAndElements = self.consumeRemainingTokenOnLine() clauses.append( @@ -95,14 +95,14 @@ extension Parser { switch match { case .poundElseif: (unexpectedBeforePound, pound) = self.eat(handle) - condition = RawExprSyntax(self.parseSequenceExpression(.basic, forDirective: true)) + condition = RawExprSyntax(self.parseSequenceExpression(flavor: .poundIfDirective)) unexpectedBetweenConditionAndElements = self.consumeRemainingTokenOnLine() case .poundElse: (unexpectedBeforePound, pound) = self.eat(handle) if let ifToken = self.consume(if: .init(.if, allowAtStartOfLine: false)) { unexpectedBeforePound = RawUnexpectedNodesSyntax(combining: unexpectedBeforePound, pound, ifToken, arena: self.arena) pound = self.missingToken(.poundElseif) - condition = RawExprSyntax(self.parseSequenceExpression(.basic, forDirective: true)) + condition = RawExprSyntax(self.parseSequenceExpression(flavor: .poundIfDirective)) } else { condition = nil } @@ -115,7 +115,7 @@ extension Parser { } unexpectedBeforePound = RawUnexpectedNodesSyntax(combining: unexpectedBeforePound, pound, elif, arena: self.arena) pound = self.missingToken(.poundElseif) - condition = RawExprSyntax(self.parseSequenceExpression(.basic, forDirective: true)) + condition = RawExprSyntax(self.parseSequenceExpression(flavor: .poundIfDirective)) unexpectedBetweenConditionAndElements = self.consumeRemainingTokenOnLine() } else { break LOOP diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index 0a94e8b35fa..944d5468c43 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -63,13 +63,26 @@ extension TokenConsumer { extension Parser { enum ExprFlavor { + /// Parsing a normal expression, eg. inside a function calls. case basic - case trailingClosure + + /// Parsing the condition of a `if`/`guard`/`for`/... statement or something + /// like the `where` clause after a `catch` clause. + /// + /// In these cases we need to disambiguate trailing closures from the + /// statement's body. + case stmtCondition + + /// Parsing the condition of a `#if` directive. + /// + /// We don't allow allow newlines here. + case poundIfDirective } enum PatternContext { /// There is no ambient pattern context. case none + /// We're parsing a matching pattern that is not introduced via `let` or `var`. /// /// In this context, identifiers are references to the enclosing scopes, not a variable binding. @@ -78,6 +91,7 @@ extension Parser { /// case x.y <- 'x' must refer to some 'x' defined in another scope, it cannot be e.g. an enum type. /// ``` case matching + /// We're parsing a matching pattern that is introduced via `let`, `var`, or `inout` /// /// ``` @@ -96,7 +110,7 @@ extension Parser { } /// Parse an expression. - mutating func parseExpression(_ flavor: ExprFlavor = .trailingClosure, pattern: PatternContext = .none) -> RawExprSyntax { + mutating func parseExpression(flavor: ExprFlavor, pattern: PatternContext) -> RawExprSyntax { // If we are parsing a refutable pattern, check to see if this is the start // of a let/var/is pattern. If so, parse it as an UnresolvedPatternExpr and // let pattern type checking determine its final form. @@ -107,18 +121,17 @@ extension Parser { let pattern = self.parseMatchingPattern(context: .matching) return RawExprSyntax(RawPatternExprSyntax(pattern: pattern, arena: self.arena)) } - return RawExprSyntax(self.parseSequenceExpression(flavor, pattern: pattern)) + return RawExprSyntax(self.parseSequenceExpression(flavor: flavor, pattern: pattern)) } } extension Parser { /// Parse a sequence of expressions. mutating func parseSequenceExpression( - _ flavor: ExprFlavor, - forDirective: Bool = false, + flavor: ExprFlavor, pattern: PatternContext = .none ) -> RawExprSyntax { - if forDirective && self.atStartOfLine { + if flavor == .poundIfDirective && self.atStartOfLine { return RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) } @@ -131,8 +144,7 @@ extension Parser { var lastElement: RawExprSyntax lastElement = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) @@ -140,7 +152,7 @@ extension Parser { while self.hasProgressed(&loopProgress) { guard !lastElement.is(RawMissingExprSyntax.self), - !(forDirective && self.atStartOfLine) + !(flavor == .poundIfDirective && self.atStartOfLine) else { break } @@ -148,7 +160,7 @@ extension Parser { // Parse the operator. guard let (operatorExpr, rhsExpr) = - self.parseSequenceExpressionOperator(flavor, pattern: pattern) + self.parseSequenceExpressionOperator(flavor: flavor, pattern: pattern) else { // Not an operator. We're done. break @@ -160,14 +172,13 @@ extension Parser { if let rhsExpr { // Operator parsing returned the RHS. lastElement = rhsExpr - } else if forDirective && self.atStartOfLine { + } else if flavor == .poundIfDirective && self.atStartOfLine { // Don't allow RHS at a newline for `#if` conditions. lastElement = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) break } else { lastElement = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) } @@ -219,7 +230,7 @@ extension Parser { /// expression. The right operand is only returned if it is not a common /// sequence element. mutating func parseSequenceExpressionOperator( - _ flavor: ExprFlavor, + flavor: ExprFlavor, pattern: PatternContext ) -> (operator: RawExprSyntax, rhs: RawExprSyntax?)? { enum ExpectedTokenKind: TokenSpecSet { @@ -270,7 +281,7 @@ extension Parser { case (.infixQuestionMark, let handle)?: // Save the '?'. let question = self.eat(handle) - let firstChoice = self.parseSequenceExpression(flavor, pattern: pattern) + let firstChoice = self.parseSequenceExpression(flavor: flavor, pattern: pattern) // Make sure there's a matching ':' after the middle expr. let (unexpectedBeforeColon, colon) = self.expect(.colon) @@ -364,8 +375,7 @@ extension Parser { /// Parse an expression sequence element. mutating func parseSequenceExpressionElement( - _ flavor: ExprFlavor, - forDirective: Bool = false, + flavor: ExprFlavor, pattern: PatternContext = .none ) -> RawExprSyntax { // Try to parse '@' sign or 'inout' as an attributed typerepr. @@ -386,8 +396,7 @@ extension Parser { case (.await, let handle)?: let awaitTok = self.eat(handle) let sub = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) return RawExprSyntax( @@ -402,8 +411,7 @@ extension Parser { let mark = self.consume(if: .exclamationMark, .postfixQuestionMark) let expression = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) return RawExprSyntax( @@ -417,8 +425,7 @@ extension Parser { case (._move, let handle)?: let moveKeyword = self.eat(handle) let sub = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) return RawExprSyntax( @@ -431,8 +438,7 @@ extension Parser { case (._borrow, let handle)?: let borrowTok = self.eat(handle) let sub = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) return RawExprSyntax( @@ -450,8 +456,7 @@ extension Parser { let copyTok = self.eat(handle) let sub = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) return RawExprSyntax( @@ -469,8 +474,7 @@ extension Parser { let consumeKeyword = self.eat(handle) let sub = self.parseSequenceExpressionElement( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) return RawExprSyntax( @@ -483,7 +487,7 @@ extension Parser { case (.repeat, let handle)?: // 'repeat' is the start of a pack expansion expression. - return RawExprSyntax(parsePackExpansionExpr(repeatHandle: handle, flavor, pattern: pattern)) + return RawExprSyntax(parsePackExpansionExpr(repeatHandle: handle, flavor: flavor, pattern: pattern)) case (.each, let handle)?: if !atContextualExpressionModifier() { @@ -491,7 +495,7 @@ extension Parser { } let each = self.eat(handle) - let pack = self.parseSequenceExpressionElement(flavor, pattern: pattern) + let pack = self.parseSequenceExpressionElement(flavor: flavor, pattern: pattern) return RawExprSyntax( RawPackElementExprSyntax( eachKeyword: each, @@ -512,13 +516,12 @@ extension Parser { case nil: break } - return self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern) + return self.parseUnaryExpression(flavor: flavor, pattern: pattern) } /// Parse an optional prefix operator followed by an expression. mutating func parseUnaryExpression( - _ flavor: ExprFlavor, - forDirective: Bool = false, + flavor: ExprFlavor, pattern: PatternContext = .none ) -> RawExprSyntax { // First check to see if we have the start of a regex literal `/.../`. @@ -541,7 +544,7 @@ extension Parser { switch self.at(anyIn: ExpressionPrefixOperator.self) { case (.prefixAmpersand, let handle)?: let amp = self.eat(handle) - let expr = self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern) + let expr = self.parseUnaryExpression(flavor: flavor, pattern: pattern) return RawExprSyntax( RawInOutExprSyntax( ampersand: amp, @@ -551,11 +554,11 @@ extension Parser { ) case (.backslash, _)?: - return RawExprSyntax(self.parseKeyPathExpression(forDirective: forDirective, pattern: pattern)) + return RawExprSyntax(self.parseKeyPathExpression(pattern: pattern)) case (.prefixOperator, let handle)?: let op = self.eat(handle) - let postfix = self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern) + let postfix = self.parseUnaryExpression(flavor: flavor, pattern: pattern) return RawExprSyntax( RawPrefixOperatorExprSyntax( operator: op, @@ -567,8 +570,7 @@ extension Parser { default: // If the next token is not an operator, just parse this as expr-postfix. return self.parsePostfixExpression( - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) } @@ -576,18 +578,16 @@ extension Parser { /// Parse a postfix expression applied to another expression. mutating func parsePostfixExpression( - _ flavor: ExprFlavor, - forDirective: Bool, + flavor: ExprFlavor, pattern: PatternContext ) -> RawExprSyntax { - let head = self.parsePrimaryExpression(pattern: pattern, forDirective: forDirective, flavor: flavor) + let head = self.parsePrimaryExpression(pattern: pattern, flavor: flavor) guard !head.is(RawMissingExprSyntax.self) else { return head } return self.parsePostfixExpressionSuffix( head, - flavor, - forDirective: forDirective, + flavor: flavor, pattern: pattern ) } @@ -661,8 +661,7 @@ extension Parser { mutating func parseIfConfigExpressionSuffix( _ start: RawExprSyntax?, - _ flavor: ExprFlavor, - forDirective: Bool + flavor: ExprFlavor ) -> RawExprSyntax { precondition(self.at(.poundIf)) @@ -674,15 +673,14 @@ extension Parser { if parser.at(.period) { head = parser.parseDottedExpressionSuffix(nil) } else if parser.at(.poundIf) { - head = parser.parseIfConfigExpressionSuffix(nil, flavor, forDirective: forDirective) + head = parser.parseIfConfigExpressionSuffix(nil, flavor: flavor) } else { // TODO: diagnose and skip. return nil } let result = parser.parsePostfixExpressionSuffix( head, - flavor, - forDirective: forDirective, + flavor: flavor, pattern: .none ) @@ -708,15 +706,14 @@ extension Parser { /// Parse the suffix of a postfix expression. mutating func parsePostfixExpressionSuffix( _ start: RawExprSyntax, - _ flavor: ExprFlavor, - forDirective: Bool, + flavor: ExprFlavor, pattern: PatternContext ) -> RawExprSyntax { // Handle suffix expressions. var leadingExpr = start var loopProgress = LoopProgressCondition() while self.hasProgressed(&loopProgress) { - if forDirective && self.atStartOfLine { + if flavor == .poundIfDirective && self.atStartOfLine { return leadingExpr } @@ -734,8 +731,8 @@ extension Parser { // If we can parse trailing closures, do so. let trailingClosure: RawClosureExprSyntax? let additionalTrailingClosures: RawMultipleTrailingClosureElementListSyntax - if case .trailingClosure = flavor, self.at(.leftBrace), self.withLookahead({ $0.atValidTrailingClosure(flavor) }) { - (trailingClosure, additionalTrailingClosures) = self.parseTrailingClosures(flavor) + if case .basic = flavor, self.at(.leftBrace), self.withLookahead({ $0.atValidTrailingClosure(flavor: flavor) }) { + (trailingClosure, additionalTrailingClosures) = self.parseTrailingClosures(flavor: flavor) } else { trailingClosure = nil additionalTrailingClosures = self.emptyCollection(RawMultipleTrailingClosureElementListSyntax.self) @@ -770,8 +767,8 @@ extension Parser { // If we can parse trailing closures, do so. let trailingClosure: RawClosureExprSyntax? let additionalTrailingClosures: RawMultipleTrailingClosureElementListSyntax - if case .trailingClosure = flavor, self.at(.leftBrace), self.withLookahead({ $0.atValidTrailingClosure(flavor) }) { - (trailingClosure, additionalTrailingClosures) = self.parseTrailingClosures(flavor) + if case .basic = flavor, self.at(.leftBrace), self.withLookahead({ $0.atValidTrailingClosure(flavor: flavor) }) { + (trailingClosure, additionalTrailingClosures) = self.parseTrailingClosures(flavor: flavor) } else { trailingClosure = nil additionalTrailingClosures = self.emptyCollection(RawMultipleTrailingClosureElementListSyntax.self) @@ -793,11 +790,11 @@ extension Parser { } // Check for a trailing closure, if allowed. - if self.at(.leftBrace) && self.withLookahead({ $0.atValidTrailingClosure(flavor) }) { + if self.at(.leftBrace) && self.withLookahead({ $0.atValidTrailingClosure(flavor: flavor) }) { // FIXME: if Result has a trailing closure, break out. // Add dummy blank argument list to the call expression syntax. let list = RawLabeledExprListSyntax(elements: [], arena: self.arena) - let (first, rest) = self.parseTrailingClosures(flavor) + let (first, rest) = self.parseTrailingClosures(flavor: flavor) leadingExpr = RawExprSyntax( RawFunctionCallExprSyntax( @@ -881,8 +878,7 @@ extension Parser { leadingExpr = self.parseIfConfigExpressionSuffix( leadingExpr, - flavor, - forDirective: forDirective + flavor: flavor ) continue } @@ -957,7 +953,7 @@ extension Parser { } /// Parse a keypath expression. - mutating func parseKeyPathExpression(forDirective: Bool, pattern: PatternContext) -> RawKeyPathExprSyntax { + mutating func parseKeyPathExpression(pattern: PatternContext) -> RawKeyPathExprSyntax { // Consume '\'. let (unexpectedBeforeBackslash, backslash) = self.expect(.backslash) @@ -1079,12 +1075,9 @@ extension Parser { /// Swift expression grammar. mutating func parsePrimaryExpression( pattern: PatternContext, - forDirective: Bool, flavor: ExprFlavor ) -> RawExprSyntax { - if forDirective == true, - let directiveExpr = self.parsePrimaryExprForDirective() - { + if flavor == .poundIfDirective, let directiveExpr = self.parsePrimaryExprForDirective() { return RawExprSyntax(directiveExpr) } @@ -1321,8 +1314,8 @@ extension Parser { // Parse the optional trailing closures. let trailingClosure: RawClosureExprSyntax? let additionalTrailingClosures: RawMultipleTrailingClosureElementListSyntax - if case .trailingClosure = flavor, self.at(.leftBrace), self.withLookahead({ $0.atValidTrailingClosure(flavor) }) { - (trailingClosure, additionalTrailingClosures) = self.parseTrailingClosures(flavor) + if case .basic = flavor, self.at(.leftBrace), self.withLookahead({ $0.atValidTrailingClosure(flavor: flavor) }) { + (trailingClosure, additionalTrailingClosures) = self.parseTrailingClosures(flavor: flavor) } else { trailingClosure = nil additionalTrailingClosures = self.emptyCollection(RawMultipleTrailingClosureElementListSyntax.self) @@ -1352,11 +1345,11 @@ extension Parser { /// Parse a pack expansion as an expression. mutating func parsePackExpansionExpr( repeatHandle: TokenConsumptionHandle, - _ flavor: ExprFlavor, + flavor: ExprFlavor, pattern: PatternContext ) -> RawPackExpansionExprSyntax { let repeatKeyword = self.eat(repeatHandle) - let repetitionPattern = self.parseExpression(flavor, pattern: pattern) + let repetitionPattern = self.parseExpression(flavor: flavor, pattern: pattern) return RawPackExpansionExprSyntax( repeatKeyword: repeatKeyword, @@ -1442,7 +1435,7 @@ extension Parser { /// Parse an element of an array or dictionary literal. mutating func parseCollectionElement(_ existing: CollectionKind?) -> CollectionKind { - let key = self.parseExpression() + let key = self.parseExpression(flavor: .basic, pattern: .none) switch existing { case .array(_): return .array(key) @@ -1453,7 +1446,7 @@ extension Parser { fallthrough case .dictionary: let (unexpectedBeforeColon, colon) = self.expect(.colon) - let value = self.parseExpression() + let value = self.parseExpression(flavor: .basic, pattern: .none) return .dictionary(key: key, unexpectedBeforeColon: unexpectedBeforeColon, colon: colon, value: value) } } @@ -1611,7 +1604,7 @@ extension Parser { (unexpectedBeforeEq, eq) = self.expect(.equal) } - let expr = self.parseExpression() + let expr = self.parseExpression(flavor: .basic, pattern: .none) return RawInitializerClauseSyntax( unexpectedBeforeEq, equal: eq, @@ -1697,7 +1690,7 @@ extension Parser { // The name is a new declaration. (unexpectedBeforeName, name) = self.expect(.identifier, TokenSpec(.self, remapping: .identifier), default: .identifier) (unexpectedBeforeEqual, equal) = self.expect(.equal) - expression = self.parseExpression() + expression = self.parseExpression(flavor: .basic, pattern: .none) } else { // This is the simple case - the identifier is both the name and // the expression to capture. @@ -1890,7 +1883,7 @@ extension Parser { if self.at(.binaryOperator) && self.peek(isAt: .comma, .rightParen, .rightSquare) { expr = RawExprSyntax(self.parseDeclReferenceExpr(.operators)) } else { - expr = self.parseExpression(pattern: pattern) + expr = self.parseExpression(flavor: .basic, pattern: pattern) } keepGoing = self.consume(if: .comma) result.append( @@ -1910,7 +1903,7 @@ extension Parser { extension Parser { /// Parse the trailing closure(s) following a call expression. - mutating func parseTrailingClosures(_ flavor: ExprFlavor) -> (RawClosureExprSyntax, RawMultipleTrailingClosureElementListSyntax) { + mutating func parseTrailingClosures(flavor: ExprFlavor) -> (RawClosureExprSyntax, RawMultipleTrailingClosureElementListSyntax) { // Parse the closure. let closure = self.parseClosureExpression() @@ -1972,7 +1965,7 @@ extension Parser.Lookahead { /// where the parser requires an expr-basic (which does not allow them). We /// handle this by doing some lookahead in common situations. And later, Sema /// will emit a diagnostic with a fixit to add wrapping parens. - mutating func atValidTrailingClosure(_ flavor: Parser.ExprFlavor) -> Bool { + mutating func atValidTrailingClosure(flavor: Parser.ExprFlavor) -> Bool { precondition(self.at(.leftBrace), "Couldn't be a trailing closure") // If this is the start of a get/set accessor, then it isn't a trailing @@ -1993,7 +1986,7 @@ extension Parser.Lookahead { // {...}() // by looking ahead for the ()'s, but this has been replaced by do{}, so this // probably isn't worthwhile. - guard case .basic = flavor else { + guard case .stmtCondition = flavor else { return true } @@ -2121,7 +2114,7 @@ extension Parser { if self.at(.leftBrace) { subject = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) } else { - subject = self.parseExpression(.basic) + subject = self.parseExpression(flavor: .stmtCondition, pattern: .none) } let (unexpectedBeforeLBrace, lbrace) = self.expect(.leftBrace) @@ -2340,7 +2333,7 @@ extension Parser { // vars in scope. let whereClause: RawWhereClauseSyntax? if let whereKeyword = self.consume(if: .keyword(.where)) { - let condition = self.parseExpression(.trailingClosure) + let condition = self.parseExpression(flavor: .basic, pattern: .none) whereClause = RawWhereClauseSyntax( whereKeyword: whereKeyword, condition: condition, diff --git a/Sources/SwiftParser/Patterns.swift b/Sources/SwiftParser/Patterns.swift index 8832e2e4e44..159e18543e0 100644 --- a/Sources/SwiftParser/Patterns.swift +++ b/Sources/SwiftParser/Patterns.swift @@ -252,7 +252,7 @@ extension Parser { // matching-pattern ::= expr // Fall back to expression parsing for ambiguous forms. Name lookup will // disambiguate. - let patternSyntax = self.parseSequenceExpression(.basic, pattern: context) + let patternSyntax = self.parseSequenceExpression(flavor: .stmtCondition, pattern: context) if let pat = patternSyntax.as(RawPatternExprSyntax.self) { // The most common case here is to parse something that was a lexically // obvious pattern, which will come back wrapped in an immediate diff --git a/Sources/SwiftParser/Statements.swift b/Sources/SwiftParser/Statements.swift index 2f2354055b9..91c4cd934f0 100644 --- a/Sources/SwiftParser/Statements.swift +++ b/Sources/SwiftParser/Statements.swift @@ -191,7 +191,7 @@ extension Parser { // another clause, so parse it as an expression. This also avoids // lookahead + backtracking on simple if conditions that are obviously // boolean conditions. - return .expression(self.parseExpression(.basic)) + return .expression(self.parseExpression(flavor: .stmtCondition, pattern: .none)) } // We're parsing a conditional binding. @@ -237,7 +237,7 @@ extension Parser { // `let newBinding`, which is shorthand for `let newBinding = newBinding` let initializer: RawInitializerClauseSyntax? if let eq = self.consume(if: .equal) { - let value = self.parseExpression(.basic) + let value = self.parseExpression(flavor: .stmtCondition, pattern: .none) initializer = RawInitializerClauseSyntax( equal: eq, value: value, @@ -312,7 +312,7 @@ extension Parser { mutating func parseThrowStatement(throwHandle: RecoveryConsumptionHandle) -> RawThrowStmtSyntax { let (unexpectedBeforeThrowKeyword, throwKeyword) = self.eat(throwHandle) let hasMisplacedTry = unexpectedBeforeThrowKeyword?.containsToken(where: { TokenSpec(.try) ~= $0 }) ?? false - var expr = self.parseExpression() + var expr = self.parseExpression(flavor: .basic, pattern: .none) if hasMisplacedTry && !expr.is(RawTryExprSyntax.self) { expr = RawExprSyntax( RawTryExprSyntax( @@ -338,7 +338,7 @@ extension Parser { /// Parse a discard statement. mutating func parseDiscardStatement(discardHandle: RecoveryConsumptionHandle) -> RawDiscardStmtSyntax { let (unexpectedBeforeDiscardKeyword, discardKeyword) = self.eat(discardHandle) - let expr = self.parseExpression() + let expr = self.parseExpression(flavor: .basic, pattern: .none) return RawDiscardStmtSyntax( unexpectedBeforeDiscardKeyword, discardKeyword: discardKeyword, @@ -437,7 +437,7 @@ extension Parser { // Parse the optional 'where' guard. let whereClause: RawWhereClauseSyntax? if let whereKeyword = self.consume(if: .keyword(.where)) { - let condition = self.parseExpression(.basic) + let condition = self.parseExpression(flavor: .stmtCondition, pattern: .none) whereClause = RawWhereClauseSyntax( whereKeyword: whereKeyword, condition: condition, @@ -489,7 +489,7 @@ extension Parser { let (unexpectedBeforeRepeatKeyword, repeatKeyword) = self.eat(repeatHandle) let body = self.parseCodeBlock(introducer: repeatKeyword) let (unexpectedBeforeWhileKeyword, whileKeyword) = self.expect(.keyword(.while)) - let condition = self.parseExpression() + let condition = self.parseExpression(flavor: .basic, pattern: .none) return RawRepeatStmtSyntax( unexpectedBeforeRepeatKeyword, repeatKeyword: repeatKeyword, @@ -542,13 +542,13 @@ extension Parser { if self.at(.leftBrace) { expr = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) } else { - expr = self.parseExpression(.basic) + expr = self.parseExpression(flavor: .stmtCondition, pattern: .none) } // Parse the 'where' expression if present. let whereClause: RawWhereClauseSyntax? if let whereKeyword = self.consume(if: .keyword(.where)) { - let condition = self.parseExpression(.basic) + let condition = self.parseExpression(flavor: .stmtCondition, pattern: .none) whereClause = RawWhereClauseSyntax( whereKeyword: whereKeyword, condition: condition, @@ -646,7 +646,7 @@ extension Parser { // followed by a '}', '', statement or decl start keyword sequence. let expr: RawExprSyntax? if isStartOfReturnExpr() { - let parsedExpr = self.parseExpression() + let parsedExpr = self.parseExpression(flavor: .basic, pattern: .none) if hasMisplacedTry && !parsedExpr.is(RawTryExprSyntax.self) { expr = RawExprSyntax( RawTryExprSyntax( @@ -686,7 +686,7 @@ extension Parser { var elementList = [RawYieldedExpressionSyntax]() var loopProgress = LoopProgressCondition() while !self.at(.endOfFile, .rightParen) && keepGoing && self.hasProgressed(&loopProgress) { - let expr = self.parseExpression() + let expr = self.parseExpression(flavor: .basic, pattern: .none) let comma = self.consume(if: .comma) elementList.append( RawYieldedExpressionSyntax( @@ -711,7 +711,7 @@ extension Parser { ) ) } else { - yieldedExpressions = .single(self.parseExpression()) + yieldedExpressions = .single(self.parseExpression(flavor: .basic, pattern: .none)) } return RawYieldStmtSyntax( diff --git a/Sources/SwiftParser/TopLevel.swift b/Sources/SwiftParser/TopLevel.swift index 3dee2442501..dbfcf43d5b0 100644 --- a/Sources/SwiftParser/TopLevel.swift +++ b/Sources/SwiftParser/TopLevel.swift @@ -240,7 +240,7 @@ extension Parser { } else if self.atStartOfStatement() { return self.parseStatementItem() } else if self.atStartOfExpression() { - return .expr(self.parseExpression()) + return .expr(self.parseExpression(flavor: .basic, pattern: .none)) } else if self.atStartOfDeclaration(isAtTopLevel: isAtTopLevel, allowInitDecl: allowInitDecl, allowRecovery: true) { return .decl(self.parseDeclaration()) } else if self.atStartOfStatement(allowRecovery: true) { diff --git a/Sources/SwiftParser/generated/LayoutNodes+Parsable.swift b/Sources/SwiftParser/generated/LayoutNodes+Parsable.swift index 6d85fce7971..796dcc276f2 100644 --- a/Sources/SwiftParser/generated/LayoutNodes+Parsable.swift +++ b/Sources/SwiftParser/generated/LayoutNodes+Parsable.swift @@ -345,4 +345,8 @@ fileprivate extension Parser { } return node } + + mutating func parseExpression() -> RawExprSyntax { + return self.parseExpression(flavor: .basic, pattern: .none) + } }