| Index: pkg/front_end/lib/src/fasta/scanner/keyword_state.dart
|
| diff --git a/pkg/front_end/lib/src/fasta/scanner/keyword_state.dart b/pkg/front_end/lib/src/fasta/scanner/keyword_state.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9b545603c72ed079cfad90a08cce0d67a015b0b2
|
| --- /dev/null
|
| +++ b/pkg/front_end/lib/src/fasta/scanner/keyword_state.dart
|
| @@ -0,0 +1,148 @@
|
| +// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library fasta.scanner.keywords;
|
| +
|
| +import '../../scanner/token.dart' as analyzer;
|
| +
|
| +import 'characters.dart' show $a, $z, $A, $Z;
|
| +
|
| +/**
|
| + * Abstract state in a state machine for scanning keywords.
|
| + */
|
| +abstract class KeywordState {
|
| + KeywordState next(int c);
|
| + KeywordState nextCapital(int c);
|
| +
|
| + analyzer.Keyword get keyword;
|
| +
|
| + static KeywordState _KEYWORD_STATE;
|
| + static KeywordState get KEYWORD_STATE {
|
| + if (_KEYWORD_STATE == null) {
|
| + List<String> strings = new List<String>(analyzer.Keyword.values.length);
|
| + for (int i = 0; i < analyzer.Keyword.values.length; i++) {
|
| + strings[i] = analyzer.Keyword.values[i].syntax;
|
| + }
|
| + strings.sort((a, b) => a.compareTo(b));
|
| + _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length);
|
| + }
|
| + return _KEYWORD_STATE;
|
| + }
|
| +
|
| + static KeywordState computeKeywordStateTable(
|
| + int start, List<String> strings, int offset, int length) {
|
| + bool isLowercase = true;
|
| +
|
| + List<KeywordState> table = new List<KeywordState>($z - $A + 1);
|
| + assert(length != 0);
|
| + int chunk = 0;
|
| + int chunkStart = -1;
|
| + bool isLeaf = false;
|
| + for (int i = offset; i < offset + length; i++) {
|
| + if (strings[i].length == start) {
|
| + isLeaf = true;
|
| + }
|
| + if (strings[i].length > start) {
|
| + int c = strings[i].codeUnitAt(start);
|
| + if ($A <= c && c <= $Z) {
|
| + isLowercase = false;
|
| + }
|
| + if (chunk != c) {
|
| + if (chunkStart != -1) {
|
| + assert(table[chunk - $A] == null);
|
| + table[chunk - $A] = computeKeywordStateTable(
|
| + start + 1, strings, chunkStart, i - chunkStart);
|
| + }
|
| + chunkStart = i;
|
| + chunk = c;
|
| + }
|
| + }
|
| + }
|
| + if (chunkStart != -1) {
|
| + assert(table[chunk - $A] == null);
|
| + table[chunk - $A] = computeKeywordStateTable(
|
| + start + 1, strings, chunkStart, offset + length - chunkStart);
|
| + } else {
|
| + assert(length == 1);
|
| + return new LeafKeywordState(strings[offset]);
|
| + }
|
| + String syntax = isLeaf ? strings[offset] : null;
|
| + if (isLowercase) {
|
| + table = table.sublist($a - $A);
|
| + return new LowerCaseArrayKeywordState(table, syntax);
|
| + } else {
|
| + return new UpperCaseArrayKeywordState(table, syntax);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A state with multiple outgoing transitions.
|
| + */
|
| +abstract class ArrayKeywordState implements KeywordState {
|
| + final List<KeywordState> table;
|
| + final analyzer.Keyword keyword;
|
| +
|
| + ArrayKeywordState(this.table, String syntax)
|
| + : keyword = ((syntax == null) ? null : analyzer.Keyword.keywords[syntax]);
|
| +
|
| + KeywordState next(int c);
|
| +
|
| + KeywordState nextCapital(int c);
|
| +
|
| + String toString() {
|
| + StringBuffer sb = new StringBuffer();
|
| + sb.write("[");
|
| + if (keyword != null) {
|
| + sb.write("*");
|
| + sb.write(keyword);
|
| + sb.write(" ");
|
| + }
|
| + List<KeywordState> foo = table;
|
| + for (int i = 0; i < foo.length; i++) {
|
| + if (foo[i] != null) {
|
| + sb.write("${new String.fromCharCodes([i + $a])}: "
|
| + "${foo[i]}; ");
|
| + }
|
| + }
|
| + sb.write("]");
|
| + return sb.toString();
|
| + }
|
| +}
|
| +
|
| +class LowerCaseArrayKeywordState extends ArrayKeywordState {
|
| + LowerCaseArrayKeywordState(List<KeywordState> table, String syntax)
|
| + : super(table, syntax) {
|
| + assert(table.length == $z - $a + 1);
|
| + }
|
| +
|
| + KeywordState next(int c) => table[c - $a];
|
| +
|
| + KeywordState nextCapital(int c) => null;
|
| +}
|
| +
|
| +class UpperCaseArrayKeywordState extends ArrayKeywordState {
|
| + UpperCaseArrayKeywordState(List<KeywordState> table, String syntax)
|
| + : super(table, syntax) {
|
| + assert(table.length == $z - $A + 1);
|
| + }
|
| +
|
| + KeywordState next(int c) => table[c - $A];
|
| +
|
| + KeywordState nextCapital(int c) => table[c - $A];
|
| +}
|
| +
|
| +/**
|
| + * A state that has no outgoing transitions.
|
| + */
|
| +class LeafKeywordState implements KeywordState {
|
| + final analyzer.Keyword keyword;
|
| +
|
| + LeafKeywordState(String syntax) : keyword = analyzer.Keyword.keywords[syntax];
|
| +
|
| + KeywordState next(int c) => null;
|
| + KeywordState nextCapital(int c) => null;
|
| +
|
| + String toString() => keyword.syntax;
|
| +}
|
|
|