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 'element.dart' show HtmlElementImpl; | 8 import 'element.dart' show HtmlElementImpl; |
9 import 'engine.dart' show AnalysisEngine; | 9 import 'engine.dart' show AnalysisEngine; |
10 /** | 10 /** |
11 * Instances of the class `Token` represent a token that was scanned from the in
put. Each | 11 * Instances of the class `Token` represent a token that was scanned from the in
put. Each |
12 * token knows which token follows it, acting as the head of a linked list of to
kens. | 12 * token knows which token follows it, acting as the head of a linked list of to
kens. |
13 * | 13 * |
14 * @coverage dart.engine.html | 14 * @coverage dart.engine.html |
15 */ | 15 */ |
16 class Token { | 16 class Token { |
17 | 17 |
18 /** | 18 /** |
19 * The offset from the beginning of the file to the first character in the tok
en. | 19 * The offset from the beginning of the file to the first character in the tok
en. |
20 */ | 20 */ |
21 int _offset = 0; | 21 int offset = 0; |
22 | 22 |
23 /** | 23 /** |
24 * The previous token in the token stream. | 24 * The previous token in the token stream. |
25 */ | 25 */ |
26 Token _previous; | 26 Token previous; |
27 | 27 |
28 /** | 28 /** |
29 * The next token in the token stream. | 29 * The next token in the token stream. |
30 */ | 30 */ |
31 Token _next; | 31 Token next; |
32 | 32 |
33 /** | 33 /** |
34 * The type of the token. | 34 * The type of the token. |
35 */ | 35 */ |
36 TokenType _type; | 36 TokenType type; |
37 | 37 |
38 /** | 38 /** |
39 * The lexeme represented by this token. | 39 * The lexeme represented by this token. |
40 */ | 40 */ |
41 String _value; | 41 String lexeme; |
42 | 42 |
43 /** | 43 /** |
44 * Initialize a newly created token. | 44 * Initialize a newly created token. |
45 * | 45 * |
46 * @param type the token type (not `null`) | 46 * @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 | 47 * @param offset the offset from the beginning of the file to the first charac
ter in the token |
48 */ | 48 */ |
49 Token.con1(TokenType type, int offset) : this.con2(type, offset, type.lexeme); | 49 Token.con1(TokenType type, int offset) : this.con2(type, offset, type.lexeme); |
50 | 50 |
51 /** | 51 /** |
52 * Initialize a newly created token. | 52 * Initialize a newly created token. |
53 * | 53 * |
54 * @param type the token type (not `null`) | 54 * @param type the token type (not `null`) |
55 * @param offset the offset from the beginning of the file to the first charac
ter in the token | 55 * @param offset the offset from the beginning of the file to the first charac
ter in the token |
56 * @param value the lexeme represented by this token (not `null`) | 56 * @param value the lexeme represented by this token (not `null`) |
57 */ | 57 */ |
58 Token.con2(TokenType type, int offset, String value) { | 58 Token.con2(TokenType type, int offset, String value) { |
59 this._type = type; | 59 this.type = type; |
60 this._value = StringUtilities.intern(value); | 60 this.lexeme = StringUtilities.intern(value); |
61 this._offset = offset; | 61 this.offset = offset; |
62 } | 62 } |
63 | 63 |
64 /** | 64 /** |
65 * Return the offset from the beginning of the file to the character after las
t character of the | 65 * Return the offset from the beginning of the file to the character after las
t character of the |
66 * token. | 66 * token. |
67 * | 67 * |
68 * @return the offset from the beginning of the file to the first character af
ter last character | 68 * @return the offset from the beginning of the file to the first character af
ter last character |
69 * of the token | 69 * of the token |
70 */ | 70 */ |
71 int get end => _offset + length; | 71 int get end => offset + length; |
72 | 72 |
73 /** | 73 /** |
74 * Return the number of characters in the node's source range. | 74 * Return the number of characters in the node's source range. |
75 * | 75 * |
76 * @return the number of characters in the node's source range | 76 * @return the number of characters in the node's source range |
77 */ | 77 */ |
78 int get length => lexeme.length; | 78 int get length => lexeme.length; |
79 | 79 |
80 /** | 80 /** |
81 * Return the lexeme that represents this token. | |
82 * | |
83 * @return the lexeme (not `null`) | |
84 */ | |
85 String get lexeme => _value; | |
86 | |
87 /** | |
88 * Return the next token in the token stream. | |
89 * | |
90 * @return the next token in the token stream | |
91 */ | |
92 Token get next => _next; | |
93 | |
94 /** | |
95 * Return the offset from the beginning of the file to the first character in
the token. | |
96 * | |
97 * @return the offset from the beginning of the file to the first character in
the token | |
98 */ | |
99 int get offset => _offset; | |
100 | |
101 /** | |
102 * Return the previous token in the token stream. | |
103 * | |
104 * @return the previous token in the token stream | |
105 */ | |
106 Token get previous => _previous; | |
107 | |
108 /** | |
109 * Answer the token type for the receiver. | |
110 * | |
111 * @return the token type (not `null`) | |
112 */ | |
113 TokenType get type => _type; | |
114 | |
115 /** | |
116 * Return `true` if this token is a synthetic token. A synthetic token is a to
ken that was | 81 * 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 | 82 * 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`). | 83 * have a length of zero (`0`). |
119 * | 84 * |
120 * @return `true` if this token is a synthetic token | 85 * @return `true` if this token is a synthetic token |
121 */ | 86 */ |
122 bool get isSynthetic => length == 0; | 87 bool get isSynthetic => length == 0; |
123 | 88 |
124 /** | 89 /** |
125 * Set the next token in the token stream to the given token. This has the sid
e-effect of setting | 90 * Set the next token in the token stream to the given token. This has the sid
e-effect of setting |
126 * this token to be the previous token for the given token. | 91 * this token to be the previous token for the given token. |
127 * | 92 * |
128 * @param token the next token in the token stream | 93 * @param token the next token in the token stream |
129 * @return the token that was passed in | 94 * @return the token that was passed in |
130 */ | 95 */ |
131 Token setNext(Token token) { | 96 Token setNext(Token token) { |
132 _next = token; | 97 next = token; |
133 token.previous = this; | 98 token.previous = this; |
134 return token; | 99 return token; |
135 } | 100 } |
136 String toString() => lexeme; | 101 String toString() => lexeme; |
137 | |
138 /** | |
139 * Set the previous token in the token stream to the given token. | |
140 * | |
141 * @param previous the previous token in the token stream | |
142 */ | |
143 void set previous(Token previous2) { | |
144 this._previous = previous2; | |
145 } | |
146 } | 102 } |
147 /** | 103 /** |
148 * Instances of `HtmlParseResult` hold the result of parsing an HTML file. | 104 * Instances of `HtmlParseResult` hold the result of parsing an HTML file. |
149 * | 105 * |
150 * @coverage dart.engine.html | 106 * @coverage dart.engine.html |
151 */ | 107 */ |
152 class HtmlParseResult extends HtmlScanResult { | 108 class HtmlParseResult extends HtmlScanResult { |
153 | 109 |
154 /** | 110 /** |
155 * The unit containing the parsed information (not `null`). | 111 * The unit containing the parsed information (not `null`). |
156 */ | 112 */ |
157 HtmlUnit _unit; | 113 HtmlUnit htmlUnit; |
158 HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlU
nit unit) : super(modificationTime, token, lineStarts) { | 114 HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlU
nit unit) : super(modificationTime, token, lineStarts) { |
159 this._unit = unit; | 115 this.htmlUnit = unit; |
160 } | 116 } |
161 | |
162 /** | |
163 * Answer the unit generated by parsing the source | |
164 * | |
165 * @return the unit (not `null`) | |
166 */ | |
167 HtmlUnit get htmlUnit => _unit; | |
168 } | 117 } |
169 /** | 118 /** |
170 * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that wi
ll recursively | 119 * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that wi
ll recursively |
171 * visit all of the nodes in an XML structure. For example, using an instance of
this class to visit | 120 * visit all of the nodes in an XML structure. For example, using an instance of
this class to visit |
172 * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and | 121 * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and |
173 * [XmlTagNode]s to be visited. | 122 * [XmlTagNode]s to be visited. |
174 * | 123 * |
175 * Subclasses that override a visit method must either invoke the overridden vis
it method or must | 124 * Subclasses that override a visit method must either invoke the overridden vis
it method or must |
176 * explicitly ask the visited node to visit its children. Failure to do so will
cause the children | 125 * explicitly ask the visited node to visit its children. Failure to do so will
cause the children |
177 * of the visited node to not be visited. | 126 * of the visited node to not be visited. |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 * required to implement the interface used to access the characters being scann
ed. | 336 * required to implement the interface used to access the characters being scann
ed. |
388 * | 337 * |
389 * @coverage dart.engine.html | 338 * @coverage dart.engine.html |
390 */ | 339 */ |
391 abstract class AbstractScanner { | 340 abstract class AbstractScanner { |
392 static List<String> _NO_PASS_THROUGH_ELEMENTS = <String> []; | 341 static List<String> _NO_PASS_THROUGH_ELEMENTS = <String> []; |
393 | 342 |
394 /** | 343 /** |
395 * The source being scanned. | 344 * The source being scanned. |
396 */ | 345 */ |
397 Source _source; | 346 Source source; |
398 | 347 |
399 /** | 348 /** |
400 * The token pointing to the head of the linked list of tokens. | 349 * The token pointing to the head of the linked list of tokens. |
401 */ | 350 */ |
402 Token _tokens; | 351 Token _tokens; |
403 | 352 |
404 /** | 353 /** |
405 * The last token that was scanned. | 354 * The last token that was scanned. |
406 */ | 355 */ |
407 Token _tail; | 356 Token _tail; |
408 | 357 |
409 /** | 358 /** |
410 * A list containing the offsets of the first character of each line in the so
urce code. | 359 * A list containing the offsets of the first character of each line in the so
urce code. |
411 */ | 360 */ |
412 List<int> _lineStarts = new List<int>(); | 361 List<int> _lineStarts = new List<int>(); |
413 | 362 |
414 /** | 363 /** |
415 * An array of element tags for which the content between tags should be consi
der a single token. | 364 * An array of element tags for which the content between tags should be consi
der a single token. |
416 */ | 365 */ |
417 List<String> _passThroughElements = _NO_PASS_THROUGH_ELEMENTS; | 366 List<String> _passThroughElements = _NO_PASS_THROUGH_ELEMENTS; |
418 | 367 |
419 /** | 368 /** |
420 * Initialize a newly created scanner. | 369 * Initialize a newly created scanner. |
421 * | 370 * |
422 * @param source the source being scanned | 371 * @param source the source being scanned |
423 */ | 372 */ |
424 AbstractScanner(Source source) { | 373 AbstractScanner(Source source) { |
425 this._source = source; | 374 this.source = source; |
426 _tokens = new Token.con1(TokenType.EOF, -1); | 375 _tokens = new Token.con1(TokenType.EOF, -1); |
427 _tokens.setNext(_tokens); | 376 _tokens.setNext(_tokens); |
428 _tail = _tokens; | 377 _tail = _tokens; |
429 recordStartOfLine(); | 378 recordStartOfLine(); |
430 } | 379 } |
431 | 380 |
432 /** | 381 /** |
433 * Return an array containing the offsets of the first character of each line
in the source code. | 382 * Return an array containing the offsets of the first character of each line
in the source code. |
434 * | 383 * |
435 * @return an array containing the offsets of the first character of each line
in the source code | 384 * @return an array containing the offsets of the first character of each line
in the source code |
436 */ | 385 */ |
437 List<int> get lineStarts => _lineStarts; | 386 List<int> get lineStarts => _lineStarts; |
438 | 387 |
439 /** | 388 /** |
440 * Return the current offset relative to the beginning of the file. Return the
initial offset if | 389 * Return the current offset relative to the beginning of the file. Return the
initial offset if |
441 * the scanner has not yet scanned the source code, and one (1) past the end o
f the source code if | 390 * the scanner has not yet scanned the source code, and one (1) past the end o
f the source code if |
442 * the source code has been scanned. | 391 * the source code has been scanned. |
443 * | 392 * |
444 * @return the current offset of the scanner in the source | 393 * @return the current offset of the scanner in the source |
445 */ | 394 */ |
446 int get offset; | 395 int get offset; |
447 | 396 |
448 /** | 397 /** |
449 * Answer the source being scanned. | |
450 * | |
451 * @return the source or `null` if undefined | |
452 */ | |
453 Source get source => _source; | |
454 | |
455 /** | |
456 * Set array of element tags for which the content between tags should be cons
ider a single token. | 398 * Set array of element tags for which the content between tags should be cons
ider a single token. |
457 */ | 399 */ |
458 void set passThroughElements(List<String> passThroughElements2) { | 400 void set passThroughElements(List<String> passThroughElements2) { |
459 this._passThroughElements = passThroughElements2 != null ? passThroughElemen
ts2 : _NO_PASS_THROUGH_ELEMENTS; | 401 this._passThroughElements = passThroughElements2 != null ? passThroughElemen
ts2 : _NO_PASS_THROUGH_ELEMENTS; |
460 } | 402 } |
461 | 403 |
462 /** | 404 /** |
463 * Scan the source code to produce a list of tokens representing the source. | 405 * Scan the source code to produce a list of tokens representing the source. |
464 * | 406 * |
465 * @return the first token in the list of tokens that were produced | 407 * @return the first token in the list of tokens that were produced |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 /** | 635 /** |
694 * Instances of `HtmlScanResult` hold the result of scanning an HTML file. | 636 * Instances of `HtmlScanResult` hold the result of scanning an HTML file. |
695 * | 637 * |
696 * @coverage dart.engine.html | 638 * @coverage dart.engine.html |
697 */ | 639 */ |
698 class HtmlScanResult { | 640 class HtmlScanResult { |
699 | 641 |
700 /** | 642 /** |
701 * The time at which the contents of the source were last set. | 643 * The time at which the contents of the source were last set. |
702 */ | 644 */ |
703 int _modificationTime = 0; | 645 int modificationTime = 0; |
704 | 646 |
705 /** | 647 /** |
706 * The first token in the token stream (not `null`). | 648 * The first token in the token stream (not `null`). |
707 */ | 649 */ |
708 Token _token; | 650 Token token; |
709 | 651 |
710 /** | 652 /** |
711 * The line start information that was produced. | 653 * The line start information that was produced. |
712 */ | 654 */ |
713 List<int> _lineStarts; | 655 List<int> lineStarts; |
714 HtmlScanResult(int modificationTime, Token token, List<int> lineStarts) { | 656 HtmlScanResult(int modificationTime, Token token, List<int> lineStarts) { |
715 this._modificationTime = modificationTime; | 657 this.modificationTime = modificationTime; |
716 this._token = token; | 658 this.token = token; |
717 this._lineStarts = lineStarts; | 659 this.lineStarts = lineStarts; |
718 } | 660 } |
719 | |
720 /** | |
721 * Answer the line start information that was produced. | |
722 * | |
723 * @return an array of line starts (not `null`) | |
724 */ | |
725 List<int> get lineStarts => _lineStarts; | |
726 | |
727 /** | |
728 * Return the time at which the contents of the source were last set. | |
729 * | |
730 * @return the time at which the contents of the source were last set | |
731 */ | |
732 int get modificationTime => _modificationTime; | |
733 | |
734 /** | |
735 * Answer the first token in the token stream. | |
736 * | |
737 * @return the token (not `null`) | |
738 */ | |
739 Token get token => _token; | |
740 } | 661 } |
741 /** | 662 /** |
742 * Instances of the class `StringScanner` implement a scanner that reads from a
string. The | 663 * Instances of the class `StringScanner` implement a scanner that reads from a
string. The |
743 * scanning logic is in the superclass. | 664 * scanning logic is in the superclass. |
744 * | 665 * |
745 * @coverage dart.engine.html | 666 * @coverage dart.engine.html |
746 */ | 667 */ |
747 class StringScanner extends AbstractScanner { | 668 class StringScanner extends AbstractScanner { |
748 | 669 |
749 /** | 670 /** |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 DECLARATION, | 871 DECLARATION, |
951 DIRECTIVE, | 872 DIRECTIVE, |
952 STRING, | 873 STRING, |
953 TAG, | 874 TAG, |
954 TEXT]; | 875 TEXT]; |
955 | 876 |
956 /** | 877 /** |
957 * The lexeme that defines this type of token, or `null` if there is more than
one possible | 878 * The lexeme that defines this type of token, or `null` if there is more than
one possible |
958 * lexeme for this type of token. | 879 * lexeme for this type of token. |
959 */ | 880 */ |
960 String _lexeme; | 881 String lexeme; |
961 TokenType(String name, int ordinal, String lexeme) : super(name, ordinal) { | 882 TokenType(String name, int ordinal, String lexeme) : super(name, ordinal) { |
962 this._lexeme = lexeme; | 883 this.lexeme = lexeme; |
963 } | 884 } |
964 | |
965 /** | |
966 * Return the lexeme that defines this type of token, or `null` if there is mo
re than one | |
967 * possible lexeme for this type of token. | |
968 * | |
969 * @return the lexeme that defines this type of token | |
970 */ | |
971 String get lexeme => _lexeme; | |
972 } | 885 } |
973 class TokenType_EOF extends TokenType { | 886 class TokenType_EOF extends TokenType { |
974 TokenType_EOF(String name, int ordinal, String arg0) : super(name, ordinal, ar
g0); | 887 TokenType_EOF(String name, int ordinal, String arg0) : super(name, ordinal, ar
g0); |
975 String toString() => "-eof-"; | 888 String toString() => "-eof-"; |
976 } | 889 } |
977 /** | 890 /** |
978 * Instances of `XmlAttributeNode` represent name/value pairs owned by an [XmlTa
gNode]. | 891 * Instances of `XmlAttributeNode` represent name/value pairs owned by an [XmlTa
gNode]. |
979 * | 892 * |
980 * @coverage dart.engine.html | 893 * @coverage dart.engine.html |
981 */ | 894 */ |
982 class XmlAttributeNode extends XmlNode { | 895 class XmlAttributeNode extends XmlNode { |
983 Token _name; | 896 Token name; |
984 Token _equals; | 897 Token equals; |
985 Token _value; | 898 Token value; |
986 | 899 |
987 /** | 900 /** |
988 * Construct a new instance representing an XML attribute. | 901 * Construct a new instance representing an XML attribute. |
989 * | 902 * |
990 * @param name the name token (not `null`). This may be a zero length token if
the attribute | 903 * @param name the name token (not `null`). This may be a zero length token if
the attribute |
991 * is badly formed. | 904 * is badly formed. |
992 * @param equals the equals sign or `null` if none | 905 * @param equals the equals sign or `null` if none |
993 * @param value the value token (not `null`) | 906 * @param value the value token (not `null`) |
994 */ | 907 */ |
995 XmlAttributeNode(Token name, Token equals, Token value) { | 908 XmlAttributeNode(Token name, Token equals, Token value) { |
996 this._name = name; | 909 this.name = name; |
997 this._equals = equals; | 910 this.equals = equals; |
998 this._value = value; | 911 this.value = value; |
999 } | 912 } |
1000 accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this); | 913 accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this); |
1001 Token get beginToken => _name; | 914 Token get beginToken => name; |
1002 Token get endToken => _value; | 915 Token get endToken => value; |
1003 | |
1004 /** | |
1005 * Answer the equals sign token that appears between the name and value tokens
. This may be | |
1006 * `null` if the attribute is badly formed. | |
1007 * | |
1008 * @return the token or `null` if there is no equals sign between the name and
value | |
1009 */ | |
1010 Token get equals => _equals; | |
1011 | |
1012 /** | |
1013 * Answer the attribute name. This may be a zero length token if the attribute
is badly formed. | |
1014 * | |
1015 * @return the name (not `null`) | |
1016 */ | |
1017 Token get name => _name; | |
1018 | 916 |
1019 /** | 917 /** |
1020 * Answer the lexeme for the value token without the leading and trailing quot
es. | 918 * Answer the lexeme for the value token without the leading and trailing quot
es. |
1021 * | 919 * |
1022 * @return the text or `null` if the value is not specified | 920 * @return the text or `null` if the value is not specified |
1023 */ | 921 */ |
1024 String get text { | 922 String get text { |
1025 if (_value == null) { | 923 if (value == null) { |
1026 return null; | 924 return null; |
1027 } | 925 } |
1028 String text = _value.lexeme; | 926 String text = value.lexeme; |
1029 int len = text.length; | 927 int len = text.length; |
1030 if (len > 0) { | 928 if (len > 0) { |
1031 if (text.codeUnitAt(0) == 0x22) { | 929 if (text.codeUnitAt(0) == 0x22) { |
1032 if (len > 1 && text.codeUnitAt(len - 1) == 0x22) { | 930 if (len > 1 && text.codeUnitAt(len - 1) == 0x22) { |
1033 return text.substring(1, len - 1); | 931 return text.substring(1, len - 1); |
1034 } else { | 932 } else { |
1035 return text.substring(1); | 933 return text.substring(1); |
1036 } | 934 } |
1037 } else if (text.codeUnitAt(0) == 0x27) { | 935 } else if (text.codeUnitAt(0) == 0x27) { |
1038 if (len > 1 && text.codeUnitAt(len - 1) == 0x27) { | 936 if (len > 1 && text.codeUnitAt(len - 1) == 0x27) { |
1039 return text.substring(1, len - 1); | 937 return text.substring(1, len - 1); |
1040 } else { | 938 } else { |
1041 return text.substring(1); | 939 return text.substring(1); |
1042 } | 940 } |
1043 } | 941 } |
1044 } | 942 } |
1045 return text; | 943 return text; |
1046 } | 944 } |
1047 | |
1048 /** | |
1049 * Answer the attribute value. A properly formed value will start and end with
matching quote | |
1050 * characters, but the value returned may not be properly formed. | |
1051 * | |
1052 * @return the value or `null` if this represents a badly formed attribute | |
1053 */ | |
1054 Token get value => _value; | |
1055 void visitChildren(XmlVisitor visitor) { | 945 void visitChildren(XmlVisitor visitor) { |
1056 } | 946 } |
1057 } | 947 } |
1058 /** | 948 /** |
1059 * The interface `XmlVisitor` defines the behavior of objects that can be used t
o visit an | 949 * The interface `XmlVisitor` defines the behavior of objects that can be used t
o visit an |
1060 * [XmlNode] structure. | 950 * [XmlNode] structure. |
1061 * | 951 * |
1062 * @coverage dart.engine.html | 952 * @coverage dart.engine.html |
1063 */ | 953 */ |
1064 abstract class XmlVisitor<R> { | 954 abstract class XmlVisitor<R> { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 * Instances of the class `XmlParser` are used to parse tokens into a AST struct
ure comprised | 1023 * Instances of the class `XmlParser` are used to parse tokens into a AST struct
ure comprised |
1134 * of [XmlNode]s. | 1024 * of [XmlNode]s. |
1135 * | 1025 * |
1136 * @coverage dart.engine.html | 1026 * @coverage dart.engine.html |
1137 */ | 1027 */ |
1138 class XmlParser { | 1028 class XmlParser { |
1139 | 1029 |
1140 /** | 1030 /** |
1141 * The source being parsed. | 1031 * The source being parsed. |
1142 */ | 1032 */ |
1143 Source _source; | 1033 Source source; |
1144 | 1034 |
1145 /** | 1035 /** |
1146 * The next token to be parsed. | 1036 * The next token to be parsed. |
1147 */ | 1037 */ |
1148 Token _currentToken; | 1038 Token currentToken; |
1149 | 1039 |
1150 /** | 1040 /** |
1151 * Construct a parser for the specified source. | 1041 * Construct a parser for the specified source. |
1152 * | 1042 * |
1153 * @param source the source being parsed | 1043 * @param source the source being parsed |
1154 */ | 1044 */ |
1155 XmlParser(Source source) { | 1045 XmlParser(Source source) { |
1156 this._source = source; | 1046 this.source = source; |
1157 } | 1047 } |
1158 | 1048 |
1159 /** | 1049 /** |
1160 * Answer the source being parsed. | |
1161 * | |
1162 * @return the source | |
1163 */ | |
1164 Source get source => _source; | |
1165 | |
1166 /** | |
1167 * Answer `true` if the specified tag is self closing and thus should never ha
ve content or | 1050 * Answer `true` if the specified tag is self closing and thus should never ha
ve content or |
1168 * child tag nodes. | 1051 * child tag nodes. |
1169 * | 1052 * |
1170 * @param tag the tag (not `null`) | 1053 * @param tag the tag (not `null`) |
1171 * @return `true` if self closing | 1054 * @return `true` if self closing |
1172 */ | 1055 */ |
1173 bool isSelfClosing(Token tag) => false; | 1056 bool isSelfClosing(Token tag) => false; |
1174 | 1057 |
1175 /** | 1058 /** |
1176 * Parse the entire token stream and in the process, advance the current token
to the end of the | 1059 * Parse the entire token stream and in the process, advance the current token
to the end of the |
1177 * token stream. | 1060 * token stream. |
1178 * | 1061 * |
1179 * @return the list of tag nodes found (not `null`, contains no `null`) | 1062 * @return the list of tag nodes found (not `null`, contains no `null`) |
1180 */ | 1063 */ |
1181 List<XmlTagNode> parseTopTagNodes(Token firstToken) { | 1064 List<XmlTagNode> parseTopTagNodes(Token firstToken) { |
1182 _currentToken = firstToken; | 1065 currentToken = firstToken; |
1183 List<XmlTagNode> tagNodes = new List<XmlTagNode>(); | 1066 List<XmlTagNode> tagNodes = new List<XmlTagNode>(); |
1184 while (true) { | 1067 while (true) { |
1185 while (true) { | 1068 while (true) { |
1186 if (_currentToken.type == TokenType.LT) { | 1069 if (currentToken.type == TokenType.LT) { |
1187 tagNodes.add(parseTagNode()); | 1070 tagNodes.add(parseTagNode()); |
1188 } else if (_currentToken.type == TokenType.DECLARATION || _currentToken.
type == TokenType.DIRECTIVE || _currentToken.type == TokenType.COMMENT) { | 1071 } else if (currentToken.type == TokenType.DECLARATION || currentToken.ty
pe == TokenType.DIRECTIVE || currentToken.type == TokenType.COMMENT) { |
1189 _currentToken = _currentToken.next; | 1072 currentToken = currentToken.next; |
1190 } else if (_currentToken.type == TokenType.EOF) { | 1073 } else if (currentToken.type == TokenType.EOF) { |
1191 return tagNodes; | 1074 return tagNodes; |
1192 } else { | 1075 } else { |
1193 reportUnexpectedToken(); | 1076 reportUnexpectedToken(); |
1194 _currentToken = _currentToken.next; | 1077 currentToken = currentToken.next; |
1195 } | 1078 } |
1196 break; | 1079 break; |
1197 } | 1080 } |
1198 } | 1081 } |
1199 } | 1082 } |
1200 | 1083 |
1201 /** | 1084 /** |
1202 * Answer the current token. | |
1203 * | |
1204 * @return the current token | |
1205 */ | |
1206 Token get currentToken => _currentToken; | |
1207 | |
1208 /** | |
1209 * Insert a synthetic token of the specified type before the current token | 1085 * Insert a synthetic token of the specified type before the current token |
1210 * | 1086 * |
1211 * @param type the type of token to be inserted (not `null`) | 1087 * @param type the type of token to be inserted (not `null`) |
1212 * @return the synthetic token that was inserted (not `null`) | 1088 * @return the synthetic token that was inserted (not `null`) |
1213 */ | 1089 */ |
1214 Token insertSyntheticToken(TokenType type) { | 1090 Token insertSyntheticToken(TokenType type) { |
1215 Token token = new Token.con2(type, _currentToken.offset, ""); | 1091 Token token = new Token.con2(type, currentToken.offset, ""); |
1216 _currentToken.previous.setNext(token); | 1092 currentToken.previous.setNext(token); |
1217 token.setNext(_currentToken); | 1093 token.setNext(currentToken); |
1218 return token; | 1094 return token; |
1219 } | 1095 } |
1220 | 1096 |
1221 /** | 1097 /** |
1222 * Parse the token stream for an attribute. This method advances the current t
oken over the | 1098 * Parse the token stream for an attribute. This method advances the current t
oken over the |
1223 * attribute, but should not be called if the [currentToken] is not [TokenType
#TAG]. | 1099 * attribute, but should not be called if the [currentToken] is not [TokenType
#TAG]. |
1224 * | 1100 * |
1225 * @return the attribute (not `null`) | 1101 * @return the attribute (not `null`) |
1226 */ | 1102 */ |
1227 XmlAttributeNode parseAttribute() { | 1103 XmlAttributeNode parseAttribute() { |
1228 Token name = _currentToken; | 1104 Token name = currentToken; |
1229 _currentToken = _currentToken.next; | 1105 currentToken = currentToken.next; |
1230 Token equals; | 1106 Token equals; |
1231 if (identical(_currentToken.type, TokenType.EQ)) { | 1107 if (identical(currentToken.type, TokenType.EQ)) { |
1232 equals = _currentToken; | 1108 equals = currentToken; |
1233 _currentToken = _currentToken.next; | 1109 currentToken = currentToken.next; |
1234 } else { | 1110 } else { |
1235 reportUnexpectedToken(); | 1111 reportUnexpectedToken(); |
1236 equals = insertSyntheticToken(TokenType.EQ); | 1112 equals = insertSyntheticToken(TokenType.EQ); |
1237 } | 1113 } |
1238 Token value; | 1114 Token value; |
1239 if (identical(_currentToken.type, TokenType.STRING)) { | 1115 if (identical(currentToken.type, TokenType.STRING)) { |
1240 value = _currentToken; | 1116 value = currentToken; |
1241 _currentToken = _currentToken.next; | 1117 currentToken = currentToken.next; |
1242 } else { | 1118 } else { |
1243 reportUnexpectedToken(); | 1119 reportUnexpectedToken(); |
1244 value = insertSyntheticToken(TokenType.STRING); | 1120 value = insertSyntheticToken(TokenType.STRING); |
1245 } | 1121 } |
1246 return new XmlAttributeNode(name, equals, value); | 1122 return new XmlAttributeNode(name, equals, value); |
1247 } | 1123 } |
1248 | 1124 |
1249 /** | 1125 /** |
1250 * Parse the stream for a sequence of attributes. This method advances the cur
rent token to the | 1126 * Parse the stream for a sequence of attributes. This method advances the cur
rent token to the |
1251 * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF]. | 1127 * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF]. |
1252 * | 1128 * |
1253 * @return a collection of zero or more attributes (not `null`, contains no `n
ull`s) | 1129 * @return a collection of zero or more attributes (not `null`, contains no `n
ull`s) |
1254 */ | 1130 */ |
1255 List<XmlAttributeNode> parseAttributes() { | 1131 List<XmlAttributeNode> parseAttributes() { |
1256 TokenType type = _currentToken.type; | 1132 TokenType type = currentToken.type; |
1257 if (identical(type, TokenType.GT) || identical(type, TokenType.SLASH_GT) ||
identical(type, TokenType.EOF)) { | 1133 if (identical(type, TokenType.GT) || identical(type, TokenType.SLASH_GT) ||
identical(type, TokenType.EOF)) { |
1258 return XmlTagNode.NO_ATTRIBUTES; | 1134 return XmlTagNode.NO_ATTRIBUTES; |
1259 } | 1135 } |
1260 List<XmlAttributeNode> attributes = new List<XmlAttributeNode>(); | 1136 List<XmlAttributeNode> attributes = new List<XmlAttributeNode>(); |
1261 while (true) { | 1137 while (true) { |
1262 while (true) { | 1138 while (true) { |
1263 if (_currentToken.type == TokenType.GT || _currentToken.type == TokenTyp
e.SLASH_GT || _currentToken.type == TokenType.EOF) { | 1139 if (currentToken.type == TokenType.GT || currentToken.type == TokenType.
SLASH_GT || currentToken.type == TokenType.EOF) { |
1264 return attributes; | 1140 return attributes; |
1265 } else if (_currentToken.type == TokenType.TAG) { | 1141 } else if (currentToken.type == TokenType.TAG) { |
1266 attributes.add(parseAttribute()); | 1142 attributes.add(parseAttribute()); |
1267 } else { | 1143 } else { |
1268 reportUnexpectedToken(); | 1144 reportUnexpectedToken(); |
1269 _currentToken = _currentToken.next; | 1145 currentToken = currentToken.next; |
1270 } | 1146 } |
1271 break; | 1147 break; |
1272 } | 1148 } |
1273 } | 1149 } |
1274 } | 1150 } |
1275 | 1151 |
1276 /** | 1152 /** |
1277 * Parse the stream for a sequence of tag nodes existing within a parent tag n
ode. This method | 1153 * Parse the stream for a sequence of tag nodes existing within a parent tag n
ode. This method |
1278 * advances the current token to the next [TokenType#LT_SLASH] or [TokenType#E
OF]. | 1154 * advances the current token to the next [TokenType#LT_SLASH] or [TokenType#E
OF]. |
1279 * | 1155 * |
1280 * @return a list of nodes (not `null`, contains no `null`s) | 1156 * @return a list of nodes (not `null`, contains no `null`s) |
1281 */ | 1157 */ |
1282 List<XmlTagNode> parseChildTagNodes() { | 1158 List<XmlTagNode> parseChildTagNodes() { |
1283 TokenType type = _currentToken.type; | 1159 TokenType type = currentToken.type; |
1284 if (identical(type, TokenType.LT_SLASH) || identical(type, TokenType.EOF)) { | 1160 if (identical(type, TokenType.LT_SLASH) || identical(type, TokenType.EOF)) { |
1285 return XmlTagNode.NO_TAG_NODES; | 1161 return XmlTagNode.NO_TAG_NODES; |
1286 } | 1162 } |
1287 List<XmlTagNode> nodes = new List<XmlTagNode>(); | 1163 List<XmlTagNode> nodes = new List<XmlTagNode>(); |
1288 while (true) { | 1164 while (true) { |
1289 while (true) { | 1165 while (true) { |
1290 if (_currentToken.type == TokenType.LT) { | 1166 if (currentToken.type == TokenType.LT) { |
1291 nodes.add(parseTagNode()); | 1167 nodes.add(parseTagNode()); |
1292 } else if (_currentToken.type == TokenType.LT_SLASH || _currentToken.typ
e == TokenType.EOF) { | 1168 } else if (currentToken.type == TokenType.LT_SLASH || currentToken.type
== TokenType.EOF) { |
1293 return nodes; | 1169 return nodes; |
1294 } else if (_currentToken.type == TokenType.COMMENT) { | 1170 } else if (currentToken.type == TokenType.COMMENT) { |
1295 _currentToken = _currentToken.next; | 1171 currentToken = currentToken.next; |
1296 } else { | 1172 } else { |
1297 reportUnexpectedToken(); | 1173 reportUnexpectedToken(); |
1298 _currentToken = _currentToken.next; | 1174 currentToken = currentToken.next; |
1299 } | 1175 } |
1300 break; | 1176 break; |
1301 } | 1177 } |
1302 } | 1178 } |
1303 } | 1179 } |
1304 | 1180 |
1305 /** | 1181 /** |
1306 * Parse the token stream for the next tag node. This method advances current
token over the | 1182 * Parse the token stream for the next tag node. This method advances current
token over the |
1307 * parsed tag node, but should only be called if the current token is [TokenTy
pe#LT] | 1183 * parsed tag node, but should only be called if the current token is [TokenTy
pe#LT] |
1308 * | 1184 * |
1309 * @return the tag node or `null` if none found | 1185 * @return the tag node or `null` if none found |
1310 */ | 1186 */ |
1311 XmlTagNode parseTagNode() { | 1187 XmlTagNode parseTagNode() { |
1312 Token nodeStart = _currentToken; | 1188 Token nodeStart = currentToken; |
1313 _currentToken = _currentToken.next; | 1189 currentToken = currentToken.next; |
1314 Token tag; | 1190 Token tag; |
1315 if (identical(_currentToken.type, TokenType.TAG)) { | 1191 if (identical(currentToken.type, TokenType.TAG)) { |
1316 tag = _currentToken; | 1192 tag = currentToken; |
1317 _currentToken = _currentToken.next; | 1193 currentToken = currentToken.next; |
1318 } else { | 1194 } else { |
1319 reportUnexpectedToken(); | 1195 reportUnexpectedToken(); |
1320 tag = insertSyntheticToken(TokenType.TAG); | 1196 tag = insertSyntheticToken(TokenType.TAG); |
1321 } | 1197 } |
1322 List<XmlAttributeNode> attributes = parseAttributes(); | 1198 List<XmlAttributeNode> attributes = parseAttributes(); |
1323 Token attributeEnd; | 1199 Token attributeEnd; |
1324 if (identical(_currentToken.type, TokenType.GT) || identical(_currentToken.t
ype, TokenType.SLASH_GT)) { | 1200 if (identical(currentToken.type, TokenType.GT) || identical(currentToken.typ
e, TokenType.SLASH_GT)) { |
1325 attributeEnd = _currentToken; | 1201 attributeEnd = currentToken; |
1326 _currentToken = _currentToken.next; | 1202 currentToken = currentToken.next; |
1327 } else { | 1203 } else { |
1328 reportUnexpectedToken(); | 1204 reportUnexpectedToken(); |
1329 attributeEnd = insertSyntheticToken(TokenType.SLASH_GT); | 1205 attributeEnd = insertSyntheticToken(TokenType.SLASH_GT); |
1330 } | 1206 } |
1331 if (identical(attributeEnd.type, TokenType.SLASH_GT) || isSelfClosing(tag))
{ | 1207 if (identical(attributeEnd.type, TokenType.SLASH_GT) || isSelfClosing(tag))
{ |
1332 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, XmlTagNode
.NO_TAG_NODES, _currentToken, null, attributeEnd); | 1208 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, XmlTagNode
.NO_TAG_NODES, currentToken, null, attributeEnd); |
1333 } | 1209 } |
1334 List<XmlTagNode> tagNodes = parseChildTagNodes(); | 1210 List<XmlTagNode> tagNodes = parseChildTagNodes(); |
1335 Token contentEnd; | 1211 Token contentEnd; |
1336 if (identical(_currentToken.type, TokenType.LT_SLASH)) { | 1212 if (identical(currentToken.type, TokenType.LT_SLASH)) { |
1337 contentEnd = _currentToken; | 1213 contentEnd = currentToken; |
1338 _currentToken = _currentToken.next; | 1214 currentToken = currentToken.next; |
1339 } else { | 1215 } else { |
1340 reportUnexpectedToken(); | 1216 reportUnexpectedToken(); |
1341 contentEnd = insertSyntheticToken(TokenType.LT_SLASH); | 1217 contentEnd = insertSyntheticToken(TokenType.LT_SLASH); |
1342 } | 1218 } |
1343 Token closingTag; | 1219 Token closingTag; |
1344 if (identical(_currentToken.type, TokenType.TAG)) { | 1220 if (identical(currentToken.type, TokenType.TAG)) { |
1345 closingTag = _currentToken; | 1221 closingTag = currentToken; |
1346 _currentToken = _currentToken.next; | 1222 currentToken = currentToken.next; |
1347 } else { | 1223 } else { |
1348 reportUnexpectedToken(); | 1224 reportUnexpectedToken(); |
1349 closingTag = insertSyntheticToken(TokenType.TAG); | 1225 closingTag = insertSyntheticToken(TokenType.TAG); |
1350 } | 1226 } |
1351 Token nodeEnd; | 1227 Token nodeEnd; |
1352 if (identical(_currentToken.type, TokenType.GT)) { | 1228 if (identical(currentToken.type, TokenType.GT)) { |
1353 nodeEnd = _currentToken; | 1229 nodeEnd = currentToken; |
1354 _currentToken = _currentToken.next; | 1230 currentToken = currentToken.next; |
1355 } else { | 1231 } else { |
1356 reportUnexpectedToken(); | 1232 reportUnexpectedToken(); |
1357 nodeEnd = insertSyntheticToken(TokenType.GT); | 1233 nodeEnd = insertSyntheticToken(TokenType.GT); |
1358 } | 1234 } |
1359 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes, co
ntentEnd, closingTag, nodeEnd); | 1235 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes, co
ntentEnd, closingTag, nodeEnd); |
1360 } | 1236 } |
1361 | 1237 |
1362 /** | 1238 /** |
1363 * Report the current token as unexpected | 1239 * Report the current token as unexpected |
1364 */ | 1240 */ |
(...skipping 14 matching lines...) Expand all Loading... |
1379 static List<XmlAttributeNode> NO_ATTRIBUTES = new UnmodifiableListView(new Lis
t<XmlAttributeNode>()); | 1255 static List<XmlAttributeNode> NO_ATTRIBUTES = new UnmodifiableListView(new Lis
t<XmlAttributeNode>()); |
1380 | 1256 |
1381 /** | 1257 /** |
1382 * Constant representing empty list of tag nodes. | 1258 * Constant representing empty list of tag nodes. |
1383 */ | 1259 */ |
1384 static List<XmlTagNode> NO_TAG_NODES = new UnmodifiableListView(new List<XmlTa
gNode>()); | 1260 static List<XmlTagNode> NO_TAG_NODES = new UnmodifiableListView(new List<XmlTa
gNode>()); |
1385 | 1261 |
1386 /** | 1262 /** |
1387 * The starting [TokenType#LT] token (not `null`). | 1263 * The starting [TokenType#LT] token (not `null`). |
1388 */ | 1264 */ |
1389 Token _nodeStart; | 1265 Token nodeStart; |
1390 | 1266 |
1391 /** | 1267 /** |
1392 * The [TokenType#TAG] token after the starting '<' (not `null`). | 1268 * The [TokenType#TAG] token after the starting '<' (not `null`). |
1393 */ | 1269 */ |
1394 Token _tag; | 1270 Token tag; |
1395 | 1271 |
1396 /** | 1272 /** |
1397 * The attributes contained by the receiver (not `null`, contains no `null`s). | 1273 * The attributes contained by the receiver (not `null`, contains no `null`s). |
1398 */ | 1274 */ |
1399 List<XmlAttributeNode> _attributes; | 1275 List<XmlAttributeNode> attributes; |
1400 | 1276 |
1401 /** | 1277 /** |
1402 * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not | 1278 * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not |
1403 * `null`). The token may be the same token as [nodeEnd] if there are no child | 1279 * `null`). The token may be the same token as [nodeEnd] if there are no child |
1404 * [tagNodes]. | 1280 * [tagNodes]. |
1405 */ | 1281 */ |
1406 Token _attributeEnd; | 1282 Token attributeEnd; |
1407 | 1283 |
1408 /** | 1284 /** |
1409 * The tag nodes contained in the receiver (not `null`, contains no `null`s). | 1285 * The tag nodes contained in the receiver (not `null`, contains no `null`s). |
1410 */ | 1286 */ |
1411 List<XmlTagNode> _tagNodes; | 1287 List<XmlTagNode> tagNodes; |
1412 | 1288 |
1413 /** | 1289 /** |
1414 * The token (not `null`) after the content, which may be | 1290 * The token (not `null`) after the content, which may be |
1415 * | 1291 * |
1416 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or | 1292 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or |
1417 * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is
self | 1293 * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is
self |
1418 * closing or the attributeEnd is [TokenType#SLASH_GT], or | 1294 * closing or the attributeEnd is [TokenType#SLASH_GT], or |
1419 * * (3) [TokenType#EOF] if the node does not have a closing tag and is the la
st node in | 1295 * * (3) [TokenType#EOF] if the node does not have a closing tag and is the la
st node in |
1420 * the stream [TokenType#LT_SLASH] token after the content, or `null` if there
is no | 1296 * the stream [TokenType#LT_SLASH] token after the content, or `null` if there
is no |
1421 * content and the attributes ended with [TokenType#SLASH_GT]. | 1297 * content and the attributes ended with [TokenType#SLASH_GT]. |
1422 * | 1298 * |
1423 */ | 1299 */ |
1424 Token _contentEnd; | 1300 Token contentEnd; |
1425 | 1301 |
1426 /** | 1302 /** |
1427 * The closing [TokenType#TAG] after the child elements or `null` if there is
no | 1303 * The closing [TokenType#TAG] after the child elements or `null` if there is
no |
1428 * content and the attributes ended with [TokenType#SLASH_GT] | 1304 * content and the attributes ended with [TokenType#SLASH_GT] |
1429 */ | 1305 */ |
1430 Token _closingTag; | 1306 Token closingTag; |
1431 | 1307 |
1432 /** | 1308 /** |
1433 * The ending [TokenType#GT] or [TokenType#SLASH_GT] token (not `null`). | 1309 * The ending [TokenType#GT] or [TokenType#SLASH_GT] token (not `null`). |
1434 */ | 1310 */ |
1435 Token _nodeEnd; | 1311 Token nodeEnd; |
1436 | 1312 |
1437 /** | 1313 /** |
1438 * Construct a new instance representing an XML or HTML element | 1314 * Construct a new instance representing an XML or HTML element |
1439 * | 1315 * |
1440 * @param nodeStart the starting [TokenType#LT] token (not `null`) | 1316 * @param nodeStart the starting [TokenType#LT] token (not `null`) |
1441 * @param tag the [TokenType#TAG] token after the starting '<' (not `null`)
. | 1317 * @param tag the [TokenType#TAG] token after the starting '<' (not `null`)
. |
1442 * @param attributes the attributes associated with this element or [NO_ATTRIB
UTES] (not | 1318 * @param attributes the attributes associated with this element or [NO_ATTRIB
UTES] (not |
1443 * `null`, contains no `null`s) | 1319 * `null`, contains no `null`s) |
1444 * @param attributeEnd The [TokenType#GT] or [TokenType#SLASH_GT] token after
the | 1320 * @param attributeEnd The [TokenType#GT] or [TokenType#SLASH_GT] token after
the |
1445 * attributes (not `null`). The token may be the same token as [nodeE
nd] if | 1321 * attributes (not `null`). The token may be the same token as [nodeE
nd] if |
1446 * there are no child [tagNodes]. | 1322 * there are no child [tagNodes]. |
1447 * @param tagNodes child tag nodes of the receiver or [NO_TAG_NODES] (not `nul
l`, | 1323 * @param tagNodes child tag nodes of the receiver or [NO_TAG_NODES] (not `nul
l`, |
1448 * contains no `null`s) | 1324 * contains no `null`s) |
1449 * @param contentEnd the token (not `null`) after the content, which may be | 1325 * @param contentEnd the token (not `null`) after the content, which may be |
1450 * | 1326 * |
1451 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or | 1327 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or |
1452 * * (2) the [TokenType#LT] nodeStart of the next sibling node if thi
s node is | 1328 * * (2) the [TokenType#LT] nodeStart of the next sibling node if thi
s node is |
1453 * self closing or the attributeEnd is [TokenType#SLASH_GT], or | 1329 * self closing or the attributeEnd is [TokenType#SLASH_GT], or |
1454 * * (3) [TokenType#EOF] if the node does not have a closing tag and
is the last | 1330 * * (3) [TokenType#EOF] if the node does not have a closing tag and
is the last |
1455 * node in the stream [TokenType#LT_SLASH] token after the content, o
r `null` | 1331 * node in the stream [TokenType#LT_SLASH] token after the content, o
r `null` |
1456 * if there is no content and the attributes ended with [TokenType#SL
ASH_GT]. | 1332 * if there is no content and the attributes ended with [TokenType#SL
ASH_GT]. |
1457 * | 1333 * |
1458 * @param closingTag the closing [TokenType#TAG] after the child elements or `
null` if | 1334 * @param closingTag the closing [TokenType#TAG] after the child elements or `
null` if |
1459 * there is no content and the attributes ended with [TokenType#SLASH
_GT] | 1335 * there is no content and the attributes ended with [TokenType#SLASH
_GT] |
1460 * @param nodeEnd the ending [TokenType#GT] or [TokenType#SLASH_GT] token (not | 1336 * @param nodeEnd the ending [TokenType#GT] or [TokenType#SLASH_GT] token (not |
1461 * `null`) | 1337 * `null`) |
1462 */ | 1338 */ |
1463 XmlTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> attributes, Toke
n attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag, T
oken nodeEnd) { | 1339 XmlTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> attributes, Toke
n attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag, T
oken nodeEnd) { |
1464 this._nodeStart = nodeStart; | 1340 this.nodeStart = nodeStart; |
1465 this._tag = tag; | 1341 this.tag = tag; |
1466 this._attributes = becomeParentOfEmpty(attributes, NO_ATTRIBUTES); | 1342 this.attributes = becomeParentOfEmpty(attributes, NO_ATTRIBUTES); |
1467 this._attributeEnd = attributeEnd; | 1343 this.attributeEnd = attributeEnd; |
1468 this._tagNodes = becomeParentOfEmpty(tagNodes, NO_TAG_NODES); | 1344 this.tagNodes = becomeParentOfEmpty(tagNodes, NO_TAG_NODES); |
1469 this._contentEnd = contentEnd; | 1345 this.contentEnd = contentEnd; |
1470 this._closingTag = closingTag; | 1346 this.closingTag = closingTag; |
1471 this._nodeEnd = nodeEnd; | 1347 this.nodeEnd = nodeEnd; |
1472 } | 1348 } |
1473 accept(XmlVisitor visitor) => visitor.visitXmlTagNode(this); | 1349 accept(XmlVisitor visitor) => visitor.visitXmlTagNode(this); |
1474 | 1350 |
1475 /** | 1351 /** |
1476 * Answer the attribute with the specified name. | 1352 * Answer the attribute with the specified name. |
1477 * | 1353 * |
1478 * @param name the attribute name | 1354 * @param name the attribute name |
1479 * @return the attribute or `null` if no matching attribute is found | 1355 * @return the attribute or `null` if no matching attribute is found |
1480 */ | 1356 */ |
1481 XmlAttributeNode getAttribute(String name2) { | 1357 XmlAttributeNode getAttribute(String name2) { |
1482 for (XmlAttributeNode attribute in _attributes) { | 1358 for (XmlAttributeNode attribute in attributes) { |
1483 if (attribute.name.lexeme == name2) { | 1359 if (attribute.name.lexeme == name2) { |
1484 return attribute; | 1360 return attribute; |
1485 } | 1361 } |
1486 } | 1362 } |
1487 return null; | 1363 return null; |
1488 } | 1364 } |
1489 | 1365 |
1490 /** | 1366 /** |
1491 * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not | |
1492 * `null`). The token may be the same token as [nodeEnd] if there are no child | |
1493 * [tagNodes]. | |
1494 * | |
1495 * @return the token (not `null`) | |
1496 */ | |
1497 Token get attributeEnd => _attributeEnd; | |
1498 | |
1499 /** | |
1500 * Answer the receiver's attributes. Callers should not manipulate the returne
d list to edit the | |
1501 * AST structure. | |
1502 * | |
1503 * @return the attributes (not `null`, contains no `null`s) | |
1504 */ | |
1505 List<XmlAttributeNode> get attributes => _attributes; | |
1506 | |
1507 /** | |
1508 * Find the attribute with the given name (see [getAttribute] and answer the l
exeme | 1367 * Find the attribute with the given name (see [getAttribute] and answer the l
exeme |
1509 * for the attribute's value token without the leading and trailing quotes (se
e | 1368 * for the attribute's value token without the leading and trailing quotes (se
e |
1510 * [XmlAttributeNode#getText]). | 1369 * [XmlAttributeNode#getText]). |
1511 * | 1370 * |
1512 * @param name the attribute name | 1371 * @param name the attribute name |
1513 * @return the attribute text or `null` if no matching attribute is found | 1372 * @return the attribute text or `null` if no matching attribute is found |
1514 */ | 1373 */ |
1515 String getAttributeText(String name) { | 1374 String getAttributeText(String name) { |
1516 XmlAttributeNode attribute = getAttribute(name); | 1375 XmlAttributeNode attribute = getAttribute(name); |
1517 return attribute != null ? attribute.text : null; | 1376 return attribute != null ? attribute.text : null; |
1518 } | 1377 } |
1519 Token get beginToken => _nodeStart; | 1378 Token get beginToken => nodeStart; |
1520 | |
1521 /** | |
1522 * The the closing [TokenType#TAG] after the child elements or `null` if there
is no | |
1523 * content and the attributes ended with [TokenType#SLASH_GT] | |
1524 * | |
1525 * @return the closing tag or `null` | |
1526 */ | |
1527 Token get closingTag => _closingTag; | |
1528 | 1379 |
1529 /** | 1380 /** |
1530 * Answer a string representing the content contained in the receiver. This in
cludes the textual | 1381 * Answer a string representing the content contained in the receiver. This in
cludes the textual |
1531 * representation of any child tag nodes ([getTagNodes]). Whitespace between '
<', | 1382 * representation of any child tag nodes ([getTagNodes]). Whitespace between '
<', |
1532 * '</', and '>', '/>' is discarded, but all other whitespace is preserved. | 1383 * '</', and '>', '/>' is discarded, but all other whitespace is preserved. |
1533 * | 1384 * |
1534 * @return the content (not `null`) | 1385 * @return the content (not `null`) |
1535 */ | 1386 */ |
1536 String get content { | 1387 String get content { |
1537 Token token = _attributeEnd.next; | 1388 Token token = attributeEnd.next; |
1538 if (identical(token, _contentEnd)) { | 1389 if (identical(token, contentEnd)) { |
1539 return ""; | 1390 return ""; |
1540 } | 1391 } |
1541 String content = token.lexeme; | 1392 String content = token.lexeme; |
1542 token = token.next; | 1393 token = token.next; |
1543 if (identical(token, _contentEnd)) { | 1394 if (identical(token, contentEnd)) { |
1544 return content; | 1395 return content; |
1545 } | 1396 } |
1546 JavaStringBuilder buffer = new JavaStringBuilder(); | 1397 JavaStringBuilder buffer = new JavaStringBuilder(); |
1547 while (token != _contentEnd) { | 1398 while (token != contentEnd) { |
1548 buffer.append(token.lexeme); | 1399 buffer.append(token.lexeme); |
1549 token = token.next; | 1400 token = token.next; |
1550 } | 1401 } |
1551 return buffer.toString(); | 1402 return buffer.toString(); |
1552 } | 1403 } |
1553 | |
1554 /** | |
1555 * Answer the token (not `null`) after the content, which may be | |
1556 * | |
1557 * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or | |
1558 * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is
self | |
1559 * closing or the attributeEnd is [TokenType#SLASH_GT], or | |
1560 * * (3) [TokenType#EOF] if the node does not have a closing tag and is the la
st node in | |
1561 * the stream [TokenType#LT_SLASH] token after the content, or `null` if there
is no | |
1562 * content and the attributes ended with [TokenType#SLASH_GT]. | |
1563 * | |
1564 * | |
1565 * @return the token (not `null`) | |
1566 */ | |
1567 Token get contentEnd => _contentEnd; | |
1568 Token get endToken { | 1404 Token get endToken { |
1569 if (_nodeEnd != null) { | 1405 if (nodeEnd != null) { |
1570 return _nodeEnd; | 1406 return nodeEnd; |
1571 } | 1407 } |
1572 if (_closingTag != null) { | 1408 if (closingTag != null) { |
1573 return _closingTag; | 1409 return closingTag; |
1574 } | 1410 } |
1575 if (_contentEnd != null) { | 1411 if (contentEnd != null) { |
1576 return _contentEnd; | 1412 return contentEnd; |
1577 } | 1413 } |
1578 if (!_tagNodes.isEmpty) { | 1414 if (!tagNodes.isEmpty) { |
1579 return _tagNodes[_tagNodes.length - 1].endToken; | 1415 return tagNodes[tagNodes.length - 1].endToken; |
1580 } | 1416 } |
1581 if (_attributeEnd != null) { | 1417 if (attributeEnd != null) { |
1582 return _attributeEnd; | 1418 return attributeEnd; |
1583 } | 1419 } |
1584 if (!_attributes.isEmpty) { | 1420 if (!attributes.isEmpty) { |
1585 return _attributes[_attributes.length - 1].endToken; | 1421 return attributes[attributes.length - 1].endToken; |
1586 } | 1422 } |
1587 return _tag; | 1423 return tag; |
1588 } | 1424 } |
1589 | |
1590 /** | |
1591 * Answer the ending [TokenType#GT] or [TokenType#SLASH_GT] token. | |
1592 * | |
1593 * @return the token (not `null`) | |
1594 */ | |
1595 Token get nodeEnd => _nodeEnd; | |
1596 | |
1597 /** | |
1598 * Answer the starting [TokenType#LT] token. | |
1599 * | |
1600 * @return the token (not `null`) | |
1601 */ | |
1602 Token get nodeStart => _nodeStart; | |
1603 | |
1604 /** | |
1605 * Answer the [TokenType#TAG] token after the starting '<'. | |
1606 * | |
1607 * @return the token (not `null`) | |
1608 */ | |
1609 Token get tag => _tag; | |
1610 | |
1611 /** | |
1612 * Answer the tag nodes contained in the receiver. Callers should not manipula
te the returned list | |
1613 * to edit the AST structure. | |
1614 * | |
1615 * @return the children (not `null`, contains no `null`s) | |
1616 */ | |
1617 List<XmlTagNode> get tagNodes => _tagNodes; | |
1618 void visitChildren(XmlVisitor visitor) { | 1425 void visitChildren(XmlVisitor visitor) { |
1619 for (XmlAttributeNode node in _attributes) { | 1426 for (XmlAttributeNode node in attributes) { |
1620 node.accept(visitor); | 1427 node.accept(visitor); |
1621 } | 1428 } |
1622 for (XmlTagNode node in _tagNodes) { | 1429 for (XmlTagNode node in tagNodes) { |
1623 node.accept(visitor); | 1430 node.accept(visitor); |
1624 } | 1431 } |
1625 } | 1432 } |
1626 | 1433 |
1627 /** | 1434 /** |
1628 * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empt
y | 1435 * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empt
y |
1629 */ | 1436 */ |
1630 List becomeParentOfEmpty(List children, List ifEmpty) { | 1437 List becomeParentOfEmpty(List children, List ifEmpty) { |
1631 if (children != null && children.isEmpty) { | 1438 if (children != null && children.isEmpty) { |
1632 return ifEmpty; | 1439 return ifEmpty; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1690 | 1497 |
1691 /** | 1498 /** |
1692 * The last token in the token stream that was parsed to form this compilation
unit. This token | 1499 * The last token in the token stream that was parsed to form this compilation
unit. This token |
1693 * should always have a type of [TokenType.EOF]. | 1500 * should always have a type of [TokenType.EOF]. |
1694 */ | 1501 */ |
1695 Token _endToken; | 1502 Token _endToken; |
1696 | 1503 |
1697 /** | 1504 /** |
1698 * The tag nodes contained in the receiver (not `null`, contains no `null`s). | 1505 * The tag nodes contained in the receiver (not `null`, contains no `null`s). |
1699 */ | 1506 */ |
1700 List<XmlTagNode> _tagNodes; | 1507 List<XmlTagNode> tagNodes; |
1701 | 1508 |
1702 /** | 1509 /** |
1703 * The element associated with this HTML unit or `null` if the receiver is not
resolved. | 1510 * The element associated with this HTML unit or `null` if the receiver is not
resolved. |
1704 */ | 1511 */ |
1705 HtmlElementImpl _element; | 1512 HtmlElementImpl element; |
1706 | 1513 |
1707 /** | 1514 /** |
1708 * Construct a new instance representing the content of an HTML file. | 1515 * Construct a new instance representing the content of an HTML file. |
1709 * | 1516 * |
1710 * @param beginToken the first token in the file (not `null`) | 1517 * @param beginToken the first token in the file (not `null`) |
1711 * @param tagNodes child tag nodes of the receiver (not `null`, contains no `n
ull`s) | 1518 * @param tagNodes child tag nodes of the receiver (not `null`, contains no `n
ull`s) |
1712 * @param endToken the last token in the token stream which should be of type | 1519 * @param endToken the last token in the token stream which should be of type |
1713 * [TokenType.EOF] | 1520 * [TokenType.EOF] |
1714 */ | 1521 */ |
1715 HtmlUnit(Token beginToken, List<XmlTagNode> tagNodes, Token endToken) { | 1522 HtmlUnit(Token beginToken, List<XmlTagNode> tagNodes, Token endToken) { |
1716 this._beginToken = beginToken; | 1523 this._beginToken = beginToken; |
1717 this._tagNodes = becomeParentOf(tagNodes); | 1524 this.tagNodes = becomeParentOf(tagNodes); |
1718 this._endToken = endToken; | 1525 this._endToken = endToken; |
1719 } | 1526 } |
1720 accept(XmlVisitor visitor) => visitor.visitHtmlUnit(this); | 1527 accept(XmlVisitor visitor) => visitor.visitHtmlUnit(this); |
1721 Token get beginToken => _beginToken; | 1528 Token get beginToken => _beginToken; |
1722 | |
1723 /** | |
1724 * Return the element associated with this HTML unit. | |
1725 * | |
1726 * @return the element or `null` if the receiver is not resolved | |
1727 */ | |
1728 HtmlElementImpl get element => _element; | |
1729 Token get endToken => _endToken; | 1529 Token get endToken => _endToken; |
1730 | |
1731 /** | |
1732 * Answer the tag nodes contained in the receiver. Callers should not manipula
te the returned list | |
1733 * to edit the AST structure. | |
1734 * | |
1735 * @return the children (not `null`, contains no `null`s) | |
1736 */ | |
1737 List<XmlTagNode> get tagNodes => _tagNodes; | |
1738 | |
1739 /** | |
1740 * Set the element associated with this HTML unit. | |
1741 * | |
1742 * @param element the element | |
1743 */ | |
1744 void set element(HtmlElementImpl element2) { | |
1745 this._element = element2; | |
1746 } | |
1747 void visitChildren(XmlVisitor visitor) { | 1530 void visitChildren(XmlVisitor visitor) { |
1748 for (XmlTagNode node in _tagNodes) { | 1531 for (XmlTagNode node in tagNodes) { |
1749 node.accept(visitor); | 1532 node.accept(visitor); |
1750 } | 1533 } |
1751 } | 1534 } |
1752 } | 1535 } |
OLD | NEW |