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 /// This file contains the node classes for the internal representations of YAML | 5 /// This file contains the node classes for the internal representations of YAML |
6 /// documents. These nodes are used for both the serialization tree and the | 6 /// documents. These nodes are used for both the serialization tree and the |
7 /// representation graph. | 7 /// representation graph. |
8 library yaml.model; | 8 library yaml.model; |
9 | 9 |
10 import 'package:source_maps/source_maps.dart'; | 10 import 'package:source_span/source_span.dart'; |
11 | 11 |
12 import 'equality.dart'; | 12 import 'equality.dart'; |
13 import 'parser.dart'; | 13 import 'parser.dart'; |
14 import 'visitor.dart'; | 14 import 'visitor.dart'; |
15 import 'yaml_exception.dart'; | 15 import 'yaml_exception.dart'; |
16 | 16 |
17 /// The prefix for tag types defined by the YAML spec. | 17 /// The prefix for tag types defined by the YAML spec. |
18 const _YAML_URI_PREFIX = "tag:yaml.org,2002:"; | 18 const _YAML_URI_PREFIX = "tag:yaml.org,2002:"; |
19 | 19 |
20 /// A tag that indicates the type of a YAML node. | 20 /// A tag that indicates the type of a YAML node. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 | 76 |
77 /// The abstract class for YAML nodes. | 77 /// The abstract class for YAML nodes. |
78 abstract class Node { | 78 abstract class Node { |
79 /// Every YAML node has a tag that describes its type. | 79 /// Every YAML node has a tag that describes its type. |
80 Tag tag; | 80 Tag tag; |
81 | 81 |
82 /// Any YAML node can have an anchor associated with it. | 82 /// Any YAML node can have an anchor associated with it. |
83 String anchor; | 83 String anchor; |
84 | 84 |
85 /// The source span for this node. | 85 /// The source span for this node. |
86 Span span; | 86 SourceSpan span; |
87 | 87 |
88 Node(this.tag, this.span, [this.anchor]); | 88 Node(this.tag, this.span, [this.anchor]); |
89 | 89 |
90 bool operator ==(other) { | 90 bool operator ==(other) { |
91 if (other is! Node) return false; | 91 if (other is! Node) return false; |
92 return tag == other.tag; | 92 return tag == other.tag; |
93 } | 93 } |
94 | 94 |
95 int get hashCode => tag.hashCode ^ anchor.hashCode; | 95 int get hashCode => tag.hashCode ^ anchor.hashCode; |
96 | 96 |
97 visit(Visitor v); | 97 visit(Visitor v); |
98 } | 98 } |
99 | 99 |
100 /// A sequence node represents an ordered list of nodes. | 100 /// A sequence node represents an ordered list of nodes. |
101 class SequenceNode extends Node { | 101 class SequenceNode extends Node { |
102 /// The nodes in the sequence. | 102 /// The nodes in the sequence. |
103 List<Node> content; | 103 List<Node> content; |
104 | 104 |
105 SequenceNode(String tagName, this.content, Span span) | 105 SequenceNode(String tagName, this.content, SourceSpan span) |
106 : super(new Tag.sequence(tagName), span); | 106 : super(new Tag.sequence(tagName), span); |
107 | 107 |
108 /// Two sequences are equal if their tags and contents are equal. | 108 /// Two sequences are equal if their tags and contents are equal. |
109 bool operator ==(other) { | 109 bool operator ==(other) { |
110 // Should be super != other; bug 2554 | 110 // Should be super != other; bug 2554 |
111 if (!(super == other) || other is! SequenceNode) return false; | 111 if (!(super == other) || other is! SequenceNode) return false; |
112 if (content.length != other.content.length) return false; | 112 if (content.length != other.content.length) return false; |
113 for (var i = 0; i < content.length; i++) { | 113 for (var i = 0; i < content.length; i++) { |
114 if (content[i] != other.content[i]) return false; | 114 if (content[i] != other.content[i]) return false; |
115 } | 115 } |
116 return true; | 116 return true; |
117 } | 117 } |
118 | 118 |
119 String toString() => '$tag [${content.map((e) => '$e').join(', ')}]'; | 119 String toString() => '$tag [${content.map((e) => '$e').join(', ')}]'; |
120 | 120 |
121 int get hashCode => super.hashCode ^ deepHashCode(content); | 121 int get hashCode => super.hashCode ^ deepHashCode(content); |
122 | 122 |
123 visit(Visitor v) => v.visitSequence(this); | 123 visit(Visitor v) => v.visitSequence(this); |
124 } | 124 } |
125 | 125 |
126 /// An alias node is a reference to an anchor. | 126 /// An alias node is a reference to an anchor. |
127 class AliasNode extends Node { | 127 class AliasNode extends Node { |
128 AliasNode(String anchor, Span span) | 128 AliasNode(String anchor, SourceSpan span) |
129 : super(new Tag.scalar(Tag.yaml("str")), span, anchor); | 129 : super(new Tag.scalar(Tag.yaml("str")), span, anchor); |
130 | 130 |
131 visit(Visitor v) => v.visitAlias(this); | 131 visit(Visitor v) => v.visitAlias(this); |
132 } | 132 } |
133 | 133 |
134 /// A scalar node represents all YAML nodes that have a single value. | 134 /// A scalar node represents all YAML nodes that have a single value. |
135 class ScalarNode extends Node { | 135 class ScalarNode extends Node { |
136 /// The string value of the scalar node, if it was created by the parser. | 136 /// The string value of the scalar node, if it was created by the parser. |
137 final String _content; | 137 final String _content; |
138 | 138 |
139 /// The Dart value of the scalar node, if it was created by the composer. | 139 /// The Dart value of the scalar node, if it was created by the composer. |
140 final value; | 140 final value; |
141 | 141 |
142 /// Creates a new Scalar node. | 142 /// Creates a new Scalar node. |
143 /// | 143 /// |
144 /// Exactly one of [content] and [value] should be specified. Content should | 144 /// Exactly one of [content] and [value] should be specified. Content should |
145 /// be specified for a newly-parsed scalar that hasn't yet been composed. | 145 /// be specified for a newly-parsed scalar that hasn't yet been composed. |
146 /// Value should be specified for a composed scalar, although `null` is a | 146 /// Value should be specified for a composed scalar, although `null` is a |
147 /// valid value. | 147 /// valid value. |
148 ScalarNode(String tagName, Span span, {String content, this.value}) | 148 ScalarNode(String tagName, SourceSpan span, {String content, this.value}) |
149 : _content = content, | 149 : _content = content, |
150 super(new Tag.scalar(tagName), span); | 150 super(new Tag.scalar(tagName), span); |
151 | 151 |
152 /// Two scalars are equal if their string representations are equal. | 152 /// Two scalars are equal if their string representations are equal. |
153 bool operator ==(other) { | 153 bool operator ==(other) { |
154 // Should be super != other; bug 2554 | 154 // Should be super != other; bug 2554 |
155 if (!(super == other) || other is! ScalarNode) return false; | 155 if (!(super == other) || other is! ScalarNode) return false; |
156 return content == other.content; | 156 return content == other.content; |
157 } | 157 } |
158 | 158 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 int get hashCode => super.hashCode ^ content.hashCode; | 224 int get hashCode => super.hashCode ^ content.hashCode; |
225 | 225 |
226 visit(Visitor v) => v.visitScalar(this); | 226 visit(Visitor v) => v.visitScalar(this); |
227 } | 227 } |
228 | 228 |
229 /// A mapping node represents an unordered map of nodes to nodes. | 229 /// A mapping node represents an unordered map of nodes to nodes. |
230 class MappingNode extends Node { | 230 class MappingNode extends Node { |
231 /// The node map. | 231 /// The node map. |
232 Map<Node, Node> content; | 232 Map<Node, Node> content; |
233 | 233 |
234 MappingNode(String tagName, this.content, Span span) | 234 MappingNode(String tagName, this.content, SourceSpan span) |
235 : super(new Tag.mapping(tagName), span); | 235 : super(new Tag.mapping(tagName), span); |
236 | 236 |
237 /// Two mappings are equal if their tags and contents are equal. | 237 /// Two mappings are equal if their tags and contents are equal. |
238 bool operator ==(other) { | 238 bool operator ==(other) { |
239 // Should be super != other; bug 2554 | 239 // Should be super != other; bug 2554 |
240 if (!(super == other) || other is! MappingNode) return false; | 240 if (!(super == other) || other is! MappingNode) return false; |
241 if (content.length != other.content.length) return false; | 241 if (content.length != other.content.length) return false; |
242 for (var key in content.keys) { | 242 for (var key in content.keys) { |
243 if (!other.content.containsKey(key)) return false; | 243 if (!other.content.containsKey(key)) return false; |
244 if (content[key] != other.content[key]) return false; | 244 if (content[key] != other.content[key]) return false; |
245 } | 245 } |
246 return true; | 246 return true; |
247 } | 247 } |
248 | 248 |
249 String toString() { | 249 String toString() { |
250 var strContent = content.keys | 250 var strContent = content.keys |
251 .map((k) => '${k}: ${content[k]}') | 251 .map((k) => '${k}: ${content[k]}') |
252 .join(', '); | 252 .join(', '); |
253 return '$tag {$strContent}'; | 253 return '$tag {$strContent}'; |
254 } | 254 } |
255 | 255 |
256 int get hashCode => super.hashCode ^ deepHashCode(content); | 256 int get hashCode => super.hashCode ^ deepHashCode(content); |
257 | 257 |
258 visit(Visitor v) => v.visitMapping(this); | 258 visit(Visitor v) => v.visitMapping(this); |
259 } | 259 } |
OLD | NEW |