| OLD | NEW |
| (Empty) |
| 1 part of petitparser; | |
| 2 | |
| 3 /** | |
| 4 * Abstract base class of all parsers. | |
| 5 */ | |
| 6 abstract class Parser { | |
| 7 | |
| 8 /** | |
| 9 * Primitive method doing the actual parsing. | |
| 10 * | |
| 11 * The method is overridden in concrete subclasses to implement the | |
| 12 * parser specific logic. The methods takes a parse [context] and | |
| 13 * returns the resulting context, which is either a [Success] or | |
| 14 * [Failure] context. | |
| 15 */ | |
| 16 Result parseOn(Context context); | |
| 17 | |
| 18 /** | |
| 19 * Returns the parse result of the [input]. | |
| 20 * | |
| 21 * The implementation creates a default parse context on the input and calls | |
| 22 * the internal parsing logic of the receiving parser. | |
| 23 * | |
| 24 * For example, `letter().plus().parse('abc')` results in an instance of | |
| 25 * [Success], where [Result.position] is `3` and [Success.value] is | |
| 26 * `[a, b, c]`. | |
| 27 * | |
| 28 * Similarly, `letter().plus().parse('123')` results in an instance of | |
| 29 * [Failure], where [Result.position] is `0` and [Failure.message] is | |
| 30 * ['letter expected']. | |
| 31 */ | |
| 32 Result parse(input) { | |
| 33 return parseOn(new Context(input, 0)); | |
| 34 } | |
| 35 | |
| 36 /** | |
| 37 * Tests if the [input] can be successfully parsed. | |
| 38 * | |
| 39 * For example, `letter().plus().accept('abc')` returns `true`, and | |
| 40 * `letter().plus().accept('123')` returns `false`. | |
| 41 */ | |
| 42 bool accept(input) { | |
| 43 return parse(input).isSuccess; | |
| 44 } | |
| 45 | |
| 46 /** | |
| 47 * Returns a list of all successful overlapping parses of the [input]. | |
| 48 * | |
| 49 * For example, `letter().plus().matches('abc de')` results in the list | |
| 50 * `[['a', 'b', 'c'], ['b', 'c'], ['c'], ['d', 'e'], ['e']]`. See | |
| 51 * [Parser.matchesSkipping] to retrieve non-overlapping parse results. | |
| 52 */ | |
| 53 Iterable matches(input) { | |
| 54 var list = new List(); | |
| 55 and() | |
| 56 .map((each) => list.add(each)) | |
| 57 .seq(any()) | |
| 58 .or(any()) | |
| 59 .star() | |
| 60 .parse(input); | |
| 61 return list; | |
| 62 } | |
| 63 | |
| 64 /** | |
| 65 * Returns a list of all successful non-overlapping parses of the input. | |
| 66 * | |
| 67 * For example, `letter().plus().matchesSkipping('abc de')` results in the | |
| 68 * list `[['a', 'b', 'c'], ['d', 'e']]`. See [Parser.matches] to retrieve | |
| 69 * overlapping parse results. | |
| 70 */ | |
| 71 Iterable matchesSkipping(input) { | |
| 72 var list = new List(); | |
| 73 map((each) => list.add(each)).or(any()).star().parse(input); | |
| 74 return list; | |
| 75 } | |
| 76 | |
| 77 /** | |
| 78 * Returns new parser that accepts the receiver, if possible. The resulting | |
| 79 * parser returns the result of the receiver, or `null` if not applicable. | |
| 80 * The returned value can be provided as an optional argument [otherwise]. | |
| 81 * | |
| 82 * For example, the parser `letter().optional()` accepts a letter as input | |
| 83 * and returns that letter. When given something else the parser succeeds as | |
| 84 * well, does not consume anything and returns `null`. | |
| 85 */ | |
| 86 Parser optional([otherwise]) => new OptionalParser(this, otherwise); | |
| 87 | |
| 88 /** | |
| 89 * Returns a parser that accepts the receiver zero or more times. The | |
| 90 * resulting parser returns a list of the parse results of the receiver. | |
| 91 * | |
| 92 * This is a greedy and blind implementation that tries to consume as much | |
| 93 * input as possible and that does not consider what comes afterwards. | |
| 94 * | |
| 95 * For example, the parser `letter().star()` accepts the empty string or | |
| 96 * any sequence of letters and returns a possibly empty list of the parsed | |
| 97 * letters. | |
| 98 */ | |
| 99 Parser star() => repeat(0, unbounded); | |
| 100 | |
| 101 /** | |
| 102 * Returns a parser that parses the receiver zero or more times until it | |
| 103 * reaches a [limit]. This is a greedy non-blind implementation of the | |
| 104 * [Parser.star] operator. The [limit] is not consumed. | |
| 105 */ | |
| 106 Parser starGreedy(Parser limit) => repeatGreedy(limit, 0, unbounded); | |
| 107 | |
| 108 /** | |
| 109 * Returns a parser that parses the receiver zero or more times until it | |
| 110 * reaches a [limit]. This is a lazy non-blind implementation of the | |
| 111 * [Parser.star] operator. The [limit] is not consumed. | |
| 112 */ | |
| 113 Parser starLazy(Parser limit) => repeatLazy(limit, 0, unbounded); | |
| 114 | |
| 115 /** | |
| 116 * Returns a parser that accepts the receiver one or more times. The | |
| 117 * resulting parser returns a list of the parse results of the receiver. | |
| 118 * | |
| 119 * This is a greedy and blind implementation that tries to consume as much | |
| 120 * input as possible and that does not consider what comes afterwards. | |
| 121 * | |
| 122 * For example, the parser `letter().plus()` accepts any sequence of | |
| 123 * letters and returns a list of the parsed letters. | |
| 124 */ | |
| 125 Parser plus() => repeat(1, unbounded); | |
| 126 | |
| 127 /** | |
| 128 * Returns a parser that parses the receiver one or more times until it | |
| 129 * reaches [limit]. This is a greedy non-blind implementation of the | |
| 130 * [Parser.plus] operator. The [limit] is not consumed. | |
| 131 */ | |
| 132 Parser plusGreedy(Parser limit) => repeatGreedy(limit, 1, unbounded); | |
| 133 | |
| 134 /** | |
| 135 * Returns a parser that parses the receiver one or more times until it | |
| 136 * reaches a [limit]. This is a lazy non-blind implementation of the | |
| 137 * [Parser.plus] operator. The [limit] is not consumed. | |
| 138 */ | |
| 139 Parser plusLazy(Parser limit) => repeatLazy(limit, 1, unbounded); | |
| 140 | |
| 141 /** | |
| 142 * Returns a parser that accepts the receiver between [min] and [max] times. | |
| 143 * The resulting parser returns a list of the parse results of the receiver. | |
| 144 * | |
| 145 * This is a greedy and blind implementation that tries to consume as much | |
| 146 * input as possible and that does not consider what comes afterwards. | |
| 147 * | |
| 148 * For example, the parser `letter().repeat(2, 4)` accepts a sequence of | |
| 149 * two, three, or four letters and returns the accepted letters as a list. | |
| 150 */ | |
| 151 Parser repeat(int min, int max) { | |
| 152 return new PossessiveRepeatingParser(this, min, max); | |
| 153 } | |
| 154 | |
| 155 /** | |
| 156 * Returns a parser that parses the receiver at least [min] and at most [max] | |
| 157 * times until it reaches a [limit]. This is a greedy non-blind implementation
of | |
| 158 * the [Parser.repeat] operator. The [limit] is not consumed. | |
| 159 */ | |
| 160 Parser repeatGreedy(Parser limit, int min, int max) { | |
| 161 return new GreedyRepeatingParser(this, limit, min, max); | |
| 162 } | |
| 163 | |
| 164 /** | |
| 165 * Returns a parser that parses the receiver at least [min] and at most [max] | |
| 166 * times until it reaches a [limit]. This is a lazy non-blind implementation o
f | |
| 167 * the [Parser.repeat] operator. The [limit] is not consumed. | |
| 168 */ | |
| 169 Parser repeatLazy(Parser limit, int min, int max) { | |
| 170 return new LazyRepeatingParser(this, limit, min, max); | |
| 171 } | |
| 172 | |
| 173 /** | |
| 174 * Returns a parser that accepts the receiver exactly [count] times. The | |
| 175 * resulting parser returns a list of the parse results of the receiver. | |
| 176 * | |
| 177 * For example, the parser `letter().times(2)` accepts two letters and | |
| 178 * returns a list of the two parsed letters. | |
| 179 */ | |
| 180 Parser times(int count) => repeat(count, count); | |
| 181 | |
| 182 /** | |
| 183 * Returns a parser that accepts the receiver followed by [other]. The | |
| 184 * resulting parser returns a list of the parse result of the receiver | |
| 185 * followed by the parse result of [other]. Calling this method on an | |
| 186 * existing sequence code not nest this sequence into a new one, but | |
| 187 * instead augments the existing sequence with [other]. | |
| 188 * | |
| 189 * For example, the parser `letter().seq(digit()).seq(letter())` accepts a | |
| 190 * letter followed by a digit and another letter. The parse result of the | |
| 191 * input string `'a1b'` is the list `['a', '1', 'b']`. | |
| 192 */ | |
| 193 Parser seq(Parser other) => new SequenceParser([this, other]); | |
| 194 | |
| 195 /** | |
| 196 * Convenience operator returning a parser that accepts the receiver followed | |
| 197 * by [other]. See [Parser.seq] for details. | |
| 198 */ | |
| 199 Parser operator &(Parser other) => this.seq(other); | |
| 200 | |
| 201 /** | |
| 202 * Returns a parser that accepts the receiver or [other]. The resulting | |
| 203 * parser returns the parse result of the receiver, if the receiver fails | |
| 204 * it returns the parse result of [other] (exclusive ordered choice). | |
| 205 * | |
| 206 * For example, the parser `letter().or(digit())` accepts a letter or a | |
| 207 * digit. An example where the order matters is the following choice between | |
| 208 * overlapping parsers: `letter().or(char('a'))`. In the example the parser | |
| 209 * `char('a')` will never be activated, because the input is always consumed | |
| 210 * `letter()`. This can be problematic if the author intended to attach a | |
| 211 * production action to `char('a')`. | |
| 212 */ | |
| 213 Parser or(Parser other) => new ChoiceParser([this, other]); | |
| 214 | |
| 215 /** | |
| 216 * Convenience operator returning a parser that accepts the receiver or | |
| 217 * [other]. See [Parser.or] for details. | |
| 218 */ | |
| 219 Parser operator |(Parser other) => this.or(other); | |
| 220 | |
| 221 /** | |
| 222 * Returns a parser (logical and-predicate) that succeeds whenever the | |
| 223 * receiver does, but never consumes input. | |
| 224 * | |
| 225 * For example, the parser `char('_').and().seq(identifier)` accepts | |
| 226 * identifiers that start with an underscore character. Since the predicate | |
| 227 * does not consume accepted input, the parser `identifier` is given the | |
| 228 * ability to process the complete identifier. | |
| 229 */ | |
| 230 Parser and() => new AndParser(this); | |
| 231 | |
| 232 /** | |
| 233 * Returns a parser (logical not-predicate) that succeeds whenever the | |
| 234 * receiver fails, but never consumes input. | |
| 235 * | |
| 236 * For example, the parser `char('_').not().seq(identifier)` accepts | |
| 237 * identifiers that do not start with an underscore character. If the parser | |
| 238 * `char('_')` accepts the input, the negation and subsequently the | |
| 239 * complete parser fails. Otherwise the parser `identifier` is given the | |
| 240 * ability to process the complete identifier. | |
| 241 */ | |
| 242 Parser not([String message]) => new NotParser(this, message); | |
| 243 | |
| 244 /** | |
| 245 * Returns a parser that consumes any input token (character), but the | |
| 246 * receiver. | |
| 247 * | |
| 248 * For example, the parser `letter().neg()` accepts any input but a letter. | |
| 249 * The parser fails for inputs like `'a'` or `'Z'`, but succeeds for | |
| 250 * input like `'1'`, `'_'` or `'$'`. | |
| 251 */ | |
| 252 Parser neg([String message]) => not(message).seq(any()).pick(1); | |
| 253 | |
| 254 /** | |
| 255 * Returns a parser that discards the result of the receiver, and returns | |
| 256 * a sub-string of the consumed range in the string/list being parsed. | |
| 257 * | |
| 258 * For example, the parser `letter().plus().flatten()` returns `'abc'` | |
| 259 * for the input `'abc'`. In contrast, the parser `letter().plus()` would | |
| 260 * return `['a', 'b', 'c']` for the same input instead. | |
| 261 */ | |
| 262 Parser flatten() => new FlattenParser(this); | |
| 263 | |
| 264 /** | |
| 265 * Returns a parser that returns a [Token]. The token carries the parsed | |
| 266 * value of the receiver [Token.value], as well as the consumed input | |
| 267 * [Token.input] from [Token.start] to [Token.stop] of the input being | |
| 268 * parsed. | |
| 269 * | |
| 270 * For example, the parser `letter().plus().token()` returns the token | |
| 271 * `Token[start: 0, stop: 3, value: abc]` for the input `'abc'`. | |
| 272 */ | |
| 273 Parser token() => new TokenParser(this); | |
| 274 | |
| 275 /** | |
| 276 * Returns a parser that consumes input before and after the receiver. The | |
| 277 * optional argument is a parser that consumes the excess input. By default | |
| 278 * `whitespace()` is used. Two arguments can be provided to have different | |
| 279 * parsers on the [left] and [right] side. | |
| 280 * | |
| 281 * For example, the parser `letter().plus().trim()` returns `['a', 'b']` | |
| 282 * for the input `' ab\n'` and consumes the complete input string. | |
| 283 */ | |
| 284 Parser trim([Parser left, Parser right]) { | |
| 285 if (left == null) left = whitespace(); | |
| 286 if (right == null) right = left; | |
| 287 return new TrimmingParser(this, left, right); | |
| 288 } | |
| 289 | |
| 290 /** | |
| 291 * Returns a parser that succeeds only if the receiver consumes the complete | |
| 292 * input, otherwise return a failure with the optional [message]. | |
| 293 * | |
| 294 * For example, the parser `letter().end()` succeeds on the input `'a'` | |
| 295 * and fails on `'ab'`. In contrast the parser `letter()` alone would | |
| 296 * succeed on both inputs, but not consume everything for the second input. | |
| 297 */ | |
| 298 Parser end([String message = 'end of input expected']) { | |
| 299 return new EndOfInputParser(this, message); | |
| 300 } | |
| 301 | |
| 302 /** | |
| 303 * Returns a parser that points to the receiver, but can be changed to point | |
| 304 * to something else at a later point in time. | |
| 305 * | |
| 306 * For example, the parser `letter().settable()` behaves exactly the same | |
| 307 * as `letter()`, but it can be replaced with another parser using | |
| 308 * [SettableParser.set]. | |
| 309 */ | |
| 310 SettableParser settable() => new SettableParser(this); | |
| 311 | |
| 312 /** | |
| 313 * Returns a parser that evaluates a [function] as the production action | |
| 314 * on success of the receiver. | |
| 315 * | |
| 316 * For example, the parser `digit().map((char) => int.parse(char))` returns | |
| 317 * the number `1` for the input string `'1'`. If the delegate fail, the | |
| 318 * production action is not executed and the failure is passed on. | |
| 319 */ | |
| 320 Parser map(Function function) => new ActionParser(this, function); | |
| 321 | |
| 322 /** | |
| 323 * Returns a parser that transform a successful parse result by returning | |
| 324 * the element at [index] of a list. A negative index can be used to access | |
| 325 * the elements from the back of the list. | |
| 326 * | |
| 327 * For example, the parser `letter().star().pick(-1)` returns the last | |
| 328 * letter parsed. For the input `'abc'` it returns `'c'`. | |
| 329 */ | |
| 330 Parser pick(int index) { | |
| 331 return this.map((List list) { | |
| 332 return list[index < 0 ? list.length + index : index]; | |
| 333 }); | |
| 334 } | |
| 335 | |
| 336 /** | |
| 337 * Returns a parser that transforms a successful parse result by returning | |
| 338 * the permuted elements at [indexes] of a list. Negative indexes can be | |
| 339 * used to access the elements from the back of the list. | |
| 340 * | |
| 341 * For example, the parser `letter().star().permute([0, -1])` returns the | |
| 342 * first and last letter parsed. For the input `'abc'` it returns | |
| 343 * `['a', 'c']`. | |
| 344 */ | |
| 345 Parser permute(List<int> indexes) { | |
| 346 return this.map((List list) { | |
| 347 return indexes.map((index) { | |
| 348 return list[index < 0 ? list.length + index : index]; | |
| 349 }).toList(); | |
| 350 }); | |
| 351 } | |
| 352 | |
| 353 /** | |
| 354 * Returns a parser that consumes the receiver one or more times separated | |
| 355 * by the [separator] parser. The resulting parser returns a flat list of | |
| 356 * the parse results of the receiver interleaved with the parse result of the | |
| 357 * separator parser. | |
| 358 * | |
| 359 * If the optional argument [includeSeparators] is set to `false`, then the | |
| 360 * separators are not included in the parse result. If the optional argument | |
| 361 * [optionalSeparatorAtEnd] is set to `true` the parser also accepts an | |
| 362 * optional separator at the end. | |
| 363 * | |
| 364 * For example, the parser `digit().separatedBy(char('-'))` returns a parser | |
| 365 * that consumes input like `'1-2-3'` and returns a list of the elements and | |
| 366 * separators: `['1', '-', '2', '-', '3']`. | |
| 367 */ | |
| 368 Parser separatedBy(Parser separator, | |
| 369 {bool includeSeparators: true, bool optionalSeparatorAtEnd: false}) { | |
| 370 var repeater = new SequenceParser([separator, this]).star(); | |
| 371 var parser = new SequenceParser(optionalSeparatorAtEnd | |
| 372 ? [this, repeater, separator.optional(separator)] | |
| 373 : [this, repeater]); | |
| 374 return parser.map((List list) { | |
| 375 var result = new List(); | |
| 376 result.add(list[0]); | |
| 377 for (var tuple in list[1]) { | |
| 378 if (includeSeparators) { | |
| 379 result.add(tuple[0]); | |
| 380 } | |
| 381 result.add(tuple[1]); | |
| 382 } | |
| 383 if (includeSeparators && | |
| 384 optionalSeparatorAtEnd && | |
| 385 !identical(list[2], separator)) { | |
| 386 result.add(list[2]); | |
| 387 } | |
| 388 return result; | |
| 389 }); | |
| 390 } | |
| 391 | |
| 392 /** | |
| 393 * Returns a shallow copy of the receiver. | |
| 394 * | |
| 395 * Override this method in all subclasses. | |
| 396 */ | |
| 397 Parser copy(); | |
| 398 | |
| 399 /** | |
| 400 * Recursively tests for structural equality of two parsers. | |
| 401 * | |
| 402 * The code can automatically deals with recursive parsers and parsers that | |
| 403 * refer to other parsers. This code is supposed to be overridden by parsers | |
| 404 * that add other state. | |
| 405 */ | |
| 406 bool isEqualTo(Parser other, [Set<Parser> seen]) { | |
| 407 if (seen == null) { | |
| 408 seen = new Set(); | |
| 409 } | |
| 410 if (this == other || seen.contains(this)) { | |
| 411 return true; | |
| 412 } | |
| 413 seen.add(this); | |
| 414 return runtimeType == other.runtimeType && | |
| 415 hasEqualProperties(other) && | |
| 416 hasEqualChildren(other, seen); | |
| 417 } | |
| 418 | |
| 419 /** | |
| 420 * Compare the properties of two parsers. Normally this method should not be | |
| 421 * called directly, instead use [Parser#equals]. | |
| 422 * | |
| 423 * Override this method in all subclasses that add new state. | |
| 424 */ | |
| 425 bool hasEqualProperties(Parser other) => true; | |
| 426 | |
| 427 /** | |
| 428 * Compare the children of two parsers. Normally this method should not be | |
| 429 * called directly, instead use [Parser#equals]. | |
| 430 * | |
| 431 * Normally this method does not need to be overridden, as this method works | |
| 432 * generically on the returned [Parser#children]. | |
| 433 */ | |
| 434 bool hasEqualChildren(Parser other, Set<Parser> seen) { | |
| 435 var thisChildren = children, | |
| 436 otherChildren = other.children; | |
| 437 if (thisChildren.length != otherChildren.length) { | |
| 438 return false; | |
| 439 } | |
| 440 for (var i = 0; i < thisChildren.length; i++) { | |
| 441 if (!thisChildren[i].isEqualTo(otherChildren[i], seen)) { | |
| 442 return false; | |
| 443 } | |
| 444 } | |
| 445 return true; | |
| 446 } | |
| 447 | |
| 448 /** | |
| 449 * Returns a list of directly referenced parsers. | |
| 450 * | |
| 451 * For example, `letter().children` returns the empty collection `[]`, | |
| 452 * because the letter parser is a primitive or leaf parser that does not | |
| 453 * depend or call any other parser. | |
| 454 * | |
| 455 * In contrast, `letter().or(digit()).children` returns a collection | |
| 456 * containing both the `letter()` and `digit()` parser. | |
| 457 */ | |
| 458 List<Parser> get children => const []; | |
| 459 | |
| 460 /** | |
| 461 * Changes the receiver by replacing [source] with [target]. Does nothing | |
| 462 * if [source] does not exist in [Parser.children]. | |
| 463 * | |
| 464 * The following example creates a letter parser and then defines a parser | |
| 465 * called `example` that accepts one or more letters. Eventually the parser | |
| 466 * `example` is modified by replacing the `letter` parser with a new | |
| 467 * parser that accepts a digit. The resulting `example` parser accepts one | |
| 468 * or more digits. | |
| 469 * | |
| 470 * var letter = letter(); | |
| 471 * var example = letter.plus(); | |
| 472 * example.replace(letter, digit()); | |
| 473 */ | |
| 474 void replace(Parser source, Parser target) { | |
| 475 // no children, nothing to do | |
| 476 } | |
| 477 } | |
| OLD | NEW |