| OLD | NEW |
| (Empty) |
| 1 part of petitparser; | |
| 2 | |
| 3 /** | |
| 4 * An [int] used to mark an unbounded maximum repetition. | |
| 5 */ | |
| 6 const int unbounded = -1; | |
| 7 | |
| 8 /** | |
| 9 * An abstract parser that repeatedly parses between 'min' and 'max' instances o
f | |
| 10 * its delegate. | |
| 11 */ | |
| 12 abstract class RepeatingParser extends DelegateParser { | |
| 13 final int _min; | |
| 14 final int _max; | |
| 15 | |
| 16 RepeatingParser(Parser parser, this._min, this._max) : super(parser) { | |
| 17 assert(0 <= _min); | |
| 18 assert(_max == unbounded || _min <= _max); | |
| 19 } | |
| 20 | |
| 21 @override | |
| 22 String toString() { | |
| 23 var max = _max == unbounded ? '*' : _max; | |
| 24 return '${super.toString()}[$_min..$max]'; | |
| 25 } | |
| 26 | |
| 27 @override | |
| 28 bool hasEqualProperties(Parser other) { | |
| 29 return other is RepeatingParser | |
| 30 && super.hasEqualProperties(other) | |
| 31 && _min == other._min | |
| 32 && _max == other._max; | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 /** | |
| 37 * A greedy parser that repeatedly parses between 'min' and 'max' instances of | |
| 38 * its delegate. | |
| 39 */ | |
| 40 class PossessiveRepeatingParser extends RepeatingParser { | |
| 41 PossessiveRepeatingParser(Parser parser, int min, int max) | |
| 42 : super(parser, min, max); | |
| 43 | |
| 44 @override | |
| 45 Result parseOn(Context context) { | |
| 46 var current = context; | |
| 47 var elements = new List(); | |
| 48 while (elements.length < _min) { | |
| 49 var result = _delegate.parseOn(current); | |
| 50 if (result.isFailure) { | |
| 51 return result; | |
| 52 } | |
| 53 elements.add(result.value); | |
| 54 current = result; | |
| 55 } | |
| 56 while (_max == unbounded || elements.length < _max) { | |
| 57 var result = _delegate.parseOn(current); | |
| 58 if (result.isFailure) { | |
| 59 return current.success(elements); | |
| 60 } | |
| 61 elements.add(result.value); | |
| 62 current = result; | |
| 63 } | |
| 64 return current.success(elements); | |
| 65 } | |
| 66 | |
| 67 @override | |
| 68 Parser copy() => new PossessiveRepeatingParser(_delegate, _min, _max); | |
| 69 } | |
| 70 | |
| 71 /** | |
| 72 * An abstract parser that repeatedly parses between 'min' and 'max' instances o
f | |
| 73 * its delegate and that requires the input to be completed with a specified par
ser | |
| 74 * 'limit'. Subclasses provide repeating behavior as typically seen in regular | |
| 75 * expression implementations (non-blind). | |
| 76 */ | |
| 77 abstract class LimitedRepeatingParser extends RepeatingParser { | |
| 78 Parser _limit; | |
| 79 | |
| 80 LimitedRepeatingParser(Parser parser, this._limit, int min, int max) | |
| 81 : super(parser, min, max); | |
| 82 | |
| 83 @override | |
| 84 List<Parser> get children => [_delegate, _limit]; | |
| 85 | |
| 86 @override | |
| 87 void replace(Parser source, Parser target) { | |
| 88 super.replace(source, target); | |
| 89 if (_limit == source) { | |
| 90 _limit = target; | |
| 91 } | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 /** | |
| 96 * A greedy repeating parser, commonly seen in regular expression implementation
s. It | |
| 97 * aggressively consumes as much input as possible and then backtracks to meet t
he | |
| 98 * 'limit' condition. | |
| 99 */ | |
| 100 class GreedyRepeatingParser extends LimitedRepeatingParser { | |
| 101 GreedyRepeatingParser(Parser parser, Parser limit, int min, int max) | |
| 102 : super(parser, limit, min, max); | |
| 103 | |
| 104 @override | |
| 105 Result parseOn(Context context) { | |
| 106 var current = context; | |
| 107 var elements = new List(); | |
| 108 while (elements.length < _min) { | |
| 109 var result = _delegate.parseOn(current); | |
| 110 if (result.isFailure) { | |
| 111 return result; | |
| 112 } | |
| 113 elements.add(result.value); | |
| 114 current = result; | |
| 115 } | |
| 116 var contexts = new List.from([current]); | |
| 117 while (_max == unbounded || elements.length < _max) { | |
| 118 var result = _delegate.parseOn(current); | |
| 119 if (result.isFailure) { | |
| 120 break; | |
| 121 } | |
| 122 elements.add(result.value); | |
| 123 contexts.add(current = result); | |
| 124 } | |
| 125 while (true) { | |
| 126 var limit = _limit.parseOn(contexts.last); | |
| 127 if (limit.isSuccess) { | |
| 128 return contexts.last.success(elements); | |
| 129 } | |
| 130 if (elements.isEmpty) { | |
| 131 return limit; | |
| 132 } | |
| 133 contexts.removeLast(); | |
| 134 elements.removeLast(); | |
| 135 if (contexts.isEmpty) { | |
| 136 return limit; | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 @override | |
| 142 Parser copy() => new GreedyRepeatingParser(_delegate, _limit, _min, _max); | |
| 143 } | |
| 144 | |
| 145 /** | |
| 146 * A lazy repeating parser, commonly seen in regular expression implementations.
It | |
| 147 * limits its consumption to meet the 'limit' condition as early as possible. | |
| 148 */ | |
| 149 class LazyRepeatingParser extends LimitedRepeatingParser { | |
| 150 LazyRepeatingParser(Parser parser, Parser limit, int min, int max) | |
| 151 : super(parser, limit, min, max); | |
| 152 | |
| 153 @override | |
| 154 Result parseOn(Context context) { | |
| 155 var current = context; | |
| 156 var elements = new List(); | |
| 157 while (elements.length < _min) { | |
| 158 var result = _delegate.parseOn(current); | |
| 159 if (result.isFailure) { | |
| 160 return result; | |
| 161 } | |
| 162 elements.add(result.value); | |
| 163 current = result; | |
| 164 } | |
| 165 while (true) { | |
| 166 var limit = _limit.parseOn(current); | |
| 167 if (limit.isSuccess) { | |
| 168 return current.success(elements); | |
| 169 } else { | |
| 170 if (_max != unbounded && elements.length >= _max) { | |
| 171 return limit; | |
| 172 } | |
| 173 var result = _delegate.parseOn(current); | |
| 174 if (result.isFailure) { | |
| 175 return limit; | |
| 176 } | |
| 177 elements.add(result.value); | |
| 178 current = result; | |
| 179 } | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 @override | |
| 184 Parser copy() => new LazyRepeatingParser(_delegate, _limit, _min, _max); | |
| 185 } | |
| OLD | NEW |