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 /** |
| 12 * Abstract state in a state machine for scanning keywords. |
| 13 */ |
| 14 abstract class KeywordState { |
| 15 KeywordState next(int c); |
| 16 KeywordState nextCapital(int c); |
| 17 |
| 18 analyzer.Keyword get keyword; |
| 19 |
| 20 static KeywordState _KEYWORD_STATE; |
| 21 static KeywordState get KEYWORD_STATE { |
| 22 if (_KEYWORD_STATE == null) { |
| 23 List<String> strings = new List<String>(analyzer.Keyword.values.length); |
| 24 for (int i = 0; i < analyzer.Keyword.values.length; i++) { |
| 25 strings[i] = analyzer.Keyword.values[i].syntax; |
| 26 } |
| 27 strings.sort((a, b) => a.compareTo(b)); |
| 28 _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length); |
| 29 } |
| 30 return _KEYWORD_STATE; |
| 31 } |
| 32 |
| 33 static KeywordState computeKeywordStateTable( |
| 34 int start, List<String> strings, int offset, int length) { |
| 35 bool isLowercase = true; |
| 36 |
| 37 List<KeywordState> table = new List<KeywordState>($z - $A + 1); |
| 38 assert(length != 0); |
| 39 int chunk = 0; |
| 40 int chunkStart = -1; |
| 41 bool isLeaf = false; |
| 42 for (int i = offset; i < offset + length; i++) { |
| 43 if (strings[i].length == start) { |
| 44 isLeaf = true; |
| 45 } |
| 46 if (strings[i].length > start) { |
| 47 int c = strings[i].codeUnitAt(start); |
| 48 if ($A <= c && c <= $Z) { |
| 49 isLowercase = false; |
| 50 } |
| 51 if (chunk != c) { |
| 52 if (chunkStart != -1) { |
| 53 assert(table[chunk - $A] == null); |
| 54 table[chunk - $A] = computeKeywordStateTable( |
| 55 start + 1, strings, chunkStart, i - chunkStart); |
| 56 } |
| 57 chunkStart = i; |
| 58 chunk = c; |
| 59 } |
| 60 } |
| 61 } |
| 62 if (chunkStart != -1) { |
| 63 assert(table[chunk - $A] == null); |
| 64 table[chunk - $A] = computeKeywordStateTable( |
| 65 start + 1, strings, chunkStart, offset + length - chunkStart); |
| 66 } else { |
| 67 assert(length == 1); |
| 68 return new LeafKeywordState(strings[offset]); |
| 69 } |
| 70 String syntax = isLeaf ? strings[offset] : null; |
| 71 if (isLowercase) { |
| 72 table = table.sublist($a - $A); |
| 73 return new LowerCaseArrayKeywordState(table, syntax); |
| 74 } else { |
| 75 return new UpperCaseArrayKeywordState(table, syntax); |
| 76 } |
| 77 } |
| 78 } |
| 79 |
| 80 /** |
| 81 * A state with multiple outgoing transitions. |
| 82 */ |
| 83 abstract class ArrayKeywordState implements KeywordState { |
| 84 final List<KeywordState> table; |
| 85 final analyzer.Keyword keyword; |
| 86 |
| 87 ArrayKeywordState(this.table, String syntax) |
| 88 : keyword = ((syntax == null) ? null : analyzer.Keyword.keywords[syntax]); |
| 89 |
| 90 KeywordState next(int c); |
| 91 |
| 92 KeywordState nextCapital(int c); |
| 93 |
| 94 String toString() { |
| 95 StringBuffer sb = new StringBuffer(); |
| 96 sb.write("["); |
| 97 if (keyword != null) { |
| 98 sb.write("*"); |
| 99 sb.write(keyword); |
| 100 sb.write(" "); |
| 101 } |
| 102 List<KeywordState> foo = table; |
| 103 for (int i = 0; i < foo.length; i++) { |
| 104 if (foo[i] != null) { |
| 105 sb.write("${new String.fromCharCodes([i + $a])}: " |
| 106 "${foo[i]}; "); |
| 107 } |
| 108 } |
| 109 sb.write("]"); |
| 110 return sb.toString(); |
| 111 } |
| 112 } |
| 113 |
| 114 class LowerCaseArrayKeywordState extends ArrayKeywordState { |
| 115 LowerCaseArrayKeywordState(List<KeywordState> table, String syntax) |
| 116 : super(table, syntax) { |
| 117 assert(table.length == $z - $a + 1); |
| 118 } |
| 119 |
| 120 KeywordState next(int c) => table[c - $a]; |
| 121 |
| 122 KeywordState nextCapital(int c) => null; |
| 123 } |
| 124 |
| 125 class UpperCaseArrayKeywordState extends ArrayKeywordState { |
| 126 UpperCaseArrayKeywordState(List<KeywordState> table, String syntax) |
| 127 : super(table, syntax) { |
| 128 assert(table.length == $z - $A + 1); |
| 129 } |
| 130 |
| 131 KeywordState next(int c) => table[c - $A]; |
| 132 |
| 133 KeywordState nextCapital(int c) => table[c - $A]; |
| 134 } |
| 135 |
| 136 /** |
| 137 * A state that has no outgoing transitions. |
| 138 */ |
| 139 class LeafKeywordState implements KeywordState { |
| 140 final analyzer.Keyword keyword; |
| 141 |
| 142 LeafKeywordState(String syntax) : keyword = analyzer.Keyword.keywords[syntax]; |
| 143 |
| 144 KeywordState next(int c) => null; |
| 145 KeywordState nextCapital(int c) => null; |
| 146 |
| 147 String toString() => keyword.syntax; |
| 148 } |
OLD | NEW |