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

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: 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
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.content, scalar.span));
Bob Nystrom 2014/06/03 00:33:14 Would it make more sense to just pass the whole Sc
nweiz 2014/06/03 02:03:21 Done.
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.content, scalar.span);
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.content, scalar.span));
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.content, scalar.span);
66 case "bool": return parseBool(scalar.content); 68 case "bool": return parseBool(scalar.content, scalar.span);
67 case "int": return parseInt(scalar.content); 69 case "int": return parseInt(scalar.content, scalar.span);
68 case "float": return parseFloat(scalar.content); 70 case "float": return parseFloat(scalar.content, scalar.span);
69 case "str": return parseString(scalar.content); 71 case "str": return parseString(scalar.content, scalar.span);
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(String content, Span span) {
109 if (!new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(content)) return null; 113 if (!new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(content)) return null;
110 return new ScalarNode(Tag.yaml("null"), value: null); 114 return new ScalarNode(Tag.yaml("null"), span, value: null);
111 } 115 }
112 116
113 /// Parses a boolean scalar. 117 /// Parses a boolean scalar.
114 ScalarNode parseBool(String content) { 118 ScalarNode parseBool(String content, Span span) {
115 var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). 119 var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$").
116 firstMatch(content); 120 firstMatch(content);
117 if (match == null) return null; 121 if (match == null) return null;
118 return new ScalarNode(Tag.yaml("bool"), value: match.group(1) != null); 122 return new ScalarNode(Tag.yaml("bool"), span,
123 value: match.group(1) != null);
119 } 124 }
120 125
121 /// Parses an integer scalar. 126 /// Parses an integer scalar.
122 ScalarNode parseInt(String content) { 127 ScalarNode parseInt(String content, Span span) {
123 var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(content); 128 var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(content);
124 if (match != null) { 129 if (match != null) {
125 return new ScalarNode(Tag.yaml("int"), 130 return new ScalarNode(Tag.yaml("int"), span,
126 value: int.parse(match.group(0))); 131 value: int.parse(match.group(0)));
127 } 132 }
128 133
129 match = new RegExp(r"^0o([0-7]+)$").firstMatch(content); 134 match = new RegExp(r"^0o([0-7]+)$").firstMatch(content);
130 if (match != null) { 135 if (match != null) {
131 int n = int.parse(match.group(1), radix: 8); 136 int n = int.parse(match.group(1), radix: 8);
132 return new ScalarNode(Tag.yaml("int"), value: n); 137 return new ScalarNode(Tag.yaml("int"), span, value: n);
133 } 138 }
134 139
135 match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(content); 140 match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(content);
136 if (match != null) { 141 if (match != null) {
137 return new ScalarNode(Tag.yaml("int"), 142 return new ScalarNode(Tag.yaml("int"), span,
138 value: int.parse(match.group(0))); 143 value: int.parse(match.group(0)));
139 } 144 }
140 145
141 return null; 146 return null;
142 } 147 }
143 148
144 /// Parses a floating-point scalar. 149 /// Parses a floating-point scalar.
145 ScalarNode parseFloat(String content) { 150 ScalarNode parseFloat(String content, Span span) {
146 var match = new RegExp( 151 var match = new RegExp(
147 r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). 152 r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$").
148 firstMatch(content); 153 firstMatch(content);
149 if (match != null) { 154 if (match != null) {
150 // YAML allows floats of the form "0.", but Dart does not. Fix up those 155 // YAML allows floats of the form "0.", but Dart does not. Fix up those
151 // floats by removing the trailing dot. 156 // floats by removing the trailing dot.
152 var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); 157 var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), "");
153 return new ScalarNode(Tag.yaml("float"), 158 return new ScalarNode(Tag.yaml("float"), span,
154 value: double.parse(matchStr)); 159 value: double.parse(matchStr));
155 } 160 }
156 161
157 match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(content); 162 match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(content);
158 if (match != null) { 163 if (match != null) {
159 var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; 164 var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY;
160 return new ScalarNode(Tag.yaml("float"), value: value); 165 return new ScalarNode(Tag.yaml("float"), span, value: value);
161 } 166 }
162 167
163 match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(content); 168 match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(content);
164 if (match != null) { 169 if (match != null) {
165 return new ScalarNode(Tag.yaml("float"), value: double.NAN); 170 return new ScalarNode(Tag.yaml("float"), span, value: double.NAN);
166 } 171 }
167 172
168 return null; 173 return null;
169 } 174 }
170 175
171 /// Parses a string scalar. 176 /// Parses a string scalar.
172 ScalarNode parseString(String content) => 177 ScalarNode parseString(String content, Span span) =>
173 new ScalarNode(Tag.yaml("str"), value: content); 178 new ScalarNode(Tag.yaml("str"), span, value: content);
174 } 179 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698