OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library fasta.scanner.keywords; | 5 library fasta.scanner.keywords; |
6 | 6 |
7 import 'characters.dart' show | 7 import 'characters.dart' show |
8 $a, $z, $A, $Z; | 8 $a; |
9 | 9 |
10 import 'precedence.dart' show | 10 import 'precedence.dart' show |
11 PrecedenceInfo; | 11 PrecedenceInfo; |
12 | 12 |
13 import 'precedence.dart' show | 13 import 'precedence.dart' show |
14 AS_INFO, | 14 AS_INFO, |
15 IS_INFO, | 15 IS_INFO, |
16 KEYWORD_INFO; | 16 KEYWORD_INFO; |
17 | 17 |
18 /** | 18 /** |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 const Keyword("library", isBuiltIn: true), | 70 const Keyword("library", isBuiltIn: true), |
71 const Keyword("operator", isBuiltIn: true), | 71 const Keyword("operator", isBuiltIn: true), |
72 const Keyword("part", isBuiltIn: true), | 72 const Keyword("part", isBuiltIn: true), |
73 const Keyword("set", isBuiltIn: true), | 73 const Keyword("set", isBuiltIn: true), |
74 const Keyword("static", isBuiltIn: true), | 74 const Keyword("static", isBuiltIn: true), |
75 const Keyword("typedef", isBuiltIn: true), | 75 const Keyword("typedef", isBuiltIn: true), |
76 | 76 |
77 const Keyword("async", isPseudo: true), | 77 const Keyword("async", isPseudo: true), |
78 const Keyword("await", isPseudo: true), | 78 const Keyword("await", isPseudo: true), |
79 const Keyword("deferred", isPseudo: true), | 79 const Keyword("deferred", isPseudo: true), |
80 const Keyword("Function", isPseudo: true), | |
81 const Keyword("hide", isPseudo: true), | 80 const Keyword("hide", isPseudo: true), |
82 const Keyword("native", isPseudo: true), | 81 const Keyword("native", isPseudo: true), |
83 const Keyword("of", isPseudo: true), | 82 const Keyword("of", isPseudo: true), |
84 const Keyword("on", isPseudo: true), | 83 const Keyword("on", isPseudo: true), |
85 const Keyword("patch", isPseudo: true), | 84 const Keyword("patch", isPseudo: true), |
86 const Keyword("show", isPseudo: true), | 85 const Keyword("show", isPseudo: true), |
87 const Keyword("source", isPseudo: true), | 86 const Keyword("source", isPseudo: true), |
88 const Keyword("sync", isPseudo: true), | 87 const Keyword("sync", isPseudo: true), |
89 const Keyword("yield", isPseudo: true), | 88 const Keyword("yield", isPseudo: true), |
90 ]; | 89 ]; |
(...skipping 24 matching lines...) Expand all Loading... |
115 return result; | 114 return result; |
116 } | 115 } |
117 | 116 |
118 String toString() => syntax; | 117 String toString() => syntax; |
119 } | 118 } |
120 | 119 |
121 /** | 120 /** |
122 * Abstract state in a state machine for scanning keywords. | 121 * Abstract state in a state machine for scanning keywords. |
123 */ | 122 */ |
124 abstract class KeywordState { | 123 abstract class KeywordState { |
| 124 KeywordState(this.keyword); |
| 125 |
125 KeywordState next(int c); | 126 KeywordState next(int c); |
126 KeywordState nextCapital(int c); | 127 final Keyword keyword; |
127 | |
128 Keyword get keyword; | |
129 | 128 |
130 static KeywordState _KEYWORD_STATE; | 129 static KeywordState _KEYWORD_STATE; |
131 static KeywordState get KEYWORD_STATE { | 130 static KeywordState get KEYWORD_STATE { |
132 if (_KEYWORD_STATE == null) { | 131 if (_KEYWORD_STATE == null) { |
133 List<String> strings = new List<String>(Keyword.values.length); | 132 List<String> strings = new List<String>(Keyword.values.length); |
134 for (int i = 0; i < Keyword.values.length; i++) { | 133 for (int i = 0; i < Keyword.values.length; i++) { |
135 strings[i] = Keyword.values[i].syntax; | 134 strings[i] = Keyword.values[i].syntax; |
136 } | 135 } |
137 strings.sort((a, b) => a.compareTo(b)); | 136 strings.sort((a, b) => a.compareTo(b)); |
138 _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length); | 137 _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length); |
139 } | 138 } |
140 return _KEYWORD_STATE; | 139 return _KEYWORD_STATE; |
141 } | 140 } |
142 | 141 |
143 static KeywordState computeKeywordStateTable( | 142 static KeywordState computeKeywordStateTable( |
144 int start, List<String> strings, int offset, int length) { | 143 int start, List<String> strings, int offset, int length) { |
145 bool isLowercase = true; | 144 List<KeywordState> result = new List<KeywordState>(26); |
146 | |
147 List<KeywordState> table = new List<KeywordState>($z - $A + 1); | |
148 assert(length != 0); | 145 assert(length != 0); |
149 int chunk = 0; | 146 int chunk = 0; |
150 int chunkStart = -1; | 147 int chunkStart = -1; |
151 bool isLeaf = false; | 148 bool isLeaf = false; |
152 for (int i = offset; i < offset + length; i++) { | 149 for (int i = offset; i < offset + length; i++) { |
153 if (strings[i].length == start) { | 150 if (strings[i].length == start) { |
154 isLeaf = true; | 151 isLeaf = true; |
155 } | 152 } |
156 if (strings[i].length > start) { | 153 if (strings[i].length > start) { |
157 int c = strings[i].codeUnitAt(start); | 154 int c = strings[i].codeUnitAt(start); |
158 if ($A <= c && c <= $Z) { | |
159 isLowercase = false; | |
160 } | |
161 if (chunk != c) { | 155 if (chunk != c) { |
162 if (chunkStart != -1) { | 156 if (chunkStart != -1) { |
163 assert(table[chunk - $A] == null); | 157 assert(result[chunk - $a] == null); |
164 table[chunk - $A] = computeKeywordStateTable( | 158 result[chunk - $a] = computeKeywordStateTable( |
165 start + 1, strings, chunkStart, i - chunkStart); | 159 start + 1, strings, chunkStart, i - chunkStart); |
166 } | 160 } |
167 chunkStart = i; | 161 chunkStart = i; |
168 chunk = c; | 162 chunk = c; |
169 } | 163 } |
170 } | 164 } |
171 } | 165 } |
172 if (chunkStart != -1) { | 166 if (chunkStart != -1) { |
173 assert(table[chunk - $A] == null); | 167 assert(result[chunk - $a] == null); |
174 table[chunk - $A] = computeKeywordStateTable( | 168 result[chunk - $a] = computeKeywordStateTable( |
175 start + 1, strings, chunkStart, offset + length - chunkStart); | 169 start + 1, strings, chunkStart, offset + length - chunkStart); |
176 } else { | 170 } else { |
177 assert(length == 1); | 171 assert(length == 1); |
178 return new LeafKeywordState(strings[offset]); | 172 return new LeafKeywordState(strings[offset]); |
179 } | 173 } |
180 String syntax = isLeaf ? strings[offset] : null; | 174 if (isLeaf) { |
181 if (isLowercase) { | 175 return new ArrayKeywordState(result, strings[offset]); |
182 table = table.sublist($a - $A); | |
183 return new LowerCaseArrayKeywordState(table, syntax); | |
184 } else { | 176 } else { |
185 return new UpperCaseArrayKeywordState(table, syntax); | 177 return new ArrayKeywordState(result, null); |
186 } | 178 } |
187 } | 179 } |
188 } | 180 } |
189 | 181 |
190 /** | 182 /** |
191 * A state with multiple outgoing transitions. | 183 * A state with multiple outgoing transitions. |
192 */ | 184 */ |
193 abstract class ArrayKeywordState implements KeywordState { | 185 class ArrayKeywordState extends KeywordState { |
194 final List<KeywordState> table; | 186 final List<KeywordState> table; |
195 final Keyword keyword; | |
196 | 187 |
197 ArrayKeywordState(List<KeywordState> this.table, String syntax) | 188 ArrayKeywordState(List<KeywordState> this.table, String syntax) |
198 : keyword = ((syntax == null) ? null : Keyword.keywords[syntax]); | 189 : super((syntax == null) ? null : Keyword.keywords[syntax]); |
199 | 190 |
200 KeywordState next(int c); | 191 KeywordState next(int c) => table[c - $a]; |
201 | |
202 KeywordState nextCapital(int c); | |
203 | 192 |
204 String toString() { | 193 String toString() { |
205 StringBuffer sb = new StringBuffer(); | 194 StringBuffer sb = new StringBuffer(); |
206 sb.write("["); | 195 sb.write("["); |
207 if (keyword != null) { | 196 if (keyword != null) { |
208 sb.write("*"); | 197 sb.write("*"); |
209 sb.write(keyword); | 198 sb.write(keyword); |
210 sb.write(" "); | 199 sb.write(" "); |
211 } | 200 } |
212 List<KeywordState> foo = table; | 201 List<KeywordState> foo = table; |
213 for (int i = 0; i < foo.length; i++) { | 202 for (int i = 0; i < foo.length; i++) { |
214 if (foo[i] != null) { | 203 if (foo[i] != null) { |
215 sb.write("${new String.fromCharCodes([i + $a])}: " | 204 sb.write("${new String.fromCharCodes([i + $a])}: " |
216 "${foo[i]}; "); | 205 "${foo[i]}; "); |
217 } | 206 } |
218 } | 207 } |
219 sb.write("]"); | 208 sb.write("]"); |
220 return sb.toString(); | 209 return sb.toString(); |
221 } | 210 } |
222 } | 211 } |
223 | 212 |
224 class LowerCaseArrayKeywordState extends ArrayKeywordState { | |
225 | |
226 LowerCaseArrayKeywordState(List<KeywordState> table, String syntax) | |
227 : super(table, syntax) { | |
228 assert(table.length == $z - $a + 1); | |
229 } | |
230 | |
231 KeywordState next(int c) => table[c - $a]; | |
232 | |
233 KeywordState nextCapital(int c) => null; | |
234 | |
235 } | |
236 | |
237 class UpperCaseArrayKeywordState extends ArrayKeywordState { | |
238 | |
239 UpperCaseArrayKeywordState(List<KeywordState> table, String syntax) | |
240 : super(table, syntax) { | |
241 assert(table.length == $z - $A + 1); | |
242 } | |
243 | |
244 KeywordState next(int c) => table[c - $A]; | |
245 | |
246 KeywordState nextCapital(int c) => table[c - $A]; | |
247 | |
248 } | |
249 | |
250 /** | 213 /** |
251 * A state that has no outgoing transitions. | 214 * A state that has no outgoing transitions. |
252 */ | 215 */ |
253 class LeafKeywordState implements KeywordState { | 216 class LeafKeywordState extends KeywordState { |
254 final Keyword keyword; | 217 LeafKeywordState(String syntax) : super(Keyword.keywords[syntax]); |
255 | |
256 LeafKeywordState(String syntax) : keyword = Keyword.keywords[syntax]; | |
257 | 218 |
258 KeywordState next(int c) => null; | 219 KeywordState next(int c) => null; |
259 KeywordState nextCapital(int c) => null; | |
260 | 220 |
261 String toString() => keyword.syntax; | 221 String toString() => keyword.syntax; |
262 } | 222 } |
OLD | NEW |