| 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); |
| } |