OLD | NEW |
| (Empty) |
1 part of petitparser; | |
2 | |
3 /** | |
4 * Returns a parser that accepts any input element. | |
5 * | |
6 * For example, `any()` succeeds and consumes any given letter. It only | |
7 * fails for an empty input. | |
8 */ | |
9 Parser any([String message = 'input expected']) { | |
10 return new AnyParser(message); | |
11 } | |
12 | |
13 /** | |
14 * A parser that accepts any input element. | |
15 */ | |
16 class AnyParser extends Parser { | |
17 final String _message; | |
18 | |
19 AnyParser(this._message); | |
20 | |
21 @override | |
22 Result parseOn(Context context) { | |
23 var position = context.position; | |
24 var buffer = context.buffer; | |
25 return position < buffer.length | |
26 ? context.success(buffer[position], position + 1) | |
27 : context.failure(_message); | |
28 } | |
29 | |
30 @override | |
31 Parser copy() => new AnyParser(_message); | |
32 | |
33 @override | |
34 bool hasEqualProperties(Parser other) { | |
35 return other is AnyParser | |
36 && super.hasEqualProperties(other) | |
37 && _message == other._message; | |
38 } | |
39 } | |
40 | |
41 /** | |
42 * Returns a parser that accepts any of the [elements]. | |
43 * | |
44 * For example, `anyIn('ab')` succeeds and consumes either the letter | |
45 * `'a'` or the letter `'b'`. For any other input the parser fails. | |
46 */ | |
47 Parser anyIn(elements, [String message]) { | |
48 return predicate(1, (each) => elements.indexOf(each) >= 0, | |
49 message != null ? message : 'any of $elements expected'); | |
50 } | |
51 | |
52 /** | |
53 * Returns a parser that accepts the string [element]. | |
54 * | |
55 * For example, `string('foo')` succeeds and consumes the input string | |
56 * `'foo'`. Fails for any other input. | |
57 */ | |
58 Parser string(String element, [String message]) { | |
59 return predicate(element.length, (String each) => element == each, | |
60 message != null ? message : '$element expected'); | |
61 } | |
62 | |
63 /** | |
64 * Returns a parser that accepts the string [element] ignoring the case. | |
65 * | |
66 * For example, `stringIgnoreCase('foo')` succeeds and consumes the input | |
67 * string `'Foo'` or `'FOO'`. Fails for any other input. | |
68 */ | |
69 Parser stringIgnoreCase(String element, [String message]) { | |
70 final lowerElement = element.toLowerCase(); | |
71 return predicate(element.length, | |
72 (String each) => lowerElement == each.toLowerCase(), | |
73 message != null ? message : '$element expected'); | |
74 } | |
75 | |
76 /** | |
77 * A generic predicate function returning [true] or [false] for a given | |
78 * [input] argument. | |
79 */ | |
80 typedef bool Predicate(input); | |
81 | |
82 /** | |
83 * Returns a parser that reads input of the specified [length], accepts | |
84 * it if the [predicate] matches, or fails with the given [message]. | |
85 */ | |
86 Parser predicate(int length, Predicate predicate, String message) { | |
87 return new PredicateParser(length, predicate, message); | |
88 } | |
89 | |
90 /** | |
91 * A parser for a literal satisfying a predicate. | |
92 */ | |
93 class PredicateParser extends Parser { | |
94 final int _length; | |
95 final Predicate _predicate; | |
96 final String _message; | |
97 | |
98 PredicateParser(this._length, this._predicate, this._message); | |
99 | |
100 @override | |
101 Result parseOn(Context context) { | |
102 final start = context.position; | |
103 final stop = start + _length; | |
104 if (stop <= context.buffer.length) { | |
105 var result = context.buffer is String | |
106 ? context.buffer.substring(start, stop) | |
107 : context.buffer.sublist(start, stop); | |
108 if (_predicate(result)) { | |
109 return context.success(result, stop); | |
110 } | |
111 } | |
112 return context.failure(_message); | |
113 } | |
114 | |
115 @override | |
116 String toString() => '${super.toString()}[$_message]'; | |
117 | |
118 @override | |
119 Parser copy() => new PredicateParser(_length, _predicate, _message); | |
120 | |
121 @override | |
122 bool hasEqualProperties(Parser other) { | |
123 return other is PredicateParser | |
124 && super.hasEqualProperties(other) | |
125 && _length == other._length | |
126 && _predicate == other._predicate | |
127 && _message == other._message; | |
128 } | |
129 } | |
OLD | NEW |