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

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

Issue 10377186: Support a much larger subset of YAML. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review chagnes Created 8 years, 7 months 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
« no previous file with comments | « utils/pub/yaml/composer.dart ('k') | utils/pub/yaml/yaml_map.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /**
6 * Translates a string of characters into a YAML serialization tree. 6 * Translates a string of characters into a YAML serialization tree.
7 * 7 *
8 * 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
9 * 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
10 * numbers. This is certainly not the most efficient way of parsing YAML, but it 10 * numbers. This is certainly not the most efficient way of parsing YAML, but it
11 * 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.
12 * 12 *
13 * Methods corresponding to productions are also named as in the spec, 13 * Methods corresponding to productions are also named as in the spec,
14 * translating the name of the method (although not the annotation characters) 14 * translating the name of the method (although not the annotation characters)
15 * into camel-case for dart style.. For example, the spec has a production named 15 * into camel-case for dart style.. For example, the spec has a production named
16 * `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
17 * `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
18 * recognize character classes; these are named `is*`. 18 * recognize character classes; these are named `is*`.
19 */ 19 */
20 class _Parser { 20 class _Parser {
21 static final TAB = 0x9; 21 static final TAB = 0x9;
22 static final LF = 0xA; 22 static final LF = 0xA;
23 static final CR = 0xD; 23 static final CR = 0xD;
24 static final SP = 0x20; 24 static final SP = 0x20;
25 static final TILDE = 0x7E; 25 static final TILDE = 0x7E;
26 static final NEL = 0x85; 26 static final NEL = 0x85;
27 static final PLUS = 0x2B;
27 static final HYPHEN = 0x2D; 28 static final HYPHEN = 0x2D;
28 static final QUESTION_MARK = 0x3F; 29 static final QUESTION_MARK = 0x3F;
29 static final COLON = 0x3A; 30 static final COLON = 0x3A;
30 static final COMMA = 0x2C; 31 static final COMMA = 0x2C;
31 static final LEFT_BRACKET = 0x5B; 32 static final LEFT_BRACKET = 0x5B;
32 static final RIGHT_BRACKET = 0x5D; 33 static final RIGHT_BRACKET = 0x5D;
33 static final LEFT_BRACE = 0x7B; 34 static final LEFT_BRACE = 0x7B;
34 static final RIGHT_BRACE = 0x7D; 35 static final RIGHT_BRACE = 0x7D;
35 static final HASH = 0x23; 36 static final HASH = 0x23;
36 static final AMPERSAND = 0x26; 37 static final AMPERSAND = 0x26;
37 static final ASTERISK = 0x2A; 38 static final ASTERISK = 0x2A;
38 static final EXCLAMATION = 0x21; 39 static final EXCLAMATION = 0x21;
39 static final VERTICAL_BAR = 0x7C; 40 static final VERTICAL_BAR = 0x7C;
40 static final GREATER_THAN = 0x3E; 41 static final GREATER_THAN = 0x3E;
41 static final SINGLE_QUOTE = 0x27; 42 static final SINGLE_QUOTE = 0x27;
42 static final DOUBLE_QUOTE = 0x22; 43 static final DOUBLE_QUOTE = 0x22;
43 static final PERCENT = 0x25; 44 static final PERCENT = 0x25;
44 static final AT = 0x40; 45 static final AT = 0x40;
45 static final GRAVE_ACCENT = 0x60; 46 static final GRAVE_ACCENT = 0x60;
46 47
47 static final NULL = 0x0; 48 static final NULL = 0x0;
48 static final BELL = 0x7; 49 static final BELL = 0x7;
49 static final BACKSPACE = 0x8; 50 static final BACKSPACE = 0x8;
50 static final VERTICAL_TAB = 0xB; 51 static final VERTICAL_TAB = 0xB;
51 static final FORM_FEED = 0xC; 52 static final FORM_FEED = 0xC;
52 static final ESCAPE = 0x1B; 53 static final ESCAPE = 0x1B;
54 static final SLASH = 0x2F;
53 static final BACKSLASH = 0x5C; 55 static final BACKSLASH = 0x5C;
56 static final UNDERSCORE = 0x5F;
54 static final NBSP = 0xA0; 57 static final NBSP = 0xA0;
55 static final LINE_SEPARATOR = 0x2028; 58 static final LINE_SEPARATOR = 0x2028;
56 static final PARAGRAPH_SEPARATOR = 0x2029; 59 static final PARAGRAPH_SEPARATOR = 0x2029;
57 60
61 static final NUMBER_0 = 0x30;
62 static final NUMBER_9 = 0x39;
63
64 static final LETTER_A = 0x61;
65 static final LETTER_B = 0x62;
66 static final LETTER_E = 0x65;
67 static final LETTER_F = 0x66;
68 static final LETTER_N = 0x6E;
69 static final LETTER_R = 0x72;
70 static final LETTER_T = 0x74;
71 static final LETTER_U = 0x75;
72 static final LETTER_V = 0x76;
73 static final LETTER_X = 0x78;
74
75 static final LETTER_CAP_A = 0x41;
76 static final LETTER_CAP_F = 0x46;
77 static final LETTER_CAP_L = 0x4C;
78 static final LETTER_CAP_N = 0x4E;
79 static final LETTER_CAP_P = 0x50;
80 static final LETTER_CAP_U = 0x55;
81 static final LETTER_CAP_X = 0x58;
82
58 static final C_SEQUENCE_ENTRY = 4; 83 static final C_SEQUENCE_ENTRY = 4;
59 static final C_MAPPING_KEY = 5; 84 static final C_MAPPING_KEY = 5;
60 static final C_MAPPING_VALUE = 6; 85 static final C_MAPPING_VALUE = 6;
61 static final C_COLLECT_ENTRY = 7; 86 static final C_COLLECT_ENTRY = 7;
62 static final C_SEQUENCE_START = 8; 87 static final C_SEQUENCE_START = 8;
63 static final C_SEQUENCE_END = 9; 88 static final C_SEQUENCE_END = 9;
64 static final C_MAPPING_START = 10; 89 static final C_MAPPING_START = 10;
65 static final C_MAPPING_END = 11; 90 static final C_MAPPING_END = 11;
66 static final C_COMMENT = 12; 91 static final C_COMMENT = 12;
67 static final C_ANCHOR = 13; 92 static final C_ANCHOR = 13;
68 static final C_ALIAS = 14; 93 static final C_ALIAS = 14;
69 static final C_TAG = 15; 94 static final C_TAG = 15;
70 static final C_LITERAL = 16; 95 static final C_LITERAL = 16;
71 static final C_FOLDED = 17; 96 static final C_FOLDED = 17;
72 static final C_SINGLE_QUOTE = 18; 97 static final C_SINGLE_QUOTE = 18;
73 static final C_DOUBLE_QUOTE = 19; 98 static final C_DOUBLE_QUOTE = 19;
74 static final C_DIRECTIVE = 20; 99 static final C_DIRECTIVE = 20;
75 static final C_RESERVED = 21; 100 static final C_RESERVED = 21;
76 101
77 static final BLOCK_OUT = 0; 102 static final BLOCK_OUT = 0;
78 static final BLOCK_IN = 1; 103 static final BLOCK_IN = 1;
79 static final FLOW_OUT = 2; 104 static final FLOW_OUT = 2;
80 static final FLOW_IN = 3; 105 static final FLOW_IN = 3;
81 static final BLOCK_KEY = 4; 106 static final BLOCK_KEY = 4;
82 static final FLOW_KEY = 5; 107 static final FLOW_KEY = 5;
83 108
109 static final CHOMPING_STRIP = 0;
110 static final CHOMPING_KEEP = 1;
111 static final CHOMPING_CLIP = 2;
112
84 /** The source string being parsed. */ 113 /** The source string being parsed. */
85 final String s; 114 final String s;
86 115
87 /** The current position in the source string. */ 116 /** The current position in the source string. */
88 int pos = 0; 117 int pos = 0;
89 118
90 /** The length of the string being parsed. */ 119 /** The length of the string being parsed. */
91 final int len; 120 final int len;
92 121
93 /** The current (0-based) line in the source string. */ 122 /** The current (0-based) line in the source string. */
(...skipping 22 matching lines...) Expand all
116 145
117 /** 146 /**
118 * The name of the context of the farthest position that has been parsed 147 * The name of the context of the farthest position that has been parsed
119 * successfully before backtracking. Used for error reporting. 148 * successfully before backtracking. Used for error reporting.
120 */ 149 */
121 String farthestContext = "document"; 150 String farthestContext = "document";
122 151
123 /** A stack of the names of parse contexts. Used for error reporting. */ 152 /** A stack of the names of parse contexts. Used for error reporting. */
124 List<String> contextStack; 153 List<String> contextStack;
125 154
155 /**
156 * The buffer containing the string currently being captured.
157 */
158 StringBuffer capturedString;
159
160 /**
161 * The beginning of the current section of the captured string.
162 */
163 int captureStart;
164
165 /**
166 * Whether the current string capture is being overridden.
167 */
168 bool capturingAs = false;
169
126 _Parser(String s) 170 _Parser(String s)
127 : this.s = s, 171 : this.s = s,
128 len = s.length, 172 len = s.length,
129 contextStack = <String>["document"]; 173 contextStack = <String>["document"];
130 174
131 /** 175 /**
132 * Return the character at the current position, then move that position 176 * Return the character at the current position, then move that position
133 * forward one character. Also updates the current line and column numbers. 177 * forward one character. Also updates the current line and column numbers.
134 */ 178 */
135 int next() { 179 int next() {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 */ 222 */
179 bool consume(bool matcher(int)) { 223 bool consume(bool matcher(int)) {
180 if (matcher(peek())) { 224 if (matcher(peek())) {
181 next(); 225 next();
182 return true; 226 return true;
183 } 227 }
184 return false; 228 return false;
185 } 229 }
186 230
187 /** 231 /**
232 * Consumes the current character if it equals [char].
233 */
234 bool consumeChar(int char) => consume((c) => c == char);
235
236 /**
188 * Calls [consumer] until it returns a falsey value. Returns a list of all 237 * Calls [consumer] until it returns a falsey value. Returns a list of all
189 * truthy return values of [consumer], or null if it didn't consume anything. 238 * truthy return values of [consumer], or null if it didn't consume anything.
190 * 239 *
191 * Conceptually, repeats a production one or more times. 240 * Conceptually, repeats a production one or more times.
192 */ 241 */
193 List oneOrMore(consumer()) { 242 List oneOrMore(consumer()) {
194 var first = consumer(); 243 var first = consumer();
195 if (!truth(first)) return null; 244 if (!truth(first)) return null;
196 var out = [first]; 245 var out = [first];
197 while (true) { 246 while (true) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 if (truth(res)) return res; 284 if (truth(res)) return res;
236 } 285 }
237 return null; 286 return null;
238 } 287 }
239 288
240 /** 289 /**
241 * Calls [consumer] and returns its result, but rolls back the parser state if 290 * Calls [consumer] and returns its result, but rolls back the parser state if
242 * [consumer] returns a falsey value. 291 * [consumer] returns a falsey value.
243 */ 292 */
244 transaction(consumer()) { 293 transaction(consumer()) {
245 int oldPos = pos, oldLine = line, oldColumn = column; 294 var oldPos = pos;
295 var oldLine = line;
296 var oldColumn = column;
297 var oldCaptureStart = captureStart;
298 String capturedSoFar = capturedString == null ? null :
299 capturedString.toString();
246 var res = consumer(); 300 var res = consumer();
247 if (truth(res)) return res; 301 if (truth(res)) return res;
248 302
249 pos = oldPos; 303 pos = oldPos;
250 line = oldLine; 304 line = oldLine;
251 column = oldColumn; 305 column = oldColumn;
306 captureStart = oldCaptureStart;
307 capturedString = capturedSoFar == null ? null :
308 new StringBuffer(capturedSoFar);
252 return res; 309 return res;
253 } 310 }
254 311
255 /** 312 /**
256 * Consumes [n] characters matching [matcher], or none if there isn't a 313 * Consumes [n] characters matching [matcher], or none if there isn't a
257 * complete match. The first argument to [matcher] is the character code, the 314 * complete match. The first argument to [matcher] is the character code, the
258 * second is the index (from 0 to [n] - 1). 315 * second is the index (from 0 to [n] - 1).
259 * 316 *
260 * Returns whether or not the characters were consumed. 317 * Returns whether or not the characters were consumed.
261 */ 318 */
(...skipping 18 matching lines...) Expand all
280 */ 337 */
281 String stringOf(bool matcher(int)) => 338 String stringOf(bool matcher(int)) =>
282 captureString(() => oneOrMore(() => consume(matcher))); 339 captureString(() => oneOrMore(() => consume(matcher)));
283 340
284 /** 341 /**
285 * Calls [consumer] and returns the string that was consumed while doing so, 342 * Calls [consumer] and returns the string that was consumed while doing so,
286 * or null if [consumer] returned a falsey value. Automatically wraps 343 * or null if [consumer] returned a falsey value. Automatically wraps
287 * [consumer] in `transaction`. 344 * [consumer] in `transaction`.
288 */ 345 */
289 String captureString(consumer()) { 346 String captureString(consumer()) {
290 int start = pos; 347 // captureString calls may not be nested
348 assert(capturedString == null);
349
350 captureStart = pos;
351 capturedString = new StringBuffer();
291 var res = transaction(consumer); 352 var res = transaction(consumer);
292 if (!truth(res)) return null; 353 if (!truth(res)) {
293 return s.substring(start, pos); 354 captureStart = null;
355 capturedString = null;
356 return null;
357 }
358
359 flushCapture();
360 var result = capturedString.toString();
361 captureStart = null;
362 capturedString = null;
363 return result;
364 }
365
366 captureAs(String replacement, consumer()) =>
367 captureAndTransform(consumer, (_) => replacement);
368
369 captureAndTransform(consumer(), String transformation(String captured)) {
370 if (capturedString == null) return consumer();
371 if (capturingAs) return consumer();
372
373 flushCapture();
374 capturingAs = true;
375 var res = consumer();
376 capturingAs = false;
377 if (!truth(res)) return res;
378
379 capturedString.add(transformation(s.substring(captureStart, pos)));
380 captureStart = pos;
381 return res;
382 }
383
384 void flushCapture() {
385 capturedString.add(s.substring(captureStart, pos));
386 captureStart = pos;
294 } 387 }
295 388
296 /** 389 /**
297 * Adds a tag and an anchor to [node], if they're defined. 390 * Adds a tag and an anchor to [node], if they're defined.
298 */ 391 */
299 _Node addProps(_Node node, _Pair<_Tag, String> props) { 392 _Node addProps(_Node node, _Pair<_Tag, String> props) {
393 if (props == null || node == null) return node;
300 if (truth(props.first)) node.tag = props.first; 394 if (truth(props.first)) node.tag = props.first;
301 if (truth(props.last)) node.anchor = props.last; 395 if (truth(props.last)) node.anchor = props.last;
302 return node; 396 return node;
303 } 397 }
304 398
305 /** Creates a MappingNode from [pairs]. */ 399 /** Creates a MappingNode from [pairs]. */
306 _MappingNode map(List<_Pair<_Node, _Node>> pairs) { 400 _MappingNode map(List<_Pair<_Node, _Node>> pairs) {
307 var content = new Map<_Node, _Node>(); 401 var content = new Map<_Node, _Node>();
308 pairs.forEach((pair) => content[pair.first] = pair.last); 402 pairs.forEach((pair) => content[pair.first] = pair.last);
309 return new _MappingNode("?", content); 403 return new _MappingNode("?", content);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 "invalid YAML in $farthestContext"); 439 "invalid YAML in $farthestContext");
346 } 440 }
347 441
348 /** Returns the number of spaces after the current position. */ 442 /** Returns the number of spaces after the current position. */
349 int countIndentation() { 443 int countIndentation() {
350 var i = 0; 444 var i = 0;
351 while (peek(i) == SP) i++; 445 while (peek(i) == SP) i++;
352 return i; 446 return i;
353 } 447 }
354 448
449 /** Returns the indentation for a block scalar. */
450 int blockScalarAdditionalIndentation(_BlockHeader header, int indent) {
451 if (!header.autoDetectIndent) return header.additionalIndent;
452
453 var maxSpaces = 0;
454 var maxSpacesLine = 0;
455 var spaces = 0;
456 transaction(() {
457 do {
458 spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length;
459 if (spaces > maxSpaces) {
460 maxSpaces = spaces;
461 maxSpacesLine = line;
462 }
463 } while (b_break());
464 return false;
465 });
466
467 // If the next non-empty line isn't indented further than the start of the
468 // block scalar, that means the scalar is going to be empty. Returning any
469 // value > 0 will cause the parser not to consume any text.
470 if (spaces <= indent) return 1;
471
472 // It's an error for a leading empty line to be indented more than the first
473 // non-empty line.
474 if (maxSpaces > spaces) {
475 throw new SyntaxError(maxSpacesLine + 1, maxSpaces,
476 "Leading empty lines may not be indented more than the first "
477 "non-empty line.");
478 }
479
480 return spaces - indent;
481 }
482
355 /** Returns whether the current position is at the beginning of a line. */ 483 /** Returns whether the current position is at the beginning of a line. */
356 bool get atStartOfLine() => column == 0; 484 bool get atStartOfLine() => column == 0;
357 485
358 /** Returns whether the current position is at the end of the input. */ 486 /** Returns whether the current position is at the end of the input. */
359 bool get atEndOfFile() => pos == len; 487 bool get atEndOfFile() => pos == len;
360 488
361 /** 489 /**
362 * Given an indicator character, returns the type of that indicator (or null 490 * Given an indicator character, returns the type of that indicator (or null
363 * if the indicator isn't found. 491 * if the indicator isn't found.
364 */ 492 */
(...skipping 28 matching lines...) Expand all
393 return char == TAB || 521 return char == TAB ||
394 char == LF || 522 char == LF ||
395 char == CR || 523 char == CR ||
396 (char >= SP && char <= TILDE) || 524 (char >= SP && char <= TILDE) ||
397 char == NEL || 525 char == NEL ||
398 (char >= 0xA0 && char <= 0xD7FF) || 526 (char >= 0xA0 && char <= 0xD7FF) ||
399 (char >= 0xE000 && char <= 0xFFFD) || 527 (char >= 0xE000 && char <= 0xFFFD) ||
400 (char >= 0x10000 && char <= 0x10FFFF); 528 (char >= 0x10000 && char <= 0x10FFFF);
401 } 529 }
402 530
531 // 2
532 bool isJson(int char) => char == TAB || (char >= SP && char <= 0x10FFFF);
533
403 // 22 534 // 22
404 bool c_indicator(int type) => consume((c) => indicatorType(c) == type); 535 bool c_indicator(int type) => consume((c) => indicatorType(c) == type);
405 536
406 // 23 537 // 23
407 bool isFlowIndicator(int char) { 538 bool isFlowIndicator(int char) {
408 var indicator = indicatorType(char); 539 var indicator = indicatorType(char);
409 return indicator == C_COLLECT_ENTRY || 540 return indicator == C_COLLECT_ENTRY ||
410 indicator == C_SEQUENCE_START || 541 indicator == C_SEQUENCE_START ||
411 indicator == C_SEQUENCE_END || 542 indicator == C_SEQUENCE_END ||
412 indicator == C_MAPPING_START || 543 indicator == C_MAPPING_START ||
413 indicator == C_MAPPING_END; 544 indicator == C_MAPPING_END;
414 } 545 }
415 546
416 // 26 547 // 26
417 bool isBreak(int char) => char == LF || char == CR; 548 bool isBreak(int char) => char == LF || char == CR;
418 549
419 // 27 550 // 27
420 bool isNonBreak(int char) => isPrintable(char) && !isBreak(char); 551 bool isNonBreak(int char) => isPrintable(char) && !isBreak(char);
421 552
553 // 28
554 bool b_break() {
555 if (consumeChar(CR)) {
556 zeroOrOne(() => consumeChar(LF));
557 return true;
558 }
559 return consumeChar(LF);
560 }
561
562 // 29
563 bool b_asLineFeed() => captureAs("\n", () => b_break());
564
422 // 30 565 // 30
423 bool b_non_content() => consume(isBreak); 566 bool b_nonContent() => captureAs("", () => b_break());
424 567
425 // 33 568 // 33
426 bool isSpace(int char) => char == SP || char == TAB; 569 bool isSpace(int char) => char == SP || char == TAB;
427 570
428 // 34 571 // 34
429 bool isNonSpace(int char) => isNonBreak(char) && !isSpace(char); 572 bool isNonSpace(int char) => isNonBreak(char) && !isSpace(char);
430 573
574 // 35
575 bool isDecDigit(int char) => char >= NUMBER_0 && char <= NUMBER_9;
576
577 // 36
578 bool isHexDigit(int char) {
579 return isDecDigit(char) ||
580 (char >= LETTER_A && char <= LETTER_F) ||
581 (char >= LETTER_CAP_A && char <= LETTER_CAP_F);
582 }
583
584 // 41
585 bool c_escape() => captureAs("", () => consumeChar(BACKSLASH));
586
587 // 42
588 bool ns_escNull() => captureAs("\x00", () => consumeChar(NUMBER_0));
589
590 // 43
591 bool ns_escBell() => captureAs("\x07", () => consumeChar(LETTER_A));
592
593 // 44
594 bool ns_escBackspace() => captureAs("\b", () => consumeChar(LETTER_B));
595
596 // 45
597 bool ns_escHorizontalTab() => captureAs("\t", () {
598 return consume((c) => c == LETTER_T || c == TAB);
599 });
600
601 // 46
602 bool ns_escLineFeed() => captureAs("\n", () => consumeChar(LETTER_N));
603
604 // 47
605 bool ns_escVerticalTab() => captureAs("\v", () => consumeChar(LETTER_V));
606
607 // 48
608 bool ns_escFormFeed() => captureAs("\f", () => consumeChar(LETTER_F));
609
610 // 49
611 bool ns_escCarriageReturn() => captureAs("\r", () => consumeChar(LETTER_R));
612
613 // 50
614 bool ns_escEscape() => captureAs("\x1B", () => consumeChar(LETTER_E));
615
616 // 51
617 bool ns_escSpace() => consumeChar(SP);
618
619 // 52
620 bool ns_escDoubleQuote() => consumeChar(DOUBLE_QUOTE);
621
622 // 53
623 bool ns_escSlash() => consumeChar(SLASH);
624
625 // 54
626 bool ns_escBackslash() => consumeChar(BACKSLASH);
627
628 // 55
629 bool ns_escNextLine() => captureAs("\x85", () => consumeChar(LETTER_CAP_N));
630
631 // 56
632 bool ns_escNonBreakingSpace() =>
633 captureAs("\xA0", () => consumeChar(UNDERSCORE));
634
635 // 57
636 bool ns_escLineSeparator() =>
637 captureAs("\u2028", () => consumeChar(LETTER_CAP_L));
638
639 // 58
640 bool ns_escParagraphSeparator() =>
641 captureAs("\u2029", () => consumeChar(LETTER_CAP_P));
642
643 // 59
644 bool ns_esc8Bit() => ns_escNBit(LETTER_X, 2);
645
646 // 60
647 bool ns_esc16Bit() => ns_escNBit(LETTER_U, 4);
648
649 // 61
650 bool ns_esc32Bit() => ns_escNBit(LETTER_CAP_U, 8);
651
652 // Helper method for 59 - 61
653 bool ns_escNBit(int char, int digits) {
654 if (!captureAs('', () => consumeChar(char))) return false;
655 var captured = captureAndTransform(
656 () => nAtOnce(digits, (c, _) => isHexDigit(c)),
657 (hex) => new String.fromCharCodes([Math.parseInt("0x$hex")]));
658 return expect(captured, "$digits hexidecimal digits");
659 }
660
661 // 62
662 bool c_ns_escChar() => context('escape sequence', () => transaction(() {
663 if (!truth(c_escape())) return false;
664 return truth(or([
665 ns_escNull, ns_escBell, ns_escBackspace, ns_escHorizontalTab,
666 ns_escLineFeed, ns_escVerticalTab, ns_escFormFeed, ns_escCarriageReturn,
667 ns_escEscape, ns_escSpace, ns_escDoubleQuote, ns_escSlash,
668 ns_escBackslash, ns_escNextLine, ns_escNonBreakingSpace,
669 ns_escLineSeparator, ns_escParagraphSeparator, ns_esc8Bit, ns_esc16Bit,
670 ns_esc32Bit
671 ]));
672 }));
673
431 // 63 674 // 63
432 bool s_indent(int indent) => nAtOnce(indent, (c, i) => c == SP); 675 bool s_indent(int indent) => nAtOnce(indent, (c, i) => c == SP);
433 676
434 // 66 677 // 64
435 bool s_separateInLine() => transaction(() => 678 bool s_indentLessThan(int indent) {
436 truth(oneOrMore(() => consume(isSpace))) || atStartOfLine); 679 for (int i = 0; i < indent - 1; i++) {
437 680 if (!consumeChar(SP)) break;
438 // 69 681 }
439 bool s_flowLinePrefix(int indent) {
440 if (!s_indent(indent)) return false;
441 zeroOrOne(s_separateInLine);
442 return true; 682 return true;
443 } 683 }
444 684
685 // 65
686 bool s_indentLessThanOrEqualTo(int indent) => s_indentLessThan(indent + 1);
687
688 // 66
689 bool s_separateInLine() => transaction(() {
690 return captureAs('', () =>
691 truth(oneOrMore(() => consume(isSpace))) || atStartOfLine);
692 });
693
694 // 67
695 bool s_linePrefix(int indent, int ctx) => captureAs("", () {
696 switch (ctx) {
697 case BLOCK_OUT:
698 case BLOCK_IN:
699 return s_blockLinePrefix(indent);
700 case FLOW_OUT:
701 case FLOW_IN:
702 return s_flowLinePrefix(indent);
703 }
704 });
705
706 // 68
707 bool s_blockLinePrefix(int indent) => s_indent(indent);
708
709 // 69
710 bool s_flowLinePrefix(int indent) => captureAs('', () {
711 if (!truth(s_indent(indent))) return false;
712 zeroOrOne(s_separateInLine);
713 return true;
714 });
715
716 // 70
717 bool l_empty(int indent, int ctx) => transaction(() {
718 var start = or([
719 () => s_linePrefix(indent, ctx),
720 () => s_indentLessThan(indent)
721 ]);
722 if (!truth(start)) return false;
723 return b_asLineFeed();
724 });
725
726 // 71
727 bool b_asSpace() => captureAs(" ", () => consume(isBreak));
728
729 // 72
730 bool b_l_trimmed(int indent, int ctx) => transaction(() {
731 if (!truth(b_nonContent())) return false;
732 return truth(oneOrMore(() => captureAs("\n", () => l_empty(indent, ctx))));
733 });
734
735 // 73
736 bool b_l_folded(int indent, int ctx) =>
737 or([() => b_l_trimmed(indent, ctx), b_asSpace]);
738
445 // 74 739 // 74
446 bool s_flowFolded(int indent) => false; // TODO(nweiz): implement 740 bool s_flowFolded(int indent) => transaction(() {
741 zeroOrOne(s_separateInLine);
742 if (!truth(b_l_folded(indent, FLOW_IN))) return false;
743 return s_flowLinePrefix(indent);
744 });
447 745
448 // 75 746 // 75
449 bool c_nb_commentText() { 747 bool c_nb_commentText() {
450 if (!c_indicator(C_COMMENT)) return false; 748 if (!truth(c_indicator(C_COMMENT))) return false;
451 zeroOrMore(() => consume(isNonBreak)); 749 zeroOrMore(() => consume(isNonBreak));
452 return true; 750 return true;
453 } 751 }
454 752
455 // 76 753 // 76
456 bool b_comment() => atEndOfFile || b_non_content(); 754 bool b_comment() => atEndOfFile || b_nonContent();
457 755
458 // 77 756 // 77
459 bool s_b_comment() { 757 bool s_b_comment() {
460 if (s_separateInLine()) { 758 if (truth(s_separateInLine())) {
461 zeroOrOne(c_nb_commentText); 759 zeroOrOne(c_nb_commentText);
462 } 760 }
463 return b_comment(); 761 return b_comment();
464 } 762 }
465 763
466 // 78 764 // 78
467 bool l_comment() => transaction(() { 765 bool l_comment() => transaction(() {
468 if (!s_separateInLine()) return false; 766 if (!truth(s_separateInLine())) return false;
469 zeroOrOne(c_nb_commentText); 767 zeroOrOne(c_nb_commentText);
470 return b_comment(); 768 return b_comment();
471 }); 769 });
472 770
473 // 79 771 // 79
474 bool s_l_comments() { 772 bool s_l_comments() {
475 if (!s_b_comment() && !atStartOfLine) return false; 773 if (!truth(s_b_comment()) && !atStartOfLine) return false;
476 zeroOrMore(l_comment); 774 zeroOrMore(l_comment);
477 return true; 775 return true;
478 } 776 }
479 777
480 // 80 778 // 80
481 bool s_separate(int indent, int ctx) { 779 bool s_separate(int indent, int ctx) {
482 switch (ctx) { 780 switch (ctx) {
483 case BLOCK_OUT: 781 case BLOCK_OUT:
484 case BLOCK_IN: 782 case BLOCK_IN:
485 case FLOW_OUT: 783 case FLOW_OUT:
(...skipping 14 matching lines...) Expand all
500 798
501 // 82 799 // 82
502 bool l_directive() => false; // TODO(nweiz): implement 800 bool l_directive() => false; // TODO(nweiz): implement
503 801
504 // 96 802 // 96
505 _Pair<_Tag, String> c_ns_properties(int indent, int ctx) { 803 _Pair<_Tag, String> c_ns_properties(int indent, int ctx) {
506 var tag, anchor; 804 var tag, anchor;
507 tag = c_ns_tagProperty(); 805 tag = c_ns_tagProperty();
508 if (truth(tag)) { 806 if (truth(tag)) {
509 anchor = transaction(() { 807 anchor = transaction(() {
510 if (!s_separate(indent, ctx)) return null; 808 if (!truth(s_separate(indent, ctx))) return null;
511 return c_ns_anchorProperty(); 809 return c_ns_anchorProperty();
512 }); 810 });
513 return new _Pair<_Tag, String>(tag, anchor); 811 return new _Pair<_Tag, String>(tag, anchor);
514 } 812 }
515 813
516 anchor = c_ns_anchorProperty(); 814 anchor = c_ns_anchorProperty();
517 if (truth(anchor)) { 815 if (truth(anchor)) {
518 tag = transaction(() { 816 tag = transaction(() {
519 if (!s_separate(indent, ctx)) return null; 817 if (!truth(s_separate(indent, ctx))) return null;
520 return c_ns_tagProperty(); 818 return c_ns_tagProperty();
521 }); 819 });
522 return new _Pair<_Tag, String>(tag, anchor); 820 return new _Pair<_Tag, String>(tag, anchor);
523 } 821 }
524 822
525 return null; 823 return null;
526 } 824 }
527 825
528 // 97 826 // 97
529 _Tag c_ns_tagProperty() => null; // TODO(nweiz): implement 827 _Tag c_ns_tagProperty() => null; // TODO(nweiz): implement
530 828
531 // 101 829 // 101
532 String c_ns_anchorProperty() => null; // TODO(nweiz): implement 830 String c_ns_anchorProperty() => null; // TODO(nweiz): implement
533 831
534 // 102 832 // 102
535 bool isAnchorChar(int char) => isNonSpace(char) && !isFlowIndicator(char); 833 bool isAnchorChar(int char) => isNonSpace(char) && !isFlowIndicator(char);
536 834
537 // 103 835 // 103
538 String ns_anchorName() => 836 String ns_anchorName() =>
539 captureString(() => oneOrMore(() => consume(isAnchorChar))); 837 captureString(() => oneOrMore(() => consume(isAnchorChar)));
540 838
541 // 104 839 // 104
542 _Node c_ns_aliasNode() { 840 _Node c_ns_aliasNode() {
543 if (!c_indicator(C_ALIAS)) return null; 841 if (!truth(c_indicator(C_ALIAS))) return null;
544 var name = expect(ns_anchorName(), 'anchor name'); 842 var name = expect(ns_anchorName(), 'anchor name');
545 return new _AliasNode(name); 843 return new _AliasNode(name);
546 } 844 }
547 845
548 // 105 846 // 105
549 _ScalarNode e_scalar() => new _ScalarNode("?", content: ""); 847 _ScalarNode e_scalar() => new _ScalarNode("?", content: "");
550 848
551 // 106 849 // 106
552 _ScalarNode e_node() => e_scalar(); 850 _ScalarNode e_node() => e_scalar();
553 851
852 // 107
853 bool nb_doubleChar() => or([
854 c_ns_escChar,
855 () => consume((c) => isJson(c) && c != BACKSLASH && c != DOUBLE_QUOTE)
856 ]);
857
858 // 108
859 bool ns_doubleChar() => !isSpace(peek()) && truth(nb_doubleChar());
860
861 // 109
862 _Node c_doubleQuoted(int indent, int ctx) => context('string', () {
863 return transaction(() {
864 if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null;
865 var contents = nb_doubleText(indent, ctx);
866 if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null;
867 return new _ScalarNode("!", contents);
868 });
869 });
870
871 // 110
872 String nb_doubleText(int indent, int ctx) => captureString(() {
873 switch (ctx) {
874 case FLOW_OUT:
875 case FLOW_IN:
876 nb_doubleMultiLine(indent);
877 break;
878 case BLOCK_KEY:
879 case FLOW_KEY:
880 nb_doubleOneLine();
881 break;
882 }
883 return true;
884 });
885
886 // 111
887 void nb_doubleOneLine() {
888 zeroOrMore(nb_doubleChar);
889 }
890
891 // 112
892 bool s_doubleEscaped(int indent) => transaction(() {
893 zeroOrMore(() => consume(isSpace));
894 if (!captureAs("", () => consumeChar(BACKSLASH))) return false;
895 if (!truth(b_nonContent())) return false;
896 zeroOrMore(() => captureAs("\n", () => l_empty(indent, FLOW_IN)));
897 return s_flowLinePrefix(indent);
898 });
899
900 // 113
901 bool s_doubleBreak(int indent) => or([
902 () => s_doubleEscaped(indent),
903 () => s_flowFolded(indent)
904 ]);
905
906 // 114
907 void nb_ns_doubleInLine() {
908 zeroOrMore(() => transaction(() {
909 zeroOrMore(() => consume(isSpace));
910 return ns_doubleChar();
911 }));
912 }
913
914 // 115
915 bool s_doubleNextLine(int indent) {
916 if (!truth(s_doubleBreak(indent))) return false;
917 zeroOrOne(() {
918 if (!truth(ns_doubleChar())) return;
919 nb_ns_doubleInLine();
920 or([
921 () => s_doubleNextLine(indent),
922 () => zeroOrMore(() => consume(isSpace))
923 ]);
924 });
925 return true;
926 }
927
928 // 116
929 void nb_doubleMultiLine(int indent) {
930 nb_ns_doubleInLine();
931 or([
932 () => s_doubleNextLine(indent),
933 () => zeroOrMore(() => consume(isSpace))
934 ]);
935 }
936
937 // 117
938 bool c_quotedQuote() => captureAs("'", () => rawString("''"));
939
940 // 118
941 bool nb_singleChar() => or([
942 c_quotedQuote,
943 () => consume((c) => isJson(c) && c != SINGLE_QUOTE)
944 ]);
945
946 // 119
947 bool ns_singleChar() => !isSpace(peek()) && truth(nb_singleChar());
948
949 // 120
950 _Node c_singleQuoted(int indent, int ctx) => context('string', () {
951 return transaction(() {
952 if (!truth(c_indicator(C_SINGLE_QUOTE))) return null;
953 var contents = nb_singleText(indent, ctx);
954 if (!truth(c_indicator(C_SINGLE_QUOTE))) return null;
955 return new _ScalarNode("!", contents);
956 });
957 });
958
959 // 121
960 String nb_singleText(int indent, int ctx) => captureString(() {
961 switch (ctx) {
962 case FLOW_OUT:
963 case FLOW_IN:
964 nb_singleMultiLine(indent);
965 break;
966 case BLOCK_KEY:
967 case FLOW_KEY:
968 nb_singleOneLine(indent);
969 break;
970 }
971 return true;
972 });
973
974 // 122
975 void nb_singleOneLine(int indent) {
976 zeroOrMore(nb_singleChar);
977 }
978
979 // 123
980 void nb_ns_singleInLine() {
981 zeroOrMore(() => transaction(() {
982 zeroOrMore(() => consume(isSpace));
983 return ns_singleChar();
984 }));
985 }
986
987 // 124
988 bool s_singleNextLine(int indent) {
989 if (!truth(s_flowFolded(indent))) return false;
990 zeroOrOne(() {
991 if (!truth(ns_singleChar())) return;
992 nb_ns_singleInLine();
993 or([
994 () => s_singleNextLine(indent),
995 () => zeroOrMore(() => consume(isSpace))
996 ]);
997 });
998 return true;
999 }
1000
1001 // 125
1002 void nb_singleMultiLine(int indent) {
1003 nb_ns_singleInLine();
1004 or([
1005 () => s_singleNextLine(indent),
1006 () => zeroOrMore(() => consume(isSpace))
1007 ]);
1008 }
1009
554 // 126 1010 // 126
555 bool ns_plainFirst(int ctx) { 1011 bool ns_plainFirst(int ctx) {
556 var char = peek(); 1012 var char = peek();
557 var indicator = indicatorType(char); 1013 var indicator = indicatorType(char);
558 if (indicator == C_RESERVED) { 1014 if (indicator == C_RESERVED) {
559 error("reserved indicators can't start a plain scalar"); 1015 error("reserved indicators can't start a plain scalar");
560 } 1016 }
561 var match = (isNonSpace(char) && indicator == null) || 1017 var match = (isNonSpace(char) && indicator == null) ||
562 ((indicator == C_MAPPING_KEY || 1018 ((indicator == C_MAPPING_KEY ||
563 indicator == C_MAPPING_VALUE || 1019 indicator == C_MAPPING_VALUE ||
(...skipping 29 matching lines...) Expand all
593 var nonMappingColon = indicator == C_MAPPING_VALUE && 1049 var nonMappingColon = indicator == C_MAPPING_VALUE &&
594 isPlainSafe(ctx, peek(1)); 1050 isPlainSafe(ctx, peek(1));
595 var match = safeChar || nonCommentHash || nonMappingColon; 1051 var match = safeChar || nonCommentHash || nonMappingColon;
596 1052
597 if (match) next(); 1053 if (match) next();
598 return match; 1054 return match;
599 } 1055 }
600 1056
601 // 131 1057 // 131
602 String ns_plain(int indent, int ctx) => context('plain scalar', () { 1058 String ns_plain(int indent, int ctx) => context('plain scalar', () {
603 switch (ctx) { 1059 return captureString(() {
604 case FLOW_OUT: 1060 switch (ctx) {
605 case FLOW_IN: 1061 case FLOW_OUT:
606 return ns_plainMultiLine(indent, ctx); 1062 case FLOW_IN:
607 case BLOCK_KEY: 1063 return ns_plainMultiLine(indent, ctx);
608 case FLOW_KEY: 1064 case BLOCK_KEY:
609 return ns_plainOneLine(ctx); 1065 case FLOW_KEY:
610 default: throw 'invalid context "$ctx"'; 1066 return ns_plainOneLine(ctx);
611 } 1067 default: throw 'invalid context "$ctx"';
1068 }
1069 });
612 }); 1070 });
613 1071
614 // 132 1072 // 132
615 void nb_ns_plainInLine(int ctx) { 1073 void nb_ns_plainInLine(int ctx) {
616 zeroOrMore(() => transaction(() { 1074 zeroOrMore(() => transaction(() {
617 zeroOrMore(() => consume(isSpace)); 1075 zeroOrMore(() => consume(isSpace));
618 return ns_plainChar(ctx); 1076 return ns_plainChar(ctx);
619 })); 1077 }));
620 } 1078 }
621 1079
622 // 133 1080 // 133
623 String ns_plainOneLine(int ctx) => captureString(() { 1081 bool ns_plainOneLine(int ctx) {
624 if (c_forbidden()) return false; 1082 if (truth(c_forbidden())) return false;
625 if (!ns_plainFirst(ctx)) return false; 1083 if (!truth(ns_plainFirst(ctx))) return false;
1084 nb_ns_plainInLine(ctx);
1085 return true;
1086 }
1087
1088 // 134
1089 bool s_ns_plainNextLine(int indent, int ctx) => transaction(() {
1090 if (!truth(s_flowFolded(indent))) return false;
1091 if (truth(c_forbidden())) return false;
1092 if (!truth(ns_plainChar(ctx))) return false;
626 nb_ns_plainInLine(ctx); 1093 nb_ns_plainInLine(ctx);
627 return true; 1094 return true;
628 }); 1095 });
629 1096
630 // 134
631 bool s_ns_plainNextLine(int indent, int ctx) => transaction(() {
632 if (c_forbidden()) return false;
633 if (!s_flowFolded(indent)) return false;
634 if (!ns_plainChar(ctx)) return false;
635 nb_ns_plainInLine(ctx);
636 return true;
637 });
638
639 // 135 1097 // 135
640 String ns_plainMultiLine(int indent, int ctx) => captureString(() { 1098 bool ns_plainMultiLine(int indent, int ctx) {
641 if (!truth(ns_plainOneLine(ctx))) return false; 1099 if (!truth(ns_plainOneLine(ctx))) return false;
642 zeroOrMore(() => s_ns_plainNextLine(indent, ctx)); 1100 zeroOrMore(() => s_ns_plainNextLine(indent, ctx));
643 return true; 1101 return true;
1102 }
1103
1104 // 136
1105 int inFlow(int ctx) {
1106 switch (ctx) {
1107 case FLOW_OUT:
1108 case FLOW_IN:
1109 return FLOW_IN;
1110 case BLOCK_KEY:
1111 case FLOW_KEY:
1112 return FLOW_KEY;
1113 }
1114 }
1115
1116 // 137
1117 _SequenceNode c_flowSequence(int indent, int ctx) => transaction(() {
1118 if (!truth(c_indicator(C_SEQUENCE_START))) return null;
1119 zeroOrOne(() => s_separate(indent, ctx));
1120 var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx)));
1121 if (!truth(c_indicator(C_SEQUENCE_END))) return null;
1122 return new _SequenceNode("?", new List<_Node>.from(content));
644 }); 1123 });
645 1124
1125 // 138
1126 Collection<_Node> ns_s_flowSeqEntries(int indent, int ctx) {
1127 var first = ns_flowSeqEntry(indent, ctx);
1128 if (!truth(first)) return new Queue<_Node>();
1129 zeroOrOne(() => s_separate(indent, ctx));
1130
1131 var rest;
1132 if (truth(c_indicator(C_COLLECT_ENTRY))) {
1133 zeroOrOne(() => s_separate(indent, ctx));
1134 rest = zeroOrOne(() => ns_s_flowSeqEntries(indent, ctx));
1135 }
1136
1137 if (rest == null) rest = new Queue<_Node>();
1138 rest.addFirst(first);
1139
1140 return rest;
1141 }
1142
1143 // 139
1144 _Node ns_flowSeqEntry(int indent, int ctx) => or([
1145 () => ns_flowPair(indent, ctx),
1146 () => ns_flowNode(indent, ctx)
1147 ]);
1148
1149 // 140
1150 _Node c_flowMapping(int indent, int ctx) {
1151 if (!truth(c_indicator(C_MAPPING_START))) return null;
1152 zeroOrOne(() => s_separate(indent, ctx));
1153 var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx)));
1154 if (!truth(c_indicator(C_MAPPING_END))) return null;
1155 return new _MappingNode("?", content);
1156 }
1157
1158 // 141
1159 YamlMap ns_s_flowMapEntries(int indent, int ctx) {
1160 var first = ns_flowMapEntry(indent, ctx);
1161 if (!truth(first)) return new YamlMap();
1162 zeroOrOne(() => s_separate(indent, ctx));
1163
1164 var rest;
1165 if (truth(c_indicator(C_COLLECT_ENTRY))) {
1166 zeroOrOne(() => s_separate(indent, ctx));
1167 rest = ns_s_flowMapEntries(indent, ctx);
1168 }
1169
1170 if (rest == null) rest = new YamlMap();
1171
1172 // TODO(nweiz): Duplicate keys should be an error. This includes keys with
1173 // different representations but the same value (e.g. 10 vs 0xa). To make
1174 // this user-friendly we'll probably also want to associate nodes with a
1175 // source range.
1176 if (!rest.containsKey(first.first)) rest[first.first] = first.last;
1177
1178 return rest;
1179 }
1180
1181 // 142
1182 _Pair<_Node, _Node> ns_flowMapEntry(int indent, int ctx) => or([
1183 () => transaction(() {
1184 if (!truth(c_indicator(C_MAPPING_KEY))) return false;
1185 if (!truth(s_separate(indent, ctx))) return false;
1186 return ns_flowMapExplicitEntry(indent, ctx);
1187 }),
1188 () => ns_flowMapImplicitEntry(indent, ctx)
1189 ]);
1190
1191 // 143
1192 _Pair<_Node, _Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([
1193 () => ns_flowMapImplicitEntry(indent, ctx),
1194 () => new _Pair<_Node, _Node>(e_node(), e_node())
1195 ]);
1196
1197 // 144
1198 _Pair<_Node, _Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([
1199 () => ns_flowMapYamlKeyEntry(indent, ctx),
1200 () => c_ns_flowMapEmptyKeyEntry(indent, ctx),
1201 () => c_ns_flowMapJsonKeyEntry(indent, ctx)
1202 ]);
1203
1204 // 145
1205 _Pair<_Node, _Node> ns_flowMapYamlKeyEntry(int indent, int ctx) {
1206 var key = ns_flowYamlNode(indent, ctx);
1207 if (!truth(key)) return null;
1208 var value = or([
1209 () => transaction(() {
1210 zeroOrOne(() => s_separate(indent, ctx));
1211 return c_ns_flowMapSeparateValue(indent, ctx);
1212 }),
1213 e_node
1214 ]);
1215 return new _Pair<_Node, _Node>(key, value);
1216 }
1217
1218 // 146
1219 _Pair<_Node, _Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) {
1220 var value = c_ns_flowMapSeparateValue(indent, ctx);
1221 if (!truth(value)) return null;
1222 return new _Pair<_Node, _Node>(e_node(), value);
1223 }
1224
1225 // 147
1226 _Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() {
1227 if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
1228 if (isPlainSafe(ctx, peek())) return null;
1229
1230 return or([
1231 () => transaction(() {
1232 if (!s_separate(indent, ctx)) return null;
1233 return ns_flowNode(indent, ctx);
1234 }),
1235 e_node
1236 ]);
1237 });
1238
1239 // 148
1240 _Pair<_Node, _Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) {
1241 var key = c_flowJsonNode(indent, ctx);
1242 if (!truth(key)) return null;
1243 var value = or([
1244 () => transaction(() {
1245 zeroOrOne(() => s_separate(indent, ctx));
1246 return c_ns_flowMapAdjacentValue(indent, ctx);
1247 }),
1248 e_node
1249 ]);
1250 return new _Pair<_Node, _Node>(key, value);
1251 }
1252
1253 // 149
1254 _Node c_ns_flowMapAdjacentValue(int indent, int ctx) {
1255 if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
1256 return or([
1257 () => transaction(() {
1258 zeroOrOne(() => s_separate(indent, ctx));
1259 return ns_flowNode(indent, ctx);
1260 }),
1261 e_node
1262 ]);
1263 }
1264
1265 // 150
1266 _Node ns_flowPair(int indent, int ctx) {
1267 var pair = or([
1268 () => transaction(() {
1269 if (!truth(c_indicator(C_MAPPING_KEY))) return null;
1270 if (!truth(s_separate(indent, ctx))) return null;
1271 return ns_flowMapExplicitEntry(indent, ctx);
1272 }),
1273 () => ns_flowPairEntry(indent, ctx)
1274 ]);
1275 if (!truth(pair)) return null;
1276
1277 return map([pair]);
1278 }
1279
1280 // 151
1281 _Pair<_Node, _Node> ns_flowPairEntry(int indent, int ctx) => or([
1282 () => ns_flowPairYamlKeyEntry(indent, ctx),
1283 () => c_ns_flowMapEmptyKeyEntry(indent, ctx),
1284 () => c_ns_flowPairJsonKeyEntry(indent, ctx)
1285 ]);
1286
1287 // 152
1288 _Pair<_Node, _Node> ns_flowPairYamlKeyEntry(int indent, int ctx) =>
1289 transaction(() {
1290 var key = ns_s_implicitYamlKey(FLOW_KEY);
1291 if (!truth(key)) return null;
1292 var value = c_ns_flowMapSeparateValue(indent, ctx);
1293 if (!truth(value)) return null;
1294 return new _Pair<_Node, _Node>(key, value);
1295 });
1296
1297 // 153
1298 _Pair<_Node, _Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) =>
1299 transaction(() {
1300 var key = c_s_implicitJsonKey(FLOW_KEY);
1301 if (!truth(key)) return null;
1302 var value = c_ns_flowMapAdjacentValue(indent, ctx);
1303 if (!truth(value)) return null;
1304 return new _Pair<_Node, _Node>(key, value);
1305 });
1306
646 // 154 1307 // 154
647 _Node c_s_implicitYamlKey(int ctx) => transaction(() { 1308 _Node ns_s_implicitYamlKey(int ctx) => transaction(() {
1309 // TODO(nweiz): this is supposed to be limited to 1024 characters.
1310
648 // The indentation parameter is "null" since it's unused in this path 1311 // The indentation parameter is "null" since it's unused in this path
649 var node = ns_flowYamlNode(null, ctx); 1312 var node = ns_flowYamlNode(null, ctx);
650 if (!truth(node)) return null; 1313 if (!truth(node)) return null;
651 zeroOrOne(s_separateInLine); 1314 zeroOrOne(s_separateInLine);
652 return node; 1315 return node;
653 }); 1316 });
654 1317
655 // 155 1318 // 155
656 _Node c_s_implicitJsonKey(int ctx) => null; // TODO(nweiz): implement 1319 _Node c_s_implicitJsonKey(int ctx) => transaction(() {
1320 // TODO(nweiz): this is supposed to be limited to 1024 characters.
1321
1322 // The indentation parameter is "null" since it's unused in this path
1323 var node = c_flowJsonNode(null, ctx);
1324 if (!truth(node)) return null;
1325 zeroOrOne(s_separateInLine);
1326 return node;
1327 });
657 1328
658 // 156 1329 // 156
659 _Node ns_flowYamlContent(int indent, int ctx) { 1330 _Node ns_flowYamlContent(int indent, int ctx) {
660 var str = ns_plain(indent, ctx); 1331 var str = ns_plain(indent, ctx);
661 if (!truth(str)) return null; 1332 if (!truth(str)) return null;
662 return new _ScalarNode("?", content: str); 1333 return new _ScalarNode("?", content: str);
663 } 1334 }
664 1335
665 // 157 1336 // 157
666 // TODO(nweiz): implement 1337 _Node c_flowJsonContent(int indent, int ctx) => or([
667 _Node ns_flowJsonContent(int indent, int ctx) => null; 1338 () => c_flowSequence(indent, ctx),
1339 () => c_flowMapping(indent, ctx),
1340 () => c_singleQuoted(indent, ctx),
1341 () => c_doubleQuoted(indent, ctx)
1342 ]);
668 1343
669 // 158 1344 // 158
670 _Node ns_flowContent(int indent, int ctx) => or([ 1345 _Node ns_flowContent(int indent, int ctx) => or([
671 () => ns_flowYamlContent(indent, ctx), 1346 () => ns_flowYamlContent(indent, ctx),
672 () => ns_flowJsonContent(indent, ctx) 1347 () => c_flowJsonContent(indent, ctx)
673 ]); 1348 ]);
674 1349
675 // 159 1350 // 159
676 _Node ns_flowYamlNode(int indent, int ctx) => or([ 1351 _Node ns_flowYamlNode(int indent, int ctx) => or([
677 c_ns_aliasNode, 1352 c_ns_aliasNode,
678 () => ns_flowYamlContent(indent, ctx), 1353 () => ns_flowYamlContent(indent, ctx),
679 () { 1354 () {
680 var props = c_ns_properties(indent, ctx); 1355 var props = c_ns_properties(indent, ctx);
681 if (!truth(props)) return null; 1356 if (!truth(props)) return null;
682 var node = or([ 1357 var node = or([
683 () => transaction(() { 1358 () => transaction(() {
684 if (!s_separate(indent, ctx)) return null; 1359 if (!truth(s_separate(indent, ctx))) return null;
685 return ns_flowYamlContent(indent, ctx); 1360 return ns_flowYamlContent(indent, ctx);
686 }), 1361 }),
687 e_scalar 1362 e_scalar
688 ]); 1363 ]);
689 return addProps(node, props); 1364 return addProps(node, props);
690 } 1365 }
691 ]); 1366 ]);
692 1367
1368 // 160
1369 _Node c_flowJsonNode(int indent, int ctx) => transaction(() {
1370 var props;
1371 zeroOrOne(() => transaction(() {
1372 props = c_ns_properties(indent, ctx);
1373 if (!truth(props)) return null;
1374 return s_separate(indent, ctx);
1375 }));
1376
1377 return addProps(c_flowJsonContent(indent, ctx), props);
1378 });
1379
693 // 161 1380 // 161
694 _Node ns_flowNode(int indent, int ctx) => or([ 1381 _Node ns_flowNode(int indent, int ctx) => or([
695 c_ns_aliasNode, 1382 c_ns_aliasNode,
696 () => ns_flowContent(indent, ctx), 1383 () => ns_flowContent(indent, ctx),
697 () => transaction(() { 1384 () => transaction(() {
698 var props = c_ns_properties(indent, ctx); 1385 var props = c_ns_properties(indent, ctx);
699 if (!truth(props)) return null; 1386 if (!truth(props)) return null;
700 var node = or([ 1387 var node = or([
701 () => transaction(() => s_separate(indent, ctx) ? 1388 () => transaction(() => s_separate(indent, ctx) ?
702 ns_flowContent(indent, ctx) : null), 1389 ns_flowContent(indent, ctx) : null),
703 e_scalar]); 1390 e_scalar]);
704 return addProps(node, props); 1391 return addProps(node, props);
705 }) 1392 })
706 ]); 1393 ]);
707 1394
1395 // 162
1396 _BlockHeader c_b_blockHeader() => transaction(() {
1397 var indentation = c_indentationIndicator();
1398 var chomping = c_chompingIndicator();
1399 if (!truth(indentation)) indentation = c_indentationIndicator();
1400 if (!truth(s_b_comment())) return null;
1401
1402 return new _BlockHeader(indentation, chomping);
1403 });
1404
1405 // 163
1406 int c_indentationIndicator() {
1407 if (!isDecDigit(peek())) return null;
1408 return next() - NUMBER_0;
1409 }
1410
1411 // 164
1412 int c_chompingIndicator() {
1413 switch (peek()) {
1414 case HYPHEN:
1415 next();
1416 return CHOMPING_STRIP;
1417 case PLUS:
1418 next();
1419 return CHOMPING_KEEP;
1420 default:
1421 return CHOMPING_CLIP;
1422 }
1423 }
1424
1425 // 165
1426 bool b_chompedLast(int chomping) {
1427 if (atEndOfFile) return true;
1428 switch (chomping) {
1429 case CHOMPING_STRIP:
1430 return b_nonContent();
1431 case CHOMPING_CLIP:
1432 case CHOMPING_KEEP:
1433 return b_asLineFeed();
1434 }
1435 }
1436
1437 // 166
1438 void l_chompedEmpty(int indent, int chomping) {
1439 switch (chomping) {
1440 case CHOMPING_STRIP:
1441 case CHOMPING_CLIP:
1442 l_stripEmpty(indent);
1443 break;
1444 case CHOMPING_KEEP:
1445 l_keepEmpty(indent);
1446 break;
1447 }
1448 }
1449
1450 // 167
1451 void l_stripEmpty(int indent) => captureAs('', () {
1452 zeroOrMore(() => transaction(() {
1453 if (!truth(s_indentLessThanOrEqualTo(indent))) return false;
1454 return b_nonContent();
1455 }));
1456 zeroOrOne(() => l_trailComments(indent));
1457 return true;
1458 });
1459
1460 // 168
1461 void l_keepEmpty(int indent) {
1462 zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN)));
1463 zeroOrOne(() => captureAs('', () => l_trailComments(indent)));
1464 }
1465
1466 // 169
1467 bool l_trailComments(int indent) => transaction(() {
1468 if (!truth(s_indentLessThanOrEqualTo(indent))) return false;
1469 if (!truth(c_nb_commentText())) return false;
1470 if (!truth(b_comment())) return false;
1471 zeroOrMore(l_comment);
1472 return true;
1473 });
1474
708 // 170 1475 // 170
709 _Node c_l_literal(int indent) => null; // TODO(nweiz); implement 1476 _Node c_l_literal(int indent) => transaction(() {
1477 if (!truth(c_indicator(C_LITERAL))) return null;
1478 var header = c_b_blockHeader();
1479 if (!truth(header)) return null;
1480
1481 var additionalIndent = blockScalarAdditionalIndentation(header, indent);
1482 var content = l_literalContent(indent + additionalIndent, header.chomping);
1483 if (!truth(content)) return null;
1484
1485 return new _ScalarNode("!", content);
1486 });
1487
1488 // 171
1489 bool l_nb_literalText(int indent) => transaction(() {
1490 zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN)));
1491 if (!truth(captureAs("", () => s_indent(indent)))) return false;
1492 return truth(oneOrMore(() => consume(isNonBreak)));
1493 });
1494
1495 // 172
1496 bool b_nb_literalNext(int indent) => transaction(() {
1497 if (!truth(b_asLineFeed())) return false;
1498 return l_nb_literalText(indent);
1499 });
1500
1501 // 173
1502 String l_literalContent(int indent, int chomping) => captureString(() {
1503 transaction(() {
1504 if (!truth(l_nb_literalText(indent))) return false;
1505 zeroOrMore(() => b_nb_literalNext(indent));
1506 return b_chompedLast(chomping);
1507 });
1508 l_chompedEmpty(indent, chomping);
1509 return true;
1510 });
710 1511
711 // 174 1512 // 174
712 _Node c_l_folded(int indent) => null; // TODO(nweiz); implement 1513 _Node c_l_folded(int indent) => transaction(() {
1514 if (!truth(c_indicator(C_FOLDED))) return null;
1515 var header = c_b_blockHeader();
1516 if (!truth(header)) return null;
1517
1518 var additionalIndent = blockScalarAdditionalIndentation(header, indent);
1519 var content = l_foldedContent(indent + additionalIndent, header.chomping);
1520 if (!truth(content)) return null;
1521
1522 return new _ScalarNode("!", content);
1523 });
1524
1525 // 175
1526 bool s_nb_foldedText(int indent) => transaction(() {
1527 if (!truth(captureAs('', () => s_indent(indent)))) return false;
1528 if (!truth(consume(isNonSpace))) return false;
1529 zeroOrMore(() => consume(isNonBreak));
1530 return true;
1531 });
1532
1533 // 176
1534 bool l_nb_foldedLines(int indent) {
1535 if (!truth(s_nb_foldedText(indent))) return false;
1536 zeroOrMore(() => transaction(() {
1537 if (!truth(b_l_folded(indent, BLOCK_IN))) return false;
1538 return s_nb_foldedText(indent);
1539 }));
1540 return true;
1541 }
1542
1543 // 177
1544 bool s_nb_spacedText(int indent) => transaction(() {
1545 if (!truth(captureAs('', () => s_indent(indent)))) return false;
1546 if (!truth(consume(isSpace))) return false;
1547 zeroOrMore(() => consume(isNonBreak));
1548 return true;
1549 });
1550
1551 // 178
1552 bool b_l_spaced(int indent) {
1553 if (!truth(b_asLineFeed())) return false;
1554 zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN)));
1555 return true;
1556 }
1557
1558 // 179
1559 bool l_nb_spacedLines(int indent) {
1560 if (!truth(s_nb_spacedText(indent))) return false;
1561 zeroOrMore(() => transaction(() {
1562 if (!truth(b_l_spaced(indent))) return false;
1563 return s_nb_spacedText(indent);
1564 }));
1565 return true;
1566 }
1567
1568 // 180
1569 bool l_nb_sameLines(int indent) => transaction(() {
1570 zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN)));
1571 return or([
1572 () => l_nb_foldedLines(indent),
1573 () => l_nb_spacedLines(indent)
1574 ]);
1575 });
1576
1577 // 181
1578 bool l_nb_diffLines(int indent) {
1579 if (!truth(l_nb_sameLines(indent))) return false;
1580 zeroOrMore(() => transaction(() {
1581 if (!truth(b_asLineFeed())) return false;
1582 return l_nb_sameLines(indent);
1583 }));
1584 return true;
1585 }
1586
1587 // 182
1588 String l_foldedContent(int indent, int chomping) => captureString(() {
1589 transaction(() {
1590 if (!truth(l_nb_diffLines(indent))) return false;
1591 return b_chompedLast(chomping);
1592 });
1593 l_chompedEmpty(indent, chomping);
1594 return true;
1595 });
713 1596
714 // 183 1597 // 183
715 _SequenceNode l_blockSequence(int indent) => context('sequence', () { 1598 _SequenceNode l_blockSequence(int indent) => context('sequence', () {
716 var additionalIndent = countIndentation() - indent; 1599 var additionalIndent = countIndentation() - indent;
717 if (additionalIndent <= 0) return null; 1600 if (additionalIndent <= 0) return null;
718 1601
719 var content = oneOrMore(() => transaction(() { 1602 var content = oneOrMore(() => transaction(() {
720 if (!s_indent(indent + additionalIndent)) return null; 1603 if (!truth(s_indent(indent + additionalIndent))) return null;
721 return c_l_blockSeqEntry(indent + additionalIndent); 1604 return c_l_blockSeqEntry(indent + additionalIndent);
722 })); 1605 }));
723 if (!truth(content)) return null; 1606 if (!truth(content)) return null;
724 1607
725 return new _SequenceNode("?", content); 1608 return new _SequenceNode("?", content);
726 }); 1609 });
727 1610
728 // 184 1611 // 184
729 _Node c_l_blockSeqEntry(int indent) => transaction(() { 1612 _Node c_l_blockSeqEntry(int indent) => transaction(() {
730 if (!c_indicator(C_SEQUENCE_ENTRY)) return null; 1613 if (!truth(c_indicator(C_SEQUENCE_ENTRY))) return null;
731 if (isNonSpace(peek())) return null; 1614 if (isNonSpace(peek())) return null;
732 1615
733 return s_l_blockIndented(indent, BLOCK_IN); 1616 return s_l_blockIndented(indent, BLOCK_IN);
734 }); 1617 });
735 1618
736 // 185 1619 // 185
737 _Node s_l_blockIndented(int indent, int ctx) { 1620 _Node s_l_blockIndented(int indent, int ctx) {
738 var additionalIndent = countIndentation(); 1621 var additionalIndent = countIndentation();
739 return or([ 1622 return or([
740 () => transaction(() { 1623 () => transaction(() {
741 if (!s_indent(additionalIndent)) return null; 1624 if (!truth(s_indent(additionalIndent))) return null;
742 return or([ 1625 return or([
743 () => ns_l_compactSequence(indent + 1 + additionalIndent), 1626 () => ns_l_compactSequence(indent + 1 + additionalIndent),
744 () => ns_l_compactMapping(indent + 1 + additionalIndent)]); 1627 () => ns_l_compactMapping(indent + 1 + additionalIndent)]);
745 }), 1628 }),
746 () => s_l_blockNode(indent, ctx), 1629 () => s_l_blockNode(indent, ctx),
747 () => s_l_comments() ? e_node() : null]); 1630 () => s_l_comments() ? e_node() : null]);
748 } 1631 }
749 1632
750 // 186 1633 // 186
751 _Node ns_l_compactSequence(int indent) => context('sequence', () { 1634 _Node ns_l_compactSequence(int indent) => context('sequence', () {
752 var first = c_l_blockSeqEntry(indent); 1635 var first = c_l_blockSeqEntry(indent);
753 if (!truth(first)) return null; 1636 if (!truth(first)) return null;
754 1637
755 var content = zeroOrMore(() => transaction(() { 1638 var content = zeroOrMore(() => transaction(() {
756 if (!s_indent(indent)) return null; 1639 if (!truth(s_indent(indent))) return null;
757 return c_l_blockSeqEntry(indent); 1640 return c_l_blockSeqEntry(indent);
758 })); 1641 }));
759 content.insertRange(0, 1, first); 1642 content.insertRange(0, 1, first);
760 1643
761 return new _SequenceNode("?", content); 1644 return new _SequenceNode("?", content);
762 }); 1645 });
763 1646
764 // 187 1647 // 187
765 _Node l_blockMapping(int indent) => context('mapping', () { 1648 _Node l_blockMapping(int indent) => context('mapping', () {
766 var additionalIndent = countIndentation() - indent; 1649 var additionalIndent = countIndentation() - indent;
767 if (additionalIndent <= 0) return null; 1650 if (additionalIndent <= 0) return null;
768 1651
769 var pairs = oneOrMore(() => transaction(() { 1652 var pairs = oneOrMore(() => transaction(() {
770 if (!s_indent(indent + additionalIndent)) return null; 1653 if (!truth(s_indent(indent + additionalIndent))) return null;
771 return ns_l_blockMapEntry(indent + additionalIndent); 1654 return ns_l_blockMapEntry(indent + additionalIndent);
772 })); 1655 }));
773 if (!truth(pairs)) return null; 1656 if (!truth(pairs)) return null;
774 1657
775 return map(pairs); 1658 return map(pairs);
776 }); 1659 });
777 1660
778 // 188 1661 // 188
779 _Pair<_Node, _Node> ns_l_blockMapEntry(int indent) => or([ 1662 _Pair<_Node, _Node> ns_l_blockMapEntry(int indent) => or([
780 () => c_l_blockMapExplicitEntry(indent), 1663 () => c_l_blockMapExplicitEntry(indent),
781 () => ns_l_blockMapImplicitEntry(indent) 1664 () => ns_l_blockMapImplicitEntry(indent)
782 ]); 1665 ]);
783 1666
784 // 189 1667 // 189
785 // TODO(nweiz): implement 1668 _Pair<_Node, _Node> c_l_blockMapExplicitEntry(int indent) {
786 _Pair<_Node, _Node> c_l_blockMapExplicitEntry(int indent) => null; 1669 var key = c_l_blockMapExplicitKey(indent);
1670 if (!truth(key)) return null;
1671
1672 var value = or([
1673 () => l_blockMapExplicitValue(indent),
1674 e_node
1675 ]);
1676
1677 return new _Pair<_Node, _Node>(key, value);
1678 }
1679
1680 // 190
1681 _Node c_l_blockMapExplicitKey(int indent) => transaction(() {
1682 if (!truth(c_indicator(C_MAPPING_KEY))) return null;
1683 return s_l_blockIndented(indent, BLOCK_OUT);
1684 });
1685
1686 // 191
1687 _Node l_blockMapExplicitValue(int indent) => transaction(() {
1688 if (!truth(s_indent(indent))) return null;
1689 if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
1690 return s_l_blockIndented(indent, BLOCK_OUT);
1691 });
787 1692
788 // 192 1693 // 192
789 _Pair<_Node, _Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() { 1694 _Pair<_Node, _Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() {
790 var key = or([ns_s_blockMapImplicitKey, e_node]); 1695 var key = or([ns_s_blockMapImplicitKey, e_node]);
791 var value = c_l_blockMapImplicitValue(indent); 1696 var value = c_l_blockMapImplicitValue(indent);
792 return truth(value) ? new _Pair<_Node, _Node>(key, value) : null; 1697 return truth(value) ? new _Pair<_Node, _Node>(key, value) : null;
793 }); 1698 });
794 1699
795 // 193 1700 // 193
796 _Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([ 1701 _Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([
797 () => c_s_implicitJsonKey(BLOCK_KEY), 1702 () => c_s_implicitJsonKey(BLOCK_KEY),
798 () => c_s_implicitYamlKey(BLOCK_KEY) 1703 () => ns_s_implicitYamlKey(BLOCK_KEY)
799 ])); 1704 ]));
800 1705
801 // 194 1706 // 194
802 _Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () => 1707 _Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () =>
803 transaction(() { 1708 transaction(() {
804 if (!c_indicator(C_MAPPING_VALUE)) return null; 1709 if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
805 return or([ 1710 return or([
806 () => s_l_blockNode(indent, BLOCK_OUT), 1711 () => s_l_blockNode(indent, BLOCK_OUT),
807 () => s_l_comments() ? e_node() : null 1712 () => s_l_comments() ? e_node() : null
808 ]); 1713 ]);
809 })); 1714 }));
810 1715
811 // 195 1716 // 195
812 _Node ns_l_compactMapping(int indent) => context('mapping', () { 1717 _Node ns_l_compactMapping(int indent) => context('mapping', () {
813 var first = ns_l_blockMapEntry(indent); 1718 var first = ns_l_blockMapEntry(indent);
814 if (!truth(first)) return null; 1719 if (!truth(first)) return null;
815 1720
816 var pairs = zeroOrMore(() => transaction(() { 1721 var pairs = zeroOrMore(() => transaction(() {
817 if (!s_indent(indent)) return null; 1722 if (!truth(s_indent(indent))) return null;
818 return ns_l_blockMapEntry(indent); 1723 return ns_l_blockMapEntry(indent);
819 })); 1724 }));
820 pairs.insertRange(0, 1, first); 1725 pairs.insertRange(0, 1, first);
821 1726
822 return map(pairs); 1727 return map(pairs);
823 }); 1728 });
824 1729
825 // 196 1730 // 196
826 _Node s_l_blockNode(int indent, int ctx) => or([ 1731 _Node s_l_blockNode(int indent, int ctx) => or([
827 () => s_l_blockInBlock(indent, ctx), 1732 () => s_l_blockInBlock(indent, ctx),
828 () => s_l_flowInBlock(indent) 1733 () => s_l_flowInBlock(indent)
829 ]); 1734 ]);
830 1735
831 // 197 1736 // 197
832 _Node s_l_flowInBlock(int indent) => transaction(() { 1737 _Node s_l_flowInBlock(int indent) => transaction(() {
833 if (!s_separate(indent + 1, FLOW_OUT)) return null; 1738 if (!truth(s_separate(indent + 1, FLOW_OUT))) return null;
834 var node = ns_flowNode(indent + 1, FLOW_OUT); 1739 var node = ns_flowNode(indent + 1, FLOW_OUT);
835 if (!truth(node)) return null; 1740 if (!truth(node)) return null;
836 if (!s_l_comments()) return null; 1741 if (!truth(s_l_comments())) return null;
837 return node; 1742 return node;
838 }); 1743 });
839 1744
840 // 198 1745 // 198
841 _Node s_l_blockInBlock(int indent, int ctx) => or([ 1746 _Node s_l_blockInBlock(int indent, int ctx) => or([
842 () => s_l_blockScalar(indent, ctx), 1747 () => s_l_blockScalar(indent, ctx),
843 () => s_l_blockCollection(indent, ctx) 1748 () => s_l_blockCollection(indent, ctx)
844 ]); 1749 ]);
845 1750
846 // 199 1751 // 199
847 _Node s_l_blockScalar(int indent, int ctx) => transaction(() { 1752 _Node s_l_blockScalar(int indent, int ctx) => transaction(() {
848 if (!s_separate(indent + 1, ctx)) return null; 1753 if (!truth(s_separate(indent + 1, ctx))) return null;
849 var props = transaction(() { 1754 var props = transaction(() {
850 var props = c_ns_properties(indent + 1, ctx); 1755 var props = c_ns_properties(indent + 1, ctx);
851 if (!truth(props)) return null; 1756 if (!truth(props)) return null;
852 if (!s_separate(indent + 1, ctx)) return null; 1757 if (!truth(s_separate(indent + 1, ctx))) return null;
853 return props; 1758 return props;
854 }); 1759 });
855 if (!truth(props)) props = new _Pair<_Tag, String>(null, null);
856 1760
857 var node = or([() => c_l_literal(indent), () => c_l_folded(indent)]); 1761 var node = or([() => c_l_literal(indent), () => c_l_folded(indent)]);
858 if (!truth(node)) return null; 1762 if (!truth(node)) return null;
859 return addProps(node, props); 1763 return addProps(node, props);
860 }); 1764 });
861 1765
862 // 200 1766 // 200
863 _Node s_l_blockCollection(int indent, int ctx) => transaction(() { 1767 _Node s_l_blockCollection(int indent, int ctx) => transaction(() {
864 var props = transaction(() { 1768 var props = transaction(() {
865 if (!s_separate(indent + 1, ctx)) return null; 1769 if (!truth(s_separate(indent + 1, ctx))) return null;
866 return c_ns_properties(indent + 1, ctx); 1770 return c_ns_properties(indent + 1, ctx);
867 }); 1771 });
868 if (!truth(props)) props = new _Pair<_Tag, String>(null, null);
869 1772
870 if (!s_l_comments()) return null; 1773 if (!truth(s_l_comments())) return null;
871 return or([ 1774 return or([
872 () => l_blockSequence(seqSpaces(indent, ctx)), 1775 () => l_blockSequence(seqSpaces(indent, ctx)),
873 () => l_blockMapping(indent)]); 1776 () => l_blockMapping(indent)]);
874 }); 1777 });
875 1778
876 // 201 1779 // 201
877 int seqSpaces(int indent, int ctx) => ctx == BLOCK_OUT ? indent - 1 : indent; 1780 int seqSpaces(int indent, int ctx) => ctx == BLOCK_OUT ? indent - 1 : indent;
878 1781
879 // 202 1782 // 202
880 void l_documentPrefix() { 1783 void l_documentPrefix() {
881 zeroOrMore(l_comment); 1784 zeroOrMore(l_comment);
882 } 1785 }
883 1786
884 // 203 1787 // 203
885 bool c_directivesEnd() => rawString("---"); 1788 bool c_directivesEnd() => rawString("---");
886 1789
887 // 204 1790 // 204
888 bool c_documentEnd() => rawString("..."); 1791 bool c_documentEnd() => rawString("...");
889 1792
890 // 205 1793 // 205
891 bool l_documentSuffix() => transaction(() { 1794 bool l_documentSuffix() => transaction(() {
892 if (!c_documentEnd()) return false; 1795 if (!truth(c_documentEnd())) return false;
893 return s_l_comments(); 1796 return s_l_comments();
894 }); 1797 });
895 1798
896 // 206 1799 // 206
897 bool c_forbidden() { 1800 bool c_forbidden() {
898 if (!inBareDocument || !atStartOfLine) return false; 1801 if (!inBareDocument || !atStartOfLine) return false;
899 var forbidden = false; 1802 var forbidden = false;
900 transaction(() { 1803 transaction(() {
901 if (!truth(or([c_directivesEnd, c_documentEnd]))) return; 1804 if (!truth(or([c_directivesEnd, c_documentEnd]))) return;
902 var char = peek(); 1805 var char = peek();
903 forbidden = isBreak(char) || isSpace(char) || atEndOfFile; 1806 forbidden = isBreak(char) || isSpace(char) || atEndOfFile;
904 return; 1807 return;
905 }); 1808 });
906 return forbidden; 1809 return forbidden;
907 } 1810 }
908 1811
909 // 207 1812 // 207
910 _Node l_bareDocument() { 1813 _Node l_bareDocument() {
911 try { 1814 try {
912 inBareDocument = true; 1815 inBareDocument = true;
913 return s_l_blockNode(-1, BLOCK_IN); 1816 return s_l_blockNode(-1, BLOCK_IN);
914 } finally { 1817 } finally {
915 inBareDocument = false; 1818 inBareDocument = false;
916 } 1819 }
917 } 1820 }
918 1821
919 // 208 1822 // 208
920 _Node l_explicitDocument() { 1823 _Node l_explicitDocument() {
921 if (!c_directivesEnd()) return null; 1824 if (!truth(c_directivesEnd())) return null;
922 var doc = l_bareDocument(); 1825 var doc = l_bareDocument();
923 if (truth(doc)) return doc; 1826 if (truth(doc)) return doc;
924 1827
925 doc = e_node(); 1828 doc = e_node();
926 s_l_comments(); 1829 s_l_comments();
927 return doc; 1830 return doc;
928 } 1831 }
929 1832
930 // 209 1833 // 209
931 _Node l_directiveDocument() { 1834 _Node l_directiveDocument() {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 1879
977 /** A pair of values. */ 1880 /** A pair of values. */
978 class _Pair<E, F> { 1881 class _Pair<E, F> {
979 E first; 1882 E first;
980 F last; 1883 F last;
981 1884
982 _Pair(this.first, this.last); 1885 _Pair(this.first, this.last);
983 1886
984 String toString() => '($first, $last)'; 1887 String toString() => '($first, $last)';
985 } 1888 }
1889
1890 /** The information in the header for a block scalar. */
1891 class _BlockHeader {
1892 final int additionalIndent;
1893 final int chomping;
1894
1895 _BlockHeader(this.additionalIndent, this.chomping);
1896
1897 bool get autoDetectIndent() => additionalIndent == null;
1898 }
OLDNEW
« no previous file with comments | « utils/pub/yaml/composer.dart ('k') | utils/pub/yaml/yaml_map.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698