2
2
// Distributed under terms of the MIT license.
3
3
4
4
use std:: collections:: HashSet ;
5
- use std:: ops:: { Deref , DerefMut } ;
5
+ use std:: ops:: { Deref , DerefMut , Range } ;
6
6
7
7
use crate :: reader:: Reader ;
8
8
@@ -21,9 +21,13 @@ enum EcmaVersion {
21
21
#[ derive( Debug ) ]
22
22
pub struct EcmaRegexValidator {
23
23
reader : Reader ,
24
+ strict : bool ,
24
25
ecma_version : EcmaVersion ,
25
26
u_flag : bool ,
26
27
n_flag : bool ,
28
+ last_int_value : usize ,
29
+ last_min_value : usize ,
30
+ last_max_value : usize ,
27
31
num_capturing_parens : u32 ,
28
32
group_names : HashSet < String > ,
29
33
backreference_names : HashSet < String > ,
@@ -47,9 +51,13 @@ impl EcmaRegexValidator {
47
51
fn new ( ecma_version : EcmaVersion ) -> Self {
48
52
EcmaRegexValidator {
49
53
reader : Reader :: new ( ) ,
54
+ strict : false ,
50
55
ecma_version,
51
56
u_flag : false ,
52
57
n_flag : false ,
58
+ last_int_value : 0 ,
59
+ last_min_value : 0 ,
60
+ last_max_value : 0 ,
53
61
num_capturing_parens : 0 ,
54
62
group_names : HashSet :: new ( ) ,
55
63
backreference_names : HashSet :: new ( ) ,
@@ -98,8 +106,18 @@ impl EcmaRegexValidator {
98
106
// TODO: return Result
99
107
self . u_flag = u_flag && self . ecma_version >= EcmaVersion :: ES2015 ;
100
108
self . n_flag = u_flag && self . ecma_version >= EcmaVersion :: ES2018 ;
101
- //TODO: rewind
109
+ self . reset ( source , 0 , source . len ( ) , u_flag ) ;
102
110
self . consume_pattern ( ) ;
111
+
112
+ if !self . n_flag &&
113
+ self . ecma_version >= EcmaVersion :: ES2018 &&
114
+ self . group_names . len ( ) > 0
115
+ {
116
+ self . n_flag = true ;
117
+ self . rewind ( 0 ) ;
118
+ self . consume_pattern ( ) ;
119
+ }
120
+
103
121
return true ;
104
122
}
105
123
@@ -180,6 +198,147 @@ impl EcmaRegexValidator {
180
198
//self.on_alternative_leave(start, self.index(), i);
181
199
}
182
200
201
+ /// Validate the next characters as a RegExp `Term` production if possible.
202
+ /// ```grammar
203
+ /// Term[U, N]::
204
+ /// [strict] Assertion[+U, ?N]
205
+ /// [strict] Atom[+U, ?N]
206
+ /// [strict] Atom[+U, ?N] Quantifier
207
+ /// [annexB][+U] Assertion[+U, ?N]
208
+ /// [annexB][+U] Atom[+U, ?N]
209
+ /// [annexB][+U] Atom[+U, ?N] Quantifier
210
+ /// [annexB][~U] QuantifiableAssertion[?N] Quantifier
211
+ /// [annexB][~U] Assertion[~U, ?N]
212
+ /// [annexB][~U] ExtendedAtom[?N] Quantifier
213
+ /// [annexB][~U] ExtendedAtom[?N]
214
+ /// ```
215
+ /// Returns `true` if it consumed the next characters successfully.
216
+ /*fn consume_term(&self) -> bool {
217
+ if self.u_flag || self.strict {
218
+ return
219
+ self.consume_assertion() ||
220
+ (self.consume_atom() && self.consume_optional_quantifier())
221
+ }
222
+ return
223
+ (self.consume_assertion() &&
224
+ (!self.last_assertion_is_quantifiable ||
225
+ self.consume_optional_quantifier())) ||
226
+ (self.consume_extended_atom() && self.consume_optional_quantifier())
227
+ }
228
+
229
+ fn consume_optional_quantifier() -> bool {
230
+ this.consume_quantifier()
231
+ true
232
+ }*/
233
+
234
+ /// Validate the next characters as a RegExp `Quantifier` production if possible.
235
+ /// ```grammar
236
+ /// Quantifier::
237
+ /// QuantifierPrefix
238
+ /// QuantifierPrefix `?`
239
+ /// QuantifierPrefix::
240
+ /// `*`
241
+ /// `+`
242
+ /// `?`
243
+ /// `{` DecimalDigits `}`
244
+ /// `{` DecimalDigits `,}`
245
+ /// `{` DecimalDigits `,` DecimalDigits `}`
246
+ /// ```
247
+ /// Returns `true` if it consumed the next characters successfully.
248
+ fn consume_quantifier ( & mut self , no_consume : bool ) -> bool {
249
+ let start = self . index ( ) ;
250
+ let mut min = 0 ;
251
+ let mut max = 0 ;
252
+ let mut greedy = false ;
253
+
254
+ // QuantifierPrefix
255
+ if self . eat ( '*' ) {
256
+ min = 0 ;
257
+ max = usize:: MAX ;
258
+ } else if self . eat ( '+' ) {
259
+ min = 1 ;
260
+ max = usize:: MAX ;
261
+ } else if self . eat ( '?' ) {
262
+ min = 0 ;
263
+ max = 1 ;
264
+ } else if self . eat_braced_quantifier ( no_consume) {
265
+ //range = self.last_min_value..self.last_max_value;
266
+ } else {
267
+ return false ;
268
+ }
269
+
270
+ greedy = !self . eat ( '?' ) ;
271
+
272
+ if !no_consume {
273
+ //self.on_quantifier(start, self.index(), range, greedy);
274
+ }
275
+ return true ;
276
+ }
277
+
278
+ /// Eats the next characters as the following alternatives if possible.
279
+ /// Sets `self.last_min_value` and `self.last_max_value` if it consumed the next characters
280
+ /// successfully.
281
+ /// ```grammar
282
+ /// `{` DecimalDigits `}`
283
+ /// `{` DecimalDigits `,}`
284
+ /// `{` DecimalDigits `,` DecimalDigits `}`
285
+ /// ```
286
+ /// Returns `true` if it consumed the next characters successfully.
287
+ fn eat_braced_quantifier ( & mut self , no_error : bool ) -> bool {
288
+ let start = self . index ( ) ;
289
+ if self . eat ( '{' ) {
290
+ self . last_min_value = 0 ;
291
+ self . last_max_value = usize:: MAX ;
292
+ if self . eat_decimal_digits ( ) {
293
+ self . last_min_value = self . last_int_value ;
294
+ self . last_max_value = self . last_int_value ;
295
+ if self . eat ( ',' ) {
296
+ self . last_max_value = if self . eat_decimal_digits ( ) {
297
+ self . last_int_value
298
+ } else {
299
+ usize:: MAX
300
+ }
301
+ }
302
+ if self . eat ( '}' ) {
303
+ if !no_error && self . last_max_value < self . last_min_value {
304
+ //self.raise("numbers out of order in {} quantifier");
305
+ }
306
+ return true ;
307
+ }
308
+ }
309
+ if !no_error && ( self . u_flag || self . strict ) {
310
+ //self.raise("Incomplete quantifier");
311
+ }
312
+ self . rewind ( start) ;
313
+ }
314
+ return false
315
+ }
316
+
317
+ /// Eat the next characters as a `DecimalDigits` production if possible.
318
+ /// Set `self.last_int_value` if it ate the next characters successfully.
319
+ /// ```grammar
320
+ /// DecimalDigits::
321
+ /// DecimalDigit
322
+ /// DecimalDigits DecimalDigit
323
+ /// DecimalDigit:: one of
324
+ /// 0 1 2 3 4 5 6 7 8 9
325
+ /// ```
326
+ /// Returns `true` if it ate the next characters successfully.
327
+ fn eat_decimal_digits ( & mut self ) -> bool {
328
+ let start = self . index ( ) ;
329
+
330
+ self . last_int_value = 0 ;
331
+ while let Some ( & c) = self . code_point_with_offset ( 0 ) {
332
+ if !c. is_digit ( 10 ) { break ; }
333
+ self . last_int_value =
334
+ 10 * self . last_int_value +
335
+ self . code_point_with_offset ( 0 ) . unwrap ( ) . to_digit ( 10 ) . unwrap ( ) as usize ;
336
+ self . advance ( ) ;
337
+ }
338
+
339
+ return self . index ( ) != start;
340
+ }
341
+
183
342
fn count_capturing_parens ( & mut self ) -> u32 {
184
343
let start = self . index ( ) ;
185
344
let mut in_class = false ;
@@ -223,4 +382,14 @@ mod tests {
223
382
assert_eq ! ( validator. validate_flags( "gimgu" ) , false ) ;
224
383
assert_eq ! ( validator. validate_flags( "gimuf" ) , false ) ;
225
384
}
385
+
386
+ #[ test]
387
+ fn validate_pattern_test ( ) {
388
+ let mut validator = EcmaRegexValidator :: new ( EcmaVersion :: ES2018 ) ;
389
+ assert_eq ! ( validator. validate_pattern( "[abc]de|fg" , false ) , true ) ;
390
+ }
391
+
392
+ #[ test]
393
+ fn count_capturing_parens_test ( ) {
394
+ }
226
395
}
0 commit comments