Skip to content

Commit db0c6e3

Browse files
committed
port more methods of Validator
1 parent 62f92ee commit db0c6e3

File tree

1 file changed

+171
-2
lines changed

1 file changed

+171
-2
lines changed

src/validator.rs

Lines changed: 171 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Distributed under terms of the MIT license.
33

44
use std::collections::HashSet;
5-
use std::ops::{Deref, DerefMut};
5+
use std::ops::{Deref, DerefMut, Range};
66

77
use crate::reader::Reader;
88

@@ -21,9 +21,13 @@ enum EcmaVersion {
2121
#[derive(Debug)]
2222
pub struct EcmaRegexValidator {
2323
reader: Reader,
24+
strict: bool,
2425
ecma_version: EcmaVersion,
2526
u_flag: bool,
2627
n_flag: bool,
28+
last_int_value: usize,
29+
last_min_value: usize,
30+
last_max_value: usize,
2731
num_capturing_parens: u32,
2832
group_names: HashSet<String>,
2933
backreference_names: HashSet<String>,
@@ -47,9 +51,13 @@ impl EcmaRegexValidator {
4751
fn new(ecma_version: EcmaVersion) -> Self {
4852
EcmaRegexValidator {
4953
reader: Reader::new(),
54+
strict: false,
5055
ecma_version,
5156
u_flag: false,
5257
n_flag: false,
58+
last_int_value: 0,
59+
last_min_value: 0,
60+
last_max_value: 0,
5361
num_capturing_parens: 0,
5462
group_names: HashSet::new(),
5563
backreference_names: HashSet::new(),
@@ -98,8 +106,18 @@ impl EcmaRegexValidator {
98106
// TODO: return Result
99107
self.u_flag = u_flag && self.ecma_version >= EcmaVersion::ES2015;
100108
self.n_flag = u_flag && self.ecma_version >= EcmaVersion::ES2018;
101-
//TODO: rewind
109+
self.reset(source, 0, source.len(), u_flag);
102110
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+
103121
return true;
104122
}
105123

@@ -180,6 +198,147 @@ impl EcmaRegexValidator {
180198
//self.on_alternative_leave(start, self.index(), i);
181199
}
182200

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+
183342
fn count_capturing_parens(&mut self) -> u32 {
184343
let start = self.index();
185344
let mut in_class = false;
@@ -223,4 +382,14 @@ mod tests {
223382
assert_eq!(validator.validate_flags("gimgu"), false);
224383
assert_eq!(validator.validate_flags("gimuf"), false);
225384
}
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+
}
226395
}

0 commit comments

Comments
 (0)