Rewrite ZeroOrMore to produce all options instead of just the first.

This commit is contained in:
Ian Gulliver
2014-06-28 16:25:08 -07:00
parent 449a4f2418
commit 24084ae523

View File

@@ -488,7 +488,7 @@ rr.StartOfLine.cache = new rr.StartOfLine_();
* @private * @private
*/ */
rr.ZeroOrMore_ = function(child) { rr.ZeroOrMore_ = function(child) {
this.child_ = child; this.pair_ = rr.SequentialPair(child, this);
}; };
@@ -497,19 +497,37 @@ rr.ZeroOrMore_ = function(child) {
* @return {rr.typeIterator} * @return {rr.typeIterator}
*/ */
rr.ZeroOrMore_.prototype.match = function(context) { rr.ZeroOrMore_.prototype.match = function(context) {
var nodes = []; // Yield:
while (!context.atEnd()) { // 1) The results of SequentialPair(child, this)
var next = this.child_.match(context).next(); // 2) An empty result
// 3) Done
//
// We must check for results from 1 that don't reduce context.remaining();
// that means infinite recursion.
var iterator = this.pair_.match(context);
return {
'next': function() {
if (!iterator) {
return { 'done': true };
}
var next = iterator.next();
if (next['done']) { if (next['done']) {
break; iterator = null;
} return {
context = next['value']['context']; 'done': false,
Array.prototype.push.apply(nodes, next['value']['nodes']); 'value': {
}
return rr.iterableFromArray_([{
'context': context, 'context': context,
'nodes': nodes 'nodes': []
}]); }
};
}
if (next['value']['context'].remaining() == context.remaining()) {
throw "Child of ZeroOrMore didn't consume input; grammar bug?";
}
return next;
}.bind(this)
};
}; };
@@ -679,6 +697,9 @@ rr.Context.prototype.remaining = function() {
* @return {rr.Context} * @return {rr.Context}
*/ */
rr.Context.prototype.advance = function(numChars) { rr.Context.prototype.advance = function(numChars) {
if (!numChars) {
throw "Context.advance(0) called";
}
var context = this.copy(); var context = this.copy();
context.inputIndex += numChars; context.inputIndex += numChars;
return context; return context;