@@ -60,7 +60,7 @@ class PatternAcceptorState {
60
60
this . pattern = pattern ;
61
61
this . unicode = unicode ;
62
62
this . index = 0 ;
63
- this . backreferences = [ ] ;
63
+ this . largestBackreference = 0 ;
64
64
this . backreferenceNames = [ ] ;
65
65
this . groupingNames = [ ] ;
66
66
this . capturingGroups = 0 ;
@@ -70,6 +70,12 @@ class PatternAcceptorState {
70
70
return this . index >= this . pattern . length ;
71
71
}
72
72
73
+ backreference ( ref ) {
74
+ if ( ref > this . largestBackreference ) {
75
+ this . largestBackreference = ref ;
76
+ }
77
+ }
78
+
73
79
nextCodePoint ( ) {
74
80
if ( this . empty ( ) ) {
75
81
return null ;
@@ -190,10 +196,8 @@ export default (pattern, { unicode = false } = {}) => {
190
196
let accepted = acceptDisjunction ( state ) ;
191
197
if ( accepted . matched ) {
192
198
if ( state . unicode ) {
193
- for ( let backreference of state . backreferences ) {
194
- if ( backreference > state . capturingGroups ) {
195
- return false ;
196
- }
199
+ if ( state . largestBackreference > state . capturingGroups ) {
200
+ return false ;
197
201
}
198
202
}
199
203
if ( state . groupingNames . length > 0 || state . unicode ) {
@@ -209,12 +213,12 @@ export default (pattern, { unicode = false } = {}) => {
209
213
210
214
const backtrackOnFailure = func => state => {
211
215
let savedIndex = state . index ;
212
- let oldBackreferences = state . backreferences . slice ( 0 ) ;
216
+ let oldBackreference = state . largestBackreference ;
213
217
let oldCapturingGroups = state . capturingGroups ;
214
218
let val = func ( state ) ;
215
219
if ( ! val . matched ) {
216
220
state . index = savedIndex ;
217
- state . backreferences = oldBackreferences ;
221
+ state . largestBackreference = oldBackreference ;
218
222
state . capturingGroups = oldCapturingGroups ;
219
223
}
220
224
return val ;
@@ -428,13 +432,16 @@ const acceptGrouping = backtrackOnFailure(state => {
428
432
} ) ;
429
433
430
434
const acceptDecimalEscape = backtrackOnFailure ( state => {
431
- let firstDecimal = state . eatAny ( ...decimalDigits . slice ( 1 ) ) ;
435
+ let firstDecimal = state . eatAny ( ...decimalDigits ) ;
432
436
if ( firstDecimal === null ) {
433
437
return { matched : false } ;
434
438
}
439
+ if ( firstDecimal === '0' ) {
440
+ return { matched : true } ;
441
+ }
435
442
// we also accept octal escapes here, but it is impossible to tell if it is a octal escape until all parsing is complete.
436
443
// octal escapes are handled in acceptCharacterEscape for classes
437
- state . backreferences . push ( parseInt ( firstDecimal + ( state . eatNaturalNumber ( ) || '' ) ) ) ;
444
+ state . backreference ( parseInt ( firstDecimal + ( state . eatNaturalNumber ( ) || '' ) ) ) ;
438
445
return { matched : true } ;
439
446
} ) ;
440
447
@@ -648,12 +655,6 @@ const acceptCharacterClass = backtrackOnFailure(state => {
648
655
subState => {
649
656
return { matched : ! ! subState . eat ( 'b' ) , value : 0x0008 } ;
650
657
} ,
651
- subState => {
652
- if ( ! subState . unicode ) {
653
- return { matched : false } ;
654
- }
655
- return acceptDecimalEscape ( subState ) ;
656
- } ,
657
658
subState => {
658
659
return { matched : subState . unicode && ! ! subState . eat ( '-' ) , value : '-' . charCodeAt ( 0 ) } ;
659
660
} ,
0 commit comments