| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library fasta.scanner.keywords; | |
| 6 | |
| 7 import '../../scanner/token.dart' as analyzer; | |
| 8 | |
| 9 import 'characters.dart' show $a, $z, $A, $Z; | |
| 10 | |
| 11 import 'precedence.dart' show PrecedenceInfo; | |
| 12 | |
| 13 import 'precedence.dart' show AS_INFO, IS_INFO, KEYWORD_INFO; | |
| 14 | |
| 15 /** | |
| 16 * A keyword in the Dart programming language. | |
| 17 */ | |
| 18 class Keyword extends analyzer.Keyword { | |
| 19 static const ASSERT = const Keyword("assert"); | |
| 20 static const BREAK = const Keyword("break"); | |
| 21 static const CASE = const Keyword("case"); | |
| 22 static const CATCH = const Keyword("catch"); | |
| 23 static const CLASS = const Keyword("class"); | |
| 24 static const CONST = const Keyword("const"); | |
| 25 static const CONTINUE = const Keyword("continue"); | |
| 26 static const DEFAULT = const Keyword("default"); | |
| 27 static const DO = const Keyword("do"); | |
| 28 static const ELSE = const Keyword("else"); | |
| 29 static const ENUM = const Keyword("enum"); | |
| 30 static const EXTENDS = const Keyword("extends"); | |
| 31 static const FALSE = const Keyword("false"); | |
| 32 static const FINAL = const Keyword("final"); | |
| 33 static const FINALLY = const Keyword("finally"); | |
| 34 static const FOR = const Keyword("for"); | |
| 35 static const IF = const Keyword("if"); | |
| 36 static const IN = const Keyword("in"); | |
| 37 static const NEW = const Keyword("new"); | |
| 38 static const NULL = const Keyword("null"); | |
| 39 static const RETHROW = const Keyword("rethrow"); | |
| 40 static const RETURN = const Keyword("return"); | |
| 41 static const SUPER = const Keyword("super"); | |
| 42 static const SWITCH = const Keyword("switch"); | |
| 43 static const THIS = const Keyword("this"); | |
| 44 static const THROW = const Keyword("throw"); | |
| 45 static const TRUE = const Keyword("true"); | |
| 46 static const TRY = const Keyword("try"); | |
| 47 static const VAR = const Keyword("var"); | |
| 48 static const VOID = const Keyword("void"); | |
| 49 static const WHILE = const Keyword("while"); | |
| 50 static const WITH = const Keyword("with"); | |
| 51 | |
| 52 // TODO(ahe): Don't think this is a reserved word. | |
| 53 // See: http://dartbug.com/5579 | |
| 54 static const IS = const Keyword("is", info: IS_INFO); | |
| 55 | |
| 56 static const ABSTRACT = const Keyword("abstract", isBuiltIn: true); | |
| 57 static const AS = const Keyword("as", info: AS_INFO, isBuiltIn: true); | |
| 58 static const COVARIANT = const Keyword("covariant", isBuiltIn: true); | |
| 59 static const DYNAMIC = const Keyword("dynamic", isBuiltIn: true); | |
| 60 static const EXPORT = const Keyword("export", isBuiltIn: true); | |
| 61 static const EXTERNAL = const Keyword("external", isBuiltIn: true); | |
| 62 static const FACTORY = const Keyword("factory", isBuiltIn: true); | |
| 63 static const GET = const Keyword("get", isBuiltIn: true); | |
| 64 static const IMPLEMENTS = const Keyword("implements", isBuiltIn: true); | |
| 65 static const IMPORT = const Keyword("import", isBuiltIn: true); | |
| 66 static const LIBRARY = const Keyword("library", isBuiltIn: true); | |
| 67 static const OPERATOR = const Keyword("operator", isBuiltIn: true); | |
| 68 static const PART = const Keyword("part", isBuiltIn: true); | |
| 69 static const SET = const Keyword("set", isBuiltIn: true); | |
| 70 static const STATIC = const Keyword("static", isBuiltIn: true); | |
| 71 static const TYPEDEF = const Keyword("typedef", isBuiltIn: true); | |
| 72 | |
| 73 static const ASYNC = const Keyword("async", isPseudo: true); | |
| 74 static const AWAIT = const Keyword("await", isPseudo: true); | |
| 75 static const DEFERRED = const Keyword("deferred", isBuiltIn: true); | |
| 76 static const FUNCTION = const Keyword("Function", isPseudo: true); | |
| 77 static const HIDE = const Keyword("hide", isPseudo: true); | |
| 78 static const NATIVE = const Keyword("native", isPseudo: true); | |
| 79 static const OF = const Keyword("of", isPseudo: true); | |
| 80 static const ON = const Keyword("on", isPseudo: true); | |
| 81 static const PATCH = const Keyword("patch", isPseudo: true); | |
| 82 static const SHOW = const Keyword("show", isPseudo: true); | |
| 83 static const SOURCE = const Keyword("source", isPseudo: true); | |
| 84 static const SYNC = const Keyword("sync", isPseudo: true); | |
| 85 static const YIELD = const Keyword("yield", isPseudo: true); | |
| 86 | |
| 87 static const List<Keyword> values = const <Keyword>[ | |
| 88 ASSERT, | |
| 89 BREAK, | |
| 90 CASE, | |
| 91 CATCH, | |
| 92 CLASS, | |
| 93 CONST, | |
| 94 CONTINUE, | |
| 95 DEFAULT, | |
| 96 DO, | |
| 97 ELSE, | |
| 98 ENUM, | |
| 99 EXTENDS, | |
| 100 FALSE, | |
| 101 FINAL, | |
| 102 FINALLY, | |
| 103 FOR, | |
| 104 IF, | |
| 105 IN, | |
| 106 NEW, | |
| 107 NULL, | |
| 108 RETHROW, | |
| 109 RETURN, | |
| 110 SUPER, | |
| 111 SWITCH, | |
| 112 THIS, | |
| 113 THROW, | |
| 114 TRUE, | |
| 115 TRY, | |
| 116 VAR, | |
| 117 VOID, | |
| 118 WHILE, | |
| 119 WITH, | |
| 120 // ==== | |
| 121 IS, | |
| 122 // ==== Built In | |
| 123 ABSTRACT, | |
| 124 AS, | |
| 125 COVARIANT, | |
| 126 DEFERRED, | |
| 127 DYNAMIC, | |
| 128 EXPORT, | |
| 129 EXTERNAL, | |
| 130 FACTORY, | |
| 131 GET, | |
| 132 IMPLEMENTS, | |
| 133 IMPORT, | |
| 134 LIBRARY, | |
| 135 OPERATOR, | |
| 136 PART, | |
| 137 SET, | |
| 138 STATIC, | |
| 139 TYPEDEF, | |
| 140 // ==== Pseudo | |
| 141 ASYNC, | |
| 142 AWAIT, | |
| 143 FUNCTION, | |
| 144 HIDE, | |
| 145 NATIVE, | |
| 146 OF, | |
| 147 ON, | |
| 148 PATCH, | |
| 149 SHOW, | |
| 150 SOURCE, | |
| 151 SYNC, | |
| 152 YIELD, | |
| 153 ]; | |
| 154 | |
| 155 static Map<String, Keyword> _keywords; | |
| 156 static Map<String, Keyword> get keywords { | |
| 157 if (_keywords == null) { | |
| 158 _keywords = computeKeywordMap(); | |
| 159 } | |
| 160 return _keywords; | |
| 161 } | |
| 162 | |
| 163 const Keyword(String syntax, | |
| 164 {bool isPseudo: false, | |
| 165 bool isBuiltIn: false, | |
| 166 PrecedenceInfo info: KEYWORD_INFO}) | |
| 167 : super(syntax, info: info, isBuiltIn: isBuiltIn, isPseudo: isPseudo); | |
| 168 | |
| 169 static Map<String, Keyword> computeKeywordMap() { | |
| 170 Map<String, Keyword> result = new Map<String, Keyword>(); | |
| 171 for (Keyword keyword in values) { | |
| 172 result[keyword.syntax] = keyword; | |
| 173 } | |
| 174 return result; | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 /** | |
| 179 * Abstract state in a state machine for scanning keywords. | |
| 180 */ | |
| 181 abstract class KeywordState { | |
| 182 KeywordState next(int c); | |
| 183 KeywordState nextCapital(int c); | |
| 184 | |
| 185 Keyword get keyword; | |
| 186 | |
| 187 static KeywordState _KEYWORD_STATE; | |
| 188 static KeywordState get KEYWORD_STATE { | |
| 189 if (_KEYWORD_STATE == null) { | |
| 190 List<String> strings = new List<String>(Keyword.values.length); | |
| 191 for (int i = 0; i < Keyword.values.length; i++) { | |
| 192 strings[i] = Keyword.values[i].syntax; | |
| 193 } | |
| 194 strings.sort((a, b) => a.compareTo(b)); | |
| 195 _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length); | |
| 196 } | |
| 197 return _KEYWORD_STATE; | |
| 198 } | |
| 199 | |
| 200 static KeywordState computeKeywordStateTable( | |
| 201 int start, List<String> strings, int offset, int length) { | |
| 202 bool isLowercase = true; | |
| 203 | |
| 204 List<KeywordState> table = new List<KeywordState>($z - $A + 1); | |
| 205 assert(length != 0); | |
| 206 int chunk = 0; | |
| 207 int chunkStart = -1; | |
| 208 bool isLeaf = false; | |
| 209 for (int i = offset; i < offset + length; i++) { | |
| 210 if (strings[i].length == start) { | |
| 211 isLeaf = true; | |
| 212 } | |
| 213 if (strings[i].length > start) { | |
| 214 int c = strings[i].codeUnitAt(start); | |
| 215 if ($A <= c && c <= $Z) { | |
| 216 isLowercase = false; | |
| 217 } | |
| 218 if (chunk != c) { | |
| 219 if (chunkStart != -1) { | |
| 220 assert(table[chunk - $A] == null); | |
| 221 table[chunk - $A] = computeKeywordStateTable( | |
| 222 start + 1, strings, chunkStart, i - chunkStart); | |
| 223 } | |
| 224 chunkStart = i; | |
| 225 chunk = c; | |
| 226 } | |
| 227 } | |
| 228 } | |
| 229 if (chunkStart != -1) { | |
| 230 assert(table[chunk - $A] == null); | |
| 231 table[chunk - $A] = computeKeywordStateTable( | |
| 232 start + 1, strings, chunkStart, offset + length - chunkStart); | |
| 233 } else { | |
| 234 assert(length == 1); | |
| 235 return new LeafKeywordState(strings[offset]); | |
| 236 } | |
| 237 String syntax = isLeaf ? strings[offset] : null; | |
| 238 if (isLowercase) { | |
| 239 table = table.sublist($a - $A); | |
| 240 return new LowerCaseArrayKeywordState(table, syntax); | |
| 241 } else { | |
| 242 return new UpperCaseArrayKeywordState(table, syntax); | |
| 243 } | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 /** | |
| 248 * A state with multiple outgoing transitions. | |
| 249 */ | |
| 250 abstract class ArrayKeywordState implements KeywordState { | |
| 251 final List<KeywordState> table; | |
| 252 final Keyword keyword; | |
| 253 | |
| 254 ArrayKeywordState(this.table, String syntax) | |
| 255 : keyword = ((syntax == null) ? null : Keyword.keywords[syntax]); | |
| 256 | |
| 257 KeywordState next(int c); | |
| 258 | |
| 259 KeywordState nextCapital(int c); | |
| 260 | |
| 261 String toString() { | |
| 262 StringBuffer sb = new StringBuffer(); | |
| 263 sb.write("["); | |
| 264 if (keyword != null) { | |
| 265 sb.write("*"); | |
| 266 sb.write(keyword); | |
| 267 sb.write(" "); | |
| 268 } | |
| 269 List<KeywordState> foo = table; | |
| 270 for (int i = 0; i < foo.length; i++) { | |
| 271 if (foo[i] != null) { | |
| 272 sb.write("${new String.fromCharCodes([i + $a])}: " | |
| 273 "${foo[i]}; "); | |
| 274 } | |
| 275 } | |
| 276 sb.write("]"); | |
| 277 return sb.toString(); | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 class LowerCaseArrayKeywordState extends ArrayKeywordState { | |
| 282 LowerCaseArrayKeywordState(List<KeywordState> table, String syntax) | |
| 283 : super(table, syntax) { | |
| 284 assert(table.length == $z - $a + 1); | |
| 285 } | |
| 286 | |
| 287 KeywordState next(int c) => table[c - $a]; | |
| 288 | |
| 289 KeywordState nextCapital(int c) => null; | |
| 290 } | |
| 291 | |
| 292 class UpperCaseArrayKeywordState extends ArrayKeywordState { | |
| 293 UpperCaseArrayKeywordState(List<KeywordState> table, String syntax) | |
| 294 : super(table, syntax) { | |
| 295 assert(table.length == $z - $A + 1); | |
| 296 } | |
| 297 | |
| 298 KeywordState next(int c) => table[c - $A]; | |
| 299 | |
| 300 KeywordState nextCapital(int c) => table[c - $A]; | |
| 301 } | |
| 302 | |
| 303 /** | |
| 304 * A state that has no outgoing transitions. | |
| 305 */ | |
| 306 class LeafKeywordState implements KeywordState { | |
| 307 final Keyword keyword; | |
| 308 | |
| 309 LeafKeywordState(String syntax) : keyword = Keyword.keywords[syntax]; | |
| 310 | |
| 311 KeywordState next(int c) => null; | |
| 312 KeywordState nextCapital(int c) => null; | |
| 313 | |
| 314 String toString() => keyword.syntax; | |
| 315 } | |
| OLD | NEW |