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

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

Powered by Google App Engine
This is Rietveld 408576698