mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Parse] Expand unbalanced ) regex literal heuristic
Previously we would only check for a starting character of `)` when performing a tentative lex of a regex literal. Expand this to cover the entire range of the regex literal, ensuring to take escapes and custom character classes into account.
This commit is contained in:
@@ -6,6 +6,8 @@ prefix operator /
|
||||
prefix operator ^/
|
||||
prefix operator /^/
|
||||
|
||||
prefix func ^/ <T> (_ x: T) -> T { x } // expected-note {{'^/' declared here}}
|
||||
|
||||
prefix operator !!
|
||||
prefix func !! <T>(_ x: T) -> T { x }
|
||||
|
||||
@@ -259,6 +261,8 @@ _ = /x // comment
|
||||
_ = /x/*comment*/
|
||||
// expected-error@-1 {{'/' is not a prefix unary operator}}
|
||||
|
||||
// MARK: Unapplied operators
|
||||
|
||||
// These become regex literals, unless surrounded in parens.
|
||||
func baz(_ x: (Int, Int) -> Int, _ y: (Int, Int) -> Int) {} // expected-note 4{{'baz' declared here}}
|
||||
baz(/, /)
|
||||
@@ -273,11 +277,7 @@ baz(/^, /)
|
||||
// expected-error@-1 {{cannot convert value of type 'Regex<Substring>' to expected argument type '(Int, Int) -> Int'}}
|
||||
// expected-error@-2 {{missing argument for parameter #2 in call}}
|
||||
|
||||
do {
|
||||
baz((/^), /)
|
||||
// expected-error@-1 {{closing ')' does not balance any groups openings}}
|
||||
// expected-note@-2 {{to match this opening '('}}
|
||||
} // expected-error {{expected ')' in expression list}}
|
||||
baz((/^), /)
|
||||
|
||||
baz(^^/, /) // expected-error {{missing argument for parameter #2 in call}}
|
||||
baz((^^/), /)
|
||||
@@ -287,20 +287,18 @@ bazbaz(/, 0)
|
||||
bazbaz(^^/, 0)
|
||||
|
||||
func qux<T>(_ x: (Int, Int) -> Int, _ y: T) -> Int { 0 }
|
||||
do {
|
||||
_ = qux(/, 1) / 2
|
||||
// expected-error@-1:15 {{cannot parse regular expression: closing ')' does not balance any groups openings}}
|
||||
// expected-error@-2:19 {{expected ',' separator}}
|
||||
}
|
||||
_ = qux(/, 1) / 2
|
||||
do {
|
||||
_ = qux(/, "(") / 2
|
||||
// expected-error@-1 {{cannot convert value of type 'Regex<(Substring, Substring)>' to expected argument type '(Int, Int) -> Int'}}
|
||||
// expected-error@-2:21 {{expected ',' separator}}
|
||||
}
|
||||
_ = qux((/), "(") / 2
|
||||
_ = qux(/, 1) // this comment tests to make sure we don't try and end the regex on the starting '/' of '//'.
|
||||
_ = qux(/, 1) /* same thing with a block comment */
|
||||
|
||||
func quxqux(_ x: (Int, Int) -> Int) {}
|
||||
@discardableResult
|
||||
func quxqux(_ x: (Int, Int) -> Int) -> Int { 0 }
|
||||
quxqux(/^/) // expected-error {{cannot convert value of type 'Regex<Substring>' to expected argument type '(Int, Int) -> Int'}}
|
||||
quxqux((/^/)) // expected-error {{cannot convert value of type 'Regex<Substring>' to expected argument type '(Int, Int) -> Int'}}
|
||||
quxqux({ $0 /^/ $1 })
|
||||
@@ -310,17 +308,88 @@ quxqux(!/^/)
|
||||
// expected-error@-2 {{cannot convert value of type 'Regex<Substring>' to expected argument type 'Bool'}}
|
||||
|
||||
quxqux(/^)
|
||||
|
||||
do {
|
||||
quxqux(/^) / 1
|
||||
// expected-error@-1 {{closing ')' does not balance any groups openings}}
|
||||
// expected-error@-2 {{expected ',' separator}}
|
||||
}
|
||||
_ = quxqux(/^) / 1
|
||||
|
||||
let arr: [Double] = [2, 3, 4]
|
||||
_ = arr.reduce(1, /) / 3
|
||||
_ = arr.reduce(1, /) + arr.reduce(1, /)
|
||||
|
||||
// MARK: ')' disambiguation behavior
|
||||
|
||||
_ = (/x)
|
||||
// expected-error@-1 {{'/' is not a prefix unary operator}}
|
||||
|
||||
_ = (/x)/
|
||||
// expected-error@-1 {{'/' is not a prefix unary operator}}
|
||||
// expected-error@-2 {{'/' is not a postfix unary operator}}
|
||||
|
||||
_ = (/[(0)])/
|
||||
// expected-error@-1 {{'/' is not a prefix unary operator}}
|
||||
// expected-error@-2 {{'/' is not a postfix unary operator}}
|
||||
|
||||
_ = /[(0)]/
|
||||
_ = /(x)/
|
||||
_ = /[)]/
|
||||
_ = /[a\])]/
|
||||
_ = /([)])/
|
||||
_ = /]]][)]/
|
||||
|
||||
_ = /
|
||||
// expected-error@-1 {{unterminated regex literal}}
|
||||
|
||||
_ = /)
|
||||
// expected-error@-1 {{unterminated regex literal}}
|
||||
// expected-error@-2 {{closing ')' does not balance any groups openings}}
|
||||
|
||||
let fn: (Int, Int) -> Int = (/)
|
||||
|
||||
_ = /\()/
|
||||
// expected-error@-1 {{'/' is not a prefix unary operator}}
|
||||
// expected-error@-2 {{'/' is not a postfix unary operator}}
|
||||
// expected-error@-3 {{invalid component of Swift key path}}
|
||||
|
||||
do {
|
||||
let _: Regex = (/whatever\)/
|
||||
// expected-note@-1 {{to match this opening '('}}
|
||||
} // expected-error {{expected ')' in expression list}}
|
||||
do {
|
||||
_ = /(()()))/
|
||||
// expected-error@-1 {{'/' is not a prefix unary operator}}
|
||||
// expected-error@-2 {{consecutive statements on a line must be separated by ';'}}
|
||||
// expected-error@-3 {{expected expression}}
|
||||
}
|
||||
do {
|
||||
_ = /[x])/
|
||||
// expected-error@-1 {{'/' is not a prefix unary operator}}
|
||||
// expected-error@-2 {{consecutive statements on a line must be separated by ';'}}
|
||||
// expected-error@-3 {{expected expression}}
|
||||
}
|
||||
do {
|
||||
_ = /[\]])/
|
||||
// expected-error@-1 {{expected expression path in Swift key path}}
|
||||
}
|
||||
|
||||
_ = ^/x/
|
||||
// expected-error@-1 {{'^' is not a prefix unary operator}}
|
||||
|
||||
_ = (^/x)/
|
||||
// expected-error@-1 {{'/' is not a postfix unary operator}}
|
||||
|
||||
_ = (!!/x/)
|
||||
|
||||
_ = ^/"/"
|
||||
// expected-error@-1 {{'^' is not a prefix unary operator}}
|
||||
// expected-error@-2 {{unterminated string literal}}
|
||||
|
||||
_ = ^/"[/"
|
||||
// expected-error@-1 {{'^' is not a prefix unary operator}}
|
||||
// expected-error@-2 {{unterminated string literal}}
|
||||
// expected-error@-3 {{expected custom character class members}}
|
||||
|
||||
_ = (^/)("/")
|
||||
|
||||
// MARK: Starting characters
|
||||
|
||||
// Fine.
|
||||
_ = /./
|
||||
|
||||
|
||||
Reference in New Issue
Block a user