OLD | NEW |
| (Empty) |
1 part of petitparser; | |
2 | |
3 /** | |
4 * A parser that delegates to another one. Normally users do not need to | |
5 * directly use a delegate parser. | |
6 */ | |
7 class DelegateParser extends Parser { | |
8 Parser _delegate; | |
9 | |
10 DelegateParser(this._delegate); | |
11 | |
12 @override | |
13 Result parseOn(Context context) { | |
14 return _delegate.parseOn(context); | |
15 } | |
16 | |
17 @override | |
18 List<Parser> get children => [_delegate]; | |
19 | |
20 @override | |
21 void replace(Parser source, Parser target) { | |
22 super.replace(source, target); | |
23 if (_delegate == source) { | |
24 _delegate = target; | |
25 } | |
26 } | |
27 | |
28 @override | |
29 Parser copy() => new DelegateParser(_delegate); | |
30 } | |
31 | |
32 /** | |
33 * A parser that succeeds only at the end of the input. | |
34 */ | |
35 class EndOfInputParser extends DelegateParser { | |
36 final String _message; | |
37 | |
38 EndOfInputParser(parser, this._message) : super(parser); | |
39 | |
40 @override | |
41 Result parseOn(Context context) { | |
42 var result = _delegate.parseOn(context); | |
43 if (result.isFailure || result.position == result.buffer.length) { | |
44 return result; | |
45 } | |
46 return result.failure(_message, result.position); | |
47 } | |
48 | |
49 @override | |
50 String toString() => '${super.toString()}[$_message]'; | |
51 | |
52 @override | |
53 Parser copy() => new EndOfInputParser(_delegate, _message); | |
54 | |
55 @override | |
56 bool hasEqualProperties(Parser other) { | |
57 return other is EndOfInputParser && super.hasEqualProperties(other) | |
58 && _message == other._message; | |
59 } | |
60 } | |
61 | |
62 /** | |
63 * The and-predicate, a parser that succeeds whenever its delegate does, but | |
64 * does not consume the input stream [Parr 1994, 1995]. | |
65 */ | |
66 class AndParser extends DelegateParser { | |
67 AndParser(parser) : super(parser); | |
68 | |
69 @override | |
70 Result parseOn(Context context) { | |
71 var result = _delegate.parseOn(context); | |
72 if (result.isSuccess) { | |
73 return context.success(result.value); | |
74 } else { | |
75 return result; | |
76 } | |
77 } | |
78 | |
79 @override | |
80 Parser copy() => new AndParser(_delegate); | |
81 } | |
82 | |
83 /** | |
84 * The not-predicate, a parser that succeeds whenever its delegate does not, | |
85 * but consumes no input [Parr 1994, 1995]. | |
86 */ | |
87 class NotParser extends DelegateParser { | |
88 final String _message; | |
89 | |
90 NotParser(parser, this._message) : super(parser); | |
91 | |
92 @override | |
93 Result parseOn(Context context) { | |
94 var result = _delegate.parseOn(context); | |
95 if (result.isFailure) { | |
96 return context.success(null); | |
97 } else { | |
98 return context.failure(_message); | |
99 } | |
100 } | |
101 | |
102 @override | |
103 String toString() => '${super.toString()}[$_message]'; | |
104 | |
105 @override | |
106 Parser copy() => new NotParser(_delegate, _message); | |
107 | |
108 @override | |
109 bool hasEqualProperties(Parser other) { | |
110 return other is NotParser | |
111 && super.hasEqualProperties(other) | |
112 && _message == other._message; | |
113 } | |
114 } | |
115 | |
116 /** | |
117 * A parser that optionally parsers its delegate, or answers nil. | |
118 */ | |
119 class OptionalParser extends DelegateParser { | |
120 final _otherwise; | |
121 | |
122 OptionalParser(parser, this._otherwise) : super(parser); | |
123 | |
124 @override | |
125 Result parseOn(Context context) { | |
126 var result = _delegate.parseOn(context); | |
127 if (result.isSuccess) { | |
128 return result; | |
129 } else { | |
130 return context.success(_otherwise); | |
131 } | |
132 } | |
133 | |
134 @override | |
135 Parser copy() => new OptionalParser(_delegate, _otherwise); | |
136 | |
137 @override | |
138 bool hasEqualProperties(Parser other) { | |
139 return other is OptionalParser | |
140 && super.hasEqualProperties(other) | |
141 && _otherwise == other._otherwise; | |
142 } | |
143 } | |
144 | |
145 /** | |
146 * Abstract parser that parses a list of things in some way. | |
147 */ | |
148 abstract class ListParser extends Parser { | |
149 final List<Parser> _parsers; | |
150 | |
151 ListParser(this._parsers); | |
152 | |
153 @override | |
154 List<Parser> get children => _parsers; | |
155 | |
156 @override | |
157 void replace(Parser source, Parser target) { | |
158 super.replace(source, target); | |
159 for (var i = 0; i < _parsers.length; i++) { | |
160 if (_parsers[i] == source) { | |
161 _parsers[i] = target; | |
162 } | |
163 } | |
164 } | |
165 } | |
166 | |
167 /** | |
168 * A parser that uses the first parser that succeeds. | |
169 */ | |
170 class ChoiceParser extends ListParser { | |
171 factory ChoiceParser(Iterable<Parser> parsers) { | |
172 return new ChoiceParser._(new List.from(parsers, growable: false)); | |
173 } | |
174 | |
175 ChoiceParser._(parsers) : super(parsers); | |
176 | |
177 @override | |
178 Result parseOn(Context context) { | |
179 var result; | |
180 for (var i = 0; i < _parsers.length; i++) { | |
181 result = _parsers[i].parseOn(context); | |
182 if (result.isSuccess) { | |
183 return result; | |
184 } | |
185 } | |
186 return result; | |
187 } | |
188 | |
189 @override | |
190 Parser or(Parser other) { | |
191 return new ChoiceParser(new List() | |
192 ..addAll(_parsers) | |
193 ..add(other)); | |
194 } | |
195 | |
196 @override | |
197 Parser copy() => new ChoiceParser(_parsers); | |
198 } | |
199 | |
200 /** | |
201 * A parser that parses a sequence of parsers. | |
202 */ | |
203 class SequenceParser extends ListParser { | |
204 factory SequenceParser(Iterable<Parser> parsers) { | |
205 return new SequenceParser._(new List.from(parsers, growable: false)); | |
206 } | |
207 | |
208 SequenceParser._(parsers) : super(parsers); | |
209 | |
210 @override | |
211 Result parseOn(Context context) { | |
212 var current = context; | |
213 var elements = new List(_parsers.length); | |
214 for (var i = 0; i < _parsers.length; i++) { | |
215 var result = _parsers[i].parseOn(current); | |
216 if (result.isFailure) { | |
217 return result; | |
218 } | |
219 elements[i] = result.value; | |
220 current = result; | |
221 } | |
222 return current.success(elements); | |
223 } | |
224 | |
225 @override | |
226 Parser seq(Parser other) { | |
227 return new SequenceParser(new List() | |
228 ..addAll(_parsers) | |
229 ..add(other)); | |
230 } | |
231 | |
232 @override | |
233 Parser copy() => new SequenceParser(_parsers); | |
234 } | |
OLD | NEW |