| 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 |