| 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 part of yaml; | 5 library parser; |
| 6 |
| 7 import 'dart:collection'; |
| 8 |
| 9 import 'model.dart'; |
| 10 import 'yaml_exception.dart'; |
| 11 import 'yaml_map.dart'; |
| 6 | 12 |
| 7 /// Translates a string of characters into a YAML serialization tree. | 13 /// Translates a string of characters into a YAML serialization tree. |
| 8 /// | 14 /// |
| 9 /// 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 |
| 10 /// spec are numbered, and the corresponding methods in the parser have the same | 16 /// spec are numbered, and the corresponding methods in the parser have the same |
| 11 /// numbers. This is certainly not the most efficient way of parsing YAML, but | 17 /// numbers. This is certainly not the most efficient way of parsing YAML, but |
| 12 /// it is the easiest to write and read in the context of the spec. | 18 /// it is the easiest to write and read in the context of the spec. |
| 13 /// | 19 /// |
| 14 /// Methods corresponding to productions are also named as in the spec, | 20 /// Methods corresponding to productions are also named as in the spec, |
| 15 /// translating the name of the method (although not the annotation characters) | 21 /// translating the name of the method (although not the annotation characters) |
| 16 /// into camel-case for dart style.. For example, the spec has a production | 22 /// into camel-case for dart style.. For example, the spec has a production |
| 17 /// named `nb-ns-plain-in-line`, and the method implementing it is named | 23 /// named `nb-ns-plain-in-line`, and the method implementing it is named |
| 18 /// `nb_ns_plainInLine`. The exception to that rule is methods that just | 24 /// `nb_ns_plainInLine`. The exception to that rule is methods that just |
| 19 /// recognize character classes; these are named `is*`. | 25 /// recognize character classes; these are named `is*`. |
| 20 class _Parser { | 26 class Parser { |
| 21 static const TAB = 0x9; | 27 static const TAB = 0x9; |
| 22 static const LF = 0xA; | 28 static const LF = 0xA; |
| 23 static const CR = 0xD; | 29 static const CR = 0xD; |
| 24 static const SP = 0x20; | 30 static const SP = 0x20; |
| 25 static const TILDE = 0x7E; | 31 static const TILDE = 0x7E; |
| 26 static const NEL = 0x85; | 32 static const NEL = 0x85; |
| 27 static const PLUS = 0x2B; | 33 static const PLUS = 0x2B; |
| 28 static const HYPHEN = 0x2D; | 34 static const HYPHEN = 0x2D; |
| 29 static const QUESTION_MARK = 0x3F; | 35 static const QUESTION_MARK = 0x3F; |
| 30 static const COLON = 0x3A; | 36 static const COLON = 0x3A; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 static const FLOW_OUT = 2; | 110 static const FLOW_OUT = 2; |
| 105 static const FLOW_IN = 3; | 111 static const FLOW_IN = 3; |
| 106 static const BLOCK_KEY = 4; | 112 static const BLOCK_KEY = 4; |
| 107 static const FLOW_KEY = 5; | 113 static const FLOW_KEY = 5; |
| 108 | 114 |
| 109 static const CHOMPING_STRIP = 0; | 115 static const CHOMPING_STRIP = 0; |
| 110 static const CHOMPING_KEEP = 1; | 116 static const CHOMPING_KEEP = 1; |
| 111 static const CHOMPING_CLIP = 2; | 117 static const CHOMPING_CLIP = 2; |
| 112 | 118 |
| 113 /// The source string being parsed. | 119 /// The source string being parsed. |
| 114 final String s; | 120 final String _s; |
| 115 | 121 |
| 116 /// The current position in the source string. | 122 /// The current position in the source string. |
| 117 int pos = 0; | 123 int _pos = 0; |
| 118 | 124 |
| 119 /// The length of the string being parsed. | 125 /// The length of the string being parsed. |
| 120 final int len; | 126 final int _len; |
| 121 | 127 |
| 122 /// The current (0-based) line in the source string. | 128 /// The current (0-based) line in the source string. |
| 123 int line = 0; | 129 int _line = 0; |
| 124 | 130 |
| 125 /// The current (0-based) column in the source string. | 131 /// The current (0-based) column in the source string. |
| 126 int column = 0; | 132 int _column = 0; |
| 127 | 133 |
| 128 /// Whether we're parsing a bare document (that is, one that doesn't begin | 134 /// Whether we're parsing a bare document (that is, one that doesn't begin |
| 129 /// with `---`). Bare documents don't allow `%` immediately following | 135 /// with `---`). Bare documents don't allow `%` immediately following |
| 130 /// newlines. | 136 /// newlines. |
| 131 bool inBareDocument = false; | 137 bool _inBareDocument = false; |
| 132 | 138 |
| 133 /// The line number of the farthest position that has been parsed successfully | 139 /// The line number of the farthest position that has been parsed successfully |
| 134 /// before backtracking. Used for error reporting. | 140 /// before backtracking. Used for error reporting. |
| 135 int farthestLine = 0; | 141 int _farthestLine = 0; |
| 136 | 142 |
| 137 /// The column number of the farthest position that has been parsed | 143 /// The column number of the farthest position that has been parsed |
| 138 /// successfully before backtracking. Used for error reporting. | 144 /// successfully before backtracking. Used for error reporting. |
| 139 int farthestColumn = 0; | 145 int _farthestColumn = 0; |
| 140 | 146 |
| 141 /// The farthest position in the source string that has been parsed | 147 /// The farthest position in the source string that has been parsed |
| 142 /// successfully before backtracking. Used for error reporting. | 148 /// successfully before backtracking. Used for error reporting. |
| 143 int farthestPos = 0; | 149 int _farthestPos = 0; |
| 144 | 150 |
| 145 /// The name of the context of the farthest position that has been parsed | 151 /// The name of the context of the farthest position that has been parsed |
| 146 /// successfully before backtracking. Used for error reporting. | 152 /// successfully before backtracking. Used for error reporting. |
| 147 String farthestContext = "document"; | 153 String _farthestContext = "document"; |
| 148 | 154 |
| 149 /// A stack of the names of parse contexts. Used for error reporting. | 155 /// A stack of the names of parse contexts. Used for error reporting. |
| 150 List<String> contextStack; | 156 List<String> _contextStack; |
| 151 | 157 |
| 152 /// Annotations attached to ranges of the source string that add extra | 158 /// Annotations attached to ranges of the source string that add extra |
| 153 /// information to any errors that occur in the annotated range. | 159 /// information to any errors that occur in the annotated range. |
| 154 _RangeMap<String> errorAnnotations; | 160 _RangeMap<String> _errorAnnotations; |
| 155 | 161 |
| 156 /// The buffer containing the string currently being captured. | 162 /// The buffer containing the string currently being captured. |
| 157 StringBuffer capturedString; | 163 StringBuffer _capturedString; |
| 158 | 164 |
| 159 /// The beginning of the current section of the captured string. | 165 /// The beginning of the current section of the captured string. |
| 160 int captureStart; | 166 int _captureStart; |
| 161 | 167 |
| 162 /// Whether the current string capture is being overridden. | 168 /// Whether the current string capture is being overridden. |
| 163 bool capturingAs = false; | 169 bool _capturingAs = false; |
| 164 | 170 |
| 165 _Parser(String s) | 171 Parser(String s) |
| 166 : this.s = s, | 172 : this._s = s, |
| 167 len = s.length, | 173 _len = s.length, |
| 168 contextStack = <String>["document"], | 174 _contextStack = <String>["document"], |
| 169 errorAnnotations = new _RangeMap(); | 175 _errorAnnotations = new _RangeMap(); |
| 170 | 176 |
| 171 /// Return the character at the current position, then move that position | 177 /// Return the character at the current position, then move that position |
| 172 /// forward one character. Also updates the current line and column numbers. | 178 /// forward one character. Also updates the current line and column numbers. |
| 173 int next() { | 179 int next() { |
| 174 if (pos == len) return -1; | 180 if (_pos == _len) return -1; |
| 175 var char = s.codeUnitAt(pos++); | 181 var char = _s.codeUnitAt(_pos++); |
| 176 if (isBreak(char)) { | 182 if (isBreak(char)) { |
| 177 line++; | 183 _line++; |
| 178 column = 0; | 184 _column = 0; |
| 179 } else { | 185 } else { |
| 180 column++; | 186 _column++; |
| 181 } | 187 } |
| 182 | 188 |
| 183 if (farthestLine < line) { | 189 if (_farthestLine < _line) { |
| 184 farthestLine = line; | 190 _farthestLine = _line; |
| 185 farthestColumn = column; | 191 _farthestColumn = _column; |
| 186 farthestContext = contextStack.last; | 192 _farthestContext = _contextStack.last; |
| 187 } else if (farthestLine == line && farthestColumn < column) { | 193 } else if (_farthestLine == _line && _farthestColumn < _column) { |
| 188 farthestColumn = column; | 194 _farthestColumn = _column; |
| 189 farthestContext = contextStack.last; | 195 _farthestContext = _contextStack.last; |
| 190 } | 196 } |
| 191 farthestPos = pos; | 197 _farthestPos = _pos; |
| 192 | 198 |
| 193 return char; | 199 return char; |
| 194 } | 200 } |
| 195 | 201 |
| 196 /// Returns the code unit at the current position, or the character [i] | 202 /// Returns the code unit at the current position, or the character [i] |
| 197 /// characters after the current position. | 203 /// characters after the current position. |
| 198 /// | 204 /// |
| 199 /// Returns -1 if this would return a character after the end or before the | 205 /// Returns -1 if this would return a character after the end or before the |
| 200 /// beginning of the input string. | 206 /// beginning of the input string. |
| 201 int peek([int i = 0]) { | 207 int peek([int i = 0]) { |
| 202 var peekPos = pos + i; | 208 var peekPos = _pos + i; |
| 203 return (peekPos >= len || peekPos < 0) ? -1 : s.codeUnitAt(peekPos); | 209 return (peekPos >= _len || peekPos < 0) ? -1 : _s.codeUnitAt(peekPos); |
| 204 } | 210 } |
| 205 | 211 |
| 206 /// The truthiness operator. Returns `false` if [obj] is `null` or `false`, | 212 /// The truthiness operator. Returns `false` if [obj] is `null` or `false`, |
| 207 /// `true` otherwise. | 213 /// `true` otherwise. |
| 208 bool truth(obj) => obj != null && obj != false; | 214 bool truth(obj) => obj != null && obj != false; |
| 209 | 215 |
| 210 /// Consumes the current character if it matches [matcher]. Returns the result | 216 /// Consumes the current character if it matches [matcher]. Returns the result |
| 211 /// of [matcher]. | 217 /// of [matcher]. |
| 212 bool consume(bool matcher(int)) { | 218 bool consume(bool matcher(int)) { |
| 213 if (matcher(peek())) { | 219 if (matcher(peek())) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 236 return null; // Unreachable. | 242 return null; // Unreachable. |
| 237 } | 243 } |
| 238 | 244 |
| 239 /// Calls [consumer] until it returns a falsey value. Returns a list of all | 245 /// Calls [consumer] until it returns a falsey value. Returns a list of all |
| 240 /// truthy return values of [consumer], or the empty list if it didn't consume | 246 /// truthy return values of [consumer], or the empty list if it didn't consume |
| 241 /// anything. | 247 /// anything. |
| 242 /// | 248 /// |
| 243 /// Conceptually, repeats a production any number of times. | 249 /// Conceptually, repeats a production any number of times. |
| 244 List zeroOrMore(consumer()) { | 250 List zeroOrMore(consumer()) { |
| 245 var out = []; | 251 var out = []; |
| 246 var oldPos = pos; | 252 var oldPos = _pos; |
| 247 while (true) { | 253 while (true) { |
| 248 var el = consumer(); | 254 var el = consumer(); |
| 249 if (!truth(el) || oldPos == pos) return out; | 255 if (!truth(el) || oldPos == _pos) return out; |
| 250 oldPos = pos; | 256 oldPos = _pos; |
| 251 out.add(el); | 257 out.add(el); |
| 252 } | 258 } |
| 253 return null; // Unreachable. | 259 return null; // Unreachable. |
| 254 } | 260 } |
| 255 | 261 |
| 256 /// Just calls [consumer] and returns its result. Used to make it explicit | 262 /// Just calls [consumer] and returns its result. Used to make it explicit |
| 257 /// that a production is intended to be optional. | 263 /// that a production is intended to be optional. |
| 258 zeroOrOne(consumer()) => consumer(); | 264 zeroOrOne(consumer()) => consumer(); |
| 259 | 265 |
| 260 /// Calls each function in [consumers] until one returns a truthy value, then | 266 /// Calls each function in [consumers] until one returns a truthy value, then |
| 261 /// returns that. | 267 /// returns that. |
| 262 or(List<Function> consumers) { | 268 or(List<Function> consumers) { |
| 263 for (var c in consumers) { | 269 for (var c in consumers) { |
| 264 var res = c(); | 270 var res = c(); |
| 265 if (truth(res)) return res; | 271 if (truth(res)) return res; |
| 266 } | 272 } |
| 267 return null; | 273 return null; |
| 268 } | 274 } |
| 269 | 275 |
| 270 /// Calls [consumer] and returns its result, but rolls back the parser state | 276 /// Calls [consumer] and returns its result, but rolls back the parser state |
| 271 /// if [consumer] returns a falsey value. | 277 /// if [consumer] returns a falsey value. |
| 272 transaction(consumer()) { | 278 transaction(consumer()) { |
| 273 var oldPos = pos; | 279 var oldPos = _pos; |
| 274 var oldLine = line; | 280 var oldLine = _line; |
| 275 var oldColumn = column; | 281 var oldColumn = _column; |
| 276 var oldCaptureStart = captureStart; | 282 var oldCaptureStart = _captureStart; |
| 277 String capturedSoFar = capturedString == null ? null : | 283 String capturedSoFar = _capturedString == null ? null : |
| 278 capturedString.toString(); | 284 _capturedString.toString(); |
| 279 var res = consumer(); | 285 var res = consumer(); |
| 280 if (truth(res)) return res; | 286 if (truth(res)) return res; |
| 281 | 287 |
| 282 pos = oldPos; | 288 _pos = oldPos; |
| 283 line = oldLine; | 289 _line = oldLine; |
| 284 column = oldColumn; | 290 _column = oldColumn; |
| 285 captureStart = oldCaptureStart; | 291 _captureStart = oldCaptureStart; |
| 286 capturedString = capturedSoFar == null ? null : | 292 _capturedString = capturedSoFar == null ? null : |
| 287 new StringBuffer(capturedSoFar); | 293 new StringBuffer(capturedSoFar); |
| 288 return res; | 294 return res; |
| 289 } | 295 } |
| 290 | 296 |
| 291 /// Consumes [n] characters matching [matcher], or none if there isn't a | 297 /// Consumes [n] characters matching [matcher], or none if there isn't a |
| 292 /// complete match. The first argument to [matcher] is the character code, the | 298 /// complete match. The first argument to [matcher] is the character code, the |
| 293 /// second is the index (from 0 to [n] - 1). | 299 /// second is the index (from 0 to [n] - 1). |
| 294 /// | 300 /// |
| 295 /// Returns whether or not the characters were consumed. | 301 /// Returns whether or not the characters were consumed. |
| 296 bool nAtOnce(int n, bool matcher(int c, int i)) => transaction(() { | 302 bool nAtOnce(int n, bool matcher(int c, int i)) => transaction(() { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 309 /// Consumes and returns a string of characters matching [matcher], or null if | 315 /// Consumes and returns a string of characters matching [matcher], or null if |
| 310 /// there are no such characters. | 316 /// there are no such characters. |
| 311 String stringOf(bool matcher(int)) => | 317 String stringOf(bool matcher(int)) => |
| 312 captureString(() => oneOrMore(() => consume(matcher))); | 318 captureString(() => oneOrMore(() => consume(matcher))); |
| 313 | 319 |
| 314 /// Calls [consumer] and returns the string that was consumed while doing so, | 320 /// Calls [consumer] and returns the string that was consumed while doing so, |
| 315 /// or null if [consumer] returned a falsey value. Automatically wraps | 321 /// or null if [consumer] returned a falsey value. Automatically wraps |
| 316 /// [consumer] in `transaction`. | 322 /// [consumer] in `transaction`. |
| 317 String captureString(consumer()) { | 323 String captureString(consumer()) { |
| 318 // captureString calls may not be nested | 324 // captureString calls may not be nested |
| 319 assert(capturedString == null); | 325 assert(_capturedString == null); |
| 320 | 326 |
| 321 captureStart = pos; | 327 _captureStart = _pos; |
| 322 capturedString = new StringBuffer(); | 328 _capturedString = new StringBuffer(); |
| 323 var res = transaction(consumer); | 329 var res = transaction(consumer); |
| 324 if (!truth(res)) { | 330 if (!truth(res)) { |
| 325 captureStart = null; | 331 _captureStart = null; |
| 326 capturedString = null; | 332 _capturedString = null; |
| 327 return null; | 333 return null; |
| 328 } | 334 } |
| 329 | 335 |
| 330 flushCapture(); | 336 flushCapture(); |
| 331 var result = capturedString.toString(); | 337 var result = _capturedString.toString(); |
| 332 captureStart = null; | 338 _captureStart = null; |
| 333 capturedString = null; | 339 _capturedString = null; |
| 334 return result; | 340 return result; |
| 335 } | 341 } |
| 336 | 342 |
| 337 captureAs(String replacement, consumer()) => | 343 captureAs(String replacement, consumer()) => |
| 338 captureAndTransform(consumer, (_) => replacement); | 344 captureAndTransform(consumer, (_) => replacement); |
| 339 | 345 |
| 340 captureAndTransform(consumer(), String transformation(String captured)) { | 346 captureAndTransform(consumer(), String transformation(String captured)) { |
| 341 if (capturedString == null) return consumer(); | 347 if (_capturedString == null) return consumer(); |
| 342 if (capturingAs) return consumer(); | 348 if (_capturingAs) return consumer(); |
| 343 | 349 |
| 344 flushCapture(); | 350 flushCapture(); |
| 345 capturingAs = true; | 351 _capturingAs = true; |
| 346 var res = consumer(); | 352 var res = consumer(); |
| 347 capturingAs = false; | 353 _capturingAs = false; |
| 348 if (!truth(res)) return res; | 354 if (!truth(res)) return res; |
| 349 | 355 |
| 350 capturedString.write(transformation(s.substring(captureStart, pos))); | 356 _capturedString.write(transformation(_s.substring(_captureStart, _pos))); |
| 351 captureStart = pos; | 357 _captureStart = _pos; |
| 352 return res; | 358 return res; |
| 353 } | 359 } |
| 354 | 360 |
| 355 void flushCapture() { | 361 void flushCapture() { |
| 356 capturedString.write(s.substring(captureStart, pos)); | 362 _capturedString.write(_s.substring(_captureStart, _pos)); |
| 357 captureStart = pos; | 363 _captureStart = _pos; |
| 358 } | 364 } |
| 359 | 365 |
| 360 /// Adds a tag and an anchor to [node], if they're defined. | 366 /// Adds a tag and an anchor to [node], if they're defined. |
| 361 _Node addProps(_Node node, _Pair<_Tag, String> props) { | 367 Node addProps(Node node, _Pair<Tag, String> props) { |
| 362 if (props == null || node == null) return node; | 368 if (props == null || node == null) return node; |
| 363 if (truth(props.first)) node.tag = props.first; | 369 if (truth(props.first)) node.tag = props.first; |
| 364 if (truth(props.last)) node.anchor = props.last; | 370 if (truth(props.last)) node.anchor = props.last; |
| 365 return node; | 371 return node; |
| 366 } | 372 } |
| 367 | 373 |
| 368 /// Creates a MappingNode from [pairs]. | 374 /// Creates a MappingNode from [pairs]. |
| 369 _MappingNode map(List<_Pair<_Node, _Node>> pairs) { | 375 MappingNode map(List<_Pair<Node, Node>> pairs) { |
| 370 var content = new Map<_Node, _Node>(); | 376 var content = new Map<Node, Node>(); |
| 371 pairs.forEach((pair) => content[pair.first] = pair.last); | 377 pairs.forEach((pair) => content[pair.first] = pair.last); |
| 372 return new _MappingNode("?", content); | 378 return new MappingNode("?", content); |
| 373 } | 379 } |
| 374 | 380 |
| 375 /// Runs [fn] in a context named [name]. Used for error reporting. | 381 /// Runs [fn] in a context named [name]. Used for error reporting. |
| 376 context(String name, fn()) { | 382 context(String name, fn()) { |
| 377 try { | 383 try { |
| 378 contextStack.add(name); | 384 _contextStack.add(name); |
| 379 return fn(); | 385 return fn(); |
| 380 } finally { | 386 } finally { |
| 381 var popped = contextStack.removeLast(); | 387 var popped = _contextStack.removeLast(); |
| 382 assert(popped == name); | 388 assert(popped == name); |
| 383 } | 389 } |
| 384 } | 390 } |
| 385 | 391 |
| 386 /// Adds [message] as extra information to any errors that occur between the | 392 /// Adds [message] as extra information to any errors that occur between the |
| 387 /// current position and the position of the cursor after running [fn]. The | 393 /// current position and the position of the cursor after running [fn]. The |
| 388 /// cursor is reset after [fn] is run. | 394 /// cursor is reset after [fn] is run. |
| 389 annotateError(String message, fn()) { | 395 annotateError(String message, fn()) { |
| 390 var start = pos; | 396 var start = _pos; |
| 391 var end; | 397 var end; |
| 392 transaction(() { | 398 transaction(() { |
| 393 fn(); | 399 fn(); |
| 394 end = pos; | 400 end = _pos; |
| 395 return false; | 401 return false; |
| 396 }); | 402 }); |
| 397 errorAnnotations[new _Range(start, end)] = message; | 403 _errorAnnotations[new _Range(start, end)] = message; |
| 398 } | 404 } |
| 399 | 405 |
| 400 /// Throws an error with additional context information. | 406 /// Throws an error with additional context information. |
| 401 error(String message) { | 407 error(String message) { |
| 402 // Line and column should be one-based. | 408 // Line and column should be one-based. |
| 403 throw new SyntaxError(line + 1, column + 1, | 409 throw new SyntaxError(_line + 1, _column + 1, |
| 404 "$message (in $farthestContext)"); | 410 "$message (in $_farthestContext)"); |
| 405 } | 411 } |
| 406 | 412 |
| 407 /// If [result] is falsey, throws an error saying that [expected] was | 413 /// If [result] is falsey, throws an error saying that [expected] was |
| 408 /// expected. | 414 /// expected. |
| 409 expect(result, String expected) { | 415 expect(result, String expected) { |
| 410 if (truth(result)) return result; | 416 if (truth(result)) return result; |
| 411 error("expected $expected"); | 417 error("expected $expected"); |
| 412 } | 418 } |
| 413 | 419 |
| 414 /// Throws an error saying that the parse failed. Uses [farthestLine], | 420 /// Throws an error saying that the parse failed. Uses [_farthestLine], |
| 415 /// [farthestColumn], and [farthestContext] to provide additional information. | 421 /// [_farthestColumn], and [_farthestContext] to provide additional informatio
n. |
| 416 parseFailed() { | 422 parseFailed() { |
| 417 var message = "invalid YAML in $farthestContext"; | 423 var message = "invalid YAML in $_farthestContext"; |
| 418 var extraError = errorAnnotations[farthestPos]; | 424 var extraError = _errorAnnotations[_farthestPos]; |
| 419 if (extraError != null) message = "$message ($extraError)"; | 425 if (extraError != null) message = "$message ($extraError)"; |
| 420 throw new SyntaxError(farthestLine + 1, farthestColumn + 1, message); | 426 throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, message); |
| 421 } | 427 } |
| 422 | 428 |
| 423 /// Returns the number of spaces after the current position. | 429 /// Returns the number of spaces after the current position. |
| 424 int countIndentation() { | 430 int countIndentation() { |
| 425 var i = 0; | 431 var i = 0; |
| 426 while (peek(i) == SP) i++; | 432 while (peek(i) == SP) i++; |
| 427 return i; | 433 return i; |
| 428 } | 434 } |
| 429 | 435 |
| 430 /// Returns the indentation for a block scalar. | 436 /// Returns the indentation for a block scalar. |
| 431 int blockScalarAdditionalIndentation(_BlockHeader header, int indent) { | 437 int blockScalarAdditionalIndentation(_BlockHeader header, int indent) { |
| 432 if (!header.autoDetectIndent) return header.additionalIndent; | 438 if (!header.autoDetectIndent) return header.additionalIndent; |
| 433 | 439 |
| 434 var maxSpaces = 0; | 440 var maxSpaces = 0; |
| 435 var maxSpacesLine = 0; | 441 var maxSpacesLine = 0; |
| 436 var spaces = 0; | 442 var spaces = 0; |
| 437 transaction(() { | 443 transaction(() { |
| 438 do { | 444 do { |
| 439 spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length; | 445 spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length; |
| 440 if (spaces > maxSpaces) { | 446 if (spaces > maxSpaces) { |
| 441 maxSpaces = spaces; | 447 maxSpaces = spaces; |
| 442 maxSpacesLine = line; | 448 maxSpacesLine = _line; |
| 443 } | 449 } |
| 444 } while (b_break()); | 450 } while (b_break()); |
| 445 return false; | 451 return false; |
| 446 }); | 452 }); |
| 447 | 453 |
| 448 // If the next non-empty line isn't indented further than the start of the | 454 // If the next non-empty line isn't indented further than the start of the |
| 449 // block scalar, that means the scalar is going to be empty. Returning any | 455 // block scalar, that means the scalar is going to be empty. Returning any |
| 450 // value > 0 will cause the parser not to consume any text. | 456 // value > 0 will cause the parser not to consume any text. |
| 451 if (spaces <= indent) return 1; | 457 if (spaces <= indent) return 1; |
| 452 | 458 |
| 453 // It's an error for a leading empty line to be indented more than the first | 459 // It's an error for a leading empty line to be indented more than the first |
| 454 // non-empty line. | 460 // non-empty line. |
| 455 if (maxSpaces > spaces) { | 461 if (maxSpaces > spaces) { |
| 456 throw new SyntaxError(maxSpacesLine + 1, maxSpaces, | 462 throw new SyntaxError(maxSpacesLine + 1, maxSpaces, |
| 457 "Leading empty lines may not be indented more than the first " | 463 "Leading empty lines may not be indented more than the first " |
| 458 "non-empty line."); | 464 "non-empty line."); |
| 459 } | 465 } |
| 460 | 466 |
| 461 return spaces - indent; | 467 return spaces - indent; |
| 462 } | 468 } |
| 463 | 469 |
| 464 /// Returns whether the current position is at the beginning of a line. | 470 /// Returns whether the current position is at the beginning of a line. |
| 465 bool get atStartOfLine => column == 0; | 471 bool get atStartOfLine => _column == 0; |
| 466 | 472 |
| 467 /// Returns whether the current position is at the end of the input. | 473 /// Returns whether the current position is at the end of the input. |
| 468 bool get atEndOfFile => pos == len; | 474 bool get atEndOfFile => _pos == _len; |
| 469 | 475 |
| 470 /// Given an indicator character, returns the type of that indicator (or null | 476 /// Given an indicator character, returns the type of that indicator (or null |
| 471 /// if the indicator isn't found. | 477 /// if the indicator isn't found. |
| 472 int indicatorType(int char) { | 478 int indicatorType(int char) { |
| 473 switch (char) { | 479 switch (char) { |
| 474 case HYPHEN: return C_SEQUENCE_ENTRY; | 480 case HYPHEN: return C_SEQUENCE_ENTRY; |
| 475 case QUESTION_MARK: return C_MAPPING_KEY; | 481 case QUESTION_MARK: return C_MAPPING_KEY; |
| 476 case COLON: return C_MAPPING_VALUE; | 482 case COLON: return C_MAPPING_VALUE; |
| 477 case COMMA: return C_COLLECT_ENTRY; | 483 case COMMA: return C_COLLECT_ENTRY; |
| 478 case LEFT_BRACKET: return C_SEQUENCE_START; | 484 case LEFT_BRACKET: return C_SEQUENCE_START; |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 789 // 81 | 795 // 81 |
| 790 bool s_separateLines(int indent) { | 796 bool s_separateLines(int indent) { |
| 791 return transaction(() => s_l_comments() && s_flowLinePrefix(indent)) || | 797 return transaction(() => s_l_comments() && s_flowLinePrefix(indent)) || |
| 792 s_separateInLine(); | 798 s_separateInLine(); |
| 793 } | 799 } |
| 794 | 800 |
| 795 // 82 | 801 // 82 |
| 796 bool l_directive() => false; // TODO(nweiz): implement | 802 bool l_directive() => false; // TODO(nweiz): implement |
| 797 | 803 |
| 798 // 96 | 804 // 96 |
| 799 _Pair<_Tag, String> c_ns_properties(int indent, int ctx) { | 805 _Pair<Tag, String> c_ns_properties(int indent, int ctx) { |
| 800 var tag, anchor; | 806 var tag, anchor; |
| 801 tag = c_ns_tagProperty(); | 807 tag = c_ns_tagProperty(); |
| 802 if (truth(tag)) { | 808 if (truth(tag)) { |
| 803 anchor = transaction(() { | 809 anchor = transaction(() { |
| 804 if (!truth(s_separate(indent, ctx))) return null; | 810 if (!truth(s_separate(indent, ctx))) return null; |
| 805 return c_ns_anchorProperty(); | 811 return c_ns_anchorProperty(); |
| 806 }); | 812 }); |
| 807 return new _Pair<_Tag, String>(tag, anchor); | 813 return new _Pair<Tag, String>(tag, anchor); |
| 808 } | 814 } |
| 809 | 815 |
| 810 anchor = c_ns_anchorProperty(); | 816 anchor = c_ns_anchorProperty(); |
| 811 if (truth(anchor)) { | 817 if (truth(anchor)) { |
| 812 tag = transaction(() { | 818 tag = transaction(() { |
| 813 if (!truth(s_separate(indent, ctx))) return null; | 819 if (!truth(s_separate(indent, ctx))) return null; |
| 814 return c_ns_tagProperty(); | 820 return c_ns_tagProperty(); |
| 815 }); | 821 }); |
| 816 return new _Pair<_Tag, String>(tag, anchor); | 822 return new _Pair<Tag, String>(tag, anchor); |
| 817 } | 823 } |
| 818 | 824 |
| 819 return null; | 825 return null; |
| 820 } | 826 } |
| 821 | 827 |
| 822 // 97 | 828 // 97 |
| 823 _Tag c_ns_tagProperty() => null; // TODO(nweiz): implement | 829 Tag c_ns_tagProperty() => null; // TODO(nweiz): implement |
| 824 | 830 |
| 825 // 101 | 831 // 101 |
| 826 String c_ns_anchorProperty() => null; // TODO(nweiz): implement | 832 String c_ns_anchorProperty() => null; // TODO(nweiz): implement |
| 827 | 833 |
| 828 // 102 | 834 // 102 |
| 829 bool isAnchorChar(int char) => isNonSpace(char) && !isFlowIndicator(char); | 835 bool isAnchorChar(int char) => isNonSpace(char) && !isFlowIndicator(char); |
| 830 | 836 |
| 831 // 103 | 837 // 103 |
| 832 String ns_anchorName() => | 838 String ns_anchorName() => |
| 833 captureString(() => oneOrMore(() => consume(isAnchorChar))); | 839 captureString(() => oneOrMore(() => consume(isAnchorChar))); |
| 834 | 840 |
| 835 // 104 | 841 // 104 |
| 836 _Node c_ns_aliasNode() { | 842 Node c_ns_aliasNode() { |
| 837 if (!truth(c_indicator(C_ALIAS))) return null; | 843 if (!truth(c_indicator(C_ALIAS))) return null; |
| 838 var name = expect(ns_anchorName(), 'anchor name'); | 844 var name = expect(ns_anchorName(), 'anchor name'); |
| 839 return new _AliasNode(name); | 845 return new AliasNode(name); |
| 840 } | 846 } |
| 841 | 847 |
| 842 // 105 | 848 // 105 |
| 843 _ScalarNode e_scalar() => new _ScalarNode("?", content: ""); | 849 ScalarNode e_scalar() => new ScalarNode("?", content: ""); |
| 844 | 850 |
| 845 // 106 | 851 // 106 |
| 846 _ScalarNode e_node() => e_scalar(); | 852 ScalarNode e_node() => e_scalar(); |
| 847 | 853 |
| 848 // 107 | 854 // 107 |
| 849 bool nb_doubleChar() => or([ | 855 bool nb_doubleChar() => or([ |
| 850 c_ns_escChar, | 856 c_ns_escChar, |
| 851 () => consume((c) => isJson(c) && c != BACKSLASH && c != DOUBLE_QUOTE) | 857 () => consume((c) => isJson(c) && c != BACKSLASH && c != DOUBLE_QUOTE) |
| 852 ]); | 858 ]); |
| 853 | 859 |
| 854 // 108 | 860 // 108 |
| 855 bool ns_doubleChar() => !isSpace(peek()) && truth(nb_doubleChar()); | 861 bool ns_doubleChar() => !isSpace(peek()) && truth(nb_doubleChar()); |
| 856 | 862 |
| 857 // 109 | 863 // 109 |
| 858 _Node c_doubleQuoted(int indent, int ctx) => context('string', () { | 864 Node c_doubleQuoted(int indent, int ctx) => context('string', () { |
| 859 return transaction(() { | 865 return transaction(() { |
| 860 if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; | 866 if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; |
| 861 var contents = nb_doubleText(indent, ctx); | 867 var contents = nb_doubleText(indent, ctx); |
| 862 if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; | 868 if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; |
| 863 return new _ScalarNode("!", content: contents); | 869 return new ScalarNode("!", content: contents); |
| 864 }); | 870 }); |
| 865 }); | 871 }); |
| 866 | 872 |
| 867 // 110 | 873 // 110 |
| 868 String nb_doubleText(int indent, int ctx) => captureString(() { | 874 String nb_doubleText(int indent, int ctx) => captureString(() { |
| 869 switch (ctx) { | 875 switch (ctx) { |
| 870 case FLOW_OUT: | 876 case FLOW_OUT: |
| 871 case FLOW_IN: | 877 case FLOW_IN: |
| 872 nb_doubleMultiLine(indent); | 878 nb_doubleMultiLine(indent); |
| 873 break; | 879 break; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 // 118 | 942 // 118 |
| 937 bool nb_singleChar() => or([ | 943 bool nb_singleChar() => or([ |
| 938 c_quotedQuote, | 944 c_quotedQuote, |
| 939 () => consume((c) => isJson(c) && c != SINGLE_QUOTE) | 945 () => consume((c) => isJson(c) && c != SINGLE_QUOTE) |
| 940 ]); | 946 ]); |
| 941 | 947 |
| 942 // 119 | 948 // 119 |
| 943 bool ns_singleChar() => !isSpace(peek()) && truth(nb_singleChar()); | 949 bool ns_singleChar() => !isSpace(peek()) && truth(nb_singleChar()); |
| 944 | 950 |
| 945 // 120 | 951 // 120 |
| 946 _Node c_singleQuoted(int indent, int ctx) => context('string', () { | 952 Node c_singleQuoted(int indent, int ctx) => context('string', () { |
| 947 return transaction(() { | 953 return transaction(() { |
| 948 if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; | 954 if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; |
| 949 var contents = nb_singleText(indent, ctx); | 955 var contents = nb_singleText(indent, ctx); |
| 950 if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; | 956 if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; |
| 951 return new _ScalarNode("!", content: contents); | 957 return new ScalarNode("!", content: contents); |
| 952 }); | 958 }); |
| 953 }); | 959 }); |
| 954 | 960 |
| 955 // 121 | 961 // 121 |
| 956 String nb_singleText(int indent, int ctx) => captureString(() { | 962 String nb_singleText(int indent, int ctx) => captureString(() { |
| 957 switch (ctx) { | 963 switch (ctx) { |
| 958 case FLOW_OUT: | 964 case FLOW_OUT: |
| 959 case FLOW_IN: | 965 case FLOW_IN: |
| 960 nb_singleMultiLine(indent); | 966 nb_singleMultiLine(indent); |
| 961 break; | 967 break; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 case FLOW_OUT: | 1109 case FLOW_OUT: |
| 1104 case FLOW_IN: | 1110 case FLOW_IN: |
| 1105 return FLOW_IN; | 1111 return FLOW_IN; |
| 1106 case BLOCK_KEY: | 1112 case BLOCK_KEY: |
| 1107 case FLOW_KEY: | 1113 case FLOW_KEY: |
| 1108 return FLOW_KEY; | 1114 return FLOW_KEY; |
| 1109 } | 1115 } |
| 1110 } | 1116 } |
| 1111 | 1117 |
| 1112 // 137 | 1118 // 137 |
| 1113 _SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { | 1119 SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { |
| 1114 if (!truth(c_indicator(C_SEQUENCE_START))) return null; | 1120 if (!truth(c_indicator(C_SEQUENCE_START))) return null; |
| 1115 zeroOrOne(() => s_separate(indent, ctx)); | 1121 zeroOrOne(() => s_separate(indent, ctx)); |
| 1116 var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); | 1122 var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); |
| 1117 if (!truth(c_indicator(C_SEQUENCE_END))) return null; | 1123 if (!truth(c_indicator(C_SEQUENCE_END))) return null; |
| 1118 return new _SequenceNode("?", new List<_Node>.from(content)); | 1124 return new SequenceNode("?", new List<Node>.from(content)); |
| 1119 }); | 1125 }); |
| 1120 | 1126 |
| 1121 // 138 | 1127 // 138 |
| 1122 Iterable<_Node> ns_s_flowSeqEntries(int indent, int ctx) { | 1128 Iterable<Node> ns_s_flowSeqEntries(int indent, int ctx) { |
| 1123 var first = ns_flowSeqEntry(indent, ctx); | 1129 var first = ns_flowSeqEntry(indent, ctx); |
| 1124 if (!truth(first)) return new Queue<_Node>(); | 1130 if (!truth(first)) return new Queue<Node>(); |
| 1125 zeroOrOne(() => s_separate(indent, ctx)); | 1131 zeroOrOne(() => s_separate(indent, ctx)); |
| 1126 | 1132 |
| 1127 var rest; | 1133 var rest; |
| 1128 if (truth(c_indicator(C_COLLECT_ENTRY))) { | 1134 if (truth(c_indicator(C_COLLECT_ENTRY))) { |
| 1129 zeroOrOne(() => s_separate(indent, ctx)); | 1135 zeroOrOne(() => s_separate(indent, ctx)); |
| 1130 rest = zeroOrOne(() => ns_s_flowSeqEntries(indent, ctx)); | 1136 rest = zeroOrOne(() => ns_s_flowSeqEntries(indent, ctx)); |
| 1131 } | 1137 } |
| 1132 | 1138 |
| 1133 if (rest == null) rest = new Queue<_Node>(); | 1139 if (rest == null) rest = new Queue<Node>(); |
| 1134 rest.addFirst(first); | 1140 rest.addFirst(first); |
| 1135 | 1141 |
| 1136 return rest; | 1142 return rest; |
| 1137 } | 1143 } |
| 1138 | 1144 |
| 1139 // 139 | 1145 // 139 |
| 1140 _Node ns_flowSeqEntry(int indent, int ctx) => or([ | 1146 Node ns_flowSeqEntry(int indent, int ctx) => or([ |
| 1141 () => ns_flowPair(indent, ctx), | 1147 () => ns_flowPair(indent, ctx), |
| 1142 () => ns_flowNode(indent, ctx) | 1148 () => ns_flowNode(indent, ctx) |
| 1143 ]); | 1149 ]); |
| 1144 | 1150 |
| 1145 // 140 | 1151 // 140 |
| 1146 _Node c_flowMapping(int indent, int ctx) { | 1152 Node c_flowMapping(int indent, int ctx) { |
| 1147 if (!truth(c_indicator(C_MAPPING_START))) return null; | 1153 if (!truth(c_indicator(C_MAPPING_START))) return null; |
| 1148 zeroOrOne(() => s_separate(indent, ctx)); | 1154 zeroOrOne(() => s_separate(indent, ctx)); |
| 1149 var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx))); | 1155 var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx))); |
| 1150 if (!truth(c_indicator(C_MAPPING_END))) return null; | 1156 if (!truth(c_indicator(C_MAPPING_END))) return null; |
| 1151 return new _MappingNode("?", content); | 1157 return new MappingNode("?", content); |
| 1152 } | 1158 } |
| 1153 | 1159 |
| 1154 // 141 | 1160 // 141 |
| 1155 YamlMap ns_s_flowMapEntries(int indent, int ctx) { | 1161 YamlMap ns_s_flowMapEntries(int indent, int ctx) { |
| 1156 var first = ns_flowMapEntry(indent, ctx); | 1162 var first = ns_flowMapEntry(indent, ctx); |
| 1157 if (!truth(first)) return new YamlMap(); | 1163 if (!truth(first)) return new YamlMap(); |
| 1158 zeroOrOne(() => s_separate(indent, ctx)); | 1164 zeroOrOne(() => s_separate(indent, ctx)); |
| 1159 | 1165 |
| 1160 var rest; | 1166 var rest; |
| 1161 if (truth(c_indicator(C_COLLECT_ENTRY))) { | 1167 if (truth(c_indicator(C_COLLECT_ENTRY))) { |
| 1162 zeroOrOne(() => s_separate(indent, ctx)); | 1168 zeroOrOne(() => s_separate(indent, ctx)); |
| 1163 rest = ns_s_flowMapEntries(indent, ctx); | 1169 rest = ns_s_flowMapEntries(indent, ctx); |
| 1164 } | 1170 } |
| 1165 | 1171 |
| 1166 if (rest == null) rest = new YamlMap(); | 1172 if (rest == null) rest = new YamlMap(); |
| 1167 | 1173 |
| 1168 // TODO(nweiz): Duplicate keys should be an error. This includes keys with | 1174 // TODO(nweiz): Duplicate keys should be an error. This includes keys with |
| 1169 // different representations but the same value (e.g. 10 vs 0xa). To make | 1175 // different representations but the same value (e.g. 10 vs 0xa). To make |
| 1170 // this user-friendly we'll probably also want to associate nodes with a | 1176 // this user-friendly we'll probably also want to associate nodes with a |
| 1171 // source range. | 1177 // source range. |
| 1172 if (!rest.containsKey(first.first)) rest[first.first] = first.last; | 1178 if (!rest.containsKey(first.first)) rest[first.first] = first.last; |
| 1173 | 1179 |
| 1174 return rest; | 1180 return rest; |
| 1175 } | 1181 } |
| 1176 | 1182 |
| 1177 // 142 | 1183 // 142 |
| 1178 _Pair<_Node, _Node> ns_flowMapEntry(int indent, int ctx) => or([ | 1184 _Pair<Node, Node> ns_flowMapEntry(int indent, int ctx) => or([ |
| 1179 () => transaction(() { | 1185 () => transaction(() { |
| 1180 if (!truth(c_indicator(C_MAPPING_KEY))) return false; | 1186 if (!truth(c_indicator(C_MAPPING_KEY))) return false; |
| 1181 if (!truth(s_separate(indent, ctx))) return false; | 1187 if (!truth(s_separate(indent, ctx))) return false; |
| 1182 return ns_flowMapExplicitEntry(indent, ctx); | 1188 return ns_flowMapExplicitEntry(indent, ctx); |
| 1183 }), | 1189 }), |
| 1184 () => ns_flowMapImplicitEntry(indent, ctx) | 1190 () => ns_flowMapImplicitEntry(indent, ctx) |
| 1185 ]); | 1191 ]); |
| 1186 | 1192 |
| 1187 // 143 | 1193 // 143 |
| 1188 _Pair<_Node, _Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([ | 1194 _Pair<Node, Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([ |
| 1189 () => ns_flowMapImplicitEntry(indent, ctx), | 1195 () => ns_flowMapImplicitEntry(indent, ctx), |
| 1190 () => new _Pair<_Node, _Node>(e_node(), e_node()) | 1196 () => new _Pair<Node, Node>(e_node(), e_node()) |
| 1191 ]); | 1197 ]); |
| 1192 | 1198 |
| 1193 // 144 | 1199 // 144 |
| 1194 _Pair<_Node, _Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([ | 1200 _Pair<Node, Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([ |
| 1195 () => ns_flowMapYamlKeyEntry(indent, ctx), | 1201 () => ns_flowMapYamlKeyEntry(indent, ctx), |
| 1196 () => c_ns_flowMapEmptyKeyEntry(indent, ctx), | 1202 () => c_ns_flowMapEmptyKeyEntry(indent, ctx), |
| 1197 () => c_ns_flowMapJsonKeyEntry(indent, ctx) | 1203 () => c_ns_flowMapJsonKeyEntry(indent, ctx) |
| 1198 ]); | 1204 ]); |
| 1199 | 1205 |
| 1200 // 145 | 1206 // 145 |
| 1201 _Pair<_Node, _Node> ns_flowMapYamlKeyEntry(int indent, int ctx) { | 1207 _Pair<Node, Node> ns_flowMapYamlKeyEntry(int indent, int ctx) { |
| 1202 var key = ns_flowYamlNode(indent, ctx); | 1208 var key = ns_flowYamlNode(indent, ctx); |
| 1203 if (!truth(key)) return null; | 1209 if (!truth(key)) return null; |
| 1204 var value = or([ | 1210 var value = or([ |
| 1205 () => transaction(() { | 1211 () => transaction(() { |
| 1206 zeroOrOne(() => s_separate(indent, ctx)); | 1212 zeroOrOne(() => s_separate(indent, ctx)); |
| 1207 return c_ns_flowMapSeparateValue(indent, ctx); | 1213 return c_ns_flowMapSeparateValue(indent, ctx); |
| 1208 }), | 1214 }), |
| 1209 e_node | 1215 e_node |
| 1210 ]); | 1216 ]); |
| 1211 return new _Pair<_Node, _Node>(key, value); | 1217 return new _Pair<Node, Node>(key, value); |
| 1212 } | 1218 } |
| 1213 | 1219 |
| 1214 // 146 | 1220 // 146 |
| 1215 _Pair<_Node, _Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { | 1221 _Pair<Node, Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { |
| 1216 var value = c_ns_flowMapSeparateValue(indent, ctx); | 1222 var value = c_ns_flowMapSeparateValue(indent, ctx); |
| 1217 if (!truth(value)) return null; | 1223 if (!truth(value)) return null; |
| 1218 return new _Pair<_Node, _Node>(e_node(), value); | 1224 return new _Pair<Node, Node>(e_node(), value); |
| 1219 } | 1225 } |
| 1220 | 1226 |
| 1221 // 147 | 1227 // 147 |
| 1222 _Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() { | 1228 Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() { |
| 1223 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; | 1229 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; |
| 1224 if (isPlainSafe(ctx, peek())) return null; | 1230 if (isPlainSafe(ctx, peek())) return null; |
| 1225 | 1231 |
| 1226 return or([ | 1232 return or([ |
| 1227 () => transaction(() { | 1233 () => transaction(() { |
| 1228 if (!s_separate(indent, ctx)) return null; | 1234 if (!s_separate(indent, ctx)) return null; |
| 1229 return ns_flowNode(indent, ctx); | 1235 return ns_flowNode(indent, ctx); |
| 1230 }), | 1236 }), |
| 1231 e_node | 1237 e_node |
| 1232 ]); | 1238 ]); |
| 1233 }); | 1239 }); |
| 1234 | 1240 |
| 1235 // 148 | 1241 // 148 |
| 1236 _Pair<_Node, _Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) { | 1242 _Pair<Node, Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) { |
| 1237 var key = c_flowJsonNode(indent, ctx); | 1243 var key = c_flowJsonNode(indent, ctx); |
| 1238 if (!truth(key)) return null; | 1244 if (!truth(key)) return null; |
| 1239 var value = or([ | 1245 var value = or([ |
| 1240 () => transaction(() { | 1246 () => transaction(() { |
| 1241 zeroOrOne(() => s_separate(indent, ctx)); | 1247 zeroOrOne(() => s_separate(indent, ctx)); |
| 1242 return c_ns_flowMapAdjacentValue(indent, ctx); | 1248 return c_ns_flowMapAdjacentValue(indent, ctx); |
| 1243 }), | 1249 }), |
| 1244 e_node | 1250 e_node |
| 1245 ]); | 1251 ]); |
| 1246 return new _Pair<_Node, _Node>(key, value); | 1252 return new _Pair<Node, Node>(key, value); |
| 1247 } | 1253 } |
| 1248 | 1254 |
| 1249 // 149 | 1255 // 149 |
| 1250 _Node c_ns_flowMapAdjacentValue(int indent, int ctx) { | 1256 Node c_ns_flowMapAdjacentValue(int indent, int ctx) { |
| 1251 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; | 1257 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; |
| 1252 return or([ | 1258 return or([ |
| 1253 () => transaction(() { | 1259 () => transaction(() { |
| 1254 zeroOrOne(() => s_separate(indent, ctx)); | 1260 zeroOrOne(() => s_separate(indent, ctx)); |
| 1255 return ns_flowNode(indent, ctx); | 1261 return ns_flowNode(indent, ctx); |
| 1256 }), | 1262 }), |
| 1257 e_node | 1263 e_node |
| 1258 ]); | 1264 ]); |
| 1259 } | 1265 } |
| 1260 | 1266 |
| 1261 // 150 | 1267 // 150 |
| 1262 _Node ns_flowPair(int indent, int ctx) { | 1268 Node ns_flowPair(int indent, int ctx) { |
| 1263 var pair = or([ | 1269 var pair = or([ |
| 1264 () => transaction(() { | 1270 () => transaction(() { |
| 1265 if (!truth(c_indicator(C_MAPPING_KEY))) return null; | 1271 if (!truth(c_indicator(C_MAPPING_KEY))) return null; |
| 1266 if (!truth(s_separate(indent, ctx))) return null; | 1272 if (!truth(s_separate(indent, ctx))) return null; |
| 1267 return ns_flowMapExplicitEntry(indent, ctx); | 1273 return ns_flowMapExplicitEntry(indent, ctx); |
| 1268 }), | 1274 }), |
| 1269 () => ns_flowPairEntry(indent, ctx) | 1275 () => ns_flowPairEntry(indent, ctx) |
| 1270 ]); | 1276 ]); |
| 1271 if (!truth(pair)) return null; | 1277 if (!truth(pair)) return null; |
| 1272 | 1278 |
| 1273 return map([pair]); | 1279 return map([pair]); |
| 1274 } | 1280 } |
| 1275 | 1281 |
| 1276 // 151 | 1282 // 151 |
| 1277 _Pair<_Node, _Node> ns_flowPairEntry(int indent, int ctx) => or([ | 1283 _Pair<Node, Node> ns_flowPairEntry(int indent, int ctx) => or([ |
| 1278 () => ns_flowPairYamlKeyEntry(indent, ctx), | 1284 () => ns_flowPairYamlKeyEntry(indent, ctx), |
| 1279 () => c_ns_flowMapEmptyKeyEntry(indent, ctx), | 1285 () => c_ns_flowMapEmptyKeyEntry(indent, ctx), |
| 1280 () => c_ns_flowPairJsonKeyEntry(indent, ctx) | 1286 () => c_ns_flowPairJsonKeyEntry(indent, ctx) |
| 1281 ]); | 1287 ]); |
| 1282 | 1288 |
| 1283 // 152 | 1289 // 152 |
| 1284 _Pair<_Node, _Node> ns_flowPairYamlKeyEntry(int indent, int ctx) => | 1290 _Pair<Node, Node> ns_flowPairYamlKeyEntry(int indent, int ctx) => |
| 1285 transaction(() { | 1291 transaction(() { |
| 1286 var key = ns_s_implicitYamlKey(FLOW_KEY); | 1292 var key = ns_s_implicitYamlKey(FLOW_KEY); |
| 1287 if (!truth(key)) return null; | 1293 if (!truth(key)) return null; |
| 1288 var value = c_ns_flowMapSeparateValue(indent, ctx); | 1294 var value = c_ns_flowMapSeparateValue(indent, ctx); |
| 1289 if (!truth(value)) return null; | 1295 if (!truth(value)) return null; |
| 1290 return new _Pair<_Node, _Node>(key, value); | 1296 return new _Pair<Node, Node>(key, value); |
| 1291 }); | 1297 }); |
| 1292 | 1298 |
| 1293 // 153 | 1299 // 153 |
| 1294 _Pair<_Node, _Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) => | 1300 _Pair<Node, Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) => |
| 1295 transaction(() { | 1301 transaction(() { |
| 1296 var key = c_s_implicitJsonKey(FLOW_KEY); | 1302 var key = c_s_implicitJsonKey(FLOW_KEY); |
| 1297 if (!truth(key)) return null; | 1303 if (!truth(key)) return null; |
| 1298 var value = c_ns_flowMapAdjacentValue(indent, ctx); | 1304 var value = c_ns_flowMapAdjacentValue(indent, ctx); |
| 1299 if (!truth(value)) return null; | 1305 if (!truth(value)) return null; |
| 1300 return new _Pair<_Node, _Node>(key, value); | 1306 return new _Pair<Node, Node>(key, value); |
| 1301 }); | 1307 }); |
| 1302 | 1308 |
| 1303 // 154 | 1309 // 154 |
| 1304 _Node ns_s_implicitYamlKey(int ctx) => transaction(() { | 1310 Node ns_s_implicitYamlKey(int ctx) => transaction(() { |
| 1305 // TODO(nweiz): this is supposed to be limited to 1024 characters. | 1311 // TODO(nweiz): this is supposed to be limited to 1024 characters. |
| 1306 | 1312 |
| 1307 // The indentation parameter is "null" since it's unused in this path | 1313 // The indentation parameter is "null" since it's unused in this path |
| 1308 var node = ns_flowYamlNode(null, ctx); | 1314 var node = ns_flowYamlNode(null, ctx); |
| 1309 if (!truth(node)) return null; | 1315 if (!truth(node)) return null; |
| 1310 zeroOrOne(s_separateInLine); | 1316 zeroOrOne(s_separateInLine); |
| 1311 return node; | 1317 return node; |
| 1312 }); | 1318 }); |
| 1313 | 1319 |
| 1314 // 155 | 1320 // 155 |
| 1315 _Node c_s_implicitJsonKey(int ctx) => transaction(() { | 1321 Node c_s_implicitJsonKey(int ctx) => transaction(() { |
| 1316 // TODO(nweiz): this is supposed to be limited to 1024 characters. | 1322 // TODO(nweiz): this is supposed to be limited to 1024 characters. |
| 1317 | 1323 |
| 1318 // The indentation parameter is "null" since it's unused in this path | 1324 // The indentation parameter is "null" since it's unused in this path |
| 1319 var node = c_flowJsonNode(null, ctx); | 1325 var node = c_flowJsonNode(null, ctx); |
| 1320 if (!truth(node)) return null; | 1326 if (!truth(node)) return null; |
| 1321 zeroOrOne(s_separateInLine); | 1327 zeroOrOne(s_separateInLine); |
| 1322 return node; | 1328 return node; |
| 1323 }); | 1329 }); |
| 1324 | 1330 |
| 1325 // 156 | 1331 // 156 |
| 1326 _Node ns_flowYamlContent(int indent, int ctx) { | 1332 Node ns_flowYamlContent(int indent, int ctx) { |
| 1327 var str = ns_plain(indent, ctx); | 1333 var str = ns_plain(indent, ctx); |
| 1328 if (!truth(str)) return null; | 1334 if (!truth(str)) return null; |
| 1329 return new _ScalarNode("?", content: str); | 1335 return new ScalarNode("?", content: str); |
| 1330 } | 1336 } |
| 1331 | 1337 |
| 1332 // 157 | 1338 // 157 |
| 1333 _Node c_flowJsonContent(int indent, int ctx) => or([ | 1339 Node c_flowJsonContent(int indent, int ctx) => or([ |
| 1334 () => c_flowSequence(indent, ctx), | 1340 () => c_flowSequence(indent, ctx), |
| 1335 () => c_flowMapping(indent, ctx), | 1341 () => c_flowMapping(indent, ctx), |
| 1336 () => c_singleQuoted(indent, ctx), | 1342 () => c_singleQuoted(indent, ctx), |
| 1337 () => c_doubleQuoted(indent, ctx) | 1343 () => c_doubleQuoted(indent, ctx) |
| 1338 ]); | 1344 ]); |
| 1339 | 1345 |
| 1340 // 158 | 1346 // 158 |
| 1341 _Node ns_flowContent(int indent, int ctx) => or([ | 1347 Node ns_flowContent(int indent, int ctx) => or([ |
| 1342 () => ns_flowYamlContent(indent, ctx), | 1348 () => ns_flowYamlContent(indent, ctx), |
| 1343 () => c_flowJsonContent(indent, ctx) | 1349 () => c_flowJsonContent(indent, ctx) |
| 1344 ]); | 1350 ]); |
| 1345 | 1351 |
| 1346 // 159 | 1352 // 159 |
| 1347 _Node ns_flowYamlNode(int indent, int ctx) => or([ | 1353 Node ns_flowYamlNode(int indent, int ctx) => or([ |
| 1348 c_ns_aliasNode, | 1354 c_ns_aliasNode, |
| 1349 () => ns_flowYamlContent(indent, ctx), | 1355 () => ns_flowYamlContent(indent, ctx), |
| 1350 () { | 1356 () { |
| 1351 var props = c_ns_properties(indent, ctx); | 1357 var props = c_ns_properties(indent, ctx); |
| 1352 if (!truth(props)) return null; | 1358 if (!truth(props)) return null; |
| 1353 var node = or([ | 1359 var node = or([ |
| 1354 () => transaction(() { | 1360 () => transaction(() { |
| 1355 if (!truth(s_separate(indent, ctx))) return null; | 1361 if (!truth(s_separate(indent, ctx))) return null; |
| 1356 return ns_flowYamlContent(indent, ctx); | 1362 return ns_flowYamlContent(indent, ctx); |
| 1357 }), | 1363 }), |
| 1358 e_scalar | 1364 e_scalar |
| 1359 ]); | 1365 ]); |
| 1360 return addProps(node, props); | 1366 return addProps(node, props); |
| 1361 } | 1367 } |
| 1362 ]); | 1368 ]); |
| 1363 | 1369 |
| 1364 // 160 | 1370 // 160 |
| 1365 _Node c_flowJsonNode(int indent, int ctx) => transaction(() { | 1371 Node c_flowJsonNode(int indent, int ctx) => transaction(() { |
| 1366 var props; | 1372 var props; |
| 1367 zeroOrOne(() => transaction(() { | 1373 zeroOrOne(() => transaction(() { |
| 1368 props = c_ns_properties(indent, ctx); | 1374 props = c_ns_properties(indent, ctx); |
| 1369 if (!truth(props)) return null; | 1375 if (!truth(props)) return null; |
| 1370 return s_separate(indent, ctx); | 1376 return s_separate(indent, ctx); |
| 1371 })); | 1377 })); |
| 1372 | 1378 |
| 1373 return addProps(c_flowJsonContent(indent, ctx), props); | 1379 return addProps(c_flowJsonContent(indent, ctx), props); |
| 1374 }); | 1380 }); |
| 1375 | 1381 |
| 1376 // 161 | 1382 // 161 |
| 1377 _Node ns_flowNode(int indent, int ctx) => or([ | 1383 Node ns_flowNode(int indent, int ctx) => or([ |
| 1378 c_ns_aliasNode, | 1384 c_ns_aliasNode, |
| 1379 () => ns_flowContent(indent, ctx), | 1385 () => ns_flowContent(indent, ctx), |
| 1380 () => transaction(() { | 1386 () => transaction(() { |
| 1381 var props = c_ns_properties(indent, ctx); | 1387 var props = c_ns_properties(indent, ctx); |
| 1382 if (!truth(props)) return null; | 1388 if (!truth(props)) return null; |
| 1383 var node = or([ | 1389 var node = or([ |
| 1384 () => transaction(() => s_separate(indent, ctx) ? | 1390 () => transaction(() => s_separate(indent, ctx) ? |
| 1385 ns_flowContent(indent, ctx) : null), | 1391 ns_flowContent(indent, ctx) : null), |
| 1386 e_scalar]); | 1392 e_scalar]); |
| 1387 return addProps(node, props); | 1393 return addProps(node, props); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 // 169 | 1470 // 169 |
| 1465 bool l_trailComments(int indent) => transaction(() { | 1471 bool l_trailComments(int indent) => transaction(() { |
| 1466 if (!truth(s_indentLessThanOrEqualTo(indent))) return false; | 1472 if (!truth(s_indentLessThanOrEqualTo(indent))) return false; |
| 1467 if (!truth(c_nb_commentText())) return false; | 1473 if (!truth(c_nb_commentText())) return false; |
| 1468 if (!truth(b_comment())) return false; | 1474 if (!truth(b_comment())) return false; |
| 1469 zeroOrMore(l_comment); | 1475 zeroOrMore(l_comment); |
| 1470 return true; | 1476 return true; |
| 1471 }); | 1477 }); |
| 1472 | 1478 |
| 1473 // 170 | 1479 // 170 |
| 1474 _Node c_l_literal(int indent) => transaction(() { | 1480 Node c_l_literal(int indent) => transaction(() { |
| 1475 if (!truth(c_indicator(C_LITERAL))) return null; | 1481 if (!truth(c_indicator(C_LITERAL))) return null; |
| 1476 var header = c_b_blockHeader(); | 1482 var header = c_b_blockHeader(); |
| 1477 if (!truth(header)) return null; | 1483 if (!truth(header)) return null; |
| 1478 | 1484 |
| 1479 var additionalIndent = blockScalarAdditionalIndentation(header, indent); | 1485 var additionalIndent = blockScalarAdditionalIndentation(header, indent); |
| 1480 var content = l_literalContent(indent + additionalIndent, header.chomping); | 1486 var content = l_literalContent(indent + additionalIndent, header.chomping); |
| 1481 if (!truth(content)) return null; | 1487 if (!truth(content)) return null; |
| 1482 | 1488 |
| 1483 return new _ScalarNode("!", content: content); | 1489 return new ScalarNode("!", content: content); |
| 1484 }); | 1490 }); |
| 1485 | 1491 |
| 1486 // 171 | 1492 // 171 |
| 1487 bool l_nb_literalText(int indent) => transaction(() { | 1493 bool l_nb_literalText(int indent) => transaction(() { |
| 1488 zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN))); | 1494 zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN))); |
| 1489 if (!truth(captureAs("", () => s_indent(indent)))) return false; | 1495 if (!truth(captureAs("", () => s_indent(indent)))) return false; |
| 1490 return truth(oneOrMore(() => consume(isNonBreak))); | 1496 return truth(oneOrMore(() => consume(isNonBreak))); |
| 1491 }); | 1497 }); |
| 1492 | 1498 |
| 1493 // 172 | 1499 // 172 |
| 1494 bool b_nb_literalNext(int indent) => transaction(() { | 1500 bool b_nb_literalNext(int indent) => transaction(() { |
| 1495 if (!truth(b_asLineFeed())) return false; | 1501 if (!truth(b_asLineFeed())) return false; |
| 1496 return l_nb_literalText(indent); | 1502 return l_nb_literalText(indent); |
| 1497 }); | 1503 }); |
| 1498 | 1504 |
| 1499 // 173 | 1505 // 173 |
| 1500 String l_literalContent(int indent, int chomping) => captureString(() { | 1506 String l_literalContent(int indent, int chomping) => captureString(() { |
| 1501 transaction(() { | 1507 transaction(() { |
| 1502 if (!truth(l_nb_literalText(indent))) return false; | 1508 if (!truth(l_nb_literalText(indent))) return false; |
| 1503 zeroOrMore(() => b_nb_literalNext(indent)); | 1509 zeroOrMore(() => b_nb_literalNext(indent)); |
| 1504 return b_chompedLast(chomping); | 1510 return b_chompedLast(chomping); |
| 1505 }); | 1511 }); |
| 1506 l_chompedEmpty(indent, chomping); | 1512 l_chompedEmpty(indent, chomping); |
| 1507 return true; | 1513 return true; |
| 1508 }); | 1514 }); |
| 1509 | 1515 |
| 1510 // 174 | 1516 // 174 |
| 1511 _Node c_l_folded(int indent) => transaction(() { | 1517 Node c_l_folded(int indent) => transaction(() { |
| 1512 if (!truth(c_indicator(C_FOLDED))) return null; | 1518 if (!truth(c_indicator(C_FOLDED))) return null; |
| 1513 var header = c_b_blockHeader(); | 1519 var header = c_b_blockHeader(); |
| 1514 if (!truth(header)) return null; | 1520 if (!truth(header)) return null; |
| 1515 | 1521 |
| 1516 var additionalIndent = blockScalarAdditionalIndentation(header, indent); | 1522 var additionalIndent = blockScalarAdditionalIndentation(header, indent); |
| 1517 var content = l_foldedContent(indent + additionalIndent, header.chomping); | 1523 var content = l_foldedContent(indent + additionalIndent, header.chomping); |
| 1518 if (!truth(content)) return null; | 1524 if (!truth(content)) return null; |
| 1519 | 1525 |
| 1520 return new _ScalarNode("!", content: content); | 1526 return new ScalarNode("!", content: content); |
| 1521 }); | 1527 }); |
| 1522 | 1528 |
| 1523 // 175 | 1529 // 175 |
| 1524 bool s_nb_foldedText(int indent) => transaction(() { | 1530 bool s_nb_foldedText(int indent) => transaction(() { |
| 1525 if (!truth(captureAs('', () => s_indent(indent)))) return false; | 1531 if (!truth(captureAs('', () => s_indent(indent)))) return false; |
| 1526 if (!truth(consume(isNonSpace))) return false; | 1532 if (!truth(consume(isNonSpace))) return false; |
| 1527 zeroOrMore(() => consume(isNonBreak)); | 1533 zeroOrMore(() => consume(isNonBreak)); |
| 1528 return true; | 1534 return true; |
| 1529 }); | 1535 }); |
| 1530 | 1536 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1586 String l_foldedContent(int indent, int chomping) => captureString(() { | 1592 String l_foldedContent(int indent, int chomping) => captureString(() { |
| 1587 transaction(() { | 1593 transaction(() { |
| 1588 if (!truth(l_nb_diffLines(indent))) return false; | 1594 if (!truth(l_nb_diffLines(indent))) return false; |
| 1589 return b_chompedLast(chomping); | 1595 return b_chompedLast(chomping); |
| 1590 }); | 1596 }); |
| 1591 l_chompedEmpty(indent, chomping); | 1597 l_chompedEmpty(indent, chomping); |
| 1592 return true; | 1598 return true; |
| 1593 }); | 1599 }); |
| 1594 | 1600 |
| 1595 // 183 | 1601 // 183 |
| 1596 _SequenceNode l_blockSequence(int indent) => context('sequence', () { | 1602 SequenceNode l_blockSequence(int indent) => context('sequence', () { |
| 1597 var additionalIndent = countIndentation() - indent; | 1603 var additionalIndent = countIndentation() - indent; |
| 1598 if (additionalIndent <= 0) return null; | 1604 if (additionalIndent <= 0) return null; |
| 1599 | 1605 |
| 1600 var content = oneOrMore(() => transaction(() { | 1606 var content = oneOrMore(() => transaction(() { |
| 1601 if (!truth(s_indent(indent + additionalIndent))) return null; | 1607 if (!truth(s_indent(indent + additionalIndent))) return null; |
| 1602 return c_l_blockSeqEntry(indent + additionalIndent); | 1608 return c_l_blockSeqEntry(indent + additionalIndent); |
| 1603 })); | 1609 })); |
| 1604 if (!truth(content)) return null; | 1610 if (!truth(content)) return null; |
| 1605 | 1611 |
| 1606 return new _SequenceNode("?", content); | 1612 return new SequenceNode("?", content); |
| 1607 }); | 1613 }); |
| 1608 | 1614 |
| 1609 // 184 | 1615 // 184 |
| 1610 _Node c_l_blockSeqEntry(int indent) => transaction(() { | 1616 Node c_l_blockSeqEntry(int indent) => transaction(() { |
| 1611 if (!truth(c_indicator(C_SEQUENCE_ENTRY))) return null; | 1617 if (!truth(c_indicator(C_SEQUENCE_ENTRY))) return null; |
| 1612 if (isNonSpace(peek())) return null; | 1618 if (isNonSpace(peek())) return null; |
| 1613 | 1619 |
| 1614 return s_l_blockIndented(indent, BLOCK_IN); | 1620 return s_l_blockIndented(indent, BLOCK_IN); |
| 1615 }); | 1621 }); |
| 1616 | 1622 |
| 1617 // 185 | 1623 // 185 |
| 1618 _Node s_l_blockIndented(int indent, int ctx) { | 1624 Node s_l_blockIndented(int indent, int ctx) { |
| 1619 var additionalIndent = countIndentation(); | 1625 var additionalIndent = countIndentation(); |
| 1620 return or([ | 1626 return or([ |
| 1621 () => transaction(() { | 1627 () => transaction(() { |
| 1622 if (!truth(s_indent(additionalIndent))) return null; | 1628 if (!truth(s_indent(additionalIndent))) return null; |
| 1623 return or([ | 1629 return or([ |
| 1624 () => ns_l_compactSequence(indent + 1 + additionalIndent), | 1630 () => ns_l_compactSequence(indent + 1 + additionalIndent), |
| 1625 () => ns_l_compactMapping(indent + 1 + additionalIndent)]); | 1631 () => ns_l_compactMapping(indent + 1 + additionalIndent)]); |
| 1626 }), | 1632 }), |
| 1627 () => s_l_blockNode(indent, ctx), | 1633 () => s_l_blockNode(indent, ctx), |
| 1628 () => s_l_comments() ? e_node() : null]); | 1634 () => s_l_comments() ? e_node() : null]); |
| 1629 } | 1635 } |
| 1630 | 1636 |
| 1631 // 186 | 1637 // 186 |
| 1632 _Node ns_l_compactSequence(int indent) => context('sequence', () { | 1638 Node ns_l_compactSequence(int indent) => context('sequence', () { |
| 1633 var first = c_l_blockSeqEntry(indent); | 1639 var first = c_l_blockSeqEntry(indent); |
| 1634 if (!truth(first)) return null; | 1640 if (!truth(first)) return null; |
| 1635 | 1641 |
| 1636 var content = zeroOrMore(() => transaction(() { | 1642 var content = zeroOrMore(() => transaction(() { |
| 1637 if (!truth(s_indent(indent))) return null; | 1643 if (!truth(s_indent(indent))) return null; |
| 1638 return c_l_blockSeqEntry(indent); | 1644 return c_l_blockSeqEntry(indent); |
| 1639 })); | 1645 })); |
| 1640 content.insert(0, first); | 1646 content.insert(0, first); |
| 1641 | 1647 |
| 1642 return new _SequenceNode("?", content); | 1648 return new SequenceNode("?", content); |
| 1643 }); | 1649 }); |
| 1644 | 1650 |
| 1645 // 187 | 1651 // 187 |
| 1646 _Node l_blockMapping(int indent) => context('mapping', () { | 1652 Node l_blockMapping(int indent) => context('mapping', () { |
| 1647 var additionalIndent = countIndentation() - indent; | 1653 var additionalIndent = countIndentation() - indent; |
| 1648 if (additionalIndent <= 0) return null; | 1654 if (additionalIndent <= 0) return null; |
| 1649 | 1655 |
| 1650 var pairs = oneOrMore(() => transaction(() { | 1656 var pairs = oneOrMore(() => transaction(() { |
| 1651 if (!truth(s_indent(indent + additionalIndent))) return null; | 1657 if (!truth(s_indent(indent + additionalIndent))) return null; |
| 1652 return ns_l_blockMapEntry(indent + additionalIndent); | 1658 return ns_l_blockMapEntry(indent + additionalIndent); |
| 1653 })); | 1659 })); |
| 1654 if (!truth(pairs)) return null; | 1660 if (!truth(pairs)) return null; |
| 1655 | 1661 |
| 1656 return map(pairs); | 1662 return map(pairs); |
| 1657 }); | 1663 }); |
| 1658 | 1664 |
| 1659 // 188 | 1665 // 188 |
| 1660 _Pair<_Node, _Node> ns_l_blockMapEntry(int indent) => or([ | 1666 _Pair<Node, Node> ns_l_blockMapEntry(int indent) => or([ |
| 1661 () => c_l_blockMapExplicitEntry(indent), | 1667 () => c_l_blockMapExplicitEntry(indent), |
| 1662 () => ns_l_blockMapImplicitEntry(indent) | 1668 () => ns_l_blockMapImplicitEntry(indent) |
| 1663 ]); | 1669 ]); |
| 1664 | 1670 |
| 1665 // 189 | 1671 // 189 |
| 1666 _Pair<_Node, _Node> c_l_blockMapExplicitEntry(int indent) { | 1672 _Pair<Node, Node> c_l_blockMapExplicitEntry(int indent) { |
| 1667 var key = c_l_blockMapExplicitKey(indent); | 1673 var key = c_l_blockMapExplicitKey(indent); |
| 1668 if (!truth(key)) return null; | 1674 if (!truth(key)) return null; |
| 1669 | 1675 |
| 1670 var value = or([ | 1676 var value = or([ |
| 1671 () => l_blockMapExplicitValue(indent), | 1677 () => l_blockMapExplicitValue(indent), |
| 1672 e_node | 1678 e_node |
| 1673 ]); | 1679 ]); |
| 1674 | 1680 |
| 1675 return new _Pair<_Node, _Node>(key, value); | 1681 return new _Pair<Node, Node>(key, value); |
| 1676 } | 1682 } |
| 1677 | 1683 |
| 1678 // 190 | 1684 // 190 |
| 1679 _Node c_l_blockMapExplicitKey(int indent) => transaction(() { | 1685 Node c_l_blockMapExplicitKey(int indent) => transaction(() { |
| 1680 if (!truth(c_indicator(C_MAPPING_KEY))) return null; | 1686 if (!truth(c_indicator(C_MAPPING_KEY))) return null; |
| 1681 return s_l_blockIndented(indent, BLOCK_OUT); | 1687 return s_l_blockIndented(indent, BLOCK_OUT); |
| 1682 }); | 1688 }); |
| 1683 | 1689 |
| 1684 // 191 | 1690 // 191 |
| 1685 _Node l_blockMapExplicitValue(int indent) => transaction(() { | 1691 Node l_blockMapExplicitValue(int indent) => transaction(() { |
| 1686 if (!truth(s_indent(indent))) return null; | 1692 if (!truth(s_indent(indent))) return null; |
| 1687 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; | 1693 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; |
| 1688 return s_l_blockIndented(indent, BLOCK_OUT); | 1694 return s_l_blockIndented(indent, BLOCK_OUT); |
| 1689 }); | 1695 }); |
| 1690 | 1696 |
| 1691 // 192 | 1697 // 192 |
| 1692 _Pair<_Node, _Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() { | 1698 _Pair<Node, Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() { |
| 1693 var key = or([ns_s_blockMapImplicitKey, e_node]); | 1699 var key = or([ns_s_blockMapImplicitKey, e_node]); |
| 1694 var value = c_l_blockMapImplicitValue(indent); | 1700 var value = c_l_blockMapImplicitValue(indent); |
| 1695 return truth(value) ? new _Pair<_Node, _Node>(key, value) : null; | 1701 return truth(value) ? new _Pair<Node, Node>(key, value) : null; |
| 1696 }); | 1702 }); |
| 1697 | 1703 |
| 1698 // 193 | 1704 // 193 |
| 1699 _Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([ | 1705 Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([ |
| 1700 () => c_s_implicitJsonKey(BLOCK_KEY), | 1706 () => c_s_implicitJsonKey(BLOCK_KEY), |
| 1701 () => ns_s_implicitYamlKey(BLOCK_KEY) | 1707 () => ns_s_implicitYamlKey(BLOCK_KEY) |
| 1702 ])); | 1708 ])); |
| 1703 | 1709 |
| 1704 // 194 | 1710 // 194 |
| 1705 _Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () => | 1711 Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () => |
| 1706 transaction(() { | 1712 transaction(() { |
| 1707 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; | 1713 if (!truth(c_indicator(C_MAPPING_VALUE))) return null; |
| 1708 return or([ | 1714 return or([ |
| 1709 () => s_l_blockNode(indent, BLOCK_OUT), | 1715 () => s_l_blockNode(indent, BLOCK_OUT), |
| 1710 () => s_l_comments() ? e_node() : null | 1716 () => s_l_comments() ? e_node() : null |
| 1711 ]); | 1717 ]); |
| 1712 })); | 1718 })); |
| 1713 | 1719 |
| 1714 // 195 | 1720 // 195 |
| 1715 _Node ns_l_compactMapping(int indent) => context('mapping', () { | 1721 Node ns_l_compactMapping(int indent) => context('mapping', () { |
| 1716 var first = ns_l_blockMapEntry(indent); | 1722 var first = ns_l_blockMapEntry(indent); |
| 1717 if (!truth(first)) return null; | 1723 if (!truth(first)) return null; |
| 1718 | 1724 |
| 1719 var pairs = zeroOrMore(() => transaction(() { | 1725 var pairs = zeroOrMore(() => transaction(() { |
| 1720 if (!truth(s_indent(indent))) return null; | 1726 if (!truth(s_indent(indent))) return null; |
| 1721 return ns_l_blockMapEntry(indent); | 1727 return ns_l_blockMapEntry(indent); |
| 1722 })); | 1728 })); |
| 1723 pairs.insert(0, first); | 1729 pairs.insert(0, first); |
| 1724 | 1730 |
| 1725 return map(pairs); | 1731 return map(pairs); |
| 1726 }); | 1732 }); |
| 1727 | 1733 |
| 1728 // 196 | 1734 // 196 |
| 1729 _Node s_l_blockNode(int indent, int ctx) => or([ | 1735 Node s_l_blockNode(int indent, int ctx) => or([ |
| 1730 () => s_l_blockInBlock(indent, ctx), | 1736 () => s_l_blockInBlock(indent, ctx), |
| 1731 () => s_l_flowInBlock(indent) | 1737 () => s_l_flowInBlock(indent) |
| 1732 ]); | 1738 ]); |
| 1733 | 1739 |
| 1734 // 197 | 1740 // 197 |
| 1735 _Node s_l_flowInBlock(int indent) => transaction(() { | 1741 Node s_l_flowInBlock(int indent) => transaction(() { |
| 1736 if (!truth(s_separate(indent + 1, FLOW_OUT))) return null; | 1742 if (!truth(s_separate(indent + 1, FLOW_OUT))) return null; |
| 1737 var node = ns_flowNode(indent + 1, FLOW_OUT); | 1743 var node = ns_flowNode(indent + 1, FLOW_OUT); |
| 1738 if (!truth(node)) return null; | 1744 if (!truth(node)) return null; |
| 1739 if (!truth(s_l_comments())) return null; | 1745 if (!truth(s_l_comments())) return null; |
| 1740 return node; | 1746 return node; |
| 1741 }); | 1747 }); |
| 1742 | 1748 |
| 1743 // 198 | 1749 // 198 |
| 1744 _Node s_l_blockInBlock(int indent, int ctx) => or([ | 1750 Node s_l_blockInBlock(int indent, int ctx) => or([ |
| 1745 () => s_l_blockScalar(indent, ctx), | 1751 () => s_l_blockScalar(indent, ctx), |
| 1746 () => s_l_blockCollection(indent, ctx) | 1752 () => s_l_blockCollection(indent, ctx) |
| 1747 ]); | 1753 ]); |
| 1748 | 1754 |
| 1749 // 199 | 1755 // 199 |
| 1750 _Node s_l_blockScalar(int indent, int ctx) => transaction(() { | 1756 Node s_l_blockScalar(int indent, int ctx) => transaction(() { |
| 1751 if (!truth(s_separate(indent + 1, ctx))) return null; | 1757 if (!truth(s_separate(indent + 1, ctx))) return null; |
| 1752 var props = transaction(() { | 1758 var props = transaction(() { |
| 1753 var innerProps = c_ns_properties(indent + 1, ctx); | 1759 var innerProps = c_ns_properties(indent + 1, ctx); |
| 1754 if (!truth(innerProps)) return null; | 1760 if (!truth(innerProps)) return null; |
| 1755 if (!truth(s_separate(indent + 1, ctx))) return null; | 1761 if (!truth(s_separate(indent + 1, ctx))) return null; |
| 1756 return innerProps; | 1762 return innerProps; |
| 1757 }); | 1763 }); |
| 1758 | 1764 |
| 1759 var node = or([() => c_l_literal(indent), () => c_l_folded(indent)]); | 1765 var node = or([() => c_l_literal(indent), () => c_l_folded(indent)]); |
| 1760 if (!truth(node)) return null; | 1766 if (!truth(node)) return null; |
| 1761 return addProps(node, props); | 1767 return addProps(node, props); |
| 1762 }); | 1768 }); |
| 1763 | 1769 |
| 1764 // 200 | 1770 // 200 |
| 1765 _Node s_l_blockCollection(int indent, int ctx) => transaction(() { | 1771 Node s_l_blockCollection(int indent, int ctx) => transaction(() { |
| 1766 var props = transaction(() { | 1772 var props = transaction(() { |
| 1767 if (!truth(s_separate(indent + 1, ctx))) return null; | 1773 if (!truth(s_separate(indent + 1, ctx))) return null; |
| 1768 return c_ns_properties(indent + 1, ctx); | 1774 return c_ns_properties(indent + 1, ctx); |
| 1769 }); | 1775 }); |
| 1770 | 1776 |
| 1771 if (!truth(s_l_comments())) return null; | 1777 if (!truth(s_l_comments())) return null; |
| 1772 return or([ | 1778 return or([ |
| 1773 () => l_blockSequence(seqSpaces(indent, ctx)), | 1779 () => l_blockSequence(seqSpaces(indent, ctx)), |
| 1774 () => l_blockMapping(indent)]); | 1780 () => l_blockMapping(indent)]); |
| 1775 }); | 1781 }); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1789 bool c_documentEnd() => rawString("..."); | 1795 bool c_documentEnd() => rawString("..."); |
| 1790 | 1796 |
| 1791 // 205 | 1797 // 205 |
| 1792 bool l_documentSuffix() => transaction(() { | 1798 bool l_documentSuffix() => transaction(() { |
| 1793 if (!truth(c_documentEnd())) return false; | 1799 if (!truth(c_documentEnd())) return false; |
| 1794 return s_l_comments(); | 1800 return s_l_comments(); |
| 1795 }); | 1801 }); |
| 1796 | 1802 |
| 1797 // 206 | 1803 // 206 |
| 1798 bool c_forbidden() { | 1804 bool c_forbidden() { |
| 1799 if (!inBareDocument || !atStartOfLine) return false; | 1805 if (!_inBareDocument || !atStartOfLine) return false; |
| 1800 var forbidden = false; | 1806 var forbidden = false; |
| 1801 transaction(() { | 1807 transaction(() { |
| 1802 if (!truth(or([c_directivesEnd, c_documentEnd]))) return; | 1808 if (!truth(or([c_directivesEnd, c_documentEnd]))) return; |
| 1803 var char = peek(); | 1809 var char = peek(); |
| 1804 forbidden = isBreak(char) || isSpace(char) || atEndOfFile; | 1810 forbidden = isBreak(char) || isSpace(char) || atEndOfFile; |
| 1805 return; | 1811 return; |
| 1806 }); | 1812 }); |
| 1807 return forbidden; | 1813 return forbidden; |
| 1808 } | 1814 } |
| 1809 | 1815 |
| 1810 // 207 | 1816 // 207 |
| 1811 _Node l_bareDocument() { | 1817 Node l_bareDocument() { |
| 1812 try { | 1818 try { |
| 1813 inBareDocument = true; | 1819 _inBareDocument = true; |
| 1814 return s_l_blockNode(-1, BLOCK_IN); | 1820 return s_l_blockNode(-1, BLOCK_IN); |
| 1815 } finally { | 1821 } finally { |
| 1816 inBareDocument = false; | 1822 _inBareDocument = false; |
| 1817 } | 1823 } |
| 1818 } | 1824 } |
| 1819 | 1825 |
| 1820 // 208 | 1826 // 208 |
| 1821 _Node l_explicitDocument() { | 1827 Node l_explicitDocument() { |
| 1822 if (!truth(c_directivesEnd())) return null; | 1828 if (!truth(c_directivesEnd())) return null; |
| 1823 var doc = l_bareDocument(); | 1829 var doc = l_bareDocument(); |
| 1824 if (truth(doc)) return doc; | 1830 if (truth(doc)) return doc; |
| 1825 | 1831 |
| 1826 doc = e_node(); | 1832 doc = e_node(); |
| 1827 s_l_comments(); | 1833 s_l_comments(); |
| 1828 return doc; | 1834 return doc; |
| 1829 } | 1835 } |
| 1830 | 1836 |
| 1831 // 209 | 1837 // 209 |
| 1832 _Node l_directiveDocument() { | 1838 Node l_directiveDocument() { |
| 1833 if (!truth(oneOrMore(l_directive))) return null; | 1839 if (!truth(oneOrMore(l_directive))) return null; |
| 1834 var doc = l_explicitDocument(); | 1840 var doc = l_explicitDocument(); |
| 1835 if (doc != null) return doc; | 1841 if (doc != null) return doc; |
| 1836 parseFailed(); | 1842 parseFailed(); |
| 1837 return null; // Unreachable. | 1843 return null; // Unreachable. |
| 1838 } | 1844 } |
| 1839 | 1845 |
| 1840 // 210 | 1846 // 210 |
| 1841 _Node l_anyDocument() => | 1847 Node l_anyDocument() => |
| 1842 or([l_directiveDocument, l_explicitDocument, l_bareDocument]); | 1848 or([l_directiveDocument, l_explicitDocument, l_bareDocument]); |
| 1843 | 1849 |
| 1844 // 211 | 1850 // 211 |
| 1845 List<_Node> l_yamlStream() { | 1851 List<Node> l_yamlStream() { |
| 1846 var docs = []; | 1852 var docs = []; |
| 1847 zeroOrMore(l_documentPrefix); | 1853 zeroOrMore(l_documentPrefix); |
| 1848 var first = zeroOrOne(l_anyDocument); | 1854 var first = zeroOrOne(l_anyDocument); |
| 1849 if (!truth(first)) first = e_node(); | 1855 if (!truth(first)) first = e_node(); |
| 1850 docs.add(first); | 1856 docs.add(first); |
| 1851 | 1857 |
| 1852 zeroOrMore(() { | 1858 zeroOrMore(() { |
| 1853 var doc; | 1859 var doc; |
| 1854 if (truth(oneOrMore(l_documentSuffix))) { | 1860 if (truth(oneOrMore(l_documentSuffix))) { |
| 1855 zeroOrMore(l_documentPrefix); | 1861 zeroOrMore(l_documentPrefix); |
| 1856 doc = zeroOrOne(l_anyDocument); | 1862 doc = zeroOrOne(l_anyDocument); |
| 1857 } else { | 1863 } else { |
| 1858 zeroOrMore(l_documentPrefix); | 1864 zeroOrMore(l_documentPrefix); |
| 1859 doc = zeroOrOne(l_explicitDocument); | 1865 doc = zeroOrOne(l_explicitDocument); |
| 1860 } | 1866 } |
| 1861 if (truth(doc)) docs.add(doc); | 1867 if (truth(doc)) docs.add(doc); |
| 1862 return doc; | 1868 return doc; |
| 1863 }); | 1869 }); |
| 1864 | 1870 |
| 1865 if (!atEndOfFile) parseFailed(); | 1871 if (!atEndOfFile) parseFailed(); |
| 1866 return docs; | 1872 return docs; |
| 1867 } | 1873 } |
| 1868 } | 1874 } |
| 1869 | 1875 |
| 1870 class SyntaxError extends YamlException { | 1876 class SyntaxError extends YamlException { |
| 1871 final int line; | 1877 final int _line; |
| 1872 final int column; | 1878 final int _column; |
| 1873 | 1879 |
| 1874 SyntaxError(this.line, this.column, String msg) : super(msg); | 1880 SyntaxError(this._line, this._column, String msg) : super(msg); |
| 1875 | 1881 |
| 1876 String toString() => "Syntax error on line $line, column $column: $msg"; | 1882 String toString() => "Syntax error on line $_line, column $_column: " |
| 1883 "${super.toString()}"; |
| 1877 } | 1884 } |
| 1878 | 1885 |
| 1879 /// A pair of values. | 1886 /// A pair of values. |
| 1880 class _Pair<E, F> { | 1887 class _Pair<E, F> { |
| 1881 E first; | 1888 E first; |
| 1882 F last; | 1889 F last; |
| 1883 | 1890 |
| 1884 _Pair(this.first, this.last); | 1891 _Pair(this.first, this.last); |
| 1885 | 1892 |
| 1886 String toString() => '($first, $last)'; | 1893 String toString() => '($first, $last)'; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1909 | 1916 |
| 1910 /// Returns whether or not [pos] lies within this range. | 1917 /// Returns whether or not [pos] lies within this range. |
| 1911 bool contains(int pos) => pos >= start && pos <= end; | 1918 bool contains(int pos) => pos >= start && pos <= end; |
| 1912 } | 1919 } |
| 1913 | 1920 |
| 1914 /// A map that associates [E] values with [_Range]s. It's efficient to create | 1921 /// A map that associates [E] values with [_Range]s. It's efficient to create |
| 1915 /// new associations, but finding the value associated with a position is more | 1922 /// new associations, but finding the value associated with a position is more |
| 1916 /// expensive. | 1923 /// expensive. |
| 1917 class _RangeMap<E> { | 1924 class _RangeMap<E> { |
| 1918 /// The ranges and their associated elements. | 1925 /// The ranges and their associated elements. |
| 1919 final List<_Pair<_Range, E>> contents; | 1926 final List<_Pair<_Range, E>> _contents = <_Pair<_Range, E>>[]; |
| 1920 | 1927 |
| 1921 _RangeMap() : this.contents = <_Pair<_Range, E>>[]; | 1928 _RangeMap(); |
| 1922 | 1929 |
| 1923 /// Returns the value associated with the range in which [pos] lies, or null | 1930 /// Returns the value associated with the range in which [pos] lies, or null |
| 1924 /// if there is no such range. If there's more than one such range, the most | 1931 /// if there is no such range. If there's more than one such range, the most |
| 1925 /// recently set one is used. | 1932 /// recently set one is used. |
| 1926 E operator[](int pos) { | 1933 E operator[](int pos) { |
| 1927 // Iterate backwards through contents so the more recent range takes | 1934 // Iterate backwards through contents so the more recent range takes |
| 1928 // precedence. TODO(nweiz): clean this up when issue 2804 is fixed. | 1935 // precedence. |
| 1929 for (var i = contents.length - 1; i >= 0; i--) { | 1936 for (var pair in _contents.reversed) { |
| 1930 var pair = contents[i]; | |
| 1931 if (pair.first.contains(pos)) return pair.last; | 1937 if (pair.first.contains(pos)) return pair.last; |
| 1932 } | 1938 } |
| 1933 return null; | 1939 return null; |
| 1934 } | 1940 } |
| 1935 | 1941 |
| 1936 /// Associates [value] with [range]. | 1942 /// Associates [value] with [range]. |
| 1937 operator[]=(_Range range, E value) => | 1943 operator[]=(_Range range, E value) => |
| 1938 contents.add(new _Pair<_Range, E>(range, value)); | 1944 _contents.add(new _Pair<_Range, E>(range, value)); |
| 1939 } | 1945 } |
| OLD | NEW |