Chromium Code Reviews| 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 |