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

Side by Side Diff: pkg/yaml/lib/src/composer.dart

Issue 302313007: Attach source range information to parsed YAML nodes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix tests Created 6 years, 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/yaml/CHANGELOG.md ('k') | pkg/yaml/lib/src/constructor.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 library yaml.composer; 5 library yaml.composer;
6 6
7 import 'package:source_maps/source_maps.dart';
8
7 import 'model.dart'; 9 import 'model.dart';
8 import 'visitor.dart'; 10 import 'visitor.dart';
9 import 'yaml_exception.dart'; 11 import 'yaml_exception.dart';
10 12
11 /// Takes a parsed YAML document (what the spec calls the "serialization tree") 13 /// Takes a parsed YAML document (what the spec calls the "serialization tree")
12 /// and resolves aliases, resolves tags, and parses scalars to produce the 14 /// and resolves aliases, resolves tags, and parses scalars to produce the
13 /// "representation graph". 15 /// "representation graph".
14 class Composer extends Visitor { 16 class Composer extends Visitor {
15 /// The root node of the serialization tree. 17 /// The root node of the serialization tree.
16 final Node _root; 18 final Node _root;
(...skipping 21 matching lines...) Expand all
38 } 40 }
39 return _anchors[alias.anchor]; 41 return _anchors[alias.anchor];
40 } 42 }
41 43
42 /// Parses a scalar node according to its tag, or auto-detects the type if no 44 /// Parses a scalar node according to its tag, or auto-detects the type if no
43 /// tag exists. 45 /// tag exists.
44 /// 46 ///
45 /// Currently this only supports the YAML core type schema. 47 /// Currently this only supports the YAML core type schema.
46 Node visitScalar(ScalarNode scalar) { 48 Node visitScalar(ScalarNode scalar) {
47 if (scalar.tag.name == "!") { 49 if (scalar.tag.name == "!") {
48 return setAnchor(scalar, parseString(scalar.content)); 50 return setAnchor(scalar, parseString(scalar));
49 } else if (scalar.tag.name == "?") { 51 } else if (scalar.tag.name == "?") {
50 for (var fn in [parseNull, parseBool, parseInt, parseFloat]) { 52 for (var fn in [parseNull, parseBool, parseInt, parseFloat]) {
51 var result = fn(scalar.content); 53 var result = fn(scalar);
52 if (result != null) return result; 54 if (result != null) return result;
53 } 55 }
54 return setAnchor(scalar, parseString(scalar.content)); 56 return setAnchor(scalar, parseString(scalar));
55 } 57 }
56 58
57 var result = _parseByTag(scalar); 59 var result = _parseByTag(scalar);
58 if (result != null) return setAnchor(scalar, result); 60 if (result != null) return setAnchor(scalar, result);
59 throw new YamlException('Invalid literal for ${scalar.tag}: ' 61 throw new YamlException('Invalid literal for ${scalar.tag}: '
60 '"${scalar.content}".'); 62 '"${scalar.content}".');
61 } 63 }
62 64
63 ScalarNode _parseByTag(ScalarNode scalar) { 65 ScalarNode _parseByTag(ScalarNode scalar) {
64 switch (scalar.tag.name) { 66 switch (scalar.tag.name) {
65 case "null": return parseNull(scalar.content); 67 case "null": return parseNull(scalar);
66 case "bool": return parseBool(scalar.content); 68 case "bool": return parseBool(scalar);
67 case "int": return parseInt(scalar.content); 69 case "int": return parseInt(scalar);
68 case "float": return parseFloat(scalar.content); 70 case "float": return parseFloat(scalar);
69 case "str": return parseString(scalar.content); 71 case "str": return parseString(scalar);
70 } 72 }
71 throw new YamlException('Undefined tag: ${scalar.tag}.'); 73 throw new YamlException('Undefined tag: ${scalar.tag}.');
72 } 74 }
73 75
74 /// Assigns a tag to the sequence and recursively composes its contents. 76 /// Assigns a tag to the sequence and recursively composes its contents.
75 Node visitSequence(SequenceNode seq) { 77 Node visitSequence(SequenceNode seq) {
76 var tagName = seq.tag.name; 78 var tagName = seq.tag.name;
77 if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("seq")) { 79 if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("seq")) {
78 throw new YamlException("Invalid tag for sequence: ${seq.tag}."); 80 throw new YamlException("Invalid tag for sequence: ${seq.tag}.");
79 } 81 }
80 82
81 var result = setAnchor(seq, new SequenceNode(Tag.yaml('seq'), null)); 83 var result = setAnchor(seq,
84 new SequenceNode(Tag.yaml('seq'), null, seq.span));
82 result.content = super.visitSequence(seq); 85 result.content = super.visitSequence(seq);
83 return result; 86 return result;
84 } 87 }
85 88
86 /// Assigns a tag to the mapping and recursively composes its contents. 89 /// Assigns a tag to the mapping and recursively composes its contents.
87 Node visitMapping(MappingNode map) { 90 Node visitMapping(MappingNode map) {
88 var tagName = map.tag.name; 91 var tagName = map.tag.name;
89 if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("map")) { 92 if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("map")) {
90 throw new YamlException("Invalid tag for mapping: ${map.tag}."); 93 throw new YamlException("Invalid tag for mapping: ${map.tag}.");
91 } 94 }
92 95
93 var result = setAnchor(map, new MappingNode(Tag.yaml('map'), null)); 96 var result = setAnchor(map,
97 new MappingNode(Tag.yaml('map'), null, map.span));
94 result.content = super.visitMapping(map); 98 result.content = super.visitMapping(map);
95 return result; 99 return result;
96 } 100 }
97 101
98 /// If the serialization tree node [anchored] has an anchor, records that 102 /// If the serialization tree node [anchored] has an anchor, records that
99 /// that anchor is pointing to the representation graph node [result]. 103 /// that anchor is pointing to the representation graph node [result].
100 Node setAnchor(Node anchored, Node result) { 104 Node setAnchor(Node anchored, Node result) {
101 if (anchored.anchor == null) return result; 105 if (anchored.anchor == null) return result;
102 result.anchor = '${_idCounter++}'; 106 result.anchor = '${_idCounter++}';
103 _anchors[anchored.anchor] = result; 107 _anchors[anchored.anchor] = result;
104 return result; 108 return result;
105 } 109 }
106 110
107 /// Parses a null scalar. 111 /// Parses a null scalar.
108 ScalarNode parseNull(String content) { 112 ScalarNode parseNull(ScalarNode scalar) {
109 if (!new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(content)) return null; 113 if (new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(scalar.content)) {
110 return new ScalarNode(Tag.yaml("null"), value: null); 114 return new ScalarNode(Tag.yaml("null"), scalar.span, value: null);
115 } else {
116 return null;
117 }
111 } 118 }
112 119
113 /// Parses a boolean scalar. 120 /// Parses a boolean scalar.
114 ScalarNode parseBool(String content) { 121 ScalarNode parseBool(ScalarNode scalar) {
115 var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). 122 var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$").
116 firstMatch(content); 123 firstMatch(scalar.content);
117 if (match == null) return null; 124 if (match == null) return null;
118 return new ScalarNode(Tag.yaml("bool"), value: match.group(1) != null); 125 return new ScalarNode(Tag.yaml("bool"), scalar.span,
126 value: match.group(1) != null);
119 } 127 }
120 128
121 /// Parses an integer scalar. 129 /// Parses an integer scalar.
122 ScalarNode parseInt(String content) { 130 ScalarNode parseInt(ScalarNode scalar) {
123 var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(content); 131 var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(scalar.content);
124 if (match != null) { 132 if (match != null) {
125 return new ScalarNode(Tag.yaml("int"), 133 return new ScalarNode(Tag.yaml("int"), scalar.span,
126 value: int.parse(match.group(0))); 134 value: int.parse(match.group(0)));
127 } 135 }
128 136
129 match = new RegExp(r"^0o([0-7]+)$").firstMatch(content); 137 match = new RegExp(r"^0o([0-7]+)$").firstMatch(scalar.content);
130 if (match != null) { 138 if (match != null) {
131 int n = int.parse(match.group(1), radix: 8); 139 int n = int.parse(match.group(1), radix: 8);
132 return new ScalarNode(Tag.yaml("int"), value: n); 140 return new ScalarNode(Tag.yaml("int"), scalar.span, value: n);
133 } 141 }
134 142
135 match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(content); 143 match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(scalar.content);
136 if (match != null) { 144 if (match != null) {
137 return new ScalarNode(Tag.yaml("int"), 145 return new ScalarNode(Tag.yaml("int"), scalar.span,
138 value: int.parse(match.group(0))); 146 value: int.parse(match.group(0)));
139 } 147 }
140 148
141 return null; 149 return null;
142 } 150 }
143 151
144 /// Parses a floating-point scalar. 152 /// Parses a floating-point scalar.
145 ScalarNode parseFloat(String content) { 153 ScalarNode parseFloat(ScalarNode scalar) {
146 var match = new RegExp( 154 var match = new RegExp(
147 r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). 155 r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$").
148 firstMatch(content); 156 firstMatch(scalar.content);
149 if (match != null) { 157 if (match != null) {
150 // YAML allows floats of the form "0.", but Dart does not. Fix up those 158 // YAML allows floats of the form "0.", but Dart does not. Fix up those
151 // floats by removing the trailing dot. 159 // floats by removing the trailing dot.
152 var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); 160 var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), "");
153 return new ScalarNode(Tag.yaml("float"), 161 return new ScalarNode(Tag.yaml("float"), scalar.span,
154 value: double.parse(matchStr)); 162 value: double.parse(matchStr));
155 } 163 }
156 164
157 match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(content); 165 match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(scalar.content);
158 if (match != null) { 166 if (match != null) {
159 var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; 167 var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY;
160 return new ScalarNode(Tag.yaml("float"), value: value); 168 return new ScalarNode(Tag.yaml("float"), scalar.span, value: value);
161 } 169 }
162 170
163 match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(content); 171 match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(scalar.content);
164 if (match != null) { 172 if (match != null) {
165 return new ScalarNode(Tag.yaml("float"), value: double.NAN); 173 return new ScalarNode(Tag.yaml("float"), scalar.span, value: double.NAN);
166 } 174 }
167 175
168 return null; 176 return null;
169 } 177 }
170 178
171 /// Parses a string scalar. 179 /// Parses a string scalar.
172 ScalarNode parseString(String content) => 180 ScalarNode parseString(ScalarNode scalar) =>
173 new ScalarNode(Tag.yaml("str"), value: content); 181 new ScalarNode(Tag.yaml("str"), scalar.span, value: scalar.content);
174 } 182 }
OLDNEW
« no previous file with comments | « pkg/yaml/CHANGELOG.md ('k') | pkg/yaml/lib/src/constructor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698