Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 yaml.scanner; | 5 library yaml.scanner; |
| 6 | 6 |
| 7 import 'package:collection/collection.dart'; | 7 import 'package:collection/collection.dart'; |
| 8 import 'package:string_scanner/string_scanner.dart'; | 8 import 'package:string_scanner/string_scanner.dart'; |
| 9 import 'package:source_span/source_span.dart'; | 9 import 'package:source_span/source_span.dart'; |
| 10 | 10 |
| (...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1077 _scanner.readChar(); | 1077 _scanner.readChar(); |
| 1078 char = _scanner.peekChar(); | 1078 char = _scanner.peekChar(); |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 // libyaml manually decodes the URL, but we don't have to do that. | 1081 // libyaml manually decodes the URL, but we don't have to do that. |
| 1082 return Uri.decodeFull(_scanner.substring(start)); | 1082 return Uri.decodeFull(_scanner.substring(start)); |
| 1083 } | 1083 } |
| 1084 | 1084 |
| 1085 /// Scans a block scalar. | 1085 /// Scans a block scalar. |
| 1086 Token _scanBlockScalar({bool literal: false}) { | 1086 Token _scanBlockScalar({bool literal: false}) { |
| 1087 print("scanning block scalar"); | |
|
Bob Nystrom
2014/12/12 01:47:37
Delete.
| |
| 1087 var start = _scanner.state; | 1088 var start = _scanner.state; |
| 1088 | 1089 |
| 1089 // Eat the indicator '|' or '>'. | 1090 // Eat the indicator '|' or '>'. |
| 1090 _scanner.readChar(); | 1091 _scanner.readChar(); |
| 1091 | 1092 |
| 1092 // Check for a chomping indicator. | 1093 // Check for a chomping indicator. |
| 1093 var chomping = _Chomping.CLIP; | 1094 var chomping = _Chomping.CLIP; |
| 1094 var increment = 0; | 1095 var increment = 0; |
| 1095 var char = _scanner.peekChar(); | 1096 var char = _scanner.peekChar(); |
| 1096 if (char == PLUS || char == HYPHEN) { | 1097 if (char == PLUS || char == HYPHEN) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1149 // needed. | 1150 // needed. |
| 1150 var pair = _scanBlockScalarBreaks(indent); | 1151 var pair = _scanBlockScalarBreaks(indent); |
| 1151 indent = pair.first; | 1152 indent = pair.first; |
| 1152 var trailingBreaks = pair.last; | 1153 var trailingBreaks = pair.last; |
| 1153 | 1154 |
| 1154 // Scan the block scalar contents. | 1155 // Scan the block scalar contents. |
| 1155 var buffer = new StringBuffer(); | 1156 var buffer = new StringBuffer(); |
| 1156 var leadingBreak = ''; | 1157 var leadingBreak = ''; |
| 1157 var leadingBlank = false; | 1158 var leadingBlank = false; |
| 1158 var trailingBlank = false; | 1159 var trailingBlank = false; |
| 1160 var end = _scanner.position; | |
| 1159 while (_scanner.column == indent && !_scanner.isDone) { | 1161 while (_scanner.column == indent && !_scanner.isDone) { |
| 1160 // Check for a document indicator. libyaml doesn't do this, but the spec | 1162 // Check for a document indicator. libyaml doesn't do this, but the spec |
| 1161 // mandates it. See example 9.5: | 1163 // mandates it. See example 9.5: |
| 1162 // http://yaml.org/spec/1.2/spec.html#id2801606. | 1164 // http://yaml.org/spec/1.2/spec.html#id2801606. |
| 1163 if (_isDocumentIndicator) break; | 1165 if (_isDocumentIndicator) break; |
| 1164 | 1166 |
| 1165 // We are at the beginning of a non-empty line. | 1167 // We are at the beginning of a non-empty line. |
| 1166 | 1168 |
| 1167 // Is there trailing whitespace? | 1169 // Is there trailing whitespace? |
| 1168 trailingBlank = _isBlank; | 1170 trailingBlank = _isBlank; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1181 buffer.write(trailingBreaks); | 1183 buffer.write(trailingBreaks); |
| 1182 | 1184 |
| 1183 // Is there leading whitespace? | 1185 // Is there leading whitespace? |
| 1184 leadingBlank = _isBlank; | 1186 leadingBlank = _isBlank; |
| 1185 | 1187 |
| 1186 var startPosition = _scanner.position; | 1188 var startPosition = _scanner.position; |
| 1187 while (!_isBreakOrEnd) { | 1189 while (!_isBreakOrEnd) { |
| 1188 _scanner.readChar(); | 1190 _scanner.readChar(); |
| 1189 } | 1191 } |
| 1190 buffer.write(_scanner.substring(startPosition)); | 1192 buffer.write(_scanner.substring(startPosition)); |
| 1193 end = _scanner.position; | |
| 1191 | 1194 |
| 1192 // libyaml always reads a line here, but this breaks on block scalars at | 1195 // libyaml always reads a line here, but this breaks on block scalars at |
| 1193 // the end of the document that end without newlines. See example 8.1: | 1196 // the end of the document that end without newlines. See example 8.1: |
| 1194 // http://yaml.org/spec/1.2/spec.html#id2793888. | 1197 // http://yaml.org/spec/1.2/spec.html#id2793888. |
| 1195 if (!_scanner.isDone) leadingBreak = _readLine(); | 1198 if (!_scanner.isDone) leadingBreak = _readLine(); |
| 1196 | 1199 |
| 1197 // Eat the following indentation and spaces. | 1200 // Eat the following indentation and spaces. |
| 1198 var pair = _scanBlockScalarBreaks(indent); | 1201 var pair = _scanBlockScalarBreaks(indent); |
| 1199 indent = pair.first; | 1202 indent = pair.first; |
| 1200 trailingBreaks = pair.last; | 1203 trailingBreaks = pair.last; |
| 1201 } | 1204 } |
| 1202 | 1205 |
| 1203 // Chomp the tail. | 1206 // Chomp the tail. |
| 1204 if (chomping != _Chomping.STRIP) buffer.write(leadingBreak); | 1207 if (chomping != _Chomping.STRIP) buffer.write(leadingBreak); |
| 1205 if (chomping == _Chomping.KEEP) buffer.write(trailingBreaks); | 1208 if (chomping == _Chomping.KEEP) buffer.write(trailingBreaks); |
| 1206 | 1209 |
| 1207 return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), | 1210 return new ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), |
| 1208 literal ? ScalarStyle.LITERAL : ScalarStyle.FOLDED); | 1211 literal ? ScalarStyle.LITERAL : ScalarStyle.FOLDED); |
| 1209 } | 1212 } |
| 1210 | 1213 |
| 1211 /// Scans indentation spaces and line breaks for a block scalar. | 1214 /// Scans indentation spaces and line breaks for a block scalar. |
| 1212 /// | 1215 /// |
| 1213 /// Determines the intendation level if needed. Returns the new indentation | 1216 /// Determines the intendation level if needed. Returns the new indentation |
| 1214 /// level and the text of the line breaks. | 1217 /// level and the text of the line breaks. |
| 1215 Pair<int, String> _scanBlockScalarBreaks(int indent) { | 1218 Pair<int, String> _scanBlockScalarBreaks(int indent) { |
| 1216 var maxIndent = 0; | 1219 var maxIndent = 0; |
| 1217 var breaks = new StringBuffer(); | 1220 var breaks = new StringBuffer(); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1423 // Eat the right quote. | 1426 // Eat the right quote. |
| 1424 _scanner.readChar(); | 1427 _scanner.readChar(); |
| 1425 | 1428 |
| 1426 return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), | 1429 return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), |
| 1427 singleQuote ? ScalarStyle.SINGLE_QUOTED : ScalarStyle.DOUBLE_QUOTED); | 1430 singleQuote ? ScalarStyle.SINGLE_QUOTED : ScalarStyle.DOUBLE_QUOTED); |
| 1428 } | 1431 } |
| 1429 | 1432 |
| 1430 /// Scans a plain scalar. | 1433 /// Scans a plain scalar. |
| 1431 Token _scanPlainScalar() { | 1434 Token _scanPlainScalar() { |
| 1432 var start = _scanner.state; | 1435 var start = _scanner.state; |
| 1436 var end = _scanner.state; | |
| 1433 var buffer = new StringBuffer(); | 1437 var buffer = new StringBuffer(); |
| 1434 var leadingBreak = ''; | 1438 var leadingBreak = ''; |
| 1435 var trailingBreaks = ''; | 1439 var trailingBreaks = ''; |
| 1436 var whitespace = new StringBuffer(); | 1440 var whitespace = new StringBuffer(); |
| 1437 var indent = _indent + 1; | 1441 var indent = _indent + 1; |
| 1438 | 1442 |
| 1439 while (true) { | 1443 while (true) { |
| 1440 // Check for a document indicator. | 1444 // Check for a document indicator. |
| 1441 if (_isDocumentIndicator) break; | 1445 if (_isDocumentIndicator) break; |
| 1442 | 1446 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1459 } | 1463 } |
| 1460 } | 1464 } |
| 1461 | 1465 |
| 1462 // libyaml's notion of valid identifiers differs substantially from YAML | 1466 // libyaml's notion of valid identifiers differs substantially from YAML |
| 1463 // 1.2's. We use [_isPlainChar] instead of libyaml's character here. | 1467 // 1.2's. We use [_isPlainChar] instead of libyaml's character here. |
| 1464 var startPosition = _scanner.position; | 1468 var startPosition = _scanner.position; |
| 1465 while (_isPlainChar) { | 1469 while (_isPlainChar) { |
| 1466 _scanner.readChar(); | 1470 _scanner.readChar(); |
| 1467 } | 1471 } |
| 1468 buffer.write(_scanner.substring(startPosition)); | 1472 buffer.write(_scanner.substring(startPosition)); |
| 1473 end = _scanner.state; | |
| 1469 | 1474 |
| 1470 // Is it the end? | 1475 // Is it the end? |
| 1471 if (!_isBlank && !_isBreak) break; | 1476 if (!_isBlank && !_isBreak) break; |
| 1472 | 1477 |
| 1473 while (_isBlank || _isBreak) { | 1478 while (_isBlank || _isBreak) { |
| 1474 if (_isBlank) { | 1479 if (_isBlank) { |
| 1475 // Check for a tab character messing up the intendation. | 1480 // Check for a tab character messing up the intendation. |
| 1476 if (leadingBreak.isNotEmpty && _scanner.column < indent && | 1481 if (leadingBreak.isNotEmpty && _scanner.column < indent && |
| 1477 _scanner.peekChar() == TAB) { | 1482 _scanner.peekChar() == TAB) { |
| 1478 _scanner.error("Expected a space but found a tab.", length: 1); | 1483 _scanner.error("Expected a space but found a tab.", length: 1); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1494 } | 1499 } |
| 1495 } | 1500 } |
| 1496 | 1501 |
| 1497 // Check the indentation level. | 1502 // Check the indentation level. |
| 1498 if (_inBlockContext && _scanner.column < indent) break; | 1503 if (_inBlockContext && _scanner.column < indent) break; |
| 1499 } | 1504 } |
| 1500 | 1505 |
| 1501 // Allow a simple key after a plain scalar with leading blanks. | 1506 // Allow a simple key after a plain scalar with leading blanks. |
| 1502 if (leadingBreak.isNotEmpty) _simpleKeyAllowed = true; | 1507 if (leadingBreak.isNotEmpty) _simpleKeyAllowed = true; |
| 1503 | 1508 |
| 1504 return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), | 1509 return new ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), |
| 1505 ScalarStyle.PLAIN); | 1510 ScalarStyle.PLAIN); |
| 1506 } | 1511 } |
| 1507 | 1512 |
| 1508 /// Moves past the current line break, if there is one. | 1513 /// Moves past the current line break, if there is one. |
| 1509 void _skipLine() { | 1514 void _skipLine() { |
| 1510 var char = _scanner.peekChar(); | 1515 var char = _scanner.peekChar(); |
| 1511 if (char != CR && char != LF) return; | 1516 if (char != CR && char != LF) return; |
| 1512 _scanner.readChar(); | 1517 _scanner.readChar(); |
| 1513 if (char == CR && _scanner.peekChar() == LF) _scanner.readChar(); | 1518 if (char == CR && _scanner.peekChar() == LF) _scanner.readChar(); |
| 1514 } | 1519 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1654 | 1659 |
| 1655 /// All trailing whitespace is preserved. | 1660 /// All trailing whitespace is preserved. |
| 1656 static const KEEP = const _Chomping("KEEP"); | 1661 static const KEEP = const _Chomping("KEEP"); |
| 1657 | 1662 |
| 1658 final String name; | 1663 final String name; |
| 1659 | 1664 |
| 1660 const _Chomping(this.name); | 1665 const _Chomping(this.name); |
| 1661 | 1666 |
| 1662 String toString() => name; | 1667 String toString() => name; |
| 1663 } | 1668 } |
| OLD | NEW |