@@ -101,7 +101,7 @@ Column.prototype.process = function(nextColumn) {
101
101
102
102
// special-case nullables
103
103
if ( state . reference === this . index ) {
104
- // make sure future predictors of this rule get completed.
104
+ // make sure future predictors of this rule get completed.
105
105
var exp = state . rule . name ;
106
106
( this . completed [ exp ] = this . completed [ exp ] || [ ] ) . push ( state ) ;
107
107
}
@@ -177,6 +177,35 @@ Grammar.fromCompiled = function(rules, start) {
177
177
}
178
178
179
179
180
+ function ChunkLexer ( ) {
181
+ this . reset ( ) ;
182
+ }
183
+ ChunkLexer . clone = function ( ) { return new ChunkLexer ( ) ; }
184
+
185
+ ChunkLexer . prototype . save = function ( ) {
186
+ return { } ;
187
+ }
188
+
189
+ ChunkLexer . prototype . reset = function ( data , state ) {
190
+ this . buffer = data || [ ] ;
191
+ this . index = 0 ;
192
+ }
193
+
194
+ ChunkLexer . prototype . feed = function ( data ) {
195
+ if ( this . index < this . buffer . length ) {
196
+ throw new Error ( "ChunkLexer doesn't support feed() before chunk finished" )
197
+ }
198
+ this . index = 0 ;
199
+ this . buffer = data ;
200
+ }
201
+
202
+ ChunkLexer . prototype . next = function ( ) {
203
+ if ( this . index < this . buffer . length ) {
204
+ return { value : this . buffer [ this . index ++ ] }
205
+ }
206
+ }
207
+
208
+
180
209
function Parser ( rules , start , options ) {
181
210
if ( rules instanceof Grammar ) {
182
211
var grammar = rules ;
@@ -189,12 +218,14 @@ function Parser(rules, start, options) {
189
218
// Read options
190
219
this . options = {
191
220
keepHistory : false ,
192
- // rewindable: false ,
221
+ lexer : ChunkLexer ,
193
222
} ;
194
223
for ( var key in ( options || { } ) ) {
195
224
this . options [ key ] = options [ key ] ;
196
225
}
197
- // if (this.options.rewindable) { this.options.keepHistory = true; }
226
+
227
+ // Setup lexer
228
+ this . lexer = this . options . lexer . clone ( ) ;
198
229
199
230
// Setup a table
200
231
var column = new Column ( grammar , 0 ) ;
@@ -212,7 +243,9 @@ function Parser(rules, start, options) {
212
243
Parser . fail = { } ;
213
244
214
245
Parser . prototype . feed = function ( chunk ) {
215
- for ( var chunkPos = 0 ; chunkPos < chunk . length ; chunkPos ++ ) {
246
+ var lexer = this . lexer ;
247
+ lexer . feed ( chunk ) ;
248
+ while ( token = lexer . next ( ) ) {
216
249
// We add new states to table[current+1]
217
250
var column = this . table [ this . current ] ;
218
251
@@ -228,16 +261,16 @@ Parser.prototype.feed = function(chunk) {
228
261
// Advance all tokens that expect the symbol
229
262
// So for each state in the previous row,
230
263
231
- var token = chunk [ chunkPos ] ;
264
+ var value = token . value ;
232
265
var scannable = column . scannable ;
233
266
for ( var w = scannable . length ; w -- ; ) {
234
267
var state = scannable [ w ] ;
235
268
var expect = state . rule . symbols [ state . dot ] ;
236
269
// Try to consume the token
237
270
// either regex or literal
238
- if ( expect . test ? expect . test ( token ) : expect . literal === token ) {
271
+ if ( expect . test ? expect . test ( value ) : expect . literal === value ) {
239
272
// Add it
240
- var next = state . nextState ( token ) ;
273
+ var next = state . nextState ( value ) ;
241
274
nextColumn . states . push ( next ) ;
242
275
}
243
276
}
@@ -289,6 +322,9 @@ Parser.prototype.rewind = function(index) {
289
322
this . table . splice ( index + 1 ) ;
290
323
this . current = index ;
291
324
325
+ // Rewind lexer too
326
+ this . lexer . reset ( ) ;
327
+
292
328
// Incrementally keep track of results
293
329
this . results = this . finish ( ) ;
294
330
} ;
0 commit comments