blob: 9999045da5f791227b4689cf21c73bdf4eceb482 [file] [log] [blame]
library petitparser.core.repeaters.greedy;
import 'package:petitparser/src/core/contexts/context.dart';
import 'package:petitparser/src/core/contexts/result.dart';
import 'package:petitparser/src/core/parser.dart';
import 'package:petitparser/src/core/repeaters/limited.dart';
import 'package:petitparser/src/core/repeaters/unbounded.dart';
/// A greedy repeating parser, commonly seen in regular expression implementations. It
/// aggressively consumes as much input as possible and then backtracks to meet the
/// 'limit' condition.
class GreedyRepeatingParser extends LimitedRepeatingParser {
GreedyRepeatingParser(Parser parser, Parser limit, int min, int max)
: super(parser, limit, min, max);
@override
Result parseOn(Context context) {
var current = context;
var elements = new List();
while (elements.length < min) {
var result = delegate.parseOn(current);
if (result.isFailure) {
return result;
}
elements.add(result.value);
current = result;
}
List<Context> contexts = new List.from([current]);
while (max == unbounded || elements.length < max) {
var result = delegate.parseOn(current);
if (result.isFailure) {
break;
}
elements.add(result.value);
contexts.add(current = result);
}
while (true) {
var limiter = limit.parseOn(contexts.last);
if (limiter.isSuccess) {
return contexts.last.success(elements);
}
if (elements.isEmpty) {
return limiter;
}
contexts.removeLast();
elements.removeLast();
if (contexts.isEmpty) {
return limiter;
}
}
}
@override
Parser copy() => new GreedyRepeatingParser(delegate, limit, min, max);
}