Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(967)

Unified Diff: mojo/public/dart/third_party/yaml/lib/src/parser.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/public/dart/third_party/yaml/lib/src/parser.dart
diff --git a/mojo/public/dart/third_party/yaml/lib/src/parser.dart b/mojo/public/dart/third_party/yaml/lib/src/parser.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8bb131f8346bb1e6d2df1d498c537131b5bc9f36
--- /dev/null
+++ b/mojo/public/dart/third_party/yaml/lib/src/parser.dart
@@ -0,0 +1,816 @@
+// 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.parser;
+
+import 'package:source_span/source_span.dart';
+import 'package:string_scanner/string_scanner.dart';
+
+import 'event.dart';
+import 'scanner.dart';
+import 'style.dart';
+import 'token.dart';
+import 'utils.dart';
+import 'yaml_document.dart';
+import 'yaml_exception.dart';
+
+/// A parser that reads [Token]s emitted by a [Scanner] and emits [Event]s.
+///
+/// This is based on the libyaml parser, available at
+/// https://github.com/yaml/libyaml/blob/master/src/parser.c. The license for
+/// that is available in ../../libyaml-license.txt.
+class Parser {
+ /// The underlying [Scanner] that generates [Token]s.
+ final Scanner _scanner;
+
+ /// The stack of parse states for nested contexts.
+ final _states = new List<_State>();
+
+ /// The current parse state.
+ var _state = _State.STREAM_START;
+
+ /// The custom tag directives, by tag handle.
+ final _tagDirectives = new Map<String, TagDirective>();
+
+ /// Whether the parser has finished parsing.
+ bool get isDone => _state == _State.END;
+
+ /// Creates a parser that parses [source].
+ ///
+ /// [sourceUrl] can be a String or a [Uri].
+ Parser(String source, {sourceUrl})
+ : _scanner = new Scanner(source, sourceUrl: sourceUrl);
+
+ /// Consumes and returns the next event.
+ Event parse() {
+ try {
+ if (isDone) throw new StateError("No more events.");
+ var event = _stateMachine();
+ return event;
+ } on StringScannerException catch (error) {
+ throw new YamlException(error.message, error.span);
+ }
+ }
+
+ /// Dispatches parsing based on the current state.
+ Event _stateMachine() {
+ switch (_state) {
+ case _State.STREAM_START:
+ return _parseStreamStart();
+ case _State.DOCUMENT_START:
+ return _parseDocumentStart();
+ case _State.DOCUMENT_CONTENT:
+ return _parseDocumentContent();
+ case _State.DOCUMENT_END:
+ return _parseDocumentEnd();
+ case _State.BLOCK_NODE:
+ return _parseNode(block: true);
+ case _State.BLOCK_NODE_OR_INDENTLESS_SEQUENCE:
+ return _parseNode(block: true, indentlessSequence: true);
+ case _State.FLOW_NODE:
+ return _parseNode();
+ case _State.BLOCK_SEQUENCE_FIRST_ENTRY:
+ // Scan past the `BLOCK-SEQUENCE-FIRST-ENTRY` token to the
+ // `BLOCK-SEQUENCE-ENTRY` token.
+ _scanner.scan();
+ return _parseBlockSequenceEntry();
+ case _State.BLOCK_SEQUENCE_ENTRY:
+ return _parseBlockSequenceEntry();
+ case _State.INDENTLESS_SEQUENCE_ENTRY:
+ return _parseIndentlessSequenceEntry();
+ case _State.BLOCK_MAPPING_FIRST_KEY:
+ // Scan past the `BLOCK-MAPPING-FIRST-KEY` token to the
+ // `BLOCK-MAPPING-KEY` token.
+ _scanner.scan();
+ return _parseBlockMappingKey();
+ case _State.BLOCK_MAPPING_KEY:
+ return _parseBlockMappingKey();
+ case _State.BLOCK_MAPPING_VALUE:
+ return _parseBlockMappingValue();
+ case _State.FLOW_SEQUENCE_FIRST_ENTRY:
+ return _parseFlowSequenceEntry(first: true);
+ case _State.FLOW_SEQUENCE_ENTRY:
+ return _parseFlowSequenceEntry();
+ case _State.FLOW_SEQUENCE_ENTRY_MAPPING_KEY:
+ return _parseFlowSequenceEntryMappingKey();
+ case _State.FLOW_SEQUENCE_ENTRY_MAPPING_VALUE:
+ return _parseFlowSequenceEntryMappingValue();
+ case _State.FLOW_SEQUENCE_ENTRY_MAPPING_END:
+ return _parseFlowSequenceEntryMappingEnd();
+ case _State.FLOW_MAPPING_FIRST_KEY:
+ return _parseFlowMappingKey(first: true);
+ case _State.FLOW_MAPPING_KEY:
+ return _parseFlowMappingKey();
+ case _State.FLOW_MAPPING_VALUE:
+ return _parseFlowMappingValue();
+ case _State.FLOW_MAPPING_EMPTY_VALUE:
+ return _parseFlowMappingValue(empty: true);
+ default:
+ throw "Unreachable";
+ }
+ }
+
+ /// Parses the production:
+ ///
+ /// stream ::=
+ /// STREAM-START implicit_document? explicit_document* STREAM-END
+ /// ************
+ Event _parseStreamStart() {
+ var token = _scanner.scan();
+ assert(token.type == TokenType.STREAM_START);
+
+ _state = _State.DOCUMENT_START;
+ return new Event(EventType.STREAM_START, token.span);
+ }
+
+ /// Parses the productions:
+ ///
+ /// implicit_document ::= block_node DOCUMENT-END*
+ /// *
+ /// explicit_document ::=
+ /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ /// *************************
+ Event _parseDocumentStart() {
+ var token = _scanner.peek();
+
+ // libyaml requires any document beyond the first in the stream to have an
+ // explicit document start indicator, but the spec allows it to be omitted
+ // as long as there was an end indicator.
+
+ // Parse extra document end indicators.
+ while (token.type == TokenType.DOCUMENT_END) {
+ token = _scanner.advance();
+ }
+
+ if (token.type != TokenType.VERSION_DIRECTIVE &&
+ token.type != TokenType.TAG_DIRECTIVE &&
+ token.type != TokenType.DOCUMENT_START &&
+ token.type != TokenType.STREAM_END) {
+ // Parse an implicit document.
+ _processDirectives();
+ _states.add(_State.DOCUMENT_END);
+ _state = _State.BLOCK_NODE;
+ return new DocumentStartEvent(token.span.start.pointSpan());
+ }
+
+ if (token.type == TokenType.STREAM_END) {
+ _state = _State.END;
+ _scanner.scan();
+ return new Event(EventType.STREAM_END, token.span);
+ }
+
+ // Parse an explicit document.
+ var start = token.span;
+ var pair = _processDirectives();
+ var versionDirective = pair.first;
+ var tagDirectives = pair.last;
+ token = _scanner.peek();
+ if (token.type != TokenType.DOCUMENT_START) {
+ throw new YamlException("Expected document start.", token.span);
+ }
+
+ _states.add(_State.DOCUMENT_END);
+ _state = _State.DOCUMENT_CONTENT;
+ _scanner.scan();
+ return new DocumentStartEvent(start.expand(token.span),
+ versionDirective: versionDirective,
+ tagDirectives: tagDirectives,
+ isImplicit: false);
+ }
+
+ /// Parses the productions:
+ ///
+ /// explicit_document ::=
+ /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ /// ***********
+ Event _parseDocumentContent() {
+ var token = _scanner.peek();
+
+ switch (token.type) {
+ case TokenType.VERSION_DIRECTIVE:
+ case TokenType.TAG_DIRECTIVE:
+ case TokenType.DOCUMENT_START:
+ case TokenType.DOCUMENT_END:
+ case TokenType.STREAM_END:
+ _state = _states.removeLast();
+ return _processEmptyScalar(token.span.start);
+ default:
+ return _parseNode(block: true);
+ }
+ }
+
+ /// Parses the productions:
+ ///
+ /// implicit_document ::= block_node DOCUMENT-END*
+ /// *************
+ /// explicit_document ::=
+ /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ /// *************
+ Event _parseDocumentEnd() {
+ _tagDirectives.clear();
+ _state = _State.DOCUMENT_START;
+
+ var token = _scanner.peek();
+ if (token.type == TokenType.DOCUMENT_END) {
+ _scanner.scan();
+ return new DocumentEndEvent(token.span, isImplicit: false);
+ } else {
+ return new DocumentEndEvent(
+ token.span.start.pointSpan(), isImplicit: true);
+ }
+ }
+
+ /// Parses the productions:
+ ///
+ /// block_node_or_indentless_sequence ::=
+ /// ALIAS
+ /// *****
+ /// | properties (block_content | indentless_block_sequence)?
+ /// ********** *
+ /// | block_content | indentless_block_sequence
+ /// *
+ /// block_node ::= ALIAS
+ /// *****
+ /// | properties block_content?
+ /// ********** *
+ /// | block_content
+ /// *
+ /// flow_node ::= ALIAS
+ /// *****
+ /// | properties flow_content?
+ /// ********** *
+ /// | flow_content
+ /// *
+ /// properties ::= TAG ANCHOR? | ANCHOR TAG?
+ /// *************************
+ /// block_content ::= block_collection | flow_collection | SCALAR
+ /// ******
+ /// flow_content ::= flow_collection | SCALAR
+ /// ******
+ Event _parseNode({bool block: false, bool indentlessSequence: false}) {
+ var token = _scanner.peek();
+
+ if (token is AliasToken) {
+ _scanner.scan();
+ _state = _states.removeLast();
+ return new AliasEvent(token.span, token.name);
+ }
+
+ var anchor;
+ var tagToken;
+ var span = token.span.start.pointSpan();
+ parseAnchor() {
+ anchor = token.name;
+ span = span.expand(token.span);
+ token = _scanner.advance();
+ }
+
+ parseTag() {
+ tagToken = token;
+ span = span.expand(token.span);
+ token = _scanner.advance();
+ }
+
+ if (token is AnchorToken) {
+ parseAnchor();
+ if (token is TagToken) parseTag();
+ } else if (token is TagToken) {
+ parseTag();
+ if (token is AnchorToken) parseAnchor();
+ }
+
+ var tag;
+ if (tagToken != null) {
+ if (tagToken.handle == null) {
+ tag = tagToken.suffix;
+ } else {
+ var tagDirective = _tagDirectives[tagToken.handle];
+ if (tagDirective == null) {
+ throw new YamlException("Undefined tag handle.", tagToken.span);
+ }
+
+ tag = tagDirective.prefix + tagToken.suffix;
+ }
+ }
+
+ if (indentlessSequence && token.type == TokenType.BLOCK_ENTRY) {
+ _state = _State.INDENTLESS_SEQUENCE_ENTRY;
+ return new SequenceStartEvent(
+ span.expand(token.span), CollectionStyle.BLOCK,
+ anchor: anchor, tag: tag);
+ }
+
+ if (token is ScalarToken) {
+ // All non-plain scalars have the "!" tag by default.
+ if (tag == null && token.style != ScalarStyle.PLAIN) tag = "!";
+
+ _state = _states.removeLast();
+ _scanner.scan();
+ return new ScalarEvent(
+ span.expand(token.span), token.value, token.style,
+ anchor: anchor, tag: tag);
+ }
+
+ if (token.type == TokenType.FLOW_SEQUENCE_START) {
+ _state = _State.FLOW_SEQUENCE_FIRST_ENTRY;
+ return new SequenceStartEvent(
+ span.expand(token.span), CollectionStyle.FLOW,
+ anchor: anchor, tag: tag);
+ }
+
+ if (token.type == TokenType.FLOW_MAPPING_START) {
+ _state = _State.FLOW_MAPPING_FIRST_KEY;
+ return new MappingStartEvent(
+ span.expand(token.span), CollectionStyle.FLOW,
+ anchor: anchor, tag: tag);
+ }
+
+ if (block && token.type == TokenType.BLOCK_SEQUENCE_START) {
+ _state = _State.BLOCK_SEQUENCE_FIRST_ENTRY;
+ return new SequenceStartEvent(
+ span.expand(token.span), CollectionStyle.BLOCK,
+ anchor: anchor, tag: tag);
+ }
+
+
+ if (block && token.type == TokenType.BLOCK_MAPPING_START) {
+ _state = _State.BLOCK_MAPPING_FIRST_KEY;
+ return new MappingStartEvent(
+ span.expand(token.span), CollectionStyle.BLOCK,
+ anchor: anchor, tag: tag);
+ }
+
+ if (anchor != null || tag != null) {
+ _state = _states.removeLast();
+ return new ScalarEvent(
+ span, '', ScalarStyle.PLAIN,
+ anchor: anchor, tag: tag);
+ }
+
+ throw new YamlException("Expected node content.", span);
+ }
+
+ /// Parses the productions:
+ ///
+ /// block_sequence ::=
+ /// BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+ /// ******************** *********** * *********
+ Event _parseBlockSequenceEntry() {
+ var token = _scanner.peek();
+
+ if (token.type == TokenType.BLOCK_ENTRY) {
+ token = _scanner.advance();
+
+ if (token.type == TokenType.BLOCK_ENTRY ||
+ token.type == TokenType.BLOCK_END) {
+ _state = _State.BLOCK_SEQUENCE_ENTRY;
+ return _processEmptyScalar(token.span.end);
+ } else {
+ _states.add(_State.BLOCK_SEQUENCE_ENTRY);
+ return _parseNode(block: true);
+ }
+ }
+
+ if (token.type == TokenType.BLOCK_END) {
+ _scanner.scan();
+ _state = _states.removeLast();
+ return new Event(EventType.SEQUENCE_END, token.span);
+ }
+
+ throw new YamlException("While parsing a block collection, expected '-'.",
+ token.span.start.pointSpan());
+ }
+
+ /// Parses the productions:
+ ///
+ /// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+ /// *********** *
+ Event _parseIndentlessSequenceEntry() {
+ var token = _scanner.peek();
+
+ if (token.type != TokenType.BLOCK_ENTRY) {
+ _state = _states.removeLast();
+ return new Event(EventType.SEQUENCE_END, token.span.start.pointSpan());
+ }
+
+ var start = token.span.start;
+ token = _scanner.advance();
+
+ if (token.type == TokenType.BLOCK_ENTRY ||
+ token.type == TokenType.KEY ||
+ token.type == TokenType.VALUE ||
+ token.type == TokenType.BLOCK_END) {
+ _state = _State.INDENTLESS_SEQUENCE_ENTRY;
+ return _processEmptyScalar(start);
+ } else {
+ _states.add(_State.INDENTLESS_SEQUENCE_ENTRY);
+ return _parseNode(block: true);
+ }
+ }
+
+ /// Parses the productions:
+ ///
+ /// block_mapping ::= BLOCK-MAPPING_START
+ /// *******************
+ /// ((KEY block_node_or_indentless_sequence?)?
+ /// *** *
+ /// (VALUE block_node_or_indentless_sequence?)?)*
+ ///
+ /// BLOCK-END
+ /// *********
+ Event _parseBlockMappingKey() {
+ var token = _scanner.peek();
+ if (token.type == TokenType.KEY) {
+ var start = token.span.start;
+ token = _scanner.advance();
+
+ if (token.type == TokenType.KEY ||
+ token.type == TokenType.VALUE ||
+ token.type == TokenType.BLOCK_END) {
+ _state = _State.BLOCK_MAPPING_VALUE;
+ return _processEmptyScalar(start);
+ } else {
+ _states.add(_State.BLOCK_MAPPING_VALUE);
+ return _parseNode(block: true, indentlessSequence: true);
+ }
+ }
+
+ // libyaml doesn't allow empty keys without an explicit key indicator, but
+ // the spec does. See example 8.18:
+ // http://yaml.org/spec/1.2/spec.html#id2798896.
+ if (token.type == TokenType.VALUE) {
+ _state = _State.BLOCK_MAPPING_VALUE;
+ return _processEmptyScalar(token.span.start);
+ }
+
+ if (token.type == TokenType.BLOCK_END) {
+ _scanner.scan();
+ _state = _states.removeLast();
+ return new Event(EventType.MAPPING_END, token.span);
+ }
+
+ throw new YamlException("Expected a key while parsing a block mapping.",
+ token.span.start.pointSpan());
+ }
+
+ /// Parses the productions:
+ ///
+ /// block_mapping ::= BLOCK-MAPPING_START
+ ///
+ /// ((KEY block_node_or_indentless_sequence?)?
+ ///
+ /// (VALUE block_node_or_indentless_sequence?)?)*
+ /// ***** *
+ /// BLOCK-END
+ ///
+ Event _parseBlockMappingValue() {
+ var token = _scanner.peek();
+
+ if (token.type != TokenType.VALUE) {
+ _state = _State.BLOCK_MAPPING_KEY;
+ return _processEmptyScalar(token.span.start);
+ }
+
+ var start = token.span.start;
+ token = _scanner.advance();
+ if (token.type == TokenType.KEY ||
+ token.type == TokenType.VALUE ||
+ token.type == TokenType.BLOCK_END) {
+ _state = _State.BLOCK_MAPPING_KEY;
+ return _processEmptyScalar(start);
+ } else {
+ _states.add(_State.BLOCK_MAPPING_KEY);
+ return _parseNode(block: true, indentlessSequence: true);
+ }
+ }
+
+ /// Parses the productions:
+ ///
+ /// flow_sequence ::= FLOW-SEQUENCE-START
+ /// *******************
+ /// (flow_sequence_entry FLOW-ENTRY)*
+ /// * **********
+ /// flow_sequence_entry?
+ /// *
+ /// FLOW-SEQUENCE-END
+ /// *****************
+ /// flow_sequence_entry ::=
+ /// flow_node | KEY flow_node? (VALUE flow_node?)?
+ /// *
+ Event _parseFlowSequenceEntry({bool first: false}) {
+ if (first) _scanner.scan();
+ var token = _scanner.peek();
+
+ if (token.type != TokenType.FLOW_SEQUENCE_END) {
+ if (!first) {
+ if (token.type != TokenType.FLOW_ENTRY) {
+ throw new YamlException(
+ "While parsing a flow sequence, expected ',' or ']'.",
+ token.span.start.pointSpan());
+ }
+
+ token = _scanner.advance();
+ }
+
+ if (token.type == TokenType.KEY) {
+ _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_KEY;
+ _scanner.scan();
+ return new MappingStartEvent(
+ token.span, CollectionStyle.FLOW);
+ } else if (token.type != TokenType.FLOW_SEQUENCE_END) {
+ _states.add(_State.FLOW_SEQUENCE_ENTRY);
+ return _parseNode();
+ }
+ }
+
+ _scanner.scan();
+ _state = _states.removeLast();
+ return new Event(EventType.SEQUENCE_END, token.span);
+ }
+
+ /// Parses the productions:
+ ///
+ /// flow_sequence_entry ::=
+ /// flow_node | KEY flow_node? (VALUE flow_node?)?
+ /// *** *
+ Event _parseFlowSequenceEntryMappingKey() {
+ var token = _scanner.peek();
+
+ if (token.type == TokenType.VALUE ||
+ token.type == TokenType.FLOW_ENTRY ||
+ token.type == TokenType.FLOW_SEQUENCE_END) {
+ // libyaml consumes the token here, but that seems like a bug, since it
+ // always causes [_parseFlowSequenceEntryMappingValue] to emit an empty
+ // scalar.
+
+ var start = token.span.start;
+ _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_VALUE;
+ return _processEmptyScalar(start);
+ } else {
+ _states.add(_State.FLOW_SEQUENCE_ENTRY_MAPPING_VALUE);
+ return _parseNode();
+ }
+ }
+
+ /// Parses the productions:
+ ///
+ /// flow_sequence_entry ::=
+ /// flow_node | KEY flow_node? (VALUE flow_node?)?
+ /// ***** *
+ Event _parseFlowSequenceEntryMappingValue() {
+ var token = _scanner.peek();
+
+ if (token.type == TokenType.VALUE) {
+ token = _scanner.advance();
+ if (token.type != TokenType.FLOW_ENTRY &&
+ token.type != TokenType.FLOW_SEQUENCE_END) {
+ _states.add(_State.FLOW_SEQUENCE_ENTRY_MAPPING_END);
+ return _parseNode();
+ }
+ }
+
+ _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_END;
+ return _processEmptyScalar(token.span.start);
+ }
+
+ /// Parses the productions:
+ ///
+ /// flow_sequence_entry ::=
+ /// flow_node | KEY flow_node? (VALUE flow_node?)?
+ /// *
+ Event _parseFlowSequenceEntryMappingEnd() {
+ _state = _State.FLOW_SEQUENCE_ENTRY;
+ return new Event(EventType.MAPPING_END,
+ _scanner.peek().span.start.pointSpan());
+ }
+
+ /// Parses the productions:
+ ///
+ /// flow_mapping ::= FLOW-MAPPING-START
+ /// ******************
+ /// (flow_mapping_entry FLOW-ENTRY)*
+ /// * **********
+ /// flow_mapping_entry?
+ /// ******************
+ /// FLOW-MAPPING-END
+ /// ****************
+ /// flow_mapping_entry ::=
+ /// flow_node | KEY flow_node? (VALUE flow_node?)?
+ /// * *** *
+ Event _parseFlowMappingKey({bool first: false}) {
+ if (first) _scanner.scan();
+ var token = _scanner.peek();
+
+ if (token.type != TokenType.FLOW_MAPPING_END) {
+ if (!first) {
+ if (token.type != TokenType.FLOW_ENTRY) {
+ throw new YamlException(
+ "While parsing a flow mapping, expected ',' or '}'.",
+ token.span.start.pointSpan());
+ }
+
+ token = _scanner.advance();
+ }
+
+ if (token.type == TokenType.KEY) {
+ token = _scanner.advance();
+ if (token.type != TokenType.VALUE &&
+ token.type != TokenType.FLOW_ENTRY &&
+ token.type != TokenType.FLOW_MAPPING_END) {
+ _states.add(_State.FLOW_MAPPING_VALUE);
+ return _parseNode();
+ } else {
+ _state = _State.FLOW_MAPPING_VALUE;
+ return _processEmptyScalar(token.span.start);
+ }
+ } else if (token.type != TokenType.FLOW_MAPPING_END) {
+ _states.add(_State.FLOW_MAPPING_EMPTY_VALUE);
+ return _parseNode();
+ }
+ }
+
+ _scanner.scan();
+ _state = _states.removeLast();
+ return new Event(EventType.MAPPING_END, token.span);
+ }
+
+ /// Parses the productions:
+ ///
+ /// flow_mapping_entry ::=
+ /// flow_node | KEY flow_node? (VALUE flow_node?)?
+ /// * ***** *
+ Event _parseFlowMappingValue({bool empty: false}) {
+ var token = _scanner.peek();
+
+ if (empty) {
+ _state = _State.FLOW_MAPPING_KEY;
+ return _processEmptyScalar(token.span.start);
+ }
+
+ if (token.type == TokenType.VALUE) {
+ token = _scanner.advance();
+ if (token.type != TokenType.FLOW_ENTRY &&
+ token.type != TokenType.FLOW_MAPPING_END) {
+ _states.add(_State.FLOW_MAPPING_KEY);
+ return _parseNode();
+ }
+ }
+
+ _state = _State.FLOW_MAPPING_KEY;
+ return _processEmptyScalar(token.span.start);
+ }
+
+ /// Generate an empty scalar event.
+ Event _processEmptyScalar(SourceLocation location) =>
+ new ScalarEvent(location.pointSpan(), '', ScalarStyle.PLAIN);
+
+ /// Parses directives.
+ Pair<VersionDirective, List<TagDirective>> _processDirectives() {
+ var token = _scanner.peek();
+
+ var versionDirective;
+ var tagDirectives = [];
+ while (token.type == TokenType.VERSION_DIRECTIVE ||
+ token.type == TokenType.TAG_DIRECTIVE) {
+ if (token is VersionDirectiveToken) {
+ if (versionDirective != null) {
+ throw new YamlException("Duplicate %YAML directive.", token.span);
+ }
+
+ if (token.major != 1 || token.minor == 0) {
+ throw new YamlException(
+ "Incompatible YAML document. This parser only supports YAML 1.1 "
+ "and 1.2.",
+ token.span);
+ } else if (token.minor > 2) {
+ // TODO(nweiz): Print to stderr when issue 6943 is fixed and dart:io
+ // is available.
+ warn("Warning: this parser only supports YAML 1.1 and 1.2.",
+ token.span);
+ }
+
+ versionDirective = new VersionDirective(token.major, token.minor);
+ } else if (token is TagDirectiveToken) {
+ var tagDirective = new TagDirective(token.handle, token.prefix);
+ _appendTagDirective(tagDirective, token.span);
+ tagDirectives.add(tagDirective);
+ }
+
+ token = _scanner.advance();
+ }
+
+ _appendTagDirective(
+ new TagDirective("!", "!"),
+ token.span.start.pointSpan(),
+ allowDuplicates: true);
+ _appendTagDirective(
+ new TagDirective("!!", "tag:yaml.org,2002:"),
+ token.span.start.pointSpan(),
+ allowDuplicates: true);
+
+ return new Pair(versionDirective, tagDirectives);
+ }
+
+ /// Adds a tag directive to the directives stack.
+ void _appendTagDirective(TagDirective newDirective, FileSpan span,
+ {bool allowDuplicates: false}) {
+ if (_tagDirectives.containsKey(newDirective.handle)) {
+ if (allowDuplicates) return;
+ throw new YamlException("Duplicate %TAG directive.", span);
+ }
+
+ _tagDirectives[newDirective.handle] = newDirective;
+ }
+}
+
+/// The possible states for the parser.
+class _State {
+ /// Expect [TokenType.STREAM_START].
+ static const STREAM_START = const _State("STREAM_START");
+
+ /// Expect the beginning of an implicit document.
+ static const IMPLICIT_DOCUMENT_START =
+ const _State("IMPLICIT_DOCUMENT_START");
+
+ /// Expect [TokenType.DOCUMENT_START].
+ static const DOCUMENT_START = const _State("DOCUMENT_START");
+
+ /// Expect the content of a document.
+ static const DOCUMENT_CONTENT = const _State("DOCUMENT_CONTENT");
+
+ /// Expect [TokenType.DOCUMENT_END].
+ static const DOCUMENT_END = const _State("DOCUMENT_END");
+
+ /// Expect a block node.
+ static const BLOCK_NODE = const _State("BLOCK_NODE");
+
+ /// Expect a block node or indentless sequence.
+ static const BLOCK_NODE_OR_INDENTLESS_SEQUENCE =
+ const _State("BLOCK_NODE_OR_INDENTLESS_SEQUENCE");
+
+ /// Expect a flow node.
+ static const FLOW_NODE = const _State("FLOW_NODE");
+
+ /// Expect the first entry of a block sequence.
+ static const BLOCK_SEQUENCE_FIRST_ENTRY =
+ const _State("BLOCK_SEQUENCE_FIRST_ENTRY");
+
+ /// Expect an entry of a block sequence.
+ static const BLOCK_SEQUENCE_ENTRY = const _State("BLOCK_SEQUENCE_ENTRY");
+
+ /// Expect an entry of an indentless sequence.
+ static const INDENTLESS_SEQUENCE_ENTRY =
+ const _State("INDENTLESS_SEQUENCE_ENTRY");
+
+ /// Expect the first key of a block mapping.
+ static const BLOCK_MAPPING_FIRST_KEY =
+ const _State("BLOCK_MAPPING_FIRST_KEY");
+
+ /// Expect a block mapping key.
+ static const BLOCK_MAPPING_KEY = const _State("BLOCK_MAPPING_KEY");
+
+ /// Expect a block mapping value.
+ static const BLOCK_MAPPING_VALUE = const _State("BLOCK_MAPPING_VALUE");
+
+ /// Expect the first entry of a flow sequence.
+ static const FLOW_SEQUENCE_FIRST_ENTRY =
+ const _State("FLOW_SEQUENCE_FIRST_ENTRY");
+
+ /// Expect an entry of a flow sequence.
+ static const FLOW_SEQUENCE_ENTRY = const _State("FLOW_SEQUENCE_ENTRY");
+
+ /// Expect a key of an ordered mapping.
+ static const FLOW_SEQUENCE_ENTRY_MAPPING_KEY =
+ const _State("FLOW_SEQUENCE_ENTRY_MAPPING_KEY");
+
+ /// Expect a value of an ordered mapping.
+ static const FLOW_SEQUENCE_ENTRY_MAPPING_VALUE =
+ const _State("FLOW_SEQUENCE_ENTRY_MAPPING_VALUE");
+
+ /// Expect the and of an ordered mapping entry.
+ static const FLOW_SEQUENCE_ENTRY_MAPPING_END =
+ const _State("FLOW_SEQUENCE_ENTRY_MAPPING_END");
+
+ /// Expect the first key of a flow mapping.
+ static const FLOW_MAPPING_FIRST_KEY = const _State("FLOW_MAPPING_FIRST_KEY");
+
+ /// Expect a key of a flow mapping.
+ static const FLOW_MAPPING_KEY = const _State("FLOW_MAPPING_KEY");
+
+ /// Expect a value of a flow mapping.
+ static const FLOW_MAPPING_VALUE = const _State("FLOW_MAPPING_VALUE");
+
+ /// Expect an empty value of a flow mapping.
+ static const FLOW_MAPPING_EMPTY_VALUE =
+ const _State("FLOW_MAPPING_EMPTY_VALUE");
+
+ /// Expect nothing.
+ static const END = const _State("END");
+
+ final String name;
+
+ const _State(this.name);
+
+ String toString() => name;
+}
« no previous file with comments | « mojo/public/dart/third_party/yaml/lib/src/null_span.dart ('k') | mojo/public/dart/third_party/yaml/lib/src/scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698