@@ -59,14 +59,14 @@ public struct CharacterClass: Hashable {
59
59
var op : SetOperator
60
60
var rhs : CharacterSetComponent
61
61
62
- public func matches( _ c: Character ) -> Bool {
62
+ public func matches( _ c: Character , with options : MatchingOptions ) -> Bool {
63
63
switch op {
64
64
case . intersection:
65
- return lhs. matches ( c) && rhs. matches ( c)
65
+ return lhs. matches ( c, with : options ) && rhs. matches ( c, with : options )
66
66
case . subtraction:
67
- return lhs. matches ( c) && !rhs. matches ( c)
67
+ return lhs. matches ( c, with : options ) && !rhs. matches ( c, with : options )
68
68
case . symmetricDifference:
69
- return lhs. matches ( c) != rhs. matches ( c)
69
+ return lhs. matches ( c, with : options ) != rhs. matches ( c, with : options )
70
70
}
71
71
}
72
72
}
@@ -87,14 +87,28 @@ public struct CharacterClass: Hashable {
87
87
. setOperation( . init( lhs: lhs, op: op, rhs: rhs) )
88
88
}
89
89
90
- public func matches( _ character: Character ) -> Bool {
90
+ public func matches( _ character: Character , with options : MatchingOptions ) -> Bool {
91
91
switch self {
92
- case . character( let c) : return c == character
93
- case . range( let range) : return range. contains ( character)
92
+ case . character( let c) :
93
+ if options. isCaseInsensitive {
94
+ return c. lowercased ( ) == character. lowercased ( )
95
+ } else {
96
+ return c == character
97
+ }
98
+ case . range( let range) :
99
+ if options. isCaseInsensitive {
100
+ let newLower = range. lowerBound. lowercased ( )
101
+ let newUpper = range. upperBound. lowercased ( )
102
+ // FIXME: Is failing this possible? Is this the right behavior if so?
103
+ guard newLower <= newUpper else { return false }
104
+ return ( newLower... newUpper) . contains ( character. lowercased ( ) )
105
+ } else {
106
+ return range. contains ( character)
107
+ }
94
108
case . characterClass( let custom) :
95
109
let str = String ( character)
96
- return custom. matches ( in: str, at: str. startIndex) != nil
97
- case . setOperation( let op) : return op. matches ( character)
110
+ return custom. matches ( in: str, at: str. startIndex, with : options ) != nil
111
+ case . setOperation( let op) : return op. matches ( character, with : options )
98
112
}
99
113
}
100
114
}
@@ -135,21 +149,26 @@ public struct CharacterClass: Hashable {
135
149
136
150
/// Returns the end of the match of this character class in `str`, if
137
151
/// it matches.
138
- public func matches( in str: String , at i: String . Index ) -> String . Index ? {
152
+ public func matches( in str: String , at i: String . Index , with options : MatchingOptions ) -> String . Index ? {
139
153
switch matchLevel {
140
154
case . graphemeCluster:
141
155
let c = str [ i]
142
156
var matched : Bool
143
157
switch cc {
144
158
case . any, . anyGrapheme: matched = true
145
- case . digit: matched = c. isNumber
146
- case . hexDigit: matched = c. isHexDigit
159
+ case . digit:
160
+ matched = c. isNumber && ( c. isASCII || !options. usesASCIIDigits)
161
+ case . hexDigit:
162
+ matched = c. isHexDigit && ( c. isASCII || !options. usesASCIIDigits)
147
163
case . horizontalWhitespace: fatalError ( " Not implemented " )
148
- case . newlineSequence: matched = c. isNewline
164
+ case . newlineSequence:
165
+ matched = c. isNewline && ( c. isASCII || !options. usesASCIISpaces)
149
166
case . verticalWhitespace: fatalError ( " Not implemented " )
150
- case . whitespace: matched = c. isWhitespace
151
- case . word: matched = c. isWordCharacter
152
- case . custom( let set) : matched = set. any { $0. matches ( c) }
167
+ case . whitespace:
168
+ matched = c. isWhitespace && ( c. isASCII || !options. usesASCIISpaces)
169
+ case . word:
170
+ matched = c. isWordCharacter && ( c. isASCII || !options. usesASCIIWord)
171
+ case . custom( let set) : matched = set. any { $0. matches ( c, with: options) }
153
172
}
154
173
if isInverted {
155
174
matched. toggle ( )
@@ -161,13 +180,17 @@ public struct CharacterClass: Hashable {
161
180
switch cc {
162
181
case . any: matched = true
163
182
case . anyGrapheme: fatalError ( " Not matched in this mode " )
164
- case . digit: matched = c. properties. numericType != nil
165
- case . hexDigit: matched = Character ( c) . isHexDigit
183
+ case . digit:
184
+ matched = c. properties. numericType != nil && ( c. isASCII || !options. usesASCIIDigits)
185
+ case . hexDigit:
186
+ matched = Character ( c) . isHexDigit && ( c. isASCII || !options. usesASCIIDigits)
166
187
case . horizontalWhitespace: fatalError ( " Not implemented " )
167
188
case . newlineSequence: fatalError ( " Not implemented " )
168
189
case . verticalWhitespace: fatalError ( " Not implemented " )
169
- case . whitespace: matched = c. properties. isWhitespace
170
- case . word: matched = c. properties. isAlphabetic || c == " _ "
190
+ case . whitespace:
191
+ matched = c. properties. isWhitespace && ( c. isASCII || !options. usesASCIISpaces)
192
+ case . word:
193
+ matched = ( c. properties. isAlphabetic || c == " _ " ) && ( c. isASCII || !options. usesASCIIWord)
171
194
case . custom: fatalError ( " Not supported " )
172
195
}
173
196
if isInverted {
@@ -495,21 +518,22 @@ extension CharacterClass {
495
518
func isBoundary(
496
519
_ input: String ,
497
520
at pos: String . Index ,
498
- bounds: Range < String . Index >
521
+ bounds: Range < String . Index > ,
522
+ with options: MatchingOptions
499
523
) -> Bool {
500
524
// FIXME: How should we handle bounds?
501
525
// We probably need two concepts
502
526
if input. isEmpty { return false }
503
527
if pos == input. startIndex {
504
- return self . matches ( in: input, at: pos) != nil
528
+ return self . matches ( in: input, at: pos, with : options ) != nil
505
529
}
506
530
let priorIdx = input. index ( before: pos)
507
531
if pos == input. endIndex {
508
- return self . matches ( in: input, at: priorIdx) != nil
532
+ return self . matches ( in: input, at: priorIdx, with : options ) != nil
509
533
}
510
534
511
- let prior = self . matches ( in: input, at: priorIdx) != nil
512
- let current = self . matches ( in: input, at: pos) != nil
535
+ let prior = self . matches ( in: input, at: priorIdx, with : options ) != nil
536
+ let current = self . matches ( in: input, at: pos, with : options ) != nil
513
537
return prior != current
514
538
}
515
539
0 commit comments