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; | 8 $a, $z, $A, $Z; |
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), |
80 const Keyword("hide", isPseudo: true), | 81 const Keyword("hide", isPseudo: true), |
81 const Keyword("native", isPseudo: true), | 82 const Keyword("native", isPseudo: true), |
82 const Keyword("of", isPseudo: true), | 83 const Keyword("of", isPseudo: true), |
83 const Keyword("on", isPseudo: true), | 84 const Keyword("on", isPseudo: true), |
84 const Keyword("patch", isPseudo: true), | 85 const Keyword("patch", isPseudo: true), |
85 const Keyword("show", isPseudo: true), | 86 const Keyword("show", isPseudo: true), |
86 const Keyword("source", isPseudo: true), | 87 const Keyword("source", isPseudo: true), |
87 const Keyword("sync", isPseudo: true), | 88 const Keyword("sync", isPseudo: true), |
88 const Keyword("yield", isPseudo: true), | 89 const Keyword("yield", isPseudo: true), |
89 ]; | 90 ]; |
(...skipping 24 matching lines...) Expand all Loading... |
114 return result; | 115 return result; |
115 } | 116 } |
116 | 117 |
117 String toString() => syntax; | 118 String toString() => syntax; |
118 } | 119 } |
119 | 120 |
120 /** | 121 /** |
121 * Abstract state in a state machine for scanning keywords. | 122 * Abstract state in a state machine for scanning keywords. |
122 */ | 123 */ |
123 abstract class KeywordState { | 124 abstract class KeywordState { |
124 KeywordState(this.keyword); | 125 KeywordState next(int c); |
| 126 KeywordState nextCapital(int c); |
125 | 127 |
126 KeywordState next(int c); | 128 Keyword get keyword; |
127 final Keyword keyword; | |
128 | 129 |
129 static KeywordState _KEYWORD_STATE; | 130 static KeywordState _KEYWORD_STATE; |
130 static KeywordState get KEYWORD_STATE { | 131 static KeywordState get KEYWORD_STATE { |
131 if (_KEYWORD_STATE == null) { | 132 if (_KEYWORD_STATE == null) { |
132 List<String> strings = new List<String>(Keyword.values.length); | 133 List<String> strings = new List<String>(Keyword.values.length); |
133 for (int i = 0; i < Keyword.values.length; i++) { | 134 for (int i = 0; i < Keyword.values.length; i++) { |
134 strings[i] = Keyword.values[i].syntax; | 135 strings[i] = Keyword.values[i].syntax; |
135 } | 136 } |
136 strings.sort((a, b) => a.compareTo(b)); | 137 strings.sort((a, b) => a.compareTo(b)); |
137 _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length); | 138 _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length); |
138 } | 139 } |
139 return _KEYWORD_STATE; | 140 return _KEYWORD_STATE; |
140 } | 141 } |
141 | 142 |
142 static KeywordState computeKeywordStateTable( | 143 static KeywordState computeKeywordStateTable( |
143 int start, List<String> strings, int offset, int length) { | 144 int start, List<String> strings, int offset, int length) { |
144 List<KeywordState> result = new List<KeywordState>(26); | 145 bool isLowercase = true; |
| 146 |
| 147 List<KeywordState> table = new List<KeywordState>($z - $A + 1); |
145 assert(length != 0); | 148 assert(length != 0); |
146 int chunk = 0; | 149 int chunk = 0; |
147 int chunkStart = -1; | 150 int chunkStart = -1; |
148 bool isLeaf = false; | 151 bool isLeaf = false; |
149 for (int i = offset; i < offset + length; i++) { | 152 for (int i = offset; i < offset + length; i++) { |
150 if (strings[i].length == start) { | 153 if (strings[i].length == start) { |
151 isLeaf = true; | 154 isLeaf = true; |
152 } | 155 } |
153 if (strings[i].length > start) { | 156 if (strings[i].length > start) { |
154 int c = strings[i].codeUnitAt(start); | 157 int c = strings[i].codeUnitAt(start); |
| 158 if ($A <= c && c <= $Z) { |
| 159 isLowercase = false; |
| 160 } |
155 if (chunk != c) { | 161 if (chunk != c) { |
156 if (chunkStart != -1) { | 162 if (chunkStart != -1) { |
157 assert(result[chunk - $a] == null); | 163 assert(table[chunk - $A] == null); |
158 result[chunk - $a] = computeKeywordStateTable( | 164 table[chunk - $A] = computeKeywordStateTable( |
159 start + 1, strings, chunkStart, i - chunkStart); | 165 start + 1, strings, chunkStart, i - chunkStart); |
160 } | 166 } |
161 chunkStart = i; | 167 chunkStart = i; |
162 chunk = c; | 168 chunk = c; |
163 } | 169 } |
164 } | 170 } |
165 } | 171 } |
166 if (chunkStart != -1) { | 172 if (chunkStart != -1) { |
167 assert(result[chunk - $a] == null); | 173 assert(table[chunk - $A] == null); |
168 result[chunk - $a] = computeKeywordStateTable( | 174 table[chunk - $A] = computeKeywordStateTable( |
169 start + 1, strings, chunkStart, offset + length - chunkStart); | 175 start + 1, strings, chunkStart, offset + length - chunkStart); |
170 } else { | 176 } else { |
171 assert(length == 1); | 177 assert(length == 1); |
172 return new LeafKeywordState(strings[offset]); | 178 return new LeafKeywordState(strings[offset]); |
173 } | 179 } |
174 if (isLeaf) { | 180 String syntax = isLeaf ? strings[offset] : null; |
175 return new ArrayKeywordState(result, strings[offset]); | 181 if (isLowercase) { |
| 182 table = table.sublist($a - $A); |
| 183 return new LowerCaseArrayKeywordState(table, syntax); |
176 } else { | 184 } else { |
177 return new ArrayKeywordState(result, null); | 185 return new UpperCaseArrayKeywordState(table, syntax); |
178 } | 186 } |
179 } | 187 } |
180 } | 188 } |
181 | 189 |
182 /** | 190 /** |
183 * A state with multiple outgoing transitions. | 191 * A state with multiple outgoing transitions. |
184 */ | 192 */ |
185 class ArrayKeywordState extends KeywordState { | 193 abstract class ArrayKeywordState implements KeywordState { |
186 final List<KeywordState> table; | 194 final List<KeywordState> table; |
| 195 final Keyword keyword; |
187 | 196 |
188 ArrayKeywordState(List<KeywordState> this.table, String syntax) | 197 ArrayKeywordState(List<KeywordState> this.table, String syntax) |
189 : super((syntax == null) ? null : Keyword.keywords[syntax]); | 198 : keyword = ((syntax == null) ? null : Keyword.keywords[syntax]); |
190 | 199 |
191 KeywordState next(int c) => table[c - $a]; | 200 KeywordState next(int c); |
| 201 |
| 202 KeywordState nextCapital(int c); |
192 | 203 |
193 String toString() { | 204 String toString() { |
194 StringBuffer sb = new StringBuffer(); | 205 StringBuffer sb = new StringBuffer(); |
195 sb.write("["); | 206 sb.write("["); |
196 if (keyword != null) { | 207 if (keyword != null) { |
197 sb.write("*"); | 208 sb.write("*"); |
198 sb.write(keyword); | 209 sb.write(keyword); |
199 sb.write(" "); | 210 sb.write(" "); |
200 } | 211 } |
201 List<KeywordState> foo = table; | 212 List<KeywordState> foo = table; |
202 for (int i = 0; i < foo.length; i++) { | 213 for (int i = 0; i < foo.length; i++) { |
203 if (foo[i] != null) { | 214 if (foo[i] != null) { |
204 sb.write("${new String.fromCharCodes([i + $a])}: " | 215 sb.write("${new String.fromCharCodes([i + $a])}: " |
205 "${foo[i]}; "); | 216 "${foo[i]}; "); |
206 } | 217 } |
207 } | 218 } |
208 sb.write("]"); | 219 sb.write("]"); |
209 return sb.toString(); | 220 return sb.toString(); |
210 } | 221 } |
211 } | 222 } |
212 | 223 |
| 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 |
213 /** | 250 /** |
214 * A state that has no outgoing transitions. | 251 * A state that has no outgoing transitions. |
215 */ | 252 */ |
216 class LeafKeywordState extends KeywordState { | 253 class LeafKeywordState implements KeywordState { |
217 LeafKeywordState(String syntax) : super(Keyword.keywords[syntax]); | 254 final Keyword keyword; |
| 255 |
| 256 LeafKeywordState(String syntax) : keyword = Keyword.keywords[syntax]; |
218 | 257 |
219 KeywordState next(int c) => null; | 258 KeywordState next(int c) => null; |
| 259 KeywordState nextCapital(int c) => null; |
220 | 260 |
221 String toString() => keyword.syntax; | 261 String toString() => keyword.syntax; |
222 } | 262 } |
OLD | NEW |