diff --git a/Sources/_StringProcessing/Engine/MEBuiltins.swift b/Sources/_StringProcessing/Engine/MEBuiltins.swift index f6d97555d..546721020 100644 --- a/Sources/_StringProcessing/Engine/MEBuiltins.swift +++ b/Sources/_StringProcessing/Engine/MEBuiltins.swift @@ -382,7 +382,9 @@ extension String { } case .word: if isScalarSemantics { - matched = scalar.properties.isAlphabetic && asciiCheck + matched = (scalar.properties.isAlphabetic + || scalar.properties.numericType != nil + || scalar == "_") && asciiCheck } else { matched = char.isWordCharacter && asciiCheck } diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index 2d9a6b1c2..5bf68c106 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -952,6 +952,17 @@ extension RegexTests { firstMatchTest( #"(?S)\v"#, input: "\r\n", match: "\r", semanticLevel: .unicodeScalar) + // \w in scalar semantics must match letters, digits, and underscore + // (matching the same definition used in grapheme-cluster semantics), + // not just alphabetics. + matchTest( + #"\w"#, + ("a", true), + ("1", true), + ("_", true), + (" ", false), + semanticLevel: .unicodeScalar) + matchTest( #"[a]\u0301"#, ("a\u{301}", false),