Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: utils/pub/yaml/parser.dart

Issue 11638010: Convert /** comments to /// in pub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix 80 column limit. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /// Translates a string of characters into a YAML serialization tree.
6 * Translates a string of characters into a YAML serialization tree. 6 ///
7 * 7 /// This parser is designed to closely follow the spec. All productions in the
8 * This parser is designed to closely follow the spec. All productions in the 8 /// spec are numbered, and the corresponding methods in the parser have the same
9 * spec are numbered, and the corresponding methods in the parser have the same 9 /// numbers. This is certainly not the most efficient way of parsing YAML, but
10 * numbers. This is certainly not the most efficient way of parsing YAML, but it 10 /// it is the easiest to write and read in the context of the spec.
11 * is the easiest to write and read in the context of the spec. 11 ///
12 * 12 /// Methods corresponding to productions are also named as in the spec,
13 * Methods corresponding to productions are also named as in the spec, 13 /// translating the name of the method (although not the annotation characters)
14 * translating the name of the method (although not the annotation characters) 14 /// into camel-case for dart style.. For example, the spec has a production
15 * into camel-case for dart style.. For example, the spec has a production named 15 /// named `nb-ns-plain-in-line`, and the method implementing it is named
16 * `nb-ns-plain-in-line`, and the method implementing it is named 16 /// `nb_ns_plainInLine`. The exception to that rule is methods that just
17 * `nb_ns_plainInLine`. The exception to that rule is methods that just 17 /// recognize character classes; these are named `is*`.
18 * recognize character classes; these are named `is*`.
19 */
20 class _Parser { 18 class _Parser {
21 static const TAB = 0x9; 19 static const TAB = 0x9;
22 static const LF = 0xA; 20 static const LF = 0xA;
23 static const CR = 0xD; 21 static const CR = 0xD;
24 static const SP = 0x20; 22 static const SP = 0x20;
25 static const TILDE = 0x7E; 23 static const TILDE = 0x7E;
26 static const NEL = 0x85; 24 static const NEL = 0x85;
27 static const PLUS = 0x2B; 25 static const PLUS = 0x2B;
28 static const HYPHEN = 0x2D; 26 static const HYPHEN = 0x2D;
29 static const QUESTION_MARK = 0x3F; 27 static const QUESTION_MARK = 0x3F;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 static const BLOCK_IN = 1; 101 static const BLOCK_IN = 1;
104 static const FLOW_OUT = 2; 102 static const FLOW_OUT = 2;
105 static const FLOW_IN = 3; 103 static const FLOW_IN = 3;
106 static const BLOCK_KEY = 4; 104 static const BLOCK_KEY = 4;
107 static const FLOW_KEY = 5; 105 static const FLOW_KEY = 5;
108 106
109 static const CHOMPING_STRIP = 0; 107 static const CHOMPING_STRIP = 0;
110 static const CHOMPING_KEEP = 1; 108 static const CHOMPING_KEEP = 1;
111 static const CHOMPING_CLIP = 2; 109 static const CHOMPING_CLIP = 2;
112 110
113 /** The source string being parsed. */ 111 /// The source string being parsed.
114 final String s; 112 final String s;
115 113
116 /** The current position in the source string. */ 114 /// The current position in the source string.
117 int pos = 0; 115 int pos = 0;
118 116
119 /** The length of the string being parsed. */ 117 /// The length of the string being parsed.
120 final int len; 118 final int len;
121 119
122 /** The current (0-based) line in the source string. */ 120 /// The current (0-based) line in the source string.
123 int line = 0; 121 int line = 0;
124 122
125 /** The current (0-based) column in the source string. */ 123 /// The current (0-based) column in the source string.
126 int column = 0; 124 int column = 0;
127 125
128 /** 126 /// Whether we're parsing a bare document (that is, one that doesn't begin
129 * Whether we're parsing a bare document (that is, one that doesn't begin with 127 /// with `---`). Bare documents don't allow `%` immediately following
130 * `---`). Bare documents don't allow `%` immediately following newlines. 128 /// newlines.
131 */
132 bool inBareDocument = false; 129 bool inBareDocument = false;
133 130
134 /** 131 /// The line number of the farthest position that has been parsed successfully
135 * The line number of the farthest position that has been parsed successfully 132 /// before backtracking. Used for error reporting.
136 * before backtracking. Used for error reporting.
137 */
138 int farthestLine = 0; 133 int farthestLine = 0;
139 134
140 /** 135 /// The column number of the farthest position that has been parsed
141 * The column number of the farthest position that has been parsed 136 /// successfully before backtracking. Used for error reporting.
142 * successfully before backtracking. Used for error reporting.
143 */
144 int farthestColumn = 0; 137 int farthestColumn = 0;
145 138
146 /** 139 /// The farthest position in the source string that has been parsed
147 * The farthest position in the source string that has been parsed 140 /// successfully before backtracking. Used for error reporting.
148 * successfully before backtracking. Used for error reporting.
149 */
150 int farthestPos = 0; 141 int farthestPos = 0;
151 142
152 /** 143 /// The name of the context of the farthest position that has been parsed
153 * The name of the context of the farthest position that has been parsed 144 /// successfully before backtracking. Used for error reporting.
154 * successfully before backtracking. Used for error reporting.
155 */
156 String farthestContext = "document"; 145 String farthestContext = "document";
157 146
158 /** A stack of the names of parse contexts. Used for error reporting. */ 147 /// A stack of the names of parse contexts. Used for error reporting.
159 List<String> contextStack; 148 List<String> contextStack;
160 149
161 /** 150 /// Annotations attached to ranges of the source string that add extra
162 * Annotations attached to ranges of the source string that add extra 151 /// information to any errors that occur in the annotated range.
163 * information to any errors that occur in the annotated range.
164 */
165 _RangeMap<String> errorAnnotations; 152 _RangeMap<String> errorAnnotations;
166 153
167 /** 154 /// The buffer containing the string currently being captured.
168 * The buffer containing the string currently being captured.
169 */
170 StringBuffer capturedString; 155 StringBuffer capturedString;
171 156
172 /** 157 /// The beginning of the current section of the captured string.
173 * The beginning of the current section of the captured string.
174 */
175 int captureStart; 158 int captureStart;
176 159
177 /** 160 /// Whether the current string capture is being overridden.
178 * Whether the current string capture is being overridden.
179 */
180 bool capturingAs = false; 161 bool capturingAs = false;
181 162
182 _Parser(String s) 163 _Parser(String s)
183 : this.s = s, 164 : this.s = s,
184 len = s.length, 165 len = s.length,
185 contextStack = <String>["document"], 166 contextStack = <String>["document"],
186 errorAnnotations = new _RangeMap(); 167 errorAnnotations = new _RangeMap();
187 168
188 /** 169 /// Return the character at the current position, then move that position
189 * Return the character at the current position, then move that position 170 /// forward one character. Also updates the current line and column numbers.
190 * forward one character. Also updates the current line and column numbers.
191 */
192 int next() { 171 int next() {
193 if (pos == len) return -1; 172 if (pos == len) return -1;
194 var char = s.charCodeAt(pos++); 173 var char = s.charCodeAt(pos++);
195 if (isBreak(char)) { 174 if (isBreak(char)) {
196 line++; 175 line++;
197 column = 0; 176 column = 0;
198 } else { 177 } else {
199 column++; 178 column++;
200 } 179 }
201 180
202 if (farthestLine < line) { 181 if (farthestLine < line) {
203 farthestLine = line; 182 farthestLine = line;
204 farthestColumn = column; 183 farthestColumn = column;
205 farthestContext = contextStack.last; 184 farthestContext = contextStack.last;
206 } else if (farthestLine == line && farthestColumn < column) { 185 } else if (farthestLine == line && farthestColumn < column) {
207 farthestColumn = column; 186 farthestColumn = column;
208 farthestContext = contextStack.last; 187 farthestContext = contextStack.last;
209 } 188 }
210 farthestPos = pos; 189 farthestPos = pos;
211 190
212 return char; 191 return char;
213 } 192 }
214 193
215 /** 194 /// Returns the character at the current position, or the character [i]
216 * Returns the character at the current position, or the character [i] 195 /// characters after the current position.
217 * characters after the current position. 196 ///
218 * 197 /// Returns -1 if this would return a character after the end or before the
219 * Returns -1 if this would return a character after the end or before the 198 /// beginning of the input string.
220 * beginning of the input string.
221 */
222 int peek([int i = 0]) { 199 int peek([int i = 0]) {
223 var peekPos = pos + i; 200 var peekPos = pos + i;
224 return (peekPos >= len || peekPos < 0) ? -1 : s.charCodeAt(peekPos); 201 return (peekPos >= len || peekPos < 0) ? -1 : s.charCodeAt(peekPos);
225 } 202 }
226 203
227 /** 204 /// The truthiness operator. Returns `false` if [obj] is `null` or `false`,
228 * The truthiness operator. Returns `false` if [obj] is `null` or `false`, 205 /// `true` otherwise.
229 * `true` otherwise.
230 */
231 bool truth(obj) => obj != null && obj != false; 206 bool truth(obj) => obj != null && obj != false;
232 207
233 /** 208 /// Consumes the current character if it matches [matcher]. Returns the result
234 * Consumes the current character if it matches [matcher]. Returns the result 209 /// of [matcher].
235 * of [matcher].
236 */
237 bool consume(bool matcher(int)) { 210 bool consume(bool matcher(int)) {
238 if (matcher(peek())) { 211 if (matcher(peek())) {
239 next(); 212 next();
240 return true; 213 return true;
241 } 214 }
242 return false; 215 return false;
243 } 216 }
244 217
245 /** 218 /// Consumes the current character if it equals [char].
246 * Consumes the current character if it equals [char].
247 */
248 bool consumeChar(int char) => consume((c) => c == char); 219 bool consumeChar(int char) => consume((c) => c == char);
249 220
250 /** 221 /// Calls [consumer] until it returns a falsey value. Returns a list of all
251 * Calls [consumer] until it returns a falsey value. Returns a list of all 222 /// truthy return values of [consumer], or null if it didn't consume anything.
252 * truthy return values of [consumer], or null if it didn't consume anything. 223 ///
253 * 224 /// Conceptually, repeats a production one or more times.
254 * Conceptually, repeats a production one or more times.
255 */
256 List oneOrMore(consumer()) { 225 List oneOrMore(consumer()) {
257 var first = consumer(); 226 var first = consumer();
258 if (!truth(first)) return null; 227 if (!truth(first)) return null;
259 var out = [first]; 228 var out = [first];
260 while (true) { 229 while (true) {
261 var el = consumer(); 230 var el = consumer();
262 if (!truth(el)) return out; 231 if (!truth(el)) return out;
263 out.add(el); 232 out.add(el);
264 } 233 }
265 return null; // Unreachable. 234 return null; // Unreachable.
266 } 235 }
267 236
268 /** 237 /// Calls [consumer] until it returns a falsey value. Returns a list of all
269 * Calls [consumer] until it returns a falsey value. Returns a list of all 238 /// truthy return values of [consumer], or the empty list if it didn't consume
270 * truthy return values of [consumer], or the empty list if it didn't consume 239 /// anything.
271 * anything. 240 ///
272 * 241 /// Conceptually, repeats a production any number of times.
273 * Conceptually, repeats a production any number of times.
274 */
275 List zeroOrMore(consumer()) { 242 List zeroOrMore(consumer()) {
276 var out = []; 243 var out = [];
277 var oldPos = pos; 244 var oldPos = pos;
278 while (true) { 245 while (true) {
279 var el = consumer(); 246 var el = consumer();
280 if (!truth(el) || oldPos == pos) return out; 247 if (!truth(el) || oldPos == pos) return out;
281 oldPos = pos; 248 oldPos = pos;
282 out.add(el); 249 out.add(el);
283 } 250 }
284 return null; // Unreachable. 251 return null; // Unreachable.
285 } 252 }
286 253
287 /** 254 /// Just calls [consumer] and returns its result. Used to make it explicit
288 * Just calls [consumer] and returns its result. Used to make it explicit that 255 /// that a production is intended to be optional.
289 * a production is intended to be optional.
290 */
291 zeroOrOne(consumer()) => consumer(); 256 zeroOrOne(consumer()) => consumer();
292 257
293 /** 258 /// Calls each function in [consumers] until one returns a truthy value, then
294 * Calls each function in [consumers] until one returns a truthy value, then 259 /// returns that.
295 * returns that.
296 */
297 or(List<Function> consumers) { 260 or(List<Function> consumers) {
298 for (var c in consumers) { 261 for (var c in consumers) {
299 var res = c(); 262 var res = c();
300 if (truth(res)) return res; 263 if (truth(res)) return res;
301 } 264 }
302 return null; 265 return null;
303 } 266 }
304 267
305 /** 268 /// Calls [consumer] and returns its result, but rolls back the parser state
306 * Calls [consumer] and returns its result, but rolls back the parser state if 269 /// if [consumer] returns a falsey value.
307 * [consumer] returns a falsey value.
308 */
309 transaction(consumer()) { 270 transaction(consumer()) {
310 var oldPos = pos; 271 var oldPos = pos;
311 var oldLine = line; 272 var oldLine = line;
312 var oldColumn = column; 273 var oldColumn = column;
313 var oldCaptureStart = captureStart; 274 var oldCaptureStart = captureStart;
314 String capturedSoFar = capturedString == null ? null : 275 String capturedSoFar = capturedString == null ? null :
315 capturedString.toString(); 276 capturedString.toString();
316 var res = consumer(); 277 var res = consumer();
317 if (truth(res)) return res; 278 if (truth(res)) return res;
318 279
319 pos = oldPos; 280 pos = oldPos;
320 line = oldLine; 281 line = oldLine;
321 column = oldColumn; 282 column = oldColumn;
322 captureStart = oldCaptureStart; 283 captureStart = oldCaptureStart;
323 capturedString = capturedSoFar == null ? null : 284 capturedString = capturedSoFar == null ? null :
324 new StringBuffer(capturedSoFar); 285 new StringBuffer(capturedSoFar);
325 return res; 286 return res;
326 } 287 }
327 288
328 /** 289 /// Consumes [n] characters matching [matcher], or none if there isn't a
329 * Consumes [n] characters matching [matcher], or none if there isn't a 290 /// complete match. The first argument to [matcher] is the character code, the
330 * complete match. The first argument to [matcher] is the character code, the 291 /// second is the index (from 0 to [n] - 1).
331 * second is the index (from 0 to [n] - 1). 292 ///
332 * 293 /// Returns whether or not the characters were consumed.
333 * Returns whether or not the characters were consumed.
334 */
335 bool nAtOnce(int n, bool matcher(int c, int i)) => transaction(() { 294 bool nAtOnce(int n, bool matcher(int c, int i)) => transaction(() {
336 for (int i = 0; i < n; i++) { 295 for (int i = 0; i < n; i++) {
337 if (!consume((c) => matcher(c, i))) return false; 296 if (!consume((c) => matcher(c, i))) return false;
338 } 297 }
339 return true; 298 return true;
340 }); 299 });
341 300
342 /** 301 /// Consumes the exact characters in [str], or nothing.
343 * Consumes the exact characters in [str], or nothing. 302 ///
344 * 303 /// Returns whether or not the string was consumed.
345 * Returns whether or not the string was consumed.
346 */
347 bool rawString(String str) => 304 bool rawString(String str) =>
348 nAtOnce(str.length, (c, i) => str.charCodeAt(i) == c); 305 nAtOnce(str.length, (c, i) => str.charCodeAt(i) == c);
349 306
350 /** 307 /// Consumes and returns a string of characters matching [matcher], or null if
351 * Consumes and returns a string of characters matching [matcher], or null if 308 /// there are no such characters.
352 * there are no such characters.
353 */
354 String stringOf(bool matcher(int)) => 309 String stringOf(bool matcher(int)) =>
355 captureString(() => oneOrMore(() => consume(matcher))); 310 captureString(() => oneOrMore(() => consume(matcher)));
356 311
357 /** 312 /// Calls [consumer] and returns the string that was consumed while doing so,
358 * Calls [consumer] and returns the string that was consumed while doing so, 313 /// or null if [consumer] returned a falsey value. Automatically wraps
359 * or null if [consumer] returned a falsey value. Automatically wraps 314 /// [consumer] in `transaction`.
360 * [consumer] in `transaction`.
361 */
362 String captureString(consumer()) { 315 String captureString(consumer()) {
363 // captureString calls may not be nested 316 // captureString calls may not be nested
364 assert(capturedString == null); 317 assert(capturedString == null);
365 318
366 captureStart = pos; 319 captureStart = pos;
367 capturedString = new StringBuffer(); 320 capturedString = new StringBuffer();
368 var res = transaction(consumer); 321 var res = transaction(consumer);
369 if (!truth(res)) { 322 if (!truth(res)) {
370 captureStart = null; 323 captureStart = null;
371 capturedString = null; 324 capturedString = null;
(...skipping 23 matching lines...) Expand all
395 capturedString.add(transformation(s.substring(captureStart, pos))); 348 capturedString.add(transformation(s.substring(captureStart, pos)));
396 captureStart = pos; 349 captureStart = pos;
397 return res; 350 return res;
398 } 351 }
399 352
400 void flushCapture() { 353 void flushCapture() {
401 capturedString.add(s.substring(captureStart, pos)); 354 capturedString.add(s.substring(captureStart, pos));
402 captureStart = pos; 355 captureStart = pos;
403 } 356 }
404 357
405 /** 358 /// Adds a tag and an anchor to [node], if they're defined.
406 * Adds a tag and an anchor to [node], if they're defined.
407 */
408 _Node addProps(_Node node, _Pair<_Tag, String> props) { 359 _Node addProps(_Node node, _Pair<_Tag, String> props) {
409 if (props == null || node == null) return node; 360 if (props == null || node == null) return node;
410 if (truth(props.first)) node.tag = props.first; 361 if (truth(props.first)) node.tag = props.first;
411 if (truth(props.last)) node.anchor = props.last; 362 if (truth(props.last)) node.anchor = props.last;
412 return node; 363 return node;
413 } 364 }
414 365
415 /** Creates a MappingNode from [pairs]. */ 366 /// Creates a MappingNode from [pairs].
416 _MappingNode map(List<_Pair<_Node, _Node>> pairs) { 367 _MappingNode map(List<_Pair<_Node, _Node>> pairs) {
417 var content = new Map<_Node, _Node>(); 368 var content = new Map<_Node, _Node>();
418 pairs.forEach((pair) => content[pair.first] = pair.last); 369 pairs.forEach((pair) => content[pair.first] = pair.last);
419 return new _MappingNode("?", content); 370 return new _MappingNode("?", content);
420 } 371 }
421 372
422 /** Runs [fn] in a context named [name]. Used for error reporting. */ 373 /// Runs [fn] in a context named [name]. Used for error reporting.
423 context(String name, fn()) { 374 context(String name, fn()) {
424 try { 375 try {
425 contextStack.add(name); 376 contextStack.add(name);
426 return fn(); 377 return fn();
427 } finally { 378 } finally {
428 var popped = contextStack.removeLast(); 379 var popped = contextStack.removeLast();
429 assert(popped == name); 380 assert(popped == name);
430 } 381 }
431 } 382 }
432 383
433 /** 384 /// Adds [message] as extra information to any errors that occur between the
434 * Adds [message] as extra information to any errors that occur between the 385 /// current position and the position of the cursor after running [fn]. The
435 * current position and the position of the cursor after running [fn]. The 386 /// cursor is reset after [fn] is run.
436 * cursor is reset after [fn] is run.
437 */
438 annotateError(String message, fn()) { 387 annotateError(String message, fn()) {
439 var start = pos; 388 var start = pos;
440 var end; 389 var end;
441 transaction(() { 390 transaction(() {
442 fn(); 391 fn();
443 end = pos; 392 end = pos;
444 return false; 393 return false;
445 }); 394 });
446 errorAnnotations[new _Range(start, end)] = message; 395 errorAnnotations[new _Range(start, end)] = message;
447 } 396 }
448 397
449 /** Throws an error with additional context information. */ 398 /// Throws an error with additional context information.
450 error(String message) { 399 error(String message) {
451 // Line and column should be one-based. 400 // Line and column should be one-based.
452 throw new SyntaxError(line + 1, column + 1, 401 throw new SyntaxError(line + 1, column + 1,
453 "$message (in $farthestContext)"); 402 "$message (in $farthestContext)");
454 } 403 }
455 404
456 /** 405 /// If [result] is falsey, throws an error saying that [expected] was
457 * If [result] is falsey, throws an error saying that [expected] was 406 /// expected.
458 * expected.
459 */
460 expect(result, String expected) { 407 expect(result, String expected) {
461 if (truth(result)) return result; 408 if (truth(result)) return result;
462 error("expected $expected"); 409 error("expected $expected");
463 } 410 }
464 411
465 /** 412 /// Throws an error saying that the parse failed. Uses [farthestLine],
466 * Throws an error saying that the parse failed. Uses [farthestLine], 413 /// [farthestColumn], and [farthestContext] to provide additional information.
467 * [farthestColumn], and [farthestContext] to provide additional information.
468 */
469 parseFailed() { 414 parseFailed() {
470 var message = "invalid YAML in $farthestContext"; 415 var message = "invalid YAML in $farthestContext";
471 var extraError = errorAnnotations[farthestPos]; 416 var extraError = errorAnnotations[farthestPos];
472 if (extraError != null) message = "$message ($extraError)"; 417 if (extraError != null) message = "$message ($extraError)";
473 throw new SyntaxError(farthestLine + 1, farthestColumn + 1, message); 418 throw new SyntaxError(farthestLine + 1, farthestColumn + 1, message);
474 } 419 }
475 420
476 /** Returns the number of spaces after the current position. */ 421 /// Returns the number of spaces after the current position.
477 int countIndentation() { 422 int countIndentation() {
478 var i = 0; 423 var i = 0;
479 while (peek(i) == SP) i++; 424 while (peek(i) == SP) i++;
480 return i; 425 return i;
481 } 426 }
482 427
483 /** Returns the indentation for a block scalar. */ 428 /// Returns the indentation for a block scalar.
484 int blockScalarAdditionalIndentation(_BlockHeader header, int indent) { 429 int blockScalarAdditionalIndentation(_BlockHeader header, int indent) {
485 if (!header.autoDetectIndent) return header.additionalIndent; 430 if (!header.autoDetectIndent) return header.additionalIndent;
486 431
487 var maxSpaces = 0; 432 var maxSpaces = 0;
488 var maxSpacesLine = 0; 433 var maxSpacesLine = 0;
489 var spaces = 0; 434 var spaces = 0;
490 transaction(() { 435 transaction(() {
491 do { 436 do {
492 spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length; 437 spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length;
493 if (spaces > maxSpaces) { 438 if (spaces > maxSpaces) {
(...skipping 13 matching lines...) Expand all
507 // non-empty line. 452 // non-empty line.
508 if (maxSpaces > spaces) { 453 if (maxSpaces > spaces) {
509 throw new SyntaxError(maxSpacesLine + 1, maxSpaces, 454 throw new SyntaxError(maxSpacesLine + 1, maxSpaces,
510 "Leading empty lines may not be indented more than the first " 455 "Leading empty lines may not be indented more than the first "
511 "non-empty line."); 456 "non-empty line.");
512 } 457 }
513 458
514 return spaces - indent; 459 return spaces - indent;
515 } 460 }
516 461
517 /** Returns whether the current position is at the beginning of a line. */ 462 /// Returns whether the current position is at the beginning of a line.
518 bool get atStartOfLine => column == 0; 463 bool get atStartOfLine => column == 0;
519 464
520 /** Returns whether the current position is at the end of the input. */ 465 /// Returns whether the current position is at the end of the input.
521 bool get atEndOfFile => pos == len; 466 bool get atEndOfFile => pos == len;
522 467
523 /** 468 /// Given an indicator character, returns the type of that indicator (or null
524 * Given an indicator character, returns the type of that indicator (or null 469 /// if the indicator isn't found.
525 * if the indicator isn't found.
526 */
527 int indicatorType(int char) { 470 int indicatorType(int char) {
528 switch (char) { 471 switch (char) {
529 case HYPHEN: return C_SEQUENCE_ENTRY; 472 case HYPHEN: return C_SEQUENCE_ENTRY;
530 case QUESTION_MARK: return C_MAPPING_KEY; 473 case QUESTION_MARK: return C_MAPPING_KEY;
531 case COLON: return C_MAPPING_VALUE; 474 case COLON: return C_MAPPING_VALUE;
532 case COMMA: return C_COLLECT_ENTRY; 475 case COMMA: return C_COLLECT_ENTRY;
533 case LEFT_BRACKET: return C_SEQUENCE_START; 476 case LEFT_BRACKET: return C_SEQUENCE_START;
534 case RIGHT_BRACKET: return C_SEQUENCE_END; 477 case RIGHT_BRACKET: return C_SEQUENCE_END;
535 case LEFT_BRACE: return C_MAPPING_START; 478 case LEFT_BRACE: return C_MAPPING_START;
536 case RIGHT_BRACE: return C_MAPPING_END; 479 case RIGHT_BRACE: return C_MAPPING_END;
(...skipping 1387 matching lines...) Expand 10 before | Expand all | Expand 10 after
1924 1867
1925 class SyntaxError extends YamlException { 1868 class SyntaxError extends YamlException {
1926 final int line; 1869 final int line;
1927 final int column; 1870 final int column;
1928 1871
1929 SyntaxError(this.line, this.column, String msg) : super(msg); 1872 SyntaxError(this.line, this.column, String msg) : super(msg);
1930 1873
1931 String toString() => "Syntax error on line $line, column $column: $msg"; 1874 String toString() => "Syntax error on line $line, column $column: $msg";
1932 } 1875 }
1933 1876
1934 /** A pair of values. */ 1877 /// A pair of values.
1935 class _Pair<E, F> { 1878 class _Pair<E, F> {
1936 E first; 1879 E first;
1937 F last; 1880 F last;
1938 1881
1939 _Pair(this.first, this.last); 1882 _Pair(this.first, this.last);
1940 1883
1941 String toString() => '($first, $last)'; 1884 String toString() => '($first, $last)';
1942 } 1885 }
1943 1886
1944 /** The information in the header for a block scalar. */ 1887 /// The information in the header for a block scalar.
1945 class _BlockHeader { 1888 class _BlockHeader {
1946 final int additionalIndent; 1889 final int additionalIndent;
1947 final int chomping; 1890 final int chomping;
1948 1891
1949 _BlockHeader(this.additionalIndent, this.chomping); 1892 _BlockHeader(this.additionalIndent, this.chomping);
1950 1893
1951 bool get autoDetectIndent => additionalIndent == null; 1894 bool get autoDetectIndent => additionalIndent == null;
1952 } 1895 }
1953 1896
1954 /** 1897 /// A range of characters in the YAML document, from [start] to [end]
1955 * A range of characters in the YAML document, from [start] to [end] (inclusive) . 1898 /// (inclusive).
1956 */
1957 class _Range { 1899 class _Range {
1958 /** The first character in the range. */ 1900 /// The first character in the range.
1959 final int start; 1901 final int start;
1960 1902
1961 /** The last character in the range. */ 1903 /// The last character in the range.
1962 final int end; 1904 final int end;
1963 1905
1964 _Range(this.start, this.end); 1906 _Range(this.start, this.end);
1965 1907
1966 /** Returns whether or not [pos] lies within this range. */ 1908 /// Returns whether or not [pos] lies within this range.
1967 bool contains(int pos) => pos >= start && pos <= end; 1909 bool contains(int pos) => pos >= start && pos <= end;
1968 } 1910 }
1969 1911
1970 /** 1912 /// A map that associates [E] values with [_Range]s. It's efficient to create
1971 * A map that associates [E] values with [_Range]s. It's efficient to create new 1913 /// new associations, but finding the value associated with a position is more
1972 * associations, but finding the value associated with a position is more 1914 /// expensive.
1973 * expensive.
1974 */
1975 class _RangeMap<E> { 1915 class _RangeMap<E> {
1976 /** The ranges and their associated elements. */ 1916 /// The ranges and their associated elements.
1977 final List<_Pair<_Range, E>> contents; 1917 final List<_Pair<_Range, E>> contents;
1978 1918
1979 _RangeMap() : this.contents = <_Pair<_Range, E>>[]; 1919 _RangeMap() : this.contents = <_Pair<_Range, E>>[];
1980 1920
1981 /** 1921 /// Returns the value associated with the range in which [pos] lies, or null
1982 * Returns the value associated with the range in which [pos] lies, or null if 1922 /// if there is no such range. If there's more than one such range, the most
1983 * there is no such range. If there's more than one such range, the most 1923 /// recently set one is used.
1984 * recently set one is used.
1985 */
1986 E operator[](int pos) { 1924 E operator[](int pos) {
1987 // Iterate backwards through contents so the more recent range takes 1925 // Iterate backwards through contents so the more recent range takes
1988 // precedence. TODO(nweiz): clean this up when issue 2804 is fixed. 1926 // precedence. TODO(nweiz): clean this up when issue 2804 is fixed.
1989 for (var i = contents.length - 1; i >= 0; i--) { 1927 for (var i = contents.length - 1; i >= 0; i--) {
1990 var pair = contents[i]; 1928 var pair = contents[i];
1991 if (pair.first.contains(pos)) return pair.last; 1929 if (pair.first.contains(pos)) return pair.last;
1992 } 1930 }
1993 return null; 1931 return null;
1994 } 1932 }
1995 1933
1996 /** Associates [value] with [range]. */ 1934 /// Associates [value] with [range].
1997 operator[]=(_Range range, E value) => 1935 operator[]=(_Range range, E value) =>
1998 contents.add(new _Pair<_Range, E>(range, value)); 1936 contents.add(new _Pair<_Range, E>(range, value));
1999 } 1937 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698