| Index: mojo/public/dart/third_party/yaml/lib/src/loader.dart
|
| diff --git a/mojo/public/dart/third_party/yaml/lib/src/loader.dart b/mojo/public/dart/third_party/yaml/lib/src/loader.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d80578fc95cf9c3fb9780b577cfdbdbcdecfa261
|
| --- /dev/null
|
| +++ b/mojo/public/dart/third_party/yaml/lib/src/loader.dart
|
| @@ -0,0 +1,257 @@
|
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library yaml.loader;
|
| +
|
| +import 'package:source_span/source_span.dart';
|
| +
|
| +import 'equality.dart';
|
| +import 'event.dart';
|
| +import 'parser.dart';
|
| +import 'yaml_document.dart';
|
| +import 'yaml_exception.dart';
|
| +import 'yaml_node.dart';
|
| +
|
| +/// A loader that reads [Event]s emitted by a [Parser] and emits
|
| +/// [YamlDocument]s.
|
| +///
|
| +/// This is based on the libyaml loader, available at
|
| +/// https://github.com/yaml/libyaml/blob/master/src/loader.c. The license for
|
| +/// that is available in ../../libyaml-license.txt.
|
| +class Loader {
|
| + /// The underlying [Parser] that generates [Event]s.
|
| + final Parser _parser;
|
| +
|
| + /// Aliases by the alias name.
|
| + final _aliases = new Map<String, YamlNode>();
|
| +
|
| + /// The span of the entire stream emitted so far.
|
| + FileSpan get span => _span;
|
| + FileSpan _span;
|
| +
|
| + /// Creates a loader that loads [source].
|
| + ///
|
| + /// [sourceUrl] can be a String or a [Uri].
|
| + Loader(String source, {sourceUrl})
|
| + : _parser = new Parser(source, sourceUrl: sourceUrl) {
|
| + var event = _parser.parse();
|
| + _span = event.span;
|
| + assert(event.type == EventType.STREAM_START);
|
| + }
|
| +
|
| + /// Loads the next document from the stream.
|
| + ///
|
| + /// If there are no more documents, returns `null`.
|
| + YamlDocument load() {
|
| + if (_parser.isDone) return null;
|
| +
|
| + var event = _parser.parse();
|
| + if (event.type == EventType.STREAM_END) {
|
| + _span = _span.expand(event.span);
|
| + return null;
|
| + }
|
| +
|
| + var document = _loadDocument(event);
|
| + _span = _span.expand(document.span);
|
| + _aliases.clear();
|
| + return document;
|
| + }
|
| +
|
| + /// Composes a document object.
|
| + YamlDocument _loadDocument(DocumentStartEvent firstEvent) {
|
| + var contents = _loadNode(_parser.parse());
|
| +
|
| + var lastEvent = _parser.parse();
|
| + assert(lastEvent.type == EventType.DOCUMENT_END);
|
| +
|
| + return new YamlDocument.internal(
|
| + contents,
|
| + firstEvent.span.expand(lastEvent.span),
|
| + firstEvent.versionDirective,
|
| + firstEvent.tagDirectives,
|
| + startImplicit: firstEvent.isImplicit,
|
| + endImplicit: lastEvent.isImplicit);
|
| + }
|
| +
|
| + /// Composes a node.
|
| + YamlNode _loadNode(Event firstEvent) {
|
| + switch (firstEvent.type) {
|
| + case EventType.ALIAS: return _loadAlias(firstEvent);
|
| + case EventType.SCALAR: return _loadScalar(firstEvent);
|
| + case EventType.SEQUENCE_START: return _loadSequence(firstEvent);
|
| + case EventType.MAPPING_START: return _loadMapping(firstEvent);
|
| + default: throw "Unreachable";
|
| + }
|
| + }
|
| +
|
| + /// Registers an anchor.
|
| + void _registerAnchor(String anchor, YamlNode node) {
|
| + if (anchor == null) return;
|
| +
|
| + // libyaml throws an error for duplicate anchors, but example 7.1 makes it
|
| + // clear that they should be overridden:
|
| + // http://yaml.org/spec/1.2/spec.html#id2786448.
|
| +
|
| + _aliases[anchor] = node;
|
| + }
|
| +
|
| + /// Composes a node corresponding to an alias.
|
| + YamlNode _loadAlias(AliasEvent event) {
|
| + var alias = _aliases[event.name];
|
| + if (alias != null) return alias;
|
| +
|
| + throw new YamlException("Undefined alias.", event.span);
|
| + }
|
| +
|
| + /// Composes a scalar node.
|
| + YamlNode _loadScalar(ScalarEvent scalar) {
|
| + var node;
|
| + if (scalar.tag == "!") {
|
| + node = _parseString(scalar);
|
| + } else if (scalar.tag != null) {
|
| + node = _parseByTag(scalar);
|
| + } else {
|
| + node = _parseNull(scalar);
|
| + if (node == null) node = _parseBool(scalar);
|
| + if (node == null) node = _parseInt(scalar);
|
| + if (node == null) node = _parseFloat(scalar);
|
| + if (node == null) node = _parseString(scalar);
|
| + }
|
| +
|
| + _registerAnchor(scalar.anchor, node);
|
| + return node;
|
| + }
|
| +
|
| + /// Composes a sequence node.
|
| + YamlNode _loadSequence(SequenceStartEvent firstEvent) {
|
| + if (firstEvent.tag != "!" && firstEvent.tag != null &&
|
| + firstEvent.tag != "tag:yaml.org,2002:seq") {
|
| + throw new YamlException("Invalid tag for sequence.", firstEvent.span);
|
| + }
|
| +
|
| + var children = [];
|
| + var node = new YamlList.internal(
|
| + children, firstEvent.span, firstEvent.style);
|
| + _registerAnchor(firstEvent.anchor, node);
|
| +
|
| + var event = _parser.parse();
|
| + while (event.type != EventType.SEQUENCE_END) {
|
| + children.add(_loadNode(event));
|
| + event = _parser.parse();
|
| + }
|
| +
|
| + setSpan(node, firstEvent.span.expand(event.span));
|
| + return node;
|
| + }
|
| +
|
| + /// Composes a mapping node.
|
| + YamlNode _loadMapping(MappingStartEvent firstEvent) {
|
| + if (firstEvent.tag != "!" && firstEvent.tag != null &&
|
| + firstEvent.tag != "tag:yaml.org,2002:map") {
|
| + throw new YamlException("Invalid tag for mapping.", firstEvent.span);
|
| + }
|
| +
|
| + var children = deepEqualsMap();
|
| + var node = new YamlMap.internal(
|
| + children, firstEvent.span, firstEvent.style);
|
| + _registerAnchor(firstEvent.anchor, node);
|
| +
|
| + var event = _parser.parse();
|
| + while (event.type != EventType.MAPPING_END) {
|
| + var key = _loadNode(event);
|
| + var value = _loadNode(_parser.parse());
|
| + children[key] = value;
|
| + event = _parser.parse();
|
| + }
|
| +
|
| + setSpan(node, firstEvent.span.expand(event.span));
|
| + return node;
|
| + }
|
| +
|
| + /// Parses a scalar according to its tag name.
|
| + YamlScalar _parseByTag(ScalarEvent scalar) {
|
| + switch (scalar.tag) {
|
| + case "tag:yaml.org,2002:null": return _parseNull(scalar);
|
| + case "tag:yaml.org,2002:bool": return _parseBool(scalar);
|
| + case "tag:yaml.org,2002:int": return _parseInt(scalar);
|
| + case "tag:yaml.org,2002:float": return _parseFloat(scalar);
|
| + case "tag:yaml.org,2002:str": return _parseString(scalar);
|
| + }
|
| + throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span);
|
| + }
|
| +
|
| + /// Parses a null scalar.
|
| + YamlScalar _parseNull(ScalarEvent scalar) {
|
| + // TODO(nweiz): stop using regexps.
|
| + // TODO(nweiz): add ScalarStyle and implicit metadata to the scalars.
|
| + if (new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(scalar.value)) {
|
| + return new YamlScalar.internal(null, scalar.span, scalar.style);
|
| + } else {
|
| + return null;
|
| + }
|
| + }
|
| +
|
| + /// Parses a boolean scalar.
|
| + YamlScalar _parseBool(ScalarEvent scalar) {
|
| + var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$").
|
| + firstMatch(scalar.value);
|
| + if (match == null) return null;
|
| + return new YamlScalar.internal(
|
| + match.group(1) != null, scalar.span, scalar.style);
|
| + }
|
| +
|
| + /// Parses an integer scalar.
|
| + YamlScalar _parseInt(ScalarEvent scalar) {
|
| + var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(scalar.value);
|
| + if (match != null) {
|
| + return new YamlScalar.internal(
|
| + int.parse(match.group(0)), scalar.span, scalar.style);
|
| + }
|
| +
|
| + match = new RegExp(r"^0o([0-7]+)$").firstMatch(scalar.value);
|
| + if (match != null) {
|
| + var n = int.parse(match.group(1), radix: 8);
|
| + return new YamlScalar.internal(n, scalar.span, scalar.style);
|
| + }
|
| +
|
| + match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(scalar.value);
|
| + if (match != null) {
|
| + return new YamlScalar.internal(
|
| + int.parse(match.group(0)), scalar.span, scalar.style);
|
| + }
|
| +
|
| + return null;
|
| + }
|
| +
|
| + /// Parses a floating-point scalar.
|
| + YamlScalar _parseFloat(ScalarEvent scalar) {
|
| + var match = new RegExp(
|
| + r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$").
|
| + firstMatch(scalar.value);
|
| + if (match != null) {
|
| + // YAML allows floats of the form "0.", but Dart does not. Fix up those
|
| + // floats by removing the trailing dot.
|
| + var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), "");
|
| + return new YamlScalar.internal(
|
| + double.parse(matchStr), scalar.span, scalar.style);
|
| + }
|
| +
|
| + match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(scalar.value);
|
| + if (match != null) {
|
| + var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY;
|
| + return new YamlScalar.internal(value, scalar.span, scalar.style);
|
| + }
|
| +
|
| + match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(scalar.value);
|
| + if (match != null) {
|
| + return new YamlScalar.internal(double.NAN, scalar.span, scalar.style);
|
| + }
|
| +
|
| + return null;
|
| + }
|
| +
|
| + /// Parses a string scalar.
|
| + YamlScalar _parseString(ScalarEvent scalar) =>
|
| + new YamlScalar.internal(scalar.value, scalar.span, scalar.style);
|
| +}
|
|
|