| Index: utils/css/tokenizer.dart
|
| diff --git a/utils/css/tokenizer.dart b/utils/css/tokenizer.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7e4148fd42e6e934ee46f45aec323e4df8f5a47b
|
| --- /dev/null
|
| +++ b/utils/css/tokenizer.dart
|
| @@ -0,0 +1,123 @@
|
| +// 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.
|
| +
|
| +class Tokenizer extends lang.TokenizerBase {
|
| + TokenKind cssTokens;
|
| +
|
| + bool _selectorParsing;
|
| +
|
| + Tokenizer(lang.SourceFile source, bool skipWhitespace, [int index = 0])
|
| + : super(source, skipWhitespace, index), _selectorParsing = false {
|
| + cssTokens = new TokenKind();
|
| + }
|
| +
|
| + lang.Token next() {
|
| + // keep track of our starting position
|
| + _startIndex = _index;
|
| +
|
| + if (_interpStack != null && _interpStack.depth == 0) {
|
| + var istack = _interpStack;
|
| + _interpStack = _interpStack.pop();
|
| +
|
| + /* TODO(terry): Enable for variable and string interpolation.
|
| + * if (istack.isMultiline) {
|
| + * return finishMultilineStringBody(istack.quote);
|
| + * } else {
|
| + * return finishStringBody(istack.quote);
|
| + * }
|
| + */
|
| + }
|
| +
|
| + int ch;
|
| + ch = _nextChar();
|
| + switch(ch) {
|
| + case 0:
|
| + return _finishToken(TokenKind.END_OF_FILE);
|
| + case cssTokens.tokens[TokenKind.SPACE]:
|
| + case cssTokens.tokens[TokenKind.TAB]:
|
| + case cssTokens.tokens[TokenKind.NEWLINE]:
|
| + case cssTokens.tokens[TokenKind.RETURN]:
|
| + return finishWhitespace();
|
| + case cssTokens.tokens[TokenKind.END_OF_FILE]:
|
| + return _finishToken(TokenKind.END_OF_FILE);
|
| + case cssTokens.tokens[TokenKind.AT]:
|
| + return _finishToken(TokenKind.AT);
|
| + case cssTokens.tokens[TokenKind.DOT]:
|
| + return _finishToken(TokenKind.DOT);
|
| + case cssTokens.tokens[TokenKind.LBRACE]:
|
| + return _finishToken(TokenKind.LBRACE);
|
| + case cssTokens.tokens[TokenKind.RBRACE]:
|
| + return _finishToken(TokenKind.RBRACE);
|
| + case cssTokens.tokens[TokenKind.HASH]:
|
| + return _finishToken(TokenKind.HASH);
|
| + case cssTokens.tokens[TokenKind.COMBINATOR_PLUS]:
|
| + return _finishToken(TokenKind.COMBINATOR_PLUS);
|
| + case cssTokens.tokens[TokenKind.COMBINATOR_GREATER]:
|
| + return _finishToken(TokenKind.COMBINATOR_GREATER);
|
| + case cssTokens.tokens[TokenKind.COMBINATOR_TILDE]:
|
| + return _finishToken(TokenKind.COMBINATOR_TILDE);
|
| + case cssTokens.tokens[TokenKind.ASTERISK]:
|
| + return _finishToken(TokenKind.ASTERISK);
|
| + case cssTokens.tokens[TokenKind.NAMESPACE]:
|
| + return _finishToken(TokenKind.NAMESPACE);
|
| + case cssTokens.tokens[TokenKind.PSEUDO]:
|
| + return _finishToken(TokenKind.PSEUDO);
|
| + case cssTokens.tokens[TokenKind.COMMA]:
|
| + return _finishToken(TokenKind.COMMA);
|
| +
|
| + default:
|
| + if (isIdentifierStart(ch)) {
|
| + return this.finishIdentifier();
|
| + } else if (isDigit(ch)) {
|
| + return this.finishNumber();
|
| + } else {
|
| + return _errorToken();
|
| + }
|
| + }
|
| + }
|
| +
|
| + // TODO(jmesserly): we need a way to emit human readable error messages from
|
| + // the tokenizer.
|
| + lang.Token _errorToken() {
|
| + return _finishToken(TokenKind.ERROR);
|
| + }
|
| +
|
| + int getIdentifierKind() {
|
| + return TokenKind.IDENTIFIER;
|
| + }
|
| +
|
| + // Need to override so CSS version of isIdentifierPart is used.
|
| + lang.Token finishIdentifier() {
|
| + while (_index < _text.length) {
|
| + if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
|
| + _index--;
|
| + break;
|
| + }
|
| + }
|
| + int kind = getIdentifierKind();
|
| + if (_interpStack != null && _interpStack.depth == -1) {
|
| + _interpStack.depth = 0;
|
| + }
|
| + if (kind == TokenKind.IDENTIFIER) {
|
| + return _finishToken(TokenKind.IDENTIFIER);
|
| + } else {
|
| + return _finishToken(kind);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/** Static helper methods. */
|
| +class TokenizerHelpers {
|
| + static bool isIdentifierStart(int c) =>
|
| + lang.TokenizerHelpers.isIdentifierStart(c) || c == 95 /*_*/;
|
| +
|
| + static bool isDigit(int c) => lang.TokenizerHelpers.isDigit(c);
|
| +
|
| + static bool isHexDigit(int c) => lang.TokenizerHelpers.isHexDigit(c);
|
| +
|
| + static bool isWhitespace(int c) => lang.TokenizerHelpers.isWhitespace(c);
|
| +
|
| + static bool isIdentifierPart(int c) =>
|
| + lang.TokenizerHelpers.isIdentifierPart(c) || c == 45 /*-*/;
|
| +}
|
|
|