Skip to content

Commit e67f494

Browse files
committed
Add Lexer option
1 parent 433ea5c commit e67f494

File tree

1 file changed

+43
-7
lines changed

1 file changed

+43
-7
lines changed

lib/nearley.js

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Column.prototype.process = function(nextColumn) {
101101

102102
// special-case nullables
103103
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.
105105
var exp = state.rule.name;
106106
(this.completed[exp] = this.completed[exp] || []).push(state);
107107
}
@@ -177,6 +177,35 @@ Grammar.fromCompiled = function(rules, start) {
177177
}
178178

179179

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+
180209
function Parser(rules, start, options) {
181210
if (rules instanceof Grammar) {
182211
var grammar = rules;
@@ -189,12 +218,14 @@ function Parser(rules, start, options) {
189218
// Read options
190219
this.options = {
191220
keepHistory: false,
192-
// rewindable: false,
221+
lexer: ChunkLexer,
193222
};
194223
for (var key in (options || {})) {
195224
this.options[key] = options[key];
196225
}
197-
// if (this.options.rewindable) { this.options.keepHistory = true; }
226+
227+
// Setup lexer
228+
this.lexer = this.options.lexer.clone();
198229

199230
// Setup a table
200231
var column = new Column(grammar, 0);
@@ -212,7 +243,9 @@ function Parser(rules, start, options) {
212243
Parser.fail = {};
213244

214245
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()) {
216249
// We add new states to table[current+1]
217250
var column = this.table[this.current];
218251

@@ -228,16 +261,16 @@ Parser.prototype.feed = function(chunk) {
228261
// Advance all tokens that expect the symbol
229262
// So for each state in the previous row,
230263

231-
var token = chunk[chunkPos];
264+
var value = token.value;
232265
var scannable = column.scannable;
233266
for (var w = scannable.length; w--; ) {
234267
var state = scannable[w];
235268
var expect = state.rule.symbols[state.dot];
236269
// Try to consume the token
237270
// either regex or literal
238-
if (expect.test ? expect.test(token) : expect.literal === token) {
271+
if (expect.test ? expect.test(value) : expect.literal === value) {
239272
// Add it
240-
var next = state.nextState(token);
273+
var next = state.nextState(value);
241274
nextColumn.states.push(next);
242275
}
243276
}
@@ -289,6 +322,9 @@ Parser.prototype.rewind = function(index) {
289322
this.table.splice(index + 1);
290323
this.current = index;
291324

325+
// Rewind lexer too
326+
this.lexer.reset();
327+
292328
// Incrementally keep track of results
293329
this.results = this.finish();
294330
};

0 commit comments

Comments
 (0)