OLD | NEW |
---|---|
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 library parser; | 5 library yaml.parser; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'model.dart'; | 9 import 'model.dart'; |
10 import 'yaml_exception.dart'; | 10 import 'yaml_exception.dart'; |
11 import 'yaml_map.dart'; | 11 import 'yaml_map.dart'; |
12 | 12 |
13 /// Translates a string of characters into a YAML serialization tree. | 13 /// Translates a string of characters into a YAML serialization tree. |
14 /// | 14 /// |
15 /// This parser is designed to closely follow the spec. All productions in the | 15 /// This parser is designed to closely follow the spec. All productions in the |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
400 end = _pos; | 400 end = _pos; |
401 return false; | 401 return false; |
402 }); | 402 }); |
403 _errorAnnotations[new _Range(start, end)] = message; | 403 _errorAnnotations[new _Range(start, end)] = message; |
404 } | 404 } |
405 | 405 |
406 /// Throws an error with additional context information. | 406 /// Throws an error with additional context information. |
407 error(String message) { | 407 error(String message) { |
408 // Line and column should be one-based. | 408 // Line and column should be one-based. |
409 throw new SyntaxError(_line + 1, _column + 1, | 409 throw new SyntaxError(_line + 1, _column + 1, |
410 "$message (in $_farthestContext)"); | 410 "$message (in $_farthestContext)."); |
411 } | 411 } |
412 | 412 |
413 /// If [result] is falsey, throws an error saying that [expected] was | 413 /// If [result] is falsey, throws an error saying that [expected] was |
414 /// expected. | 414 /// expected. |
415 expect(result, String expected) { | 415 expect(result, String expected) { |
416 if (truth(result)) return result; | 416 if (truth(result)) return result; |
417 error("expected $expected"); | 417 error("Expected $expected"); |
418 } | 418 } |
419 | 419 |
420 /// Throws an error saying that the parse failed. Uses [_farthestLine], | 420 /// Throws an error saying that the parse failed. Uses [_farthestLine], |
421 /// [_farthestColumn], and [_farthestContext] to provide additional informatio n. | 421 /// [_farthestColumn], and [_farthestContext] to provide additional informatio n. |
Bob Nystrom
2014/05/09 00:18:56
Long line.
nweiz
2014/05/20 00:15:07
Done.
| |
422 parseFailed() { | 422 parseFailed() { |
423 var message = "invalid YAML in $_farthestContext"; | 423 var message = "Invalid YAML in $_farthestContext"; |
424 var extraError = _errorAnnotations[_farthestPos]; | 424 var extraError = _errorAnnotations[_farthestPos]; |
425 if (extraError != null) message = "$message ($extraError)"; | 425 if (extraError != null) message = "$message ($extraError)"; |
426 throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, message); | 426 throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, "$message."); |
427 } | 427 } |
428 | 428 |
429 /// Returns the number of spaces after the current position. | 429 /// Returns the number of spaces after the current position. |
430 int countIndentation() { | 430 int countIndentation() { |
431 var i = 0; | 431 var i = 0; |
432 while (peek(i) == SP) i++; | 432 while (peek(i) == SP) i++; |
433 return i; | 433 return i; |
434 } | 434 } |
435 | 435 |
436 /// Returns the indentation for a block scalar. | 436 /// Returns the indentation for a block scalar. |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 bool s_separate(int indent, int ctx) { | 781 bool s_separate(int indent, int ctx) { |
782 switch (ctx) { | 782 switch (ctx) { |
783 case BLOCK_OUT: | 783 case BLOCK_OUT: |
784 case BLOCK_IN: | 784 case BLOCK_IN: |
785 case FLOW_OUT: | 785 case FLOW_OUT: |
786 case FLOW_IN: | 786 case FLOW_IN: |
787 return s_separateLines(indent); | 787 return s_separateLines(indent); |
788 case BLOCK_KEY: | 788 case BLOCK_KEY: |
789 case FLOW_KEY: | 789 case FLOW_KEY: |
790 return s_separateInLine(); | 790 return s_separateInLine(); |
791 default: throw 'invalid context "$ctx"'; | 791 default: throw 'Invalid context "$ctx".'; |
792 } | 792 } |
793 } | 793 } |
794 | 794 |
795 // 81 | 795 // 81 |
796 bool s_separateLines(int indent) { | 796 bool s_separateLines(int indent) { |
797 return transaction(() => s_l_comments() && s_flowLinePrefix(indent)) || | 797 return transaction(() => s_l_comments() && s_flowLinePrefix(indent)) || |
798 s_separateInLine(); | 798 s_separateInLine(); |
799 } | 799 } |
800 | 800 |
801 // 82 | 801 // 82 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1007 () => s_singleNextLine(indent), | 1007 () => s_singleNextLine(indent), |
1008 () => zeroOrMore(() => consume(isSpace)) | 1008 () => zeroOrMore(() => consume(isSpace)) |
1009 ]); | 1009 ]); |
1010 } | 1010 } |
1011 | 1011 |
1012 // 126 | 1012 // 126 |
1013 bool ns_plainFirst(int ctx) { | 1013 bool ns_plainFirst(int ctx) { |
1014 var char = peek(); | 1014 var char = peek(); |
1015 var indicator = indicatorType(char); | 1015 var indicator = indicatorType(char); |
1016 if (indicator == C_RESERVED) { | 1016 if (indicator == C_RESERVED) { |
1017 error("reserved indicators can't start a plain scalar"); | 1017 error("Reserved indicators can't start a plain scalar"); |
Bob Nystrom
2014/05/09 00:18:56
"."
nweiz
2014/05/20 00:15:07
[error] automatically adds a period.
| |
1018 } | 1018 } |
1019 var match = (isNonSpace(char) && indicator == null) || | 1019 var match = (isNonSpace(char) && indicator == null) || |
1020 ((indicator == C_MAPPING_KEY || | 1020 ((indicator == C_MAPPING_KEY || |
1021 indicator == C_MAPPING_VALUE || | 1021 indicator == C_MAPPING_VALUE || |
1022 indicator == C_SEQUENCE_ENTRY) && | 1022 indicator == C_SEQUENCE_ENTRY) && |
1023 isPlainSafe(ctx, peek(1))); | 1023 isPlainSafe(ctx, peek(1))); |
1024 | 1024 |
1025 if (match) next(); | 1025 if (match) next(); |
1026 return match; | 1026 return match; |
1027 } | 1027 } |
1028 | 1028 |
1029 // 127 | 1029 // 127 |
1030 bool isPlainSafe(int ctx, int char) { | 1030 bool isPlainSafe(int ctx, int char) { |
1031 switch (ctx) { | 1031 switch (ctx) { |
1032 case FLOW_OUT: | 1032 case FLOW_OUT: |
1033 case BLOCK_KEY: | 1033 case BLOCK_KEY: |
1034 // 128 | 1034 // 128 |
1035 return isNonSpace(char); | 1035 return isNonSpace(char); |
1036 case FLOW_IN: | 1036 case FLOW_IN: |
1037 case FLOW_KEY: | 1037 case FLOW_KEY: |
1038 // 129 | 1038 // 129 |
1039 return isNonSpace(char) && !isFlowIndicator(char); | 1039 return isNonSpace(char) && !isFlowIndicator(char); |
1040 default: throw 'invalid context "$ctx"'; | 1040 default: throw 'Invalid context "$ctx".'; |
1041 } | 1041 } |
1042 } | 1042 } |
1043 | 1043 |
1044 // 130 | 1044 // 130 |
1045 bool ns_plainChar(int ctx) { | 1045 bool ns_plainChar(int ctx) { |
1046 var char = peek(); | 1046 var char = peek(); |
1047 var indicator = indicatorType(char); | 1047 var indicator = indicatorType(char); |
1048 var safeChar = isPlainSafe(ctx, char) && indicator != C_MAPPING_VALUE && | 1048 var safeChar = isPlainSafe(ctx, char) && indicator != C_MAPPING_VALUE && |
1049 indicator != C_COMMENT; | 1049 indicator != C_COMMENT; |
1050 var nonCommentHash = isNonSpace(peek(-1)) && indicator == C_COMMENT; | 1050 var nonCommentHash = isNonSpace(peek(-1)) && indicator == C_COMMENT; |
1051 var nonMappingColon = indicator == C_MAPPING_VALUE && | 1051 var nonMappingColon = indicator == C_MAPPING_VALUE && |
1052 isPlainSafe(ctx, peek(1)); | 1052 isPlainSafe(ctx, peek(1)); |
1053 var match = safeChar || nonCommentHash || nonMappingColon; | 1053 var match = safeChar || nonCommentHash || nonMappingColon; |
1054 | 1054 |
1055 if (match) next(); | 1055 if (match) next(); |
1056 return match; | 1056 return match; |
1057 } | 1057 } |
1058 | 1058 |
1059 // 131 | 1059 // 131 |
1060 String ns_plain(int indent, int ctx) => context('plain scalar', () { | 1060 String ns_plain(int indent, int ctx) => context('plain scalar', () { |
1061 return captureString(() { | 1061 return captureString(() { |
1062 switch (ctx) { | 1062 switch (ctx) { |
1063 case FLOW_OUT: | 1063 case FLOW_OUT: |
1064 case FLOW_IN: | 1064 case FLOW_IN: |
1065 return ns_plainMultiLine(indent, ctx); | 1065 return ns_plainMultiLine(indent, ctx); |
1066 case BLOCK_KEY: | 1066 case BLOCK_KEY: |
1067 case FLOW_KEY: | 1067 case FLOW_KEY: |
1068 return ns_plainOneLine(ctx); | 1068 return ns_plainOneLine(ctx); |
1069 default: throw 'invalid context "$ctx"'; | 1069 default: throw 'Invalid context "$ctx".'; |
1070 } | 1070 } |
1071 }); | 1071 }); |
1072 }); | 1072 }); |
1073 | 1073 |
1074 // 132 | 1074 // 132 |
1075 void nb_ns_plainInLine(int ctx) { | 1075 void nb_ns_plainInLine(int ctx) { |
1076 zeroOrMore(() => transaction(() { | 1076 zeroOrMore(() => transaction(() { |
1077 zeroOrMore(() => consume(isSpace)); | 1077 zeroOrMore(() => consume(isSpace)); |
1078 return ns_plainChar(ctx); | 1078 return ns_plainChar(ctx); |
1079 })); | 1079 })); |
(...skipping 19 matching lines...) Expand all Loading... | |
1099 // 135 | 1099 // 135 |
1100 bool ns_plainMultiLine(int indent, int ctx) { | 1100 bool ns_plainMultiLine(int indent, int ctx) { |
1101 if (!truth(ns_plainOneLine(ctx))) return false; | 1101 if (!truth(ns_plainOneLine(ctx))) return false; |
1102 zeroOrMore(() => s_ns_plainNextLine(indent, ctx)); | 1102 zeroOrMore(() => s_ns_plainNextLine(indent, ctx)); |
1103 return true; | 1103 return true; |
1104 } | 1104 } |
1105 | 1105 |
1106 // 136 | 1106 // 136 |
1107 int inFlow(int ctx) { | 1107 int inFlow(int ctx) { |
1108 switch (ctx) { | 1108 switch (ctx) { |
1109 case FLOW_OUT: | 1109 case FLOW_OUT: |
1110 case FLOW_IN: | 1110 case FLOW_IN: |
1111 return FLOW_IN; | 1111 return FLOW_IN; |
1112 case BLOCK_KEY: | 1112 case BLOCK_KEY: |
1113 case FLOW_KEY: | 1113 case FLOW_KEY: |
1114 return FLOW_KEY; | 1114 return FLOW_KEY; |
1115 } | 1115 } |
1116 throw "unreachable"; | |
1116 } | 1117 } |
1117 | 1118 |
1118 // 137 | 1119 // 137 |
1119 SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { | 1120 SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { |
1120 if (!truth(c_indicator(C_SEQUENCE_START))) return null; | 1121 if (!truth(c_indicator(C_SEQUENCE_START))) return null; |
1121 zeroOrOne(() => s_separate(indent, ctx)); | 1122 zeroOrOne(() => s_separate(indent, ctx)); |
1122 var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); | 1123 var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); |
1123 if (!truth(c_indicator(C_SEQUENCE_END))) return null; | 1124 if (!truth(c_indicator(C_SEQUENCE_END))) return null; |
1124 return new SequenceNode("?", new List<Node>.from(content)); | 1125 return new SequenceNode("?", new List<Node>.from(content)); |
1125 }); | 1126 }); |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1427 // 165 | 1428 // 165 |
1428 bool b_chompedLast(int chomping) { | 1429 bool b_chompedLast(int chomping) { |
1429 if (atEndOfFile) return true; | 1430 if (atEndOfFile) return true; |
1430 switch (chomping) { | 1431 switch (chomping) { |
1431 case CHOMPING_STRIP: | 1432 case CHOMPING_STRIP: |
1432 return b_nonContent(); | 1433 return b_nonContent(); |
1433 case CHOMPING_CLIP: | 1434 case CHOMPING_CLIP: |
1434 case CHOMPING_KEEP: | 1435 case CHOMPING_KEEP: |
1435 return b_asLineFeed(); | 1436 return b_asLineFeed(); |
1436 } | 1437 } |
1438 throw "unreachable"; | |
1437 } | 1439 } |
1438 | 1440 |
1439 // 166 | 1441 // 166 |
1440 void l_chompedEmpty(int indent, int chomping) { | 1442 void l_chompedEmpty(int indent, int chomping) { |
1441 switch (chomping) { | 1443 switch (chomping) { |
1442 case CHOMPING_STRIP: | 1444 case CHOMPING_STRIP: |
1443 case CHOMPING_CLIP: | 1445 case CHOMPING_CLIP: |
1444 l_stripEmpty(indent); | 1446 l_stripEmpty(indent); |
1445 break; | 1447 break; |
1446 case CHOMPING_KEEP: | 1448 case CHOMPING_KEEP: |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1936 for (var pair in _contents.reversed) { | 1938 for (var pair in _contents.reversed) { |
1937 if (pair.first.contains(pos)) return pair.last; | 1939 if (pair.first.contains(pos)) return pair.last; |
1938 } | 1940 } |
1939 return null; | 1941 return null; |
1940 } | 1942 } |
1941 | 1943 |
1942 /// Associates [value] with [range]. | 1944 /// Associates [value] with [range]. |
1943 operator[]=(_Range range, E value) => | 1945 operator[]=(_Range range, E value) => |
1944 _contents.add(new _Pair<_Range, E>(range, value)); | 1946 _contents.add(new _Pair<_Range, E>(range, value)); |
1945 } | 1947 } |
OLD | NEW |