OLD | NEW |
1 // This code was auto-generated, is not intended to be edited, and is subject to | 1 // This code was auto-generated, is not intended to be edited, and is subject to |
2 // significant change. Please see the README file for more information. | 2 // significant change. Please see the README file for more information. |
3 library engine.html; | 3 library engine.html; |
4 import 'dart:collection'; | 4 import 'dart:collection'; |
5 import 'java_core.dart'; | 5 import 'java_core.dart'; |
6 import 'java_engine.dart'; | 6 import 'java_engine.dart'; |
7 import 'source.dart'; | 7 import 'source.dart'; |
8 import 'error.dart'; | 8 import 'error.dart'; |
9 import 'instrumentation.dart'; | 9 import 'instrumentation.dart'; |
10 import 'element.dart' show HtmlElementImpl; | 10 import 'element.dart' show HtmlElementImpl; |
11 import 'engine.dart' show AnalysisEngine; | 11 import 'engine.dart' show AnalysisEngine; |
12 /** | 12 /** |
13 * Instances of the class `Token` represent a token that was scanned from the in
put. Each | 13 * Instances of the class `Token` represent a token that was scanned from the in
put. Each |
14 * token knows which token follows it, acting as the head of a linked list of to
kens. | 14 * token knows which token follows it, acting as the head of a linked list of to
kens. |
| 15 * |
15 * @coverage dart.engine.html | 16 * @coverage dart.engine.html |
16 */ | 17 */ |
17 class Token { | 18 class Token { |
18 | 19 |
19 /** | 20 /** |
20 * The offset from the beginning of the file to the first character in the tok
en. | 21 * The offset from the beginning of the file to the first character in the tok
en. |
21 */ | 22 */ |
22 int _offset = 0; | 23 int _offset = 0; |
23 | 24 |
24 /** | 25 /** |
(...skipping 11 matching lines...) Expand all Loading... |
36 */ | 37 */ |
37 TokenType _type; | 38 TokenType _type; |
38 | 39 |
39 /** | 40 /** |
40 * The lexeme represented by this token. | 41 * The lexeme represented by this token. |
41 */ | 42 */ |
42 String _value; | 43 String _value; |
43 | 44 |
44 /** | 45 /** |
45 * Initialize a newly created token. | 46 * Initialize a newly created token. |
| 47 * |
46 * @param type the token type (not `null`) | 48 * @param type the token type (not `null`) |
47 * @param offset the offset from the beginning of the file to the first charac
ter in the token | 49 * @param offset the offset from the beginning of the file to the first charac
ter in the token |
48 */ | 50 */ |
49 Token.con1(TokenType type, int offset) { | 51 Token.con1(TokenType type, int offset) { |
50 _jtd_constructor_155_impl(type, offset); | 52 _jtd_constructor_155_impl(type, offset); |
51 } | 53 } |
52 _jtd_constructor_155_impl(TokenType type, int offset) { | 54 _jtd_constructor_155_impl(TokenType type, int offset) { |
53 _jtd_constructor_156_impl(type, offset, type.lexeme); | 55 _jtd_constructor_156_impl(type, offset, type.lexeme); |
54 } | 56 } |
55 | 57 |
56 /** | 58 /** |
57 * Initialize a newly created token. | 59 * Initialize a newly created token. |
| 60 * |
58 * @param type the token type (not `null`) | 61 * @param type the token type (not `null`) |
59 * @param offset the offset from the beginning of the file to the first charac
ter in the token | 62 * @param offset the offset from the beginning of the file to the first charac
ter in the token |
60 * @param value the lexeme represented by this token (not `null`) | 63 * @param value the lexeme represented by this token (not `null`) |
61 */ | 64 */ |
62 Token.con2(TokenType type2, int offset2, String value2) { | 65 Token.con2(TokenType type2, int offset2, String value2) { |
63 _jtd_constructor_156_impl(type2, offset2, value2); | 66 _jtd_constructor_156_impl(type2, offset2, value2); |
64 } | 67 } |
65 _jtd_constructor_156_impl(TokenType type2, int offset2, String value2) { | 68 _jtd_constructor_156_impl(TokenType type2, int offset2, String value2) { |
66 this._type = type2; | 69 this._type = type2; |
67 this._value = StringUtilities.intern(value2); | 70 this._value = StringUtilities.intern(value2); |
68 this._offset = offset2; | 71 this._offset = offset2; |
69 } | 72 } |
70 | 73 |
71 /** | 74 /** |
72 * Return the offset from the beginning of the file to the character after las
t character of the | 75 * Return the offset from the beginning of the file to the character after las
t character of the |
73 * token. | 76 * token. |
| 77 * |
74 * @return the offset from the beginning of the file to the first character af
ter last character | 78 * @return the offset from the beginning of the file to the first character af
ter last character |
75 * of the token | 79 * of the token |
76 */ | 80 */ |
77 int get end => _offset + length; | 81 int get end => _offset + length; |
78 | 82 |
79 /** | 83 /** |
80 * Return the number of characters in the node's source range. | 84 * Return the number of characters in the node's source range. |
| 85 * |
81 * @return the number of characters in the node's source range | 86 * @return the number of characters in the node's source range |
82 */ | 87 */ |
83 int get length => lexeme.length; | 88 int get length => lexeme.length; |
84 | 89 |
85 /** | 90 /** |
86 * Return the lexeme that represents this token. | 91 * Return the lexeme that represents this token. |
| 92 * |
87 * @return the lexeme (not `null`) | 93 * @return the lexeme (not `null`) |
88 */ | 94 */ |
89 String get lexeme => _value; | 95 String get lexeme => _value; |
90 | 96 |
91 /** | 97 /** |
92 * Return the next token in the token stream. | 98 * Return the next token in the token stream. |
| 99 * |
93 * @return the next token in the token stream | 100 * @return the next token in the token stream |
94 */ | 101 */ |
95 Token get next => _next; | 102 Token get next => _next; |
96 | 103 |
97 /** | 104 /** |
98 * Return the offset from the beginning of the file to the first character in
the token. | 105 * Return the offset from the beginning of the file to the first character in
the token. |
| 106 * |
99 * @return the offset from the beginning of the file to the first character in
the token | 107 * @return the offset from the beginning of the file to the first character in
the token |
100 */ | 108 */ |
101 int get offset => _offset; | 109 int get offset => _offset; |
102 | 110 |
103 /** | 111 /** |
104 * Return the previous token in the token stream. | 112 * Return the previous token in the token stream. |
| 113 * |
105 * @return the previous token in the token stream | 114 * @return the previous token in the token stream |
106 */ | 115 */ |
107 Token get previous => _previous; | 116 Token get previous => _previous; |
108 | 117 |
109 /** | 118 /** |
110 * Answer the token type for the receiver. | 119 * Answer the token type for the receiver. |
| 120 * |
111 * @return the token type (not `null`) | 121 * @return the token type (not `null`) |
112 */ | 122 */ |
113 TokenType get type => _type; | 123 TokenType get type => _type; |
114 | 124 |
115 /** | 125 /** |
116 * Return `true` if this token is a synthetic token. A synthetic token is a to
ken that was | 126 * Return `true` if this token is a synthetic token. A synthetic token is a to
ken that was |
117 * introduced by the parser in order to recover from an error in the code. Syn
thetic tokens always | 127 * introduced by the parser in order to recover from an error in the code. Syn
thetic tokens always |
118 * have a length of zero (`0`). | 128 * have a length of zero (`0`). |
| 129 * |
119 * @return `true` if this token is a synthetic token | 130 * @return `true` if this token is a synthetic token |
120 */ | 131 */ |
121 bool get isSynthetic => length == 0; | 132 bool get isSynthetic => length == 0; |
122 | 133 |
123 /** | 134 /** |
124 * Set the next token in the token stream to the given token. This has the sid
e-effect of setting | 135 * Set the next token in the token stream to the given token. This has the sid
e-effect of setting |
125 * this token to be the previous token for the given token. | 136 * this token to be the previous token for the given token. |
| 137 * |
126 * @param token the next token in the token stream | 138 * @param token the next token in the token stream |
127 * @return the token that was passed in | 139 * @return the token that was passed in |
128 */ | 140 */ |
129 Token setNext(Token token) { | 141 Token setNext(Token token) { |
130 _next = token; | 142 _next = token; |
131 token.previous = this; | 143 token.previous = this; |
132 return token; | 144 return token; |
133 } | 145 } |
134 String toString() => lexeme; | 146 String toString() => lexeme; |
135 | 147 |
136 /** | 148 /** |
137 * Set the previous token in the token stream to the given token. | 149 * Set the previous token in the token stream to the given token. |
| 150 * |
138 * @param previous the previous token in the token stream | 151 * @param previous the previous token in the token stream |
139 */ | 152 */ |
140 void set previous(Token previous2) { | 153 void set previous(Token previous2) { |
141 this._previous = previous2; | 154 this._previous = previous2; |
142 } | 155 } |
143 } | 156 } |
144 /** | 157 /** |
145 * Instances of `HtmlParseResult` hold the result of parsing an HTML file. | 158 * Instances of `HtmlParseResult` hold the result of parsing an HTML file. |
| 159 * |
146 * @coverage dart.engine.html | 160 * @coverage dart.engine.html |
147 */ | 161 */ |
148 class HtmlParseResult extends HtmlScanResult { | 162 class HtmlParseResult extends HtmlScanResult { |
149 | 163 |
150 /** | 164 /** |
151 * The unit containing the parsed information (not `null`). | 165 * The unit containing the parsed information (not `null`). |
152 */ | 166 */ |
153 HtmlUnit _unit; | 167 HtmlUnit _unit; |
154 HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlU
nit unit) : super(modificationTime, token, lineStarts) { | 168 HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlU
nit unit) : super(modificationTime, token, lineStarts) { |
155 this._unit = unit; | 169 this._unit = unit; |
156 } | 170 } |
157 | 171 |
158 /** | 172 /** |
159 * Answer the unit generated by parsing the source | 173 * Answer the unit generated by parsing the source |
| 174 * |
160 * @return the unit (not `null`) | 175 * @return the unit (not `null`) |
161 */ | 176 */ |
162 HtmlUnit get htmlUnit => _unit; | 177 HtmlUnit get htmlUnit => _unit; |
163 } | 178 } |
164 /** | 179 /** |
165 * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that wi
ll recursively | 180 * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that wi
ll recursively |
166 * visit all of the nodes in an XML structure. For example, using an instance of
this class to visit | 181 * visit all of the nodes in an XML structure. For example, using an instance of
this class to visit |
167 * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and[X
mlTagNode]s to be visited. | 182 * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and |
| 183 * [XmlTagNode]s to be visited. |
168 * | 184 * |
169 * Subclasses that override a visit method must either invoke the overridden vis
it method or must | 185 * Subclasses that override a visit method must either invoke the overridden vis
it method or must |
170 * explicitly ask the visited node to visit its children. Failure to do so will
cause the children | 186 * explicitly ask the visited node to visit its children. Failure to do so will
cause the children |
171 * of the visited node to not be visited. | 187 * of the visited node to not be visited. |
| 188 * |
172 * @coverage dart.engine.html | 189 * @coverage dart.engine.html |
173 */ | 190 */ |
174 class RecursiveXmlVisitor<R> implements XmlVisitor<R> { | 191 class RecursiveXmlVisitor<R> implements XmlVisitor<R> { |
175 R visitHtmlUnit(HtmlUnit node) { | 192 R visitHtmlUnit(HtmlUnit node) { |
176 node.visitChildren(this); | 193 node.visitChildren(this); |
177 return null; | 194 return null; |
178 } | 195 } |
179 R visitXmlAttributeNode(XmlAttributeNode node) { | 196 R visitXmlAttributeNode(XmlAttributeNode node) { |
180 node.visitChildren(this); | 197 node.visitChildren(this); |
181 return null; | 198 return null; |
182 } | 199 } |
183 R visitXmlTagNode(XmlTagNode node) { | 200 R visitXmlTagNode(XmlTagNode node) { |
184 node.visitChildren(this); | 201 node.visitChildren(this); |
185 return null; | 202 return null; |
186 } | 203 } |
187 } | 204 } |
188 /** | 205 /** |
189 * The abstract class `XmlNode` defines behavior common to all XML/HTML nodes. | 206 * The abstract class `XmlNode` defines behavior common to all XML/HTML nodes. |
| 207 * |
190 * @coverage dart.engine.html | 208 * @coverage dart.engine.html |
191 */ | 209 */ |
192 abstract class XmlNode { | 210 abstract class XmlNode { |
193 | 211 |
194 /** | 212 /** |
195 * The parent of the node, or `null` if the node is the root of an AST structu
re. | 213 * The parent of the node, or `null` if the node is the root of an AST structu
re. |
196 */ | 214 */ |
197 XmlNode _parent; | 215 XmlNode _parent; |
198 | 216 |
199 /** | 217 /** |
200 * Use the given visitor to visit this node. | 218 * Use the given visitor to visit this node. |
| 219 * |
201 * @param visitor the visitor that will visit this node | 220 * @param visitor the visitor that will visit this node |
202 * @return the value returned by the visitor as a result of visiting this node | 221 * @return the value returned by the visitor as a result of visiting this node |
203 */ | 222 */ |
204 accept(XmlVisitor visitor); | 223 accept(XmlVisitor visitor); |
205 | 224 |
206 /** | 225 /** |
207 * Return the first token included in this node's source range. | 226 * Return the first token included in this node's source range. |
| 227 * |
208 * @return the first token or `null` if none | 228 * @return the first token or `null` if none |
209 */ | 229 */ |
210 Token get beginToken; | 230 Token get beginToken; |
211 | 231 |
212 /** | 232 /** |
213 * Return the offset of the character immediately following the last character
of this node's | 233 * Return the offset of the character immediately following the last character
of this node's |
214 * source range. This is equivalent to `node.getOffset() + node.getLength()`.
For an html | 234 * source range. This is equivalent to `node.getOffset() + node.getLength()`.
For an html |
215 * unit this will be equal to the length of the unit's source. | 235 * unit this will be equal to the length of the unit's source. |
| 236 * |
216 * @return the offset of the character just past the node's source range | 237 * @return the offset of the character just past the node's source range |
217 */ | 238 */ |
218 int get end => offset + length; | 239 int get end => offset + length; |
219 | 240 |
220 /** | 241 /** |
221 * Return the last token included in this node's source range. | 242 * Return the last token included in this node's source range. |
| 243 * |
222 * @return the last token or `null` if none | 244 * @return the last token or `null` if none |
223 */ | 245 */ |
224 Token get endToken; | 246 Token get endToken; |
225 | 247 |
226 /** | 248 /** |
227 * Return the number of characters in the node's source range. | 249 * Return the number of characters in the node's source range. |
| 250 * |
228 * @return the number of characters in the node's source range | 251 * @return the number of characters in the node's source range |
229 */ | 252 */ |
230 int get length { | 253 int get length { |
231 Token beginToken = this.beginToken; | 254 Token beginToken = this.beginToken; |
232 Token endToken = this.endToken; | 255 Token endToken = this.endToken; |
233 if (beginToken == null || endToken == null) { | 256 if (beginToken == null || endToken == null) { |
234 return -1; | 257 return -1; |
235 } | 258 } |
236 return endToken.offset + endToken.length - beginToken.offset; | 259 return endToken.offset + endToken.length - beginToken.offset; |
237 } | 260 } |
238 | 261 |
239 /** | 262 /** |
240 * Return the offset from the beginning of the file to the first character in
the node's source | 263 * Return the offset from the beginning of the file to the first character in
the node's source |
241 * range. | 264 * range. |
| 265 * |
242 * @return the offset from the beginning of the file to the first character in
the node's source | 266 * @return the offset from the beginning of the file to the first character in
the node's source |
243 * range | 267 * range |
244 */ | 268 */ |
245 int get offset { | 269 int get offset { |
246 Token beginToken = this.beginToken; | 270 Token beginToken = this.beginToken; |
247 if (beginToken == null) { | 271 if (beginToken == null) { |
248 return -1; | 272 return -1; |
249 } | 273 } |
250 return beginToken.offset; | 274 return beginToken.offset; |
251 } | 275 } |
252 | 276 |
253 /** | 277 /** |
254 * Return this node's parent node, or `null` if this node is the root of an AS
T structure. | 278 * Return this node's parent node, or `null` if this node is the root of an AS
T structure. |
255 * | 279 * |
256 * Note that the relationship between an AST node and its parent node may chan
ge over the lifetime | 280 * Note that the relationship between an AST node and its parent node may chan
ge over the lifetime |
257 * of a node. | 281 * of a node. |
| 282 * |
258 * @return the parent of this node, or `null` if none | 283 * @return the parent of this node, or `null` if none |
259 */ | 284 */ |
260 XmlNode get parent => _parent; | 285 XmlNode get parent => _parent; |
261 String toString() { | 286 String toString() { |
262 PrintStringWriter writer = new PrintStringWriter(); | 287 PrintStringWriter writer = new PrintStringWriter(); |
263 accept(new ToSourceVisitor(writer)); | 288 accept(new ToSourceVisitor(writer)); |
264 return writer.toString(); | 289 return writer.toString(); |
265 } | 290 } |
266 | 291 |
267 /** | 292 /** |
268 * Use the given visitor to visit all of the children of this node. The childr
en will be visited | 293 * Use the given visitor to visit all of the children of this node. The childr
en will be visited |
269 * in source order. | 294 * in source order. |
| 295 * |
270 * @param visitor the visitor that will be used to visit the children of this
node | 296 * @param visitor the visitor that will be used to visit the children of this
node |
271 */ | 297 */ |
272 void visitChildren(XmlVisitor<Object> visitor); | 298 void visitChildren(XmlVisitor<Object> visitor); |
273 | 299 |
274 /** | 300 /** |
275 * Make this node the parent of the given child nodes. | 301 * Make this node the parent of the given child nodes. |
| 302 * |
276 * @param children the nodes that will become the children of this node | 303 * @param children the nodes that will become the children of this node |
277 * @return the nodes that were made children of this node | 304 * @return the nodes that were made children of this node |
278 */ | 305 */ |
279 List becomeParentOf(List children) { | 306 List becomeParentOf(List children) { |
280 if (children != null) { | 307 if (children != null) { |
281 for (JavaIterator iter = new JavaIterator(children); iter.hasNext;) { | 308 for (JavaIterator iter = new JavaIterator(children); iter.hasNext;) { |
282 XmlNode node = iter.next(); | 309 XmlNode node = iter.next(); |
283 node.parent = this; | 310 node.parent = this; |
284 } | 311 } |
285 return new List.from(children); | 312 return new List.from(children); |
286 } | 313 } |
287 return children; | 314 return children; |
288 } | 315 } |
289 | 316 |
290 /** | 317 /** |
291 * Make this node the parent of the given child node. | 318 * Make this node the parent of the given child node. |
| 319 * |
292 * @param child the node that will become a child of this node | 320 * @param child the node that will become a child of this node |
293 * @return the node that was made a child of this node | 321 * @return the node that was made a child of this node |
294 */ | 322 */ |
295 XmlNode becomeParentOf2(XmlNode child) { | 323 XmlNode becomeParentOf2(XmlNode child) { |
296 if (child != null) { | 324 if (child != null) { |
297 XmlNode node = child; | 325 XmlNode node = child; |
298 node.parent = this; | 326 node.parent = this; |
299 } | 327 } |
300 return child; | 328 return child; |
301 } | 329 } |
(...skipping 29 matching lines...) Expand all Loading... |
331 } else { | 359 } else { |
332 appendIdentifier(builder, current); | 360 appendIdentifier(builder, current); |
333 } | 361 } |
334 current = current.parent; | 362 current = current.parent; |
335 } | 363 } |
336 return builder.toString(); | 364 return builder.toString(); |
337 } | 365 } |
338 | 366 |
339 /** | 367 /** |
340 * Set the parent of this node to the given node. | 368 * Set the parent of this node to the given node. |
| 369 * |
341 * @param newParent the node that is to be made the parent of this node | 370 * @param newParent the node that is to be made the parent of this node |
342 */ | 371 */ |
343 void set parent(XmlNode newParent) { | 372 void set parent(XmlNode newParent) { |
344 XmlNode current = newParent; | 373 XmlNode current = newParent; |
345 while (current != null) { | 374 while (current != null) { |
346 if (identical(current, this)) { | 375 if (identical(current, this)) { |
347 AnalysisEngine.instance.logger.logError3(new IllegalArgumentException(bu
ildRecursiveStructureMessage(newParent))); | 376 AnalysisEngine.instance.logger.logError3(new IllegalArgumentException(bu
ildRecursiveStructureMessage(newParent))); |
348 return; | 377 return; |
349 } | 378 } |
350 current = current.parent; | 379 current = current.parent; |
351 } | 380 } |
352 _parent = newParent; | 381 _parent = newParent; |
353 } | 382 } |
354 } | 383 } |
355 /** | 384 /** |
356 * Instances of the class `SimpleXmlVisitor` implement an AST visitor that will
do nothing | 385 * Instances of the class `SimpleXmlVisitor` implement an AST visitor that will
do nothing |
357 * when visiting an AST node. It is intended to be a superclass for classes that
use the visitor | 386 * when visiting an AST node. It is intended to be a superclass for classes that
use the visitor |
358 * pattern primarily as a dispatch mechanism (and hence don't need to recursivel
y visit a whole | 387 * pattern primarily as a dispatch mechanism (and hence don't need to recursivel
y visit a whole |
359 * structure) and that only need to visit a small number of node types. | 388 * structure) and that only need to visit a small number of node types. |
360 */ | 389 */ |
361 class SimpleXmlVisitor<R> implements XmlVisitor<R> { | 390 class SimpleXmlVisitor<R> implements XmlVisitor<R> { |
362 R visitHtmlUnit(HtmlUnit htmlUnit) => null; | 391 R visitHtmlUnit(HtmlUnit htmlUnit) => null; |
363 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode) => null; | 392 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode) => null; |
364 R visitXmlTagNode(XmlTagNode xmlTagNode) => null; | 393 R visitXmlTagNode(XmlTagNode xmlTagNode) => null; |
365 } | 394 } |
366 /** | 395 /** |
367 * The abstract class `AbstractScanner` implements a scanner for HTML code. Subc
lasses are | 396 * The abstract class `AbstractScanner` implements a scanner for HTML code. Subc
lasses are |
368 * required to implement the interface used to access the characters being scann
ed. | 397 * required to implement the interface used to access the characters being scann
ed. |
| 398 * |
369 * @coverage dart.engine.html | 399 * @coverage dart.engine.html |
370 */ | 400 */ |
371 abstract class AbstractScanner { | 401 abstract class AbstractScanner { |
372 static List<String> _NO_PASS_THROUGH_ELEMENTS = <String> []; | 402 static List<String> _NO_PASS_THROUGH_ELEMENTS = <String> []; |
373 | 403 |
374 /** | 404 /** |
375 * The source being scanned. | 405 * The source being scanned. |
376 */ | 406 */ |
377 Source _source; | 407 Source _source; |
378 | 408 |
(...skipping 12 matching lines...) Expand all Loading... |
391 */ | 421 */ |
392 List<int> _lineStarts = new List<int>(); | 422 List<int> _lineStarts = new List<int>(); |
393 | 423 |
394 /** | 424 /** |
395 * An array of element tags for which the content between tags should be consi
der a single token. | 425 * An array of element tags for which the content between tags should be consi
der a single token. |
396 */ | 426 */ |
397 List<String> _passThroughElements = _NO_PASS_THROUGH_ELEMENTS; | 427 List<String> _passThroughElements = _NO_PASS_THROUGH_ELEMENTS; |
398 | 428 |
399 /** | 429 /** |
400 * Initialize a newly created scanner. | 430 * Initialize a newly created scanner. |
| 431 * |
401 * @param source the source being scanned | 432 * @param source the source being scanned |
402 */ | 433 */ |
403 AbstractScanner(Source source) { | 434 AbstractScanner(Source source) { |
404 this._source = source; | 435 this._source = source; |
405 _tokens = new Token.con1(TokenType.EOF, -1); | 436 _tokens = new Token.con1(TokenType.EOF, -1); |
406 _tokens.setNext(_tokens); | 437 _tokens.setNext(_tokens); |
407 _tail = _tokens; | 438 _tail = _tokens; |
408 recordStartOfLine(); | 439 recordStartOfLine(); |
409 } | 440 } |
410 | 441 |
411 /** | 442 /** |
412 * Return an array containing the offsets of the first character of each line
in the source code. | 443 * Return an array containing the offsets of the first character of each line
in the source code. |
| 444 * |
413 * @return an array containing the offsets of the first character of each line
in the source code | 445 * @return an array containing the offsets of the first character of each line
in the source code |
414 */ | 446 */ |
415 List<int> get lineStarts => _lineStarts; | 447 List<int> get lineStarts => _lineStarts; |
416 | 448 |
417 /** | 449 /** |
418 * Return the current offset relative to the beginning of the file. Return the
initial offset if | 450 * Return the current offset relative to the beginning of the file. Return the
initial offset if |
419 * the scanner has not yet scanned the source code, and one (1) past the end o
f the source code if | 451 * the scanner has not yet scanned the source code, and one (1) past the end o
f the source code if |
420 * the source code has been scanned. | 452 * the source code has been scanned. |
| 453 * |
421 * @return the current offset of the scanner in the source | 454 * @return the current offset of the scanner in the source |
422 */ | 455 */ |
423 int get offset; | 456 int get offset; |
424 | 457 |
425 /** | 458 /** |
426 * Answer the source being scanned. | 459 * Answer the source being scanned. |
| 460 * |
427 * @return the source or `null` if undefined | 461 * @return the source or `null` if undefined |
428 */ | 462 */ |
429 Source get source => _source; | 463 Source get source => _source; |
430 | 464 |
431 /** | 465 /** |
432 * Set array of element tags for which the content between tags should be cons
ider a single token. | 466 * Set array of element tags for which the content between tags should be cons
ider a single token. |
433 */ | 467 */ |
434 void set passThroughElements(List<String> passThroughElements2) { | 468 void set passThroughElements(List<String> passThroughElements2) { |
435 this._passThroughElements = passThroughElements2 != null ? passThroughElemen
ts2 : _NO_PASS_THROUGH_ELEMENTS; | 469 this._passThroughElements = passThroughElements2 != null ? passThroughElemen
ts2 : _NO_PASS_THROUGH_ELEMENTS; |
436 } | 470 } |
437 | 471 |
438 /** | 472 /** |
439 * Scan the source code to produce a list of tokens representing the source. | 473 * Scan the source code to produce a list of tokens representing the source. |
| 474 * |
440 * @return the first token in the list of tokens that were produced | 475 * @return the first token in the list of tokens that were produced |
441 */ | 476 */ |
442 Token tokenize() { | 477 Token tokenize() { |
443 scan(); | 478 scan(); |
444 appendEofToken(); | 479 appendEofToken(); |
445 return firstToken(); | 480 return firstToken(); |
446 } | 481 } |
447 | 482 |
448 /** | 483 /** |
449 * Advance the current position and return the character at the new current po
sition. | 484 * Advance the current position and return the character at the new current po
sition. |
| 485 * |
450 * @return the character at the new current position | 486 * @return the character at the new current position |
451 */ | 487 */ |
452 int advance(); | 488 int advance(); |
453 | 489 |
454 /** | 490 /** |
455 * Return the substring of the source code between the start offset and the mo
dified current | 491 * Return the substring of the source code between the start offset and the mo
dified current |
456 * position. The current position is modified by adding the end delta. | 492 * position. The current position is modified by adding the end delta. |
| 493 * |
457 * @param start the offset to the beginning of the string, relative to the sta
rt of the file | 494 * @param start the offset to the beginning of the string, relative to the sta
rt of the file |
458 * @param endDelta the number of character after the current location to be in
cluded in the | 495 * @param endDelta the number of character after the current location to be in
cluded in the |
459 * string, or the number of characters before the current location to be exclu
ded if the | 496 * string, or the number of characters before the current location to
be excluded if the |
460 * offset is negative | 497 * offset is negative |
461 * @return the specified substring of the source code | 498 * @return the specified substring of the source code |
462 */ | 499 */ |
463 String getString(int start, int endDelta); | 500 String getString(int start, int endDelta); |
464 | 501 |
465 /** | 502 /** |
466 * Return the character at the current position without changing the current p
osition. | 503 * Return the character at the current position without changing the current p
osition. |
| 504 * |
467 * @return the character at the current position | 505 * @return the character at the current position |
468 */ | 506 */ |
469 int peek(); | 507 int peek(); |
470 | 508 |
471 /** | 509 /** |
472 * Record the fact that we are at the beginning of a new line in the source. | 510 * Record the fact that we are at the beginning of a new line in the source. |
473 */ | 511 */ |
474 void recordStartOfLine() { | 512 void recordStartOfLine() { |
475 _lineStarts.add(offset); | 513 _lineStarts.add(offset); |
476 } | 514 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 emit3(TokenType.TAG, start, -1); | 670 emit3(TokenType.TAG, start, -1); |
633 } else { | 671 } else { |
634 emit3(TokenType.TEXT, start, 0); | 672 emit3(TokenType.TEXT, start, 0); |
635 c = advance(); | 673 c = advance(); |
636 } | 674 } |
637 } | 675 } |
638 } | 676 } |
639 } | 677 } |
640 /** | 678 /** |
641 * Instances of `HtmlScanResult` hold the result of scanning an HTML file. | 679 * Instances of `HtmlScanResult` hold the result of scanning an HTML file. |
| 680 * |
642 * @coverage dart.engine.html | 681 * @coverage dart.engine.html |
643 */ | 682 */ |
644 class HtmlScanResult { | 683 class HtmlScanResult { |
645 | 684 |
646 /** | 685 /** |
647 * The time at which the contents of the source were last set. | 686 * The time at which the contents of the source were last set. |
648 */ | 687 */ |
649 int _modificationTime = 0; | 688 int _modificationTime = 0; |
650 | 689 |
651 /** | 690 /** |
652 * The first token in the token stream (not `null`). | 691 * The first token in the token stream (not `null`). |
653 */ | 692 */ |
654 Token _token; | 693 Token _token; |
655 | 694 |
656 /** | 695 /** |
657 * The line start information that was produced. | 696 * The line start information that was produced. |
658 */ | 697 */ |
659 List<int> _lineStarts; | 698 List<int> _lineStarts; |
660 HtmlScanResult(int modificationTime, Token token, List<int> lineStarts) { | 699 HtmlScanResult(int modificationTime, Token token, List<int> lineStarts) { |
661 this._modificationTime = modificationTime; | 700 this._modificationTime = modificationTime; |
662 this._token = token; | 701 this._token = token; |
663 this._lineStarts = lineStarts; | 702 this._lineStarts = lineStarts; |
664 } | 703 } |
665 | 704 |
666 /** | 705 /** |
667 * Answer the line start information that was produced. | 706 * Answer the line start information that was produced. |
| 707 * |
668 * @return an array of line starts (not `null`) | 708 * @return an array of line starts (not `null`) |
669 */ | 709 */ |
670 List<int> get lineStarts => _lineStarts; | 710 List<int> get lineStarts => _lineStarts; |
671 | 711 |
672 /** | 712 /** |
673 * Return the time at which the contents of the source were last set. | 713 * Return the time at which the contents of the source were last set. |
| 714 * |
674 * @return the time at which the contents of the source were last set | 715 * @return the time at which the contents of the source were last set |
675 */ | 716 */ |
676 int get modificationTime => _modificationTime; | 717 int get modificationTime => _modificationTime; |
677 | 718 |
678 /** | 719 /** |
679 * Answer the first token in the token stream. | 720 * Answer the first token in the token stream. |
| 721 * |
680 * @return the token (not `null`) | 722 * @return the token (not `null`) |
681 */ | 723 */ |
682 Token get token => _token; | 724 Token get token => _token; |
683 } | 725 } |
684 /** | 726 /** |
685 * Instances of the class `StringScanner` implement a scanner that reads from a
string. The | 727 * Instances of the class `StringScanner` implement a scanner that reads from a
string. The |
686 * scanning logic is in the superclass. | 728 * scanning logic is in the superclass. |
| 729 * |
687 * @coverage dart.engine.html | 730 * @coverage dart.engine.html |
688 */ | 731 */ |
689 class StringScanner extends AbstractScanner { | 732 class StringScanner extends AbstractScanner { |
690 | 733 |
691 /** | 734 /** |
692 * The string from which characters will be read. | 735 * The string from which characters will be read. |
693 */ | 736 */ |
694 String _string; | 737 String _string; |
695 | 738 |
696 /** | 739 /** |
697 * The number of characters in the string. | 740 * The number of characters in the string. |
698 */ | 741 */ |
699 int _stringLength = 0; | 742 int _stringLength = 0; |
700 | 743 |
701 /** | 744 /** |
702 * The index, relative to the string, of the last character that was read. | 745 * The index, relative to the string, of the last character that was read. |
703 */ | 746 */ |
704 int _charOffset = 0; | 747 int _charOffset = 0; |
705 | 748 |
706 /** | 749 /** |
707 * Initialize a newly created scanner to scan the characters in the given stri
ng. | 750 * Initialize a newly created scanner to scan the characters in the given stri
ng. |
| 751 * |
708 * @param source the source being scanned | 752 * @param source the source being scanned |
709 * @param string the string from which characters will be read | 753 * @param string the string from which characters will be read |
710 */ | 754 */ |
711 StringScanner(Source source, String string) : super(source) { | 755 StringScanner(Source source, String string) : super(source) { |
712 this._string = string; | 756 this._string = string; |
713 this._stringLength = string.length; | 757 this._stringLength = string.length; |
714 this._charOffset = -1; | 758 this._charOffset = -1; |
715 } | 759 } |
716 int get offset => _charOffset; | 760 int get offset => _charOffset; |
717 void set offset(int offset2) { | 761 void set offset(int offset2) { |
(...skipping 10 matching lines...) Expand all Loading... |
728 int peek() { | 772 int peek() { |
729 if (_charOffset + 1 < _stringLength) { | 773 if (_charOffset + 1 < _stringLength) { |
730 return _string.codeUnitAt(_charOffset + 1); | 774 return _string.codeUnitAt(_charOffset + 1); |
731 } | 775 } |
732 return -1; | 776 return -1; |
733 } | 777 } |
734 } | 778 } |
735 /** | 779 /** |
736 * Instances of the class `CharBufferScanner` implement a scanner that reads fro
m a character | 780 * Instances of the class `CharBufferScanner` implement a scanner that reads fro
m a character |
737 * buffer. The scanning logic is in the superclass. | 781 * buffer. The scanning logic is in the superclass. |
| 782 * |
738 * @coverage dart.engine.html | 783 * @coverage dart.engine.html |
739 */ | 784 */ |
740 class CharBufferScanner extends AbstractScanner { | 785 class CharBufferScanner extends AbstractScanner { |
741 | 786 |
742 /** | 787 /** |
743 * The buffer from which characters will be read. | 788 * The buffer from which characters will be read. |
744 */ | 789 */ |
745 CharSequence _buffer; | 790 CharSequence _buffer; |
746 | 791 |
747 /** | 792 /** |
748 * The number of characters in the buffer. | 793 * The number of characters in the buffer. |
749 */ | 794 */ |
750 int _bufferLength = 0; | 795 int _bufferLength = 0; |
751 | 796 |
752 /** | 797 /** |
753 * The index of the last character that was read. | 798 * The index of the last character that was read. |
754 */ | 799 */ |
755 int _charOffset = 0; | 800 int _charOffset = 0; |
756 | 801 |
757 /** | 802 /** |
758 * Initialize a newly created scanner to scan the characters in the given char
acter buffer. | 803 * Initialize a newly created scanner to scan the characters in the given char
acter buffer. |
| 804 * |
759 * @param source the source being scanned | 805 * @param source the source being scanned |
760 * @param buffer the buffer from which characters will be read | 806 * @param buffer the buffer from which characters will be read |
761 */ | 807 */ |
762 CharBufferScanner(Source source, CharSequence buffer) : super(source) { | 808 CharBufferScanner(Source source, CharSequence buffer) : super(source) { |
763 this._buffer = buffer; | 809 this._buffer = buffer; |
764 this._bufferLength = buffer.length(); | 810 this._bufferLength = buffer.length(); |
765 this._charOffset = -1; | 811 this._charOffset = -1; |
766 } | 812 } |
767 int get offset => _charOffset; | 813 int get offset => _charOffset; |
768 int advance() { | 814 int advance() { |
769 if (++_charOffset < _bufferLength) { | 815 if (++_charOffset < _bufferLength) { |
770 return _buffer.charAt(_charOffset); | 816 return _buffer.charAt(_charOffset); |
771 } | 817 } |
772 _charOffset = _bufferLength; | 818 _charOffset = _bufferLength; |
773 return -1; | 819 return -1; |
774 } | 820 } |
775 String getString(int start, int endDelta) => _buffer.subSequence(start, _charO
ffset + 1 + endDelta).toString(); | 821 String getString(int start, int endDelta) => _buffer.subSequence(start, _charO
ffset + 1 + endDelta).toString(); |
776 int peek() { | 822 int peek() { |
777 if (_charOffset + 1 < _bufferLength) { | 823 if (_charOffset + 1 < _bufferLength) { |
778 return _buffer.charAt(_charOffset + 1); | 824 return _buffer.charAt(_charOffset + 1); |
779 } | 825 } |
780 return -1; | 826 return -1; |
781 } | 827 } |
782 } | 828 } |
783 /** | 829 /** |
784 * Instances of the class `ToSourceVisitor` write a source representation of a v
isited XML | 830 * Instances of the class `ToSourceVisitor` write a source representation of a v
isited XML |
785 * node (and all of it's children) to a writer. | 831 * node (and all of it's children) to a writer. |
| 832 * |
786 * @coverage dart.engine.html | 833 * @coverage dart.engine.html |
787 */ | 834 */ |
788 class ToSourceVisitor implements XmlVisitor<Object> { | 835 class ToSourceVisitor implements XmlVisitor<Object> { |
789 | 836 |
790 /** | 837 /** |
791 * The writer to which the source is to be written. | 838 * The writer to which the source is to be written. |
792 */ | 839 */ |
793 PrintWriter _writer; | 840 PrintWriter _writer; |
794 | 841 |
795 /** | 842 /** |
796 * Initialize a newly created visitor to write source code representing the vi
sited nodes to the | 843 * Initialize a newly created visitor to write source code representing the vi
sited nodes to the |
797 * given writer. | 844 * given writer. |
| 845 * |
798 * @param writer the writer to which the source is to be written | 846 * @param writer the writer to which the source is to be written |
799 */ | 847 */ |
800 ToSourceVisitor(PrintWriter writer) { | 848 ToSourceVisitor(PrintWriter writer) { |
801 this._writer = writer; | 849 this._writer = writer; |
802 } | 850 } |
803 Object visitHtmlUnit(HtmlUnit node) { | 851 Object visitHtmlUnit(HtmlUnit node) { |
804 for (XmlTagNode child in node.tagNodes) { | 852 for (XmlTagNode child in node.tagNodes) { |
805 visit(child); | 853 visit(child); |
806 } | 854 } |
807 return null; | 855 return null; |
(...skipping 29 matching lines...) Expand all Loading... |
837 } | 885 } |
838 _writer.print("</"); | 886 _writer.print("</"); |
839 _writer.print(tagName); | 887 _writer.print(tagName); |
840 _writer.print(">"); | 888 _writer.print(">"); |
841 } | 889 } |
842 return null; | 890 return null; |
843 } | 891 } |
844 | 892 |
845 /** | 893 /** |
846 * Safely visit the given node. | 894 * Safely visit the given node. |
| 895 * |
847 * @param node the node to be visited | 896 * @param node the node to be visited |
848 */ | 897 */ |
849 void visit(XmlNode node) { | 898 void visit(XmlNode node) { |
850 if (node != null) { | 899 if (node != null) { |
851 node.accept(this); | 900 node.accept(this); |
852 } | 901 } |
853 } | 902 } |
854 } | 903 } |
855 /** | 904 /** |
856 * The enumeration `TokenType` defines the types of tokens that can be returned
by the | 905 * The enumeration `TokenType` defines the types of tokens that can be returned
by the |
857 * scanner. | 906 * scanner. |
| 907 * |
858 * @coverage dart.engine.html | 908 * @coverage dart.engine.html |
859 */ | 909 */ |
860 class TokenType implements Comparable<TokenType> { | 910 class TokenType implements Comparable<TokenType> { |
861 | 911 |
862 /** | 912 /** |
863 * The type of the token that marks the end of the input. | 913 * The type of the token that marks the end of the input. |
864 */ | 914 */ |
865 static final TokenType EOF = new TokenType_EOF('EOF', 0, ""); | 915 static final TokenType EOF = new TokenType_EOF('EOF', 0, ""); |
866 static final TokenType EQ = new TokenType('EQ', 1, "="); | 916 static final TokenType EQ = new TokenType('EQ', 1, "="); |
867 static final TokenType GT = new TokenType('GT', 2, ">"); | 917 static final TokenType GT = new TokenType('GT', 2, ">"); |
(...skipping 19 matching lines...) Expand all Loading... |
887 * lexeme for this type of token. | 937 * lexeme for this type of token. |
888 */ | 938 */ |
889 String _lexeme; | 939 String _lexeme; |
890 TokenType(this.name, this.ordinal, String lexeme) { | 940 TokenType(this.name, this.ordinal, String lexeme) { |
891 this._lexeme = lexeme; | 941 this._lexeme = lexeme; |
892 } | 942 } |
893 | 943 |
894 /** | 944 /** |
895 * Return the lexeme that defines this type of token, or `null` if there is mo
re than one | 945 * Return the lexeme that defines this type of token, or `null` if there is mo
re than one |
896 * possible lexeme for this type of token. | 946 * possible lexeme for this type of token. |
| 947 * |
897 * @return the lexeme that defines this type of token | 948 * @return the lexeme that defines this type of token |
898 */ | 949 */ |
899 String get lexeme => _lexeme; | 950 String get lexeme => _lexeme; |
900 int compareTo(TokenType other) => ordinal - other.ordinal; | 951 int compareTo(TokenType other) => ordinal - other.ordinal; |
901 int get hashCode => ordinal; | 952 int get hashCode => ordinal; |
902 String toString() => name; | 953 String toString() => name; |
903 } | 954 } |
904 class TokenType_EOF extends TokenType { | 955 class TokenType_EOF extends TokenType { |
905 TokenType_EOF(String name, int ordinal, String arg0) : super(name, ordinal, ar
g0); | 956 TokenType_EOF(String name, int ordinal, String arg0) : super(name, ordinal, ar
g0); |
906 String toString() => "-eof-"; | 957 String toString() => "-eof-"; |
907 } | 958 } |
908 /** | 959 /** |
909 * Instances of `XmlAttributeNode` represent name/value pairs owned by an [XmlTa
gNode]. | 960 * Instances of `XmlAttributeNode` represent name/value pairs owned by an [XmlTa
gNode]. |
| 961 * |
910 * @coverage dart.engine.html | 962 * @coverage dart.engine.html |
911 */ | 963 */ |
912 class XmlAttributeNode extends XmlNode { | 964 class XmlAttributeNode extends XmlNode { |
913 Token _name; | 965 Token _name; |
914 Token _equals; | 966 Token _equals; |
915 Token _value; | 967 Token _value; |
916 | 968 |
917 /** | 969 /** |
918 * Construct a new instance representing an XML attribute. | 970 * Construct a new instance representing an XML attribute. |
| 971 * |
919 * @param name the name token (not `null`). This may be a zero length token if
the attribute | 972 * @param name the name token (not `null`). This may be a zero length token if
the attribute |
920 * is badly formed. | 973 * is badly formed. |
921 * @param equals the equals sign or `null` if none | 974 * @param equals the equals sign or `null` if none |
922 * @param value the value token (not `null`) | 975 * @param value the value token (not `null`) |
923 */ | 976 */ |
924 XmlAttributeNode(Token name, Token equals, Token value) { | 977 XmlAttributeNode(Token name, Token equals, Token value) { |
925 this._name = name; | 978 this._name = name; |
926 this._equals = equals; | 979 this._equals = equals; |
927 this._value = value; | 980 this._value = value; |
928 } | 981 } |
929 accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this); | 982 accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this); |
930 Token get beginToken => _name; | 983 Token get beginToken => _name; |
931 Token get endToken => _value; | 984 Token get endToken => _value; |
932 | 985 |
933 /** | 986 /** |
934 * Answer the equals sign token that appears between the name and value tokens
. This may be`null` if the attribute is badly formed. | 987 * Answer the equals sign token that appears between the name and value tokens
. This may be |
| 988 * `null` if the attribute is badly formed. |
| 989 * |
935 * @return the token or `null` if there is no equals sign between the name and
value | 990 * @return the token or `null` if there is no equals sign between the name and
value |
936 */ | 991 */ |
937 Token get equals => _equals; | 992 Token get equals => _equals; |
938 | 993 |
939 /** | 994 /** |
940 * Answer the attribute name. This may be a zero length token if the attribute
is badly formed. | 995 * Answer the attribute name. This may be a zero length token if the attribute
is badly formed. |
| 996 * |
941 * @return the name (not `null`) | 997 * @return the name (not `null`) |
942 */ | 998 */ |
943 Token get name => _name; | 999 Token get name => _name; |
944 | 1000 |
945 /** | 1001 /** |
946 * Answer the lexeme for the value token without the leading and trailing quot
es. | 1002 * Answer the lexeme for the value token without the leading and trailing quot
es. |
| 1003 * |
947 * @return the text or `null` if the value is not specified | 1004 * @return the text or `null` if the value is not specified |
948 */ | 1005 */ |
949 String get text { | 1006 String get text { |
950 if (_value == null) { | 1007 if (_value == null) { |
951 return null; | 1008 return null; |
952 } | 1009 } |
953 String text = _value.lexeme; | 1010 String text = _value.lexeme; |
954 int len = text.length; | 1011 int len = text.length; |
955 if (len > 0) { | 1012 if (len > 0) { |
956 if (text.codeUnitAt(0) == 0x22) { | 1013 if (text.codeUnitAt(0) == 0x22) { |
957 if (len > 1 && text.codeUnitAt(len - 1) == 0x22) { | 1014 if (len > 1 && text.codeUnitAt(len - 1) == 0x22) { |
958 return text.substring(1, len - 1); | 1015 return text.substring(1, len - 1); |
959 } else { | 1016 } else { |
960 return text.substring(1); | 1017 return text.substring(1); |
961 } | 1018 } |
962 } else if (text.codeUnitAt(0) == 0x27) { | 1019 } else if (text.codeUnitAt(0) == 0x27) { |
963 if (len > 1 && text.codeUnitAt(len - 1) == 0x27) { | 1020 if (len > 1 && text.codeUnitAt(len - 1) == 0x27) { |
964 return text.substring(1, len - 1); | 1021 return text.substring(1, len - 1); |
965 } else { | 1022 } else { |
966 return text.substring(1); | 1023 return text.substring(1); |
967 } | 1024 } |
968 } | 1025 } |
969 } | 1026 } |
970 return text; | 1027 return text; |
971 } | 1028 } |
972 | 1029 |
973 /** | 1030 /** |
974 * Answer the attribute value. A properly formed value will start and end with
matching quote | 1031 * Answer the attribute value. A properly formed value will start and end with
matching quote |
975 * characters, but the value returned may not be properly formed. | 1032 * characters, but the value returned may not be properly formed. |
| 1033 * |
976 * @return the value or `null` if this represents a badly formed attribute | 1034 * @return the value or `null` if this represents a badly formed attribute |
977 */ | 1035 */ |
978 Token get value => _value; | 1036 Token get value => _value; |
979 void visitChildren(XmlVisitor<Object> visitor) { | 1037 void visitChildren(XmlVisitor<Object> visitor) { |
980 } | 1038 } |
981 } | 1039 } |
982 /** | 1040 /** |
983 * The interface `XmlVisitor` defines the behavior of objects that can be used t
o visit an[XmlNode] structure. | 1041 * The interface `XmlVisitor` defines the behavior of objects that can be used t
o visit an |
| 1042 * [XmlNode] structure. |
| 1043 * |
984 * @coverage dart.engine.html | 1044 * @coverage dart.engine.html |
985 */ | 1045 */ |
986 abstract class XmlVisitor<R> { | 1046 abstract class XmlVisitor<R> { |
987 R visitHtmlUnit(HtmlUnit htmlUnit); | 1047 R visitHtmlUnit(HtmlUnit htmlUnit); |
988 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode); | 1048 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode); |
989 R visitXmlTagNode(XmlTagNode xmlTagNode); | 1049 R visitXmlTagNode(XmlTagNode xmlTagNode); |
990 } | 1050 } |
991 /** | 1051 /** |
992 * Instances of `HtmlScanner` receive and scan HTML content from a [Source].<br/
> | 1052 * Instances of `HtmlScanner` receive and scan HTML content from a [Source].<br/
> |
993 * For example, the following code scans HTML source and returns the result: | 1053 * For example, the following code scans HTML source and returns the result: |
| 1054 * |
994 * <pre> | 1055 * <pre> |
995 * HtmlScanner scanner = new HtmlScanner(source); | 1056 * HtmlScanner scanner = new HtmlScanner(source); |
996 * source.getContents(scanner); | 1057 * source.getContents(scanner); |
997 * return scanner.getResult(); | 1058 * return scanner.getResult(); |
998 * </pre> | 1059 * </pre> |
| 1060 * |
999 * @coverage dart.engine.html | 1061 * @coverage dart.engine.html |
1000 */ | 1062 */ |
1001 class HtmlScanner implements Source_ContentReceiver { | 1063 class HtmlScanner implements Source_ContentReceiver { |
1002 List<String> _SCRIPT_TAG = <String> ["script"]; | 1064 List<String> _SCRIPT_TAG = <String> ["script"]; |
1003 | 1065 |
1004 /** | 1066 /** |
1005 * The source being scanned (not `null`) | 1067 * The source being scanned (not `null`) |
1006 */ | 1068 */ |
1007 Source _source; | 1069 Source _source; |
1008 | 1070 |
1009 /** | 1071 /** |
1010 * The time at which the contents of the source were last set. | 1072 * The time at which the contents of the source were last set. |
1011 */ | 1073 */ |
1012 int _modificationTime = 0; | 1074 int _modificationTime = 0; |
1013 | 1075 |
1014 /** | 1076 /** |
1015 * The scanner used to scan the source | 1077 * The scanner used to scan the source |
1016 */ | 1078 */ |
1017 AbstractScanner _scanner; | 1079 AbstractScanner _scanner; |
1018 | 1080 |
1019 /** | 1081 /** |
1020 * The first token in the token stream. | 1082 * The first token in the token stream. |
1021 */ | 1083 */ |
1022 Token _token; | 1084 Token _token; |
1023 | 1085 |
1024 /** | 1086 /** |
1025 * Construct a new instance to scan the specified source. | 1087 * Construct a new instance to scan the specified source. |
| 1088 * |
1026 * @param source the source to be scanned (not `null`) | 1089 * @param source the source to be scanned (not `null`) |
1027 */ | 1090 */ |
1028 HtmlScanner(Source source) { | 1091 HtmlScanner(Source source) { |
1029 this._source = source; | 1092 this._source = source; |
1030 } | 1093 } |
1031 void accept(CharBuffer contents, int modificationTime2) { | 1094 void accept(CharBuffer contents, int modificationTime2) { |
1032 this._modificationTime = modificationTime2; | 1095 this._modificationTime = modificationTime2; |
1033 _scanner = new CharBufferScanner(_source, contents); | 1096 _scanner = new CharBufferScanner(_source, contents); |
1034 _scanner.passThroughElements = _SCRIPT_TAG; | 1097 _scanner.passThroughElements = _SCRIPT_TAG; |
1035 _token = _scanner.tokenize(); | 1098 _token = _scanner.tokenize(); |
1036 } | 1099 } |
1037 void accept2(String contents, int modificationTime2) { | 1100 void accept2(String contents, int modificationTime2) { |
1038 this._modificationTime = modificationTime2; | 1101 this._modificationTime = modificationTime2; |
1039 _scanner = new StringScanner(_source, contents); | 1102 _scanner = new StringScanner(_source, contents); |
1040 _scanner.passThroughElements = _SCRIPT_TAG; | 1103 _scanner.passThroughElements = _SCRIPT_TAG; |
1041 _token = _scanner.tokenize(); | 1104 _token = _scanner.tokenize(); |
1042 } | 1105 } |
1043 | 1106 |
1044 /** | 1107 /** |
1045 * Answer the result of scanning the source | 1108 * Answer the result of scanning the source |
| 1109 * |
1046 * @return the result (not `null`) | 1110 * @return the result (not `null`) |
1047 */ | 1111 */ |
1048 HtmlScanResult get result => new HtmlScanResult(_modificationTime, _token, _sc
anner.lineStarts); | 1112 HtmlScanResult get result => new HtmlScanResult(_modificationTime, _token, _sc
anner.lineStarts); |
1049 } | 1113 } |
1050 /** | 1114 /** |
1051 * Instances of the class `XmlParser` are used to parse tokens into a AST struct
ure comprised | 1115 * Instances of the class `XmlParser` are used to parse tokens into a AST struct
ure comprised |
1052 * of [XmlNode]s. | 1116 * of [XmlNode]s. |
| 1117 * |
1053 * @coverage dart.engine.html | 1118 * @coverage dart.engine.html |
1054 */ | 1119 */ |
1055 class XmlParser { | 1120 class XmlParser { |
1056 | 1121 |
1057 /** | 1122 /** |
1058 * The source being parsed. | 1123 * The source being parsed. |
1059 */ | 1124 */ |
1060 Source _source; | 1125 Source _source; |
1061 | 1126 |
1062 /** | 1127 /** |
1063 * The next token to be parsed. | 1128 * The next token to be parsed. |
1064 */ | 1129 */ |
1065 Token _currentToken; | 1130 Token _currentToken; |
1066 | 1131 |
1067 /** | 1132 /** |
1068 * Construct a parser for the specified source. | 1133 * Construct a parser for the specified source. |
| 1134 * |
1069 * @param source the source being parsed | 1135 * @param source the source being parsed |
1070 */ | 1136 */ |
1071 XmlParser(Source source) { | 1137 XmlParser(Source source) { |
1072 this._source = source; | 1138 this._source = source; |
1073 } | 1139 } |
1074 | 1140 |
1075 /** | 1141 /** |
1076 * Answer the source being parsed. | 1142 * Answer the source being parsed. |
| 1143 * |
1077 * @return the source | 1144 * @return the source |
1078 */ | 1145 */ |
1079 Source get source => _source; | 1146 Source get source => _source; |
1080 | 1147 |
1081 /** | 1148 /** |
1082 * Answer `true` if the specified tag is self closing and thus should never ha
ve content or | 1149 * Answer `true` if the specified tag is self closing and thus should never ha
ve content or |
1083 * child tag nodes. | 1150 * child tag nodes. |
| 1151 * |
1084 * @param tag the tag (not `null`) | 1152 * @param tag the tag (not `null`) |
1085 * @return `true` if self closing | 1153 * @return `true` if self closing |
1086 */ | 1154 */ |
1087 bool isSelfClosing(Token tag) => false; | 1155 bool isSelfClosing(Token tag) => false; |
1088 | 1156 |
1089 /** | 1157 /** |
1090 * Parse the entire token stream and in the process, advance the current token
to the end of the | 1158 * Parse the entire token stream and in the process, advance the current token
to the end of the |
1091 * token stream. | 1159 * token stream. |
| 1160 * |
1092 * @return the list of tag nodes found (not `null`, contains no `null`) | 1161 * @return the list of tag nodes found (not `null`, contains no `null`) |
1093 */ | 1162 */ |
1094 List<XmlTagNode> parseTopTagNodes(Token firstToken) { | 1163 List<XmlTagNode> parseTopTagNodes(Token firstToken) { |
1095 _currentToken = firstToken; | 1164 _currentToken = firstToken; |
1096 List<XmlTagNode> tagNodes = new List<XmlTagNode>(); | 1165 List<XmlTagNode> tagNodes = new List<XmlTagNode>(); |
1097 while (true) { | 1166 while (true) { |
1098 while (true) { | 1167 while (true) { |
1099 if (_currentToken.type == TokenType.LT) { | 1168 if (_currentToken.type == TokenType.LT) { |
1100 tagNodes.add(parseTagNode()); | 1169 tagNodes.add(parseTagNode()); |
1101 } else if (_currentToken.type == TokenType.DECLARATION || _currentToken.
type == TokenType.DIRECTIVE || _currentToken.type == TokenType.COMMENT) { | 1170 } else if (_currentToken.type == TokenType.DECLARATION || _currentToken.
type == TokenType.DIRECTIVE || _currentToken.type == TokenType.COMMENT) { |
1102 _currentToken = _currentToken.next; | 1171 _currentToken = _currentToken.next; |
1103 } else if (_currentToken.type == TokenType.EOF) { | 1172 } else if (_currentToken.type == TokenType.EOF) { |
1104 return tagNodes; | 1173 return tagNodes; |
1105 } else { | 1174 } else { |
1106 reportUnexpectedToken(); | 1175 reportUnexpectedToken(); |
1107 _currentToken = _currentToken.next; | 1176 _currentToken = _currentToken.next; |
1108 } | 1177 } |
1109 break; | 1178 break; |
1110 } | 1179 } |
1111 } | 1180 } |
1112 } | 1181 } |
1113 | 1182 |
1114 /** | 1183 /** |
1115 * Answer the current token. | 1184 * Answer the current token. |
| 1185 * |
1116 * @return the current token | 1186 * @return the current token |
1117 */ | 1187 */ |
1118 Token get currentToken => _currentToken; | 1188 Token get currentToken => _currentToken; |
1119 | 1189 |
1120 /** | 1190 /** |
1121 * Insert a synthetic token of the specified type before the current token | 1191 * Insert a synthetic token of the specified type before the current token |
| 1192 * |
1122 * @param type the type of token to be inserted (not `null`) | 1193 * @param type the type of token to be inserted (not `null`) |
1123 * @return the synthetic token that was inserted (not `null`) | 1194 * @return the synthetic token that was inserted (not `null`) |
1124 */ | 1195 */ |
1125 Token insertSyntheticToken(TokenType type) { | 1196 Token insertSyntheticToken(TokenType type) { |
1126 Token token = new Token.con2(type, _currentToken.offset, ""); | 1197 Token token = new Token.con2(type, _currentToken.offset, ""); |
1127 _currentToken.previous.setNext(token); | 1198 _currentToken.previous.setNext(token); |
1128 token.setNext(_currentToken); | 1199 token.setNext(_currentToken); |
1129 return token; | 1200 return token; |
1130 } | 1201 } |
1131 | 1202 |
1132 /** | 1203 /** |
1133 * Parse the token stream for an attribute. This method advances the current t
oken over the | 1204 * Parse the token stream for an attribute. This method advances the current t
oken over the |
1134 * attribute, but should not be called if the [currentToken] is not [TokenType
#TAG]. | 1205 * attribute, but should not be called if the [currentToken] is not [TokenType
#TAG]. |
| 1206 * |
1135 * @return the attribute (not `null`) | 1207 * @return the attribute (not `null`) |
1136 */ | 1208 */ |
1137 XmlAttributeNode parseAttribute() { | 1209 XmlAttributeNode parseAttribute() { |
1138 Token name = _currentToken; | 1210 Token name = _currentToken; |
1139 _currentToken = _currentToken.next; | 1211 _currentToken = _currentToken.next; |
1140 Token equals; | 1212 Token equals; |
1141 if (identical(_currentToken.type, TokenType.EQ)) { | 1213 if (identical(_currentToken.type, TokenType.EQ)) { |
1142 equals = _currentToken; | 1214 equals = _currentToken; |
1143 _currentToken = _currentToken.next; | 1215 _currentToken = _currentToken.next; |
1144 } else { | 1216 } else { |
1145 reportUnexpectedToken(); | 1217 reportUnexpectedToken(); |
1146 equals = insertSyntheticToken(TokenType.EQ); | 1218 equals = insertSyntheticToken(TokenType.EQ); |
1147 } | 1219 } |
1148 Token value; | 1220 Token value; |
1149 if (identical(_currentToken.type, TokenType.STRING)) { | 1221 if (identical(_currentToken.type, TokenType.STRING)) { |
1150 value = _currentToken; | 1222 value = _currentToken; |
1151 _currentToken = _currentToken.next; | 1223 _currentToken = _currentToken.next; |
1152 } else { | 1224 } else { |
1153 reportUnexpectedToken(); | 1225 reportUnexpectedToken(); |
1154 value = insertSyntheticToken(TokenType.STRING); | 1226 value = insertSyntheticToken(TokenType.STRING); |
1155 } | 1227 } |
1156 return new XmlAttributeNode(name, equals, value); | 1228 return new XmlAttributeNode(name, equals, value); |
1157 } | 1229 } |
1158 | 1230 |
1159 /** | 1231 /** |
1160 * Parse the stream for a sequence of attributes. This method advances the cur
rent token to the | 1232 * Parse the stream for a sequence of attributes. This method advances the cur
rent token to the |
1161 * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF]. | 1233 * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF]. |
| 1234 * |
1162 * @return a collection of zero or more attributes (not `null`, contains no `n
ull`s) | 1235 * @return a collection of zero or more attributes (not `null`, contains no `n
ull`s) |
1163 */ | 1236 */ |
1164 List<XmlAttributeNode> parseAttributes() { | 1237 List<XmlAttributeNode> parseAttributes() { |
1165 TokenType type = _currentToken.type; | 1238 TokenType type = _currentToken.type; |
1166 if (identical(type, TokenType.GT) || identical(type, TokenType.SLASH_GT) ||
identical(type, TokenType.EOF)) { | 1239 if (identical(type, TokenType.GT) || identical(type, TokenType.SLASH_GT) ||
identical(type, TokenType.EOF)) { |
1167 return XmlTagNode.NO_ATTRIBUTES; | 1240 return XmlTagNode.NO_ATTRIBUTES; |
1168 } | 1241 } |
1169 List<XmlAttributeNode> attributes = new List<XmlAttributeNode>(); | 1242 List<XmlAttributeNode> attributes = new List<XmlAttributeNode>(); |
1170 while (true) { | 1243 while (true) { |
1171 while (true) { | 1244 while (true) { |
1172 if (_currentToken.type == TokenType.GT || _currentToken.type == TokenTyp
e.SLASH_GT || _currentToken.type == TokenType.EOF) { | 1245 if (_currentToken.type == TokenType.GT || _currentToken.type == TokenTyp
e.SLASH_GT || _currentToken.type == TokenType.EOF) { |
1173 return attributes; | 1246 return attributes; |
1174 } else if (_currentToken.type == TokenType.TAG) { | 1247 } else if (_currentToken.type == TokenType.TAG) { |
1175 attributes.add(parseAttribute()); | 1248 attributes.add(parseAttribute()); |
1176 } else { | 1249 } else { |
1177 reportUnexpectedToken(); | 1250 reportUnexpectedToken(); |
1178 _currentToken = _currentToken.next; | 1251 _currentToken = _currentToken.next; |
1179 } | 1252 } |
1180 break; | 1253 break; |
1181 } | 1254 } |
1182 } | 1255 } |
1183 } | 1256 } |
1184 | 1257 |
1185 /** | 1258 /** |
1186 * Parse the stream for a sequence of tag nodes existing within a parent tag n
ode. This method | 1259 * Parse the stream for a sequence of tag nodes existing within a parent tag n
ode. This method |
1187 * advances the current token to the next [TokenType#LT_SLASH] or [TokenType#E
OF]. | 1260 * advances the current token to the next [TokenType#LT_SLASH] or [TokenType#E
OF]. |
| 1261 * |
1188 * @return a list of nodes (not `null`, contains no `null`s) | 1262 * @return a list of nodes (not `null`, contains no `null`s) |
1189 */ | 1263 */ |
1190 List<XmlTagNode> parseChildTagNodes() { | 1264 List<XmlTagNode> parseChildTagNodes() { |
1191 TokenType type = _currentToken.type; | 1265 TokenType type = _currentToken.type; |
1192 if (identical(type, TokenType.LT_SLASH) || identical(type, TokenType.EOF)) { | 1266 if (identical(type, TokenType.LT_SLASH) || identical(type, TokenType.EOF)) { |
1193 return XmlTagNode.NO_TAG_NODES; | 1267 return XmlTagNode.NO_TAG_NODES; |
1194 } | 1268 } |
1195 List<XmlTagNode> nodes = new List<XmlTagNode>(); | 1269 List<XmlTagNode> nodes = new List<XmlTagNode>(); |
1196 while (true) { | 1270 while (true) { |
1197 while (true) { | 1271 while (true) { |
1198 if (_currentToken.type == TokenType.LT) { | 1272 if (_currentToken.type == TokenType.LT) { |
1199 nodes.add(parseTagNode()); | 1273 nodes.add(parseTagNode()); |
1200 } else if (_currentToken.type == TokenType.LT_SLASH || _currentToken.typ
e == TokenType.EOF) { | 1274 } else if (_currentToken.type == TokenType.LT_SLASH || _currentToken.typ
e == TokenType.EOF) { |
1201 return nodes; | 1275 return nodes; |
1202 } else if (_currentToken.type == TokenType.COMMENT) { | 1276 } else if (_currentToken.type == TokenType.COMMENT) { |
1203 _currentToken = _currentToken.next; | 1277 _currentToken = _currentToken.next; |
1204 } else { | 1278 } else { |
1205 reportUnexpectedToken(); | 1279 reportUnexpectedToken(); |
1206 _currentToken = _currentToken.next; | 1280 _currentToken = _currentToken.next; |
1207 } | 1281 } |
1208 break; | 1282 break; |
1209 } | 1283 } |
1210 } | 1284 } |
1211 } | 1285 } |
1212 | 1286 |
1213 /** | 1287 /** |
1214 * Parse the token stream for the next tag node. This method advances current
token over the | 1288 * Parse the token stream for the next tag node. This method advances current
token over the |
1215 * parsed tag node, but should only be called if the current token is [TokenTy
pe#LT] | 1289 * parsed tag node, but should only be called if the current token is [TokenTy
pe#LT] |
| 1290 * |
1216 * @return the tag node or `null` if none found | 1291 * @return the tag node or `null` if none found |
1217 */ | 1292 */ |
1218 XmlTagNode parseTagNode() { | 1293 XmlTagNode parseTagNode() { |
1219 Token nodeStart = _currentToken; | 1294 Token nodeStart = _currentToken; |
1220 _currentToken = _currentToken.next; | 1295 _currentToken = _currentToken.next; |
1221 Token tag; | 1296 Token tag; |
1222 if (identical(_currentToken.type, TokenType.TAG)) { | 1297 if (identical(_currentToken.type, TokenType.TAG)) { |
1223 tag = _currentToken; | 1298 tag = _currentToken; |
1224 _currentToken = _currentToken.next; | 1299 _currentToken = _currentToken.next; |
1225 } else { | 1300 } else { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes, co
ntentEnd, closingTag, nodeEnd); | 1341 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes, co
ntentEnd, closingTag, nodeEnd); |
1267 } | 1342 } |
1268 | 1343 |
1269 /** | 1344 /** |
1270 * Report the current token as unexpected | 1345 * Report the current token as unexpected |
1271 */ | 1346 */ |
1272 void reportUnexpectedToken() { | 1347 void reportUnexpectedToken() { |
1273 } | 1348 } |
1274 } | 1349 } |
1275 /** | 1350 /** |
1276 * Instances of `XmlTagNode` represent XML or HTML elements such as `` and`<body
foo="bar"> ... </body>`. | 1351 * Instances of `XmlTagNode` represent XML or HTML elements such as `` and |
| 1352 * `<body foo="bar"> ... </body>`. |
| 1353 * |
1277 * @coverage dart.engine.html | 1354 * @coverage dart.engine.html |
1278 */ | 1355 */ |
1279 class XmlTagNode extends XmlNode { | 1356 class XmlTagNode extends XmlNode { |
1280 | 1357 |
1281 /** | 1358 /** |
1282 * Constant representing empty list of attributes. | 1359 * Constant representing empty list of attributes. |
1283 */ | 1360 */ |
1284 static List<XmlAttributeNode> NO_ATTRIBUTES = new UnmodifiableListView(new Lis
t<XmlAttributeNode>()); | 1361 static List<XmlAttributeNode> NO_ATTRIBUTES = new UnmodifiableListView(new Lis
t<XmlAttributeNode>()); |
1285 | 1362 |
1286 /** | 1363 /** |
(...skipping 10 matching lines...) Expand all Loading... |
1297 * The [TokenType#TAG] token after the starting '<' (not `null`). | 1374 * The [TokenType#TAG] token after the starting '<' (not `null`). |
1298 */ | 1375 */ |
1299 Token _tag; | 1376 Token _tag; |
1300 | 1377 |
1301 /** | 1378 /** |
1302 * The attributes contained by the receiver (not `null`, contains no `null`s). | 1379 * The attributes contained by the receiver (not `null`, contains no `null`s). |
1303 */ | 1380 */ |
1304 List<XmlAttributeNode> _attributes; | 1381 List<XmlAttributeNode> _attributes; |
1305 | 1382 |
1306 /** | 1383 /** |
1307 * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not`
null`). The token may be the same token as [nodeEnd] if there are no child[tagNo
des]. | 1384 * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not |
| 1385 * `null`). The token may be the same token as [nodeEnd] if there are no child |
| 1386 * [tagNodes]. |
1308 */ | 1387 */ |
1309 Token _attributeEnd; | 1388 Token _attributeEnd; |
1310 | 1389 |
1311 /** | 1390 /** |
1312 * The tag nodes contained in the receiver (not `null`, contains no `null`s). | 1391 * The tag nodes contained in the receiver (not `null`, contains no `null`s). |
1313 */ | 1392 */ |
1314 List<XmlTagNode> _tagNodes; | 1393 List<XmlTagNode> _tagNodes; |
1315 | 1394 |
1316 /** | 1395 /** |
1317 * The token (not `null`) after the content, which may be | 1396 * The token (not `null`) after the content, which may be |
(...skipping 14 matching lines...) Expand all Loading... |
1332 */ | 1411 */ |
1333 Token _closingTag; | 1412 Token _closingTag; |
1334 | 1413 |
1335 /** | 1414 /** |
1336 * The ending [TokenType#GT] or [TokenType#SLASH_GT] token (not `null`). | 1415 * The ending [TokenType#GT] or [TokenType#SLASH_GT] token (not `null`). |
1337 */ | 1416 */ |
1338 Token _nodeEnd; | 1417 Token _nodeEnd; |
1339 | 1418 |
1340 /** | 1419 /** |
1341 * Construct a new instance representing an XML or HTML element | 1420 * Construct a new instance representing an XML or HTML element |
| 1421 * |
1342 * @param nodeStart the starting [TokenType#LT] token (not `null`) | 1422 * @param nodeStart the starting [TokenType#LT] token (not `null`) |
1343 * @param tag the [TokenType#TAG] token after the starting '<' (not `null`)
. | 1423 * @param tag the [TokenType#TAG] token after the starting '<' (not `null`)
. |
1344 * @param attributes the attributes associated with this element or [NO_ATTRIB
UTES] (not`null`, contains no `null`s) | 1424 * @param attributes the attributes associated with this element or [NO_ATTRIB
UTES] (not |
| 1425 * `null`, contains no `null`s) |
1345 * @param attributeEnd The [TokenType#GT] or [TokenType#SLASH_GT] token after
the | 1426 * @param attributeEnd The [TokenType#GT] or [TokenType#SLASH_GT] token after
the |
1346 * attributes (not `null`). The token may be the same token as [nodeEnd] if | 1427 * attributes (not `null`). The token may be the same token as [nodeE
nd] if |
1347 * there are no child [tagNodes]. | 1428 * there are no child [tagNodes]. |
1348 * @param tagNodes child tag nodes of the receiver or [NO_TAG_NODES] (not `nul
l`, | 1429 * @param tagNodes child tag nodes of the receiver or [NO_TAG_NODES] (not `nul
l`, |
1349 * contains no `null`s) | 1430 * contains no `null`s) |
1350 * @param contentEnd the token (not `null`) after the content, which may be | 1431 * @param contentEnd the token (not `null`) after the content, which may be |
1351 * | 1432 * |
1352 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or | 1433 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or |
1353 * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is | 1434 * * (2) the [TokenType#LT] nodeStart of the next sibling node if thi
s node is |
1354 * self closing or the attributeEnd is [TokenType#SLASH_GT], or | 1435 * self closing or the attributeEnd is [TokenType#SLASH_GT], or |
1355 * * (3) [TokenType#EOF] if the node does not have a closing tag and is the la
st | 1436 * * (3) [TokenType#EOF] if the node does not have a closing tag and
is the last |
1356 * node in the stream [TokenType#LT_SLASH] token after the content, or `null`i
f there is no content and the attributes ended with [TokenType#SLASH_GT]. | 1437 * node in the stream [TokenType#LT_SLASH] token after the content, o
r `null` |
| 1438 * if there is no content and the attributes ended with [TokenType#SL
ASH_GT]. |
1357 * | 1439 * |
1358 * @param closingTag the closing [TokenType#TAG] after the child elements or `
null` if | 1440 * @param closingTag the closing [TokenType#TAG] after the child elements or `
null` if |
1359 * there is no content and the attributes ended with [TokenType#SLASH_GT] | 1441 * there is no content and the attributes ended with [TokenType#SLASH
_GT] |
1360 * @param nodeEnd the ending [TokenType#GT] or [TokenType#SLASH_GT] token (not
`null`) | 1442 * @param nodeEnd the ending [TokenType#GT] or [TokenType#SLASH_GT] token (not |
| 1443 * `null`) |
1361 */ | 1444 */ |
1362 XmlTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> attributes, Toke
n attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag, T
oken nodeEnd) { | 1445 XmlTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> attributes, Toke
n attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag, T
oken nodeEnd) { |
1363 this._nodeStart = nodeStart; | 1446 this._nodeStart = nodeStart; |
1364 this._tag = tag; | 1447 this._tag = tag; |
1365 this._attributes = becomeParentOfEmpty(attributes, NO_ATTRIBUTES); | 1448 this._attributes = becomeParentOfEmpty(attributes, NO_ATTRIBUTES); |
1366 this._attributeEnd = attributeEnd; | 1449 this._attributeEnd = attributeEnd; |
1367 this._tagNodes = becomeParentOfEmpty(tagNodes, NO_TAG_NODES); | 1450 this._tagNodes = becomeParentOfEmpty(tagNodes, NO_TAG_NODES); |
1368 this._contentEnd = contentEnd; | 1451 this._contentEnd = contentEnd; |
1369 this._closingTag = closingTag; | 1452 this._closingTag = closingTag; |
1370 this._nodeEnd = nodeEnd; | 1453 this._nodeEnd = nodeEnd; |
1371 } | 1454 } |
1372 accept(XmlVisitor visitor) => visitor.visitXmlTagNode(this); | 1455 accept(XmlVisitor visitor) => visitor.visitXmlTagNode(this); |
1373 | 1456 |
1374 /** | 1457 /** |
1375 * Answer the attribute with the specified name. | 1458 * Answer the attribute with the specified name. |
| 1459 * |
1376 * @param name the attribute name | 1460 * @param name the attribute name |
1377 * @return the attribute or `null` if no matching attribute is found | 1461 * @return the attribute or `null` if no matching attribute is found |
1378 */ | 1462 */ |
1379 XmlAttributeNode getAttribute(String name2) { | 1463 XmlAttributeNode getAttribute(String name2) { |
1380 for (XmlAttributeNode attribute in _attributes) { | 1464 for (XmlAttributeNode attribute in _attributes) { |
1381 if (attribute.name.lexeme == name2) { | 1465 if (attribute.name.lexeme == name2) { |
1382 return attribute; | 1466 return attribute; |
1383 } | 1467 } |
1384 } | 1468 } |
1385 return null; | 1469 return null; |
1386 } | 1470 } |
1387 | 1471 |
1388 /** | 1472 /** |
1389 * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not`
null`). The token may be the same token as [nodeEnd] if there are no child[tagNo
des]. | 1473 * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not |
| 1474 * `null`). The token may be the same token as [nodeEnd] if there are no child |
| 1475 * [tagNodes]. |
| 1476 * |
1390 * @return the token (not `null`) | 1477 * @return the token (not `null`) |
1391 */ | 1478 */ |
1392 Token get attributeEnd => _attributeEnd; | 1479 Token get attributeEnd => _attributeEnd; |
1393 | 1480 |
1394 /** | 1481 /** |
1395 * Answer the receiver's attributes. Callers should not manipulate the returne
d list to edit the | 1482 * Answer the receiver's attributes. Callers should not manipulate the returne
d list to edit the |
1396 * AST structure. | 1483 * AST structure. |
| 1484 * |
1397 * @return the attributes (not `null`, contains no `null`s) | 1485 * @return the attributes (not `null`, contains no `null`s) |
1398 */ | 1486 */ |
1399 List<XmlAttributeNode> get attributes => _attributes; | 1487 List<XmlAttributeNode> get attributes => _attributes; |
1400 | 1488 |
1401 /** | 1489 /** |
1402 * Find the attribute with the given name (see [getAttribute] and answer the l
exeme | 1490 * Find the attribute with the given name (see [getAttribute] and answer the l
exeme |
1403 * for the attribute's value token without the leading and trailing quotes (se
e[XmlAttributeNode#getText]). | 1491 * for the attribute's value token without the leading and trailing quotes (se
e |
| 1492 * [XmlAttributeNode#getText]). |
| 1493 * |
1404 * @param name the attribute name | 1494 * @param name the attribute name |
1405 * @return the attribute text or `null` if no matching attribute is found | 1495 * @return the attribute text or `null` if no matching attribute is found |
1406 */ | 1496 */ |
1407 String getAttributeText(String name) { | 1497 String getAttributeText(String name) { |
1408 XmlAttributeNode attribute = getAttribute(name); | 1498 XmlAttributeNode attribute = getAttribute(name); |
1409 return attribute != null ? attribute.text : null; | 1499 return attribute != null ? attribute.text : null; |
1410 } | 1500 } |
1411 Token get beginToken => _nodeStart; | 1501 Token get beginToken => _nodeStart; |
1412 | 1502 |
1413 /** | 1503 /** |
1414 * The the closing [TokenType#TAG] after the child elements or `null` if there
is no | 1504 * The the closing [TokenType#TAG] after the child elements or `null` if there
is no |
1415 * content and the attributes ended with [TokenType#SLASH_GT] | 1505 * content and the attributes ended with [TokenType#SLASH_GT] |
| 1506 * |
1416 * @return the closing tag or `null` | 1507 * @return the closing tag or `null` |
1417 */ | 1508 */ |
1418 Token get closingTag => _closingTag; | 1509 Token get closingTag => _closingTag; |
1419 | 1510 |
1420 /** | 1511 /** |
1421 * Answer a string representing the content contained in the receiver. This in
cludes the textual | 1512 * Answer a string representing the content contained in the receiver. This in
cludes the textual |
1422 * representation of any child tag nodes ([getTagNodes]). Whitespace between '
<', | 1513 * representation of any child tag nodes ([getTagNodes]). Whitespace between '
<', |
1423 * '</', and '>', '/>' is discarded, but all other whitespace is preserved. | 1514 * '</', and '>', '/>' is discarded, but all other whitespace is preserved. |
| 1515 * |
1424 * @return the content (not `null`) | 1516 * @return the content (not `null`) |
1425 */ | 1517 */ |
1426 String get content { | 1518 String get content { |
1427 Token token = _attributeEnd.next; | 1519 Token token = _attributeEnd.next; |
1428 if (identical(token, _contentEnd)) { | 1520 if (identical(token, _contentEnd)) { |
1429 return ""; | 1521 return ""; |
1430 } | 1522 } |
1431 String content = token.lexeme; | 1523 String content = token.lexeme; |
1432 token = token.next; | 1524 token = token.next; |
1433 if (identical(token, _contentEnd)) { | 1525 if (identical(token, _contentEnd)) { |
(...skipping 10 matching lines...) Expand all Loading... |
1444 /** | 1536 /** |
1445 * Answer the token (not `null`) after the content, which may be | 1537 * Answer the token (not `null`) after the content, which may be |
1446 * | 1538 * |
1447 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or | 1539 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or |
1448 * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is
self | 1540 * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is
self |
1449 * closing or the attributeEnd is [TokenType#SLASH_GT], or | 1541 * closing or the attributeEnd is [TokenType#SLASH_GT], or |
1450 * * (3) [TokenType#EOF] if the node does not have a closing tag and is the la
st node in | 1542 * * (3) [TokenType#EOF] if the node does not have a closing tag and is the la
st node in |
1451 * the stream [TokenType#LT_SLASH] token after the content, or `null` if there
is no | 1543 * the stream [TokenType#LT_SLASH] token after the content, or `null` if there
is no |
1452 * content and the attributes ended with [TokenType#SLASH_GT]. | 1544 * content and the attributes ended with [TokenType#SLASH_GT]. |
1453 * | 1545 * |
| 1546 * |
1454 * @return the token (not `null`) | 1547 * @return the token (not `null`) |
1455 */ | 1548 */ |
1456 Token get contentEnd => _contentEnd; | 1549 Token get contentEnd => _contentEnd; |
1457 Token get endToken { | 1550 Token get endToken { |
1458 if (_nodeEnd != null) { | 1551 if (_nodeEnd != null) { |
1459 return _nodeEnd; | 1552 return _nodeEnd; |
1460 } | 1553 } |
1461 if (_closingTag != null) { | 1554 if (_closingTag != null) { |
1462 return _closingTag; | 1555 return _closingTag; |
1463 } | 1556 } |
1464 if (_contentEnd != null) { | 1557 if (_contentEnd != null) { |
1465 return _contentEnd; | 1558 return _contentEnd; |
1466 } | 1559 } |
1467 if (!_tagNodes.isEmpty) { | 1560 if (!_tagNodes.isEmpty) { |
1468 return _tagNodes[_tagNodes.length - 1].endToken; | 1561 return _tagNodes[_tagNodes.length - 1].endToken; |
1469 } | 1562 } |
1470 if (_attributeEnd != null) { | 1563 if (_attributeEnd != null) { |
1471 return _attributeEnd; | 1564 return _attributeEnd; |
1472 } | 1565 } |
1473 if (!_attributes.isEmpty) { | 1566 if (!_attributes.isEmpty) { |
1474 return _attributes[_attributes.length - 1].endToken; | 1567 return _attributes[_attributes.length - 1].endToken; |
1475 } | 1568 } |
1476 return _tag; | 1569 return _tag; |
1477 } | 1570 } |
1478 | 1571 |
1479 /** | 1572 /** |
1480 * Answer the ending [TokenType#GT] or [TokenType#SLASH_GT] token. | 1573 * Answer the ending [TokenType#GT] or [TokenType#SLASH_GT] token. |
| 1574 * |
1481 * @return the token (not `null`) | 1575 * @return the token (not `null`) |
1482 */ | 1576 */ |
1483 Token get nodeEnd => _nodeEnd; | 1577 Token get nodeEnd => _nodeEnd; |
1484 | 1578 |
1485 /** | 1579 /** |
1486 * Answer the starting [TokenType#LT] token. | 1580 * Answer the starting [TokenType#LT] token. |
| 1581 * |
1487 * @return the token (not `null`) | 1582 * @return the token (not `null`) |
1488 */ | 1583 */ |
1489 Token get nodeStart => _nodeStart; | 1584 Token get nodeStart => _nodeStart; |
1490 | 1585 |
1491 /** | 1586 /** |
1492 * Answer the [TokenType#TAG] token after the starting '<'. | 1587 * Answer the [TokenType#TAG] token after the starting '<'. |
| 1588 * |
1493 * @return the token (not `null`) | 1589 * @return the token (not `null`) |
1494 */ | 1590 */ |
1495 Token get tag => _tag; | 1591 Token get tag => _tag; |
1496 | 1592 |
1497 /** | 1593 /** |
1498 * Answer the tag nodes contained in the receiver. Callers should not manipula
te the returned list | 1594 * Answer the tag nodes contained in the receiver. Callers should not manipula
te the returned list |
1499 * to edit the AST structure. | 1595 * to edit the AST structure. |
| 1596 * |
1500 * @return the children (not `null`, contains no `null`s) | 1597 * @return the children (not `null`, contains no `null`s) |
1501 */ | 1598 */ |
1502 List<XmlTagNode> get tagNodes => _tagNodes; | 1599 List<XmlTagNode> get tagNodes => _tagNodes; |
1503 void visitChildren(XmlVisitor<Object> visitor) { | 1600 void visitChildren(XmlVisitor<Object> visitor) { |
1504 for (XmlAttributeNode node in _attributes) { | 1601 for (XmlAttributeNode node in _attributes) { |
1505 node.accept(visitor); | 1602 node.accept(visitor); |
1506 } | 1603 } |
1507 for (XmlTagNode node in _tagNodes) { | 1604 for (XmlTagNode node in _tagNodes) { |
1508 node.accept(visitor); | 1605 node.accept(visitor); |
1509 } | 1606 } |
1510 } | 1607 } |
1511 | 1608 |
1512 /** | 1609 /** |
1513 * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empt
y | 1610 * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empt
y |
1514 */ | 1611 */ |
1515 List becomeParentOfEmpty(List children, List ifEmpty) { | 1612 List becomeParentOfEmpty(List children, List ifEmpty) { |
1516 if (children != null && children.isEmpty) { | 1613 if (children != null && children.isEmpty) { |
1517 return ifEmpty; | 1614 return ifEmpty; |
1518 } | 1615 } |
1519 return becomeParentOf(children); | 1616 return becomeParentOf(children); |
1520 } | 1617 } |
1521 } | 1618 } |
1522 /** | 1619 /** |
1523 * Instances of the class `HtmlParser` are used to parse tokens into a AST struc
ture comprised | 1620 * Instances of the class `HtmlParser` are used to parse tokens into a AST struc
ture comprised |
1524 * of [XmlNode]s. | 1621 * of [XmlNode]s. |
| 1622 * |
1525 * @coverage dart.engine.html | 1623 * @coverage dart.engine.html |
1526 */ | 1624 */ |
1527 class HtmlParser extends XmlParser { | 1625 class HtmlParser extends XmlParser { |
1528 static Set<String> SELF_CLOSING = new Set<String>(); | 1626 static Set<String> SELF_CLOSING = new Set<String>(); |
1529 | 1627 |
1530 /** | 1628 /** |
1531 * Construct a parser for the specified source. | 1629 * Construct a parser for the specified source. |
| 1630 * |
1532 * @param source the source being parsed | 1631 * @param source the source being parsed |
1533 */ | 1632 */ |
1534 HtmlParser(Source source) : super(source) { | 1633 HtmlParser(Source source) : super(source) { |
1535 } | 1634 } |
1536 | 1635 |
1537 /** | 1636 /** |
1538 * Parse the tokens specified by the given scan result. | 1637 * Parse the tokens specified by the given scan result. |
| 1638 * |
1539 * @param scanResult the result of scanning an HTML source (not `null`) | 1639 * @param scanResult the result of scanning an HTML source (not `null`) |
1540 * @return the parse result (not `null`) | 1640 * @return the parse result (not `null`) |
1541 */ | 1641 */ |
1542 HtmlParseResult parse(HtmlScanResult scanResult) { | 1642 HtmlParseResult parse(HtmlScanResult scanResult) { |
1543 Token firstToken = scanResult.token; | 1643 Token firstToken = scanResult.token; |
1544 List<XmlTagNode> tagNodes = parseTopTagNodes(firstToken); | 1644 List<XmlTagNode> tagNodes = parseTopTagNodes(firstToken); |
1545 HtmlUnit unit = new HtmlUnit(firstToken, tagNodes, currentToken); | 1645 HtmlUnit unit = new HtmlUnit(firstToken, tagNodes, currentToken); |
1546 return new HtmlParseResult(scanResult.modificationTime, firstToken, scanResu
lt.lineStarts, unit); | 1646 return new HtmlParseResult(scanResult.modificationTime, firstToken, scanResu
lt.lineStarts, unit); |
1547 } | 1647 } |
1548 | 1648 |
1549 /** | 1649 /** |
1550 * Scan then parse the specified source. | 1650 * Scan then parse the specified source. |
| 1651 * |
1551 * @param source the source to be scanned and parsed (not `null`) | 1652 * @param source the source to be scanned and parsed (not `null`) |
1552 * @return the parse result (not `null`) | 1653 * @return the parse result (not `null`) |
1553 */ | 1654 */ |
1554 HtmlParseResult parse2(Source source) { | 1655 HtmlParseResult parse2(Source source) { |
1555 HtmlScanner scanner = new HtmlScanner(source); | 1656 HtmlScanner scanner = new HtmlScanner(source); |
1556 source.getContents(scanner); | 1657 source.getContents(scanner); |
1557 return parse(scanner.result); | 1658 return parse(scanner.result); |
1558 } | 1659 } |
1559 bool isSelfClosing(Token tag) => SELF_CLOSING.contains(tag.lexeme); | 1660 bool isSelfClosing(Token tag) => SELF_CLOSING.contains(tag.lexeme); |
1560 } | 1661 } |
1561 /** | 1662 /** |
1562 * Instances of the class `HtmlUnit` represent the contents of an HTML file. | 1663 * Instances of the class `HtmlUnit` represent the contents of an HTML file. |
| 1664 * |
1563 * @coverage dart.engine.html | 1665 * @coverage dart.engine.html |
1564 */ | 1666 */ |
1565 class HtmlUnit extends XmlNode { | 1667 class HtmlUnit extends XmlNode { |
1566 | 1668 |
1567 /** | 1669 /** |
1568 * The first token in the token stream that was parsed to form this HTML unit. | 1670 * The first token in the token stream that was parsed to form this HTML unit. |
1569 */ | 1671 */ |
1570 Token _beginToken; | 1672 Token _beginToken; |
1571 | 1673 |
1572 /** | 1674 /** |
1573 * The last token in the token stream that was parsed to form this compilation
unit. This token | 1675 * The last token in the token stream that was parsed to form this compilation
unit. This token |
1574 * should always have a type of [TokenType.EOF]. | 1676 * should always have a type of [TokenType.EOF]. |
1575 */ | 1677 */ |
1576 Token _endToken; | 1678 Token _endToken; |
1577 | 1679 |
1578 /** | 1680 /** |
1579 * The tag nodes contained in the receiver (not `null`, contains no `null`s). | 1681 * The tag nodes contained in the receiver (not `null`, contains no `null`s). |
1580 */ | 1682 */ |
1581 List<XmlTagNode> _tagNodes; | 1683 List<XmlTagNode> _tagNodes; |
1582 | 1684 |
1583 /** | 1685 /** |
1584 * The element associated with this HTML unit or `null` if the receiver is not
resolved. | 1686 * The element associated with this HTML unit or `null` if the receiver is not
resolved. |
1585 */ | 1687 */ |
1586 HtmlElementImpl _element; | 1688 HtmlElementImpl _element; |
1587 | 1689 |
1588 /** | 1690 /** |
1589 * Construct a new instance representing the content of an HTML file. | 1691 * Construct a new instance representing the content of an HTML file. |
| 1692 * |
1590 * @param beginToken the first token in the file (not `null`) | 1693 * @param beginToken the first token in the file (not `null`) |
1591 * @param tagNodes child tag nodes of the receiver (not `null`, contains no `n
ull`s) | 1694 * @param tagNodes child tag nodes of the receiver (not `null`, contains no `n
ull`s) |
1592 * @param endToken the last token in the token stream which should be of type[
TokenType.EOF] | 1695 * @param endToken the last token in the token stream which should be of type |
| 1696 * [TokenType.EOF] |
1593 */ | 1697 */ |
1594 HtmlUnit(Token beginToken, List<XmlTagNode> tagNodes, Token endToken) { | 1698 HtmlUnit(Token beginToken, List<XmlTagNode> tagNodes, Token endToken) { |
1595 this._beginToken = beginToken; | 1699 this._beginToken = beginToken; |
1596 this._tagNodes = becomeParentOf(tagNodes); | 1700 this._tagNodes = becomeParentOf(tagNodes); |
1597 this._endToken = endToken; | 1701 this._endToken = endToken; |
1598 } | 1702 } |
1599 accept(XmlVisitor visitor) => visitor.visitHtmlUnit(this); | 1703 accept(XmlVisitor visitor) => visitor.visitHtmlUnit(this); |
1600 Token get beginToken => _beginToken; | 1704 Token get beginToken => _beginToken; |
1601 | 1705 |
1602 /** | 1706 /** |
1603 * Return the element associated with this HTML unit. | 1707 * Return the element associated with this HTML unit. |
| 1708 * |
1604 * @return the element or `null` if the receiver is not resolved | 1709 * @return the element or `null` if the receiver is not resolved |
1605 */ | 1710 */ |
1606 HtmlElementImpl get element => _element; | 1711 HtmlElementImpl get element => _element; |
1607 Token get endToken => _endToken; | 1712 Token get endToken => _endToken; |
1608 | 1713 |
1609 /** | 1714 /** |
1610 * Answer the tag nodes contained in the receiver. Callers should not manipula
te the returned list | 1715 * Answer the tag nodes contained in the receiver. Callers should not manipula
te the returned list |
1611 * to edit the AST structure. | 1716 * to edit the AST structure. |
| 1717 * |
1612 * @return the children (not `null`, contains no `null`s) | 1718 * @return the children (not `null`, contains no `null`s) |
1613 */ | 1719 */ |
1614 List<XmlTagNode> get tagNodes => _tagNodes; | 1720 List<XmlTagNode> get tagNodes => _tagNodes; |
1615 | 1721 |
1616 /** | 1722 /** |
1617 * Set the element associated with this HTML unit. | 1723 * Set the element associated with this HTML unit. |
| 1724 * |
1618 * @param element the element | 1725 * @param element the element |
1619 */ | 1726 */ |
1620 void set element(HtmlElementImpl element2) { | 1727 void set element(HtmlElementImpl element2) { |
1621 this._element = element2; | 1728 this._element = element2; |
1622 } | 1729 } |
1623 void visitChildren(XmlVisitor<Object> visitor) { | 1730 void visitChildren(XmlVisitor<Object> visitor) { |
1624 for (XmlTagNode node in _tagNodes) { | 1731 for (XmlTagNode node in _tagNodes) { |
1625 node.accept(visitor); | 1732 node.accept(visitor); |
1626 } | 1733 } |
1627 } | 1734 } |
1628 } | 1735 } |
OLD | NEW |