// Copyright (c) 2012, 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 csslib.parser;

import 'dart:math' as math;

import 'package:source_span/source_span.dart';

import 'visitor.dart';
import 'src/messages.dart';
import 'src/options.dart';

export 'src/messages.dart' show Message;
export 'src/options.dart';

part 'src/analyzer.dart';
part 'src/polyfill.dart';
part 'src/property.dart';
part 'src/token.dart';
part 'src/tokenizer_base.dart';
part 'src/tokenizer.dart';
part 'src/tokenkind.dart';

/** Used for parser lookup ahead (used for nested selectors Less support). */
class ParserState extends TokenizerState {
  final Token peekToken;
  final Token previousToken;

  ParserState(this.peekToken, this.previousToken, Tokenizer tokenizer)
      : super(tokenizer);
}

// TODO(jmesserly): this should not be global
void _createMessages({List<Message> errors, PreprocessorOptions options}) {
  if (errors == null) errors = [];

  if (options == null) {
    options = new PreprocessorOptions(useColors: false, inputFile: 'memory');
  }

  messages = new Messages(options: options, printHandler: errors.add);
}

/** CSS checked mode enabled. */
bool get isChecked => messages.options.checked;

// TODO(terry): Remove nested name parameter.
/** Parse and analyze the CSS file. */
StyleSheet compile(input,
    {List<Message> errors,
    PreprocessorOptions options,
    bool nested: true,
    bool polyfill: false,
    List<StyleSheet> includes: null}) {
  if (includes == null) {
    includes = [];
  }

  var source = _inputAsString(input);

  _createMessages(errors: errors, options: options);

  var file = new SourceFile(source);

  var tree = new _Parser(file, source).parse();

  analyze([tree], errors: errors, options: options);

  if (polyfill) {
    var processCss = new PolyFill(messages);
    processCss.process(tree, includes: includes);
  }

  return tree;
}

/** Analyze the CSS file. */
void analyze(List<StyleSheet> styleSheets,
    {List<Message> errors, PreprocessorOptions options}) {
  _createMessages(errors: errors, options: options);
  new Analyzer(styleSheets, messages).run();
}

/**
 * Parse the [input] CSS stylesheet into a tree. The [input] can be a [String],
 * or [List<int>] of bytes and returns a [StyleSheet] AST.  The optional
 * [errors] list will contain each error/warning as a [Message].
 */
StyleSheet parse(input, {List<Message> errors, PreprocessorOptions options}) {
  var source = _inputAsString(input);

  _createMessages(errors: errors, options: options);

  var file = new SourceFile(source);
  return new _Parser(file, source).parse();
}

/**
 * Parse the [input] CSS selector into a tree. The [input] can be a [String],
 * or [List<int>] of bytes and returns a [StyleSheet] AST.  The optional
 * [errors] list will contain each error/warning as a [Message].
 */
// TODO(jmesserly): should rename "parseSelector" and return Selector
StyleSheet selector(input, {List<Message> errors}) {
  var source = _inputAsString(input);

  _createMessages(errors: errors);

  var file = new SourceFile(source);
  return (new _Parser(file, source)..tokenizer.inSelector = true)
      .parseSelector();
}

SelectorGroup parseSelectorGroup(input, {List<Message> errors}) {
  var source = _inputAsString(input);

  _createMessages(errors: errors);

  var file = new SourceFile(source);
  return (new _Parser(file, source)
        // TODO(jmesserly): this fix should be applied to the parser. It's tricky
        // because by the time the flag is set one token has already been fetched.
        ..tokenizer.inSelector = true)
      .processSelectorGroup();
}

String _inputAsString(input) {
  String source;

  if (input is String) {
    source = input;
  } else if (input is List) {
    // TODO(terry): The parse function needs an "encoding" argument and will
    //              default to whatever encoding CSS defaults to.
    //
    // Here's some info about CSS encodings:
    // http://www.w3.org/International/questions/qa-css-charset.en.php
    //
    // As JMesserly suggests it will probably need a "preparser" html5lib
    // (encoding_parser.dart) that interprets the bytes as ASCII and scans for
    // @charset. But for now an "encoding" argument would work.  Often the
    // HTTP header will indicate the correct encoding.
    //
    // See encoding helpers at: package:html5lib/lib/src/char_encodings.dart
    // These helpers can decode in different formats given an encoding name
    // (mostly unicode, ascii, windows-1252 which is html5 default encoding).
    source = new String.fromCharCodes(input as List<int>);
  } else {
    // TODO(terry): Support RandomAccessFile using console.
    throw new ArgumentError("'source' must be a String or "
        "List<int> (of bytes). RandomAccessFile not supported from this "
        "simple interface");
  }

  return source;
}

// TODO(terry): Consider removing this class when all usages can be eliminated
//               or replaced with compile API.
/** Public parsing interface for csslib. */
class Parser {
  final _Parser _parser;

  // TODO(jmesserly): having file and text is redundant.
  // TODO(rnystrom): baseUrl isn't used. Remove from API.
  Parser(SourceFile file, String text, {int start: 0, String baseUrl})
      : _parser = new _Parser(file, text, start: start);

  StyleSheet parse() => _parser.parse();
}

/** A simple recursive descent parser for CSS. */
class _Parser {
  final Tokenizer tokenizer;

  /**
   * File containing the source being parsed, used to report errors with
   * source-span locations.
   */
  final SourceFile file;

  Token _previousToken;
  Token _peekToken;

  _Parser(SourceFile file, String text, {int start: 0})
      : this.file = file,
        tokenizer = new Tokenizer(file, text, true, start) {
    _peekToken = tokenizer.next();
  }

  /** Main entry point for parsing an entire CSS file. */
  StyleSheet parse() {
    List<TreeNode> productions = [];

    var start = _peekToken.span;
    while (!_maybeEat(TokenKind.END_OF_FILE) && !_peekKind(TokenKind.RBRACE)) {
      // TODO(terry): Need to handle charset.
      var directive = processDirective();
      if (directive != null) {
        productions.add(directive);
        _maybeEat(TokenKind.SEMICOLON);
      } else {
        RuleSet ruleset = processRuleSet();
        if (ruleset != null) {
          productions.add(ruleset);
        } else {
          break;
        }
      }
    }

    checkEndOfFile();

    return new StyleSheet(productions, _makeSpan(start));
  }

  /** Main entry point for parsing a simple selector sequence. */
  StyleSheet parseSelector() {
    List<TreeNode> productions = [];

    var start = _peekToken.span;
    while (!_maybeEat(TokenKind.END_OF_FILE) && !_peekKind(TokenKind.RBRACE)) {
      var selector = processSelector();
      if (selector != null) {
        productions.add(selector);
      }
    }

    checkEndOfFile();

    return new StyleSheet.selector(productions, _makeSpan(start));
  }

  /** Generate an error if [file] has not been completely consumed. */
  void checkEndOfFile() {
    if (!(_peekKind(TokenKind.END_OF_FILE) ||
        _peekKind(TokenKind.INCOMPLETE_COMMENT))) {
      _error('premature end of file unknown CSS', _peekToken.span);
    }
  }

  /** Guard to break out of parser when an unexpected end of file is found. */
  // TODO(jimhug): Failure to call this method can lead to inifinite parser
  //   loops.  Consider embracing exceptions for more errors to reduce
  //   the danger here.
  bool isPrematureEndOfFile() {
    if (_maybeEat(TokenKind.END_OF_FILE)) {
      _error('unexpected end of file', _peekToken.span);
      return true;
    } else {
      return false;
    }
  }

  ///////////////////////////////////////////////////////////////////
  // Basic support methods
  ///////////////////////////////////////////////////////////////////
  int _peek() {
    return _peekToken.kind;
  }

  Token _next({unicodeRange: false}) {
    _previousToken = _peekToken;
    _peekToken = tokenizer.next(unicodeRange: unicodeRange);
    return _previousToken;
  }

  bool _peekKind(int kind) {
    return _peekToken.kind == kind;
  }

  /* Is the next token a legal identifier?  This includes pseudo-keywords. */
  bool _peekIdentifier() {
    return TokenKind.isIdentifier(_peekToken.kind);
  }

  /** Marks the parser/tokenizer look ahead to support Less nested selectors. */
  ParserState get _mark =>
      new ParserState(_peekToken, _previousToken, tokenizer);

  /** Restores the parser/tokenizer state to state remembered by _mark. */
  void _restore(ParserState markedData) {
    tokenizer.restore(markedData);
    _peekToken = markedData.peekToken;
    _previousToken = markedData.previousToken;
  }

  bool _maybeEat(int kind, {unicodeRange: false}) {
    if (_peekToken.kind == kind) {
      _previousToken = _peekToken;
      _peekToken = tokenizer.next(unicodeRange: unicodeRange);
      return true;
    } else {
      return false;
    }
  }

  void _eat(int kind, {unicodeRange: false}) {
    if (!_maybeEat(kind, unicodeRange: unicodeRange)) {
      _errorExpected(TokenKind.kindToString(kind));
    }
  }

  void _errorExpected(String expected) {
    var tok = _next();
    var message;
    try {
      message = 'expected $expected, but found $tok';
    } catch (e) {
      message = 'parsing error expected $expected';
    }
    _error(message, tok.span);
  }

  void _error(String message, SourceSpan location) {
    if (location == null) {
      location = _peekToken.span;
    }
    messages.error(message, location);
  }

  void _warning(String message, SourceSpan location) {
    if (location == null) {
      location = _peekToken.span;
    }
    messages.warning(message, location);
  }

  SourceSpan _makeSpan(FileSpan start) {
    // TODO(terry): there are places where we are creating spans before we eat
    // the tokens, so using _previousToken is not always valid.
    // TODO(nweiz): use < rather than compareTo when SourceSpan supports it.
    if (_previousToken == null || _previousToken.span.compareTo(start) < 0) {
      return start;
    }
    return start.expand(_previousToken.span);
  }

  ///////////////////////////////////////////////////////////////////
  // Top level productions
  ///////////////////////////////////////////////////////////////////

  /**
   * The media_query_list production below replaces the media_list production
   * from CSS2 the new grammar is:
   *
   *   media_query_list
   *    : S* [media_query [ ',' S* media_query ]* ]?
   *   media_query
   *    : [ONLY | NOT]? S* media_type S* [ AND S* expression ]*
   *    | expression [ AND S* expression ]*
   *   media_type
   *    : IDENT
   *   expression
   *    : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
   *   media_feature
   *    : IDENT
   */
  List<MediaQuery> processMediaQueryList() {
    var mediaQueries = <MediaQuery>[];

    bool firstTime = true;
    var mediaQuery;
    do {
      mediaQuery = processMediaQuery(firstTime == true);
      if (mediaQuery != null) {
        mediaQueries.add(mediaQuery);
        firstTime = false;
        continue;
      }

      // Any more more media types separated by comma.
      if (!_maybeEat(TokenKind.COMMA)) break;

      // Yep more media types start again.
      firstTime = true;
    } while ((!firstTime && mediaQuery != null) || firstTime);

    return mediaQueries;
  }

  MediaQuery processMediaQuery([bool startQuery = true]) {
    // Grammar: [ONLY | NOT]? S* media_type S*
    //          [ AND S* MediaExpr ]* | MediaExpr [ AND S* MediaExpr ]*

    var start = _peekToken.span;

    // Is it a unary media operator?
    var op = _peekToken.text;
    var opLen = op.length;
    var unaryOp = TokenKind.matchMediaOperator(op, 0, opLen);
    if (unaryOp != -1) {
      if (isChecked) {
        if (startQuery && unaryOp != TokenKind.MEDIA_OP_NOT ||
            unaryOp != TokenKind.MEDIA_OP_ONLY) {
          _warning("Only the unary operators NOT and ONLY allowed",
              _makeSpan(start));
        }
        if (!startQuery && unaryOp != TokenKind.MEDIA_OP_AND) {
          _warning("Only the binary AND operator allowed", _makeSpan(start));
        }
      }
      _next();
      start = _peekToken.span;
    }

    var type;
    if (startQuery && unaryOp != TokenKind.MEDIA_OP_AND) {
      // Get the media type.
      if (_peekIdentifier()) type = identifier();
    }

    var exprs = <MediaExpression>[];

    if (unaryOp == -1 || unaryOp == TokenKind.MEDIA_OP_AND) {
      var andOp = false;
      while (true) {
        var expr = processMediaExpression(andOp);
        if (expr == null) break;

        exprs.add(expr);
        op = _peekToken.text;
        opLen = op.length;
        andOp = TokenKind.matchMediaOperator(op, 0, opLen) ==
            TokenKind.MEDIA_OP_AND;
        if (!andOp) break;
        _next();
      }
    }

    if (unaryOp != -1 || type != null || exprs.length > 0) {
      return new MediaQuery(unaryOp, type, exprs, _makeSpan(start));
    }
    return null;
  }

  MediaExpression processMediaExpression([bool andOperator = false]) {
    var start = _peekToken.span;

    // Grammar: '(' S* media_feature S* [ ':' S* expr ]? ')' S*
    if (_maybeEat(TokenKind.LPAREN)) {
      if (_peekIdentifier()) {
        var feature = identifier(); // Media feature.
        while (_maybeEat(TokenKind.COLON)) {
          var startExpr = _peekToken.span;
          var exprs = processExpr();
          if (_maybeEat(TokenKind.RPAREN)) {
            return new MediaExpression(
                andOperator, feature, exprs, _makeSpan(startExpr));
          } else if (isChecked) {
            _warning("Missing parenthesis around media expression",
                _makeSpan(start));
            return null;
          }
        }
      } else if (isChecked) {
        _warning("Missing media feature in media expression", _makeSpan(start));
      }
    }
    return null;
  }

  /**
   * Directive grammar:
   *
   *  import:             '@import' [string | URI] media_list?
   *  media:              '@media' media_query_list '{' ruleset '}'
   *  page:               '@page' [':' IDENT]? '{' declarations '}'
   *  stylet:             '@stylet' IDENT '{' ruleset '}'
   *  media_query_list:   IDENT [',' IDENT]
   *  keyframes:          '@-webkit-keyframes ...' (see grammar below).
   *  font_face:          '@font-face' '{' declarations '}'
   *  namespace:          '@namespace name url("xmlns")
   *  host:               '@host '{' ruleset '}'
   *  mixin:              '@mixin name [(args,...)] '{' declarations/ruleset '}'
   *  include:            '@include name [(@arg,@arg1)]
   *                      '@include name [(@arg...)]
   *  content             '@content'
   */
  processDirective() {
    var start = _peekToken.span;

    var tokId = processVariableOrDirective();
    if (tokId is VarDefinitionDirective) return tokId;
    switch (tokId) {
      case TokenKind.DIRECTIVE_IMPORT:
        _next();

        // @import "uri_string" or @import url("uri_string") are identical; only
        // a url can follow an @import.
        String importStr;
        if (_peekIdentifier()) {
          var func = processFunction(identifier());
          if (func is UriTerm) {
            importStr = func.text;
          }
        } else {
          importStr = processQuotedString(false);
        }

        // Any medias?
        var medias = processMediaQueryList();

        if (importStr == null) {
          _error('missing import string', _peekToken.span);
        }

        return new ImportDirective(importStr.trim(), medias, _makeSpan(start));

      case TokenKind.DIRECTIVE_MEDIA:
        _next();

        // Any medias?
        var media = processMediaQueryList();

        List<TreeNode> rulesets = [];
        if (_maybeEat(TokenKind.LBRACE)) {
          while (!_maybeEat(TokenKind.END_OF_FILE)) {
            RuleSet ruleset = processRuleSet();
            if (ruleset == null) break;
            rulesets.add(ruleset);
          }

          if (!_maybeEat(TokenKind.RBRACE)) {
            _error('expected } after ruleset for @media', _peekToken.span);
          }
        } else {
          _error('expected { after media before ruleset', _peekToken.span);
        }
        return new MediaDirective(media, rulesets, _makeSpan(start));

      case TokenKind.DIRECTIVE_HOST:
        _next();

        List<TreeNode> rulesets = [];
        if (_maybeEat(TokenKind.LBRACE)) {
          while (!_maybeEat(TokenKind.END_OF_FILE)) {
            RuleSet ruleset = processRuleSet();
            if (ruleset == null) break;
            rulesets.add(ruleset);
          }

          if (!_maybeEat(TokenKind.RBRACE)) {
            _error('expected } after ruleset for @host', _peekToken.span);
          }
        } else {
          _error('expected { after host before ruleset', _peekToken.span);
        }
        return new HostDirective(rulesets, _makeSpan(start));

      case TokenKind.DIRECTIVE_PAGE:
        /*
         * @page S* IDENT? pseudo_page?
         *      S* '{' S*
         *      [ declaration | margin ]?
         *      [ ';' S* [ declaration | margin ]? ]* '}' S*
         *
         * pseudo_page :
         *      ':' [ "left" | "right" | "first" ]
         *
         * margin :
         *      margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S*
         *
         * margin_sym : @top-left-corner, @top-left, @bottom-left, etc.
         *
         * See http://www.w3.org/TR/css3-page/#CSS21
         */
        _next();

        // Page name
        var name;
        if (_peekIdentifier()) {
          name = identifier();
        }

        // Any pseudo page?
        var pseudoPage;
        if (_maybeEat(TokenKind.COLON)) {
          if (_peekIdentifier()) {
            pseudoPage = identifier();
            // TODO(terry): Normalize pseudoPage to lowercase.
            if (isChecked &&
                !(pseudoPage.name == 'left' ||
                    pseudoPage.name == 'right' ||
                    pseudoPage.name == 'first')) {
              _warning(
                  "Pseudo page must be left, top or first", pseudoPage.span);
              return null;
            }
          }
        }

        String pseudoName = pseudoPage is Identifier ? pseudoPage.name : '';
        String ident = name is Identifier ? name.name : '';
        return new PageDirective(
            ident, pseudoName, processMarginsDeclarations(), _makeSpan(start));

      case TokenKind.DIRECTIVE_CHARSET:
        // @charset S* STRING S* ';'
        _next();

        var charEncoding = processQuotedString(false);
        if (isChecked && charEncoding == null) {
          // Missing character encoding.
          _warning('missing character encoding string', _makeSpan(start));
        }

        return new CharsetDirective(charEncoding, _makeSpan(start));

      // TODO(terry): Workaround Dart2js bug continue not implemented in switch
      //              see https://code.google.com/p/dart/issues/detail?id=8270
      /*
      case TokenKind.DIRECTIVE_MS_KEYFRAMES:
        // TODO(terry): For now only IE 10 (are base level) supports @keyframes,
        // -moz- has only been optional since Oct 2012 release of Firefox, not
        // all versions of webkit support @keyframes and opera doesn't yet
        // support w/o -o- prefix.  Add more warnings for other prefixes when
        // they become optional.
        if (isChecked) {
          _warning('@-ms-keyframes should be @keyframes', _makeSpan(start));
        }
        continue keyframeDirective;

      keyframeDirective:
      */
      case TokenKind.DIRECTIVE_KEYFRAMES:
      case TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES:
      case TokenKind.DIRECTIVE_MOZ_KEYFRAMES:
      case TokenKind.DIRECTIVE_O_KEYFRAMES:
      // TODO(terry): Remove workaround when bug 8270 is fixed.
      case TokenKind.DIRECTIVE_MS_KEYFRAMES:
        if (tokId == TokenKind.DIRECTIVE_MS_KEYFRAMES && isChecked) {
          _warning('@-ms-keyframes should be @keyframes', _makeSpan(start));
        }
        // TODO(terry): End of workaround.

        /*  Key frames grammar:
         *
         *  @[browser]? keyframes [IDENT|STRING] '{' keyframes-blocks '}';
         *
         *  browser: [-webkit-, -moz-, -ms-, -o-]
         *
         *  keyframes-blocks:
         *    [keyframe-selectors '{' declarations '}']* ;
         *
         *  keyframe-selectors:
         *    ['from'|'to'|PERCENTAGE] [',' ['from'|'to'|PERCENTAGE] ]* ;
         */
        _next();

        var name;
        if (_peekIdentifier()) {
          name = identifier();
        }

        _eat(TokenKind.LBRACE);

        var keyframe = new KeyFrameDirective(tokId, name, _makeSpan(start));

        do {
          Expressions selectors = new Expressions(_makeSpan(start));

          do {
            var term = processTerm();

            // TODO(terry): Only allow from, to and PERCENTAGE ...

            selectors.add(term);
          } while (_maybeEat(TokenKind.COMMA));

          keyframe.add(new KeyFrameBlock(
              selectors, processDeclarations(), _makeSpan(start)));
        } while (!_maybeEat(TokenKind.RBRACE) && !isPrematureEndOfFile());

        return keyframe;

      case TokenKind.DIRECTIVE_FONTFACE:
        _next();
        return new FontFaceDirective(processDeclarations(), _makeSpan(start));

      case TokenKind.DIRECTIVE_STYLET:
        /* Stylet grammar:
         *
         *  @stylet IDENT '{'
         *    ruleset
         *  '}'
         */
        _next();

        var name;
        if (_peekIdentifier()) {
          name = identifier();
        }

        _eat(TokenKind.LBRACE);

        List<TreeNode> productions = [];

        start = _peekToken.span;
        while (!_maybeEat(TokenKind.END_OF_FILE)) {
          RuleSet ruleset = processRuleSet();
          if (ruleset == null) {
            break;
          }
          productions.add(ruleset);
        }

        _eat(TokenKind.RBRACE);

        return new StyletDirective(name, productions, _makeSpan(start));

      case TokenKind.DIRECTIVE_NAMESPACE:
        /* Namespace grammar:
         *
         * @namespace S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
         * namespace_prefix : IDENT
         *
         */
        _next();

        var prefix;
        if (_peekIdentifier()) {
          prefix = identifier();
        }

        // The namespace URI can be either a quoted string url("uri_string")
        // are identical.
        String namespaceUri;
        if (_peekIdentifier()) {
          var func = processFunction(identifier());
          if (func is UriTerm) {
            namespaceUri = func.text;
          }
        } else {
          if (prefix != null && prefix.name == 'url') {
            var func = processFunction(prefix);
            if (func is UriTerm) {
              // @namespace url("");
              namespaceUri = func.text;
              prefix = null;
            }
          } else {
            namespaceUri = processQuotedString(false);
          }
        }

        return new NamespaceDirective(
            prefix != null ? prefix.name : '', namespaceUri, _makeSpan(start));

      case TokenKind.DIRECTIVE_MIXIN:
        return processMixin();

      case TokenKind.DIRECTIVE_INCLUDE:
        return processInclude(_makeSpan(start));

      case TokenKind.DIRECTIVE_CONTENT:
        // TODO(terry): TBD
        _warning("@content not implemented.", _makeSpan(start));
        return null;
    }
    return null;
  }

  /**
   * Parse the mixin beginning token offset [start]. Returns a [MixinDefinition]
   * node.
   *
   * Mixin grammar:
   *
   *  @mixin IDENT [(args,...)] '{'
   *    [ruleset | property | directive]*
   *  '}'
   */
  MixinDefinition processMixin() {
    _next();

    var name = identifier();

    var params = <TreeNode>[];
    // Any parameters?
    if (_maybeEat(TokenKind.LPAREN)) {
      var mustHaveParam = false;
      var keepGoing = true;
      while (keepGoing) {
        var varDef = processVariableOrDirective(mixinParameter: true);
        if (varDef is VarDefinitionDirective || varDef is VarDefinition) {
          params.add(varDef);
        } else if (mustHaveParam) {
          _warning("Expecting parameter", _makeSpan(_peekToken.span));
          keepGoing = false;
        }
        if (_maybeEat(TokenKind.COMMA)) {
          mustHaveParam = true;
          continue;
        }
        keepGoing = !_maybeEat(TokenKind.RPAREN);
      }
    }

    _eat(TokenKind.LBRACE);

    List<TreeNode> productions = [];
    var mixinDirective;

    var start = _peekToken.span;
    while (!_maybeEat(TokenKind.END_OF_FILE)) {
      var directive = processDirective();
      if (directive != null) {
        productions.add(directive);
        continue;
      }

      var declGroup = processDeclarations(checkBrace: false);
      if (declGroup.declarations.any((decl) {
        return decl is Declaration && decl is! IncludeMixinAtDeclaration;
      })) {
        var newDecls = <Declaration>[];
        productions.forEach((include) {
          // If declGroup has items that are declarations then we assume
          // this mixin is a declaration mixin not a top-level mixin.
          if (include is IncludeDirective) {
            newDecls.add(new IncludeMixinAtDeclaration(include, include.span));
          } else {
            _warning("Error mixing of top-level vs declarations mixins",
                _makeSpan(include.span));
          }
        });
        declGroup.declarations.insertAll(0, newDecls);
        productions = [];
      } else {
        // Declarations are just @includes make it a list of productions
        // not a declaration group (anything else is a ruleset).  Make it a
        // list of productions, not a declaration group.
        for (var decl in declGroup.declarations) {
          productions
              .add(decl is IncludeMixinAtDeclaration ? decl.include : decl);
        }
        ;
        declGroup.declarations.clear();
      }

      if (declGroup.declarations.isNotEmpty) {
        if (productions.isEmpty) {
          mixinDirective = new MixinDeclarationDirective(
              name.name, params, false, declGroup, _makeSpan(start));
          break;
        } else {
          for (var decl in declGroup.declarations) {
            productions
                .add(decl is IncludeMixinAtDeclaration ? decl.include : decl);
          }
        }
      } else {
        mixinDirective = new MixinRulesetDirective(
            name.name, params, false, productions, _makeSpan(start));
        break;
      }
    }

    if (productions.isNotEmpty) {
      mixinDirective = new MixinRulesetDirective(
          name.name, params, false, productions, _makeSpan(start));
    }

    _eat(TokenKind.RBRACE);

    return mixinDirective;
  }

  /**
   * Returns a VarDefinitionDirective or VarDefinition if a varaible otherwise
   * return the token id of a directive or -1 if neither.
   */
  processVariableOrDirective({bool mixinParameter: false}) {
    var start = _peekToken.span;

    var tokId = _peek();
    // Handle case for @ directive (where there's a whitespace between the @
    // sign and the directive name.  Technically, it's not valid grammar but
    // a number of CSS tests test for whitespace between @ and name.
    if (tokId == TokenKind.AT) {
      _next();
      tokId = _peek();
      if (_peekIdentifier()) {
        // Is it a directive?
        var directive = _peekToken.text;
        var directiveLen = directive.length;
        tokId = TokenKind.matchDirectives(directive, 0, directiveLen);
        if (tokId == -1) {
          tokId = TokenKind.matchMarginDirectives(directive, 0, directiveLen);
        }
      }

      if (tokId == -1) {
        if (messages.options.lessSupport) {
          // Less compatibility:
          //    @name: value;      =>    var-name: value;       (VarDefinition)
          //    property: @name;   =>    property: var(name);   (VarUsage)
          var name;
          if (_peekIdentifier()) {
            name = identifier();
          }

          Expressions exprs;
          if (mixinParameter && _maybeEat(TokenKind.COLON)) {
            exprs = processExpr();
          } else if (!mixinParameter) {
            _eat(TokenKind.COLON);
            exprs = processExpr();
          }

          var span = _makeSpan(start);
          return new VarDefinitionDirective(
              new VarDefinition(name, exprs, span), span);
        } else if (isChecked) {
          _error('unexpected directive @$_peekToken', _peekToken.span);
        }
      }
    } else if (mixinParameter && _peekToken.kind == TokenKind.VAR_DEFINITION) {
      _next();
      var definedName;
      if (_peekIdentifier()) definedName = identifier();

      Expressions exprs;
      if (_maybeEat(TokenKind.COLON)) {
        exprs = processExpr();
      }

      return new VarDefinition(definedName, exprs, _makeSpan(start));
    }

    return tokId;
  }

  IncludeDirective processInclude(SourceSpan span, {bool eatSemiColon: true}) {
    /* Stylet grammar:
    *
     *  @include IDENT [(args,...)];
     */
    _next();

    var name;
    if (_peekIdentifier()) {
      name = identifier();
    }

    var params = <List<Expression>>[];

    // Any parameters?  Parameters can be multiple terms per argument e.g.,
    // 3px solid yellow, green is two parameters:
    //    1. 3px solid yellow
    //    2. green
    // the first has 3 terms and the second has 1 term.
    if (_maybeEat(TokenKind.LPAREN)) {
      var terms = <Expression>[];
      var expr;
      var keepGoing = true;
      while (keepGoing && (expr = processTerm()) != null) {
        // VarUsage is returns as a list
        terms.add(expr is List ? expr[0] : expr);
        keepGoing = !_peekKind(TokenKind.RPAREN);
        if (keepGoing) {
          if (_maybeEat(TokenKind.COMMA)) {
            params.add(terms);
            terms = [];
          }
        }
      }
      params.add(terms);
      _maybeEat(TokenKind.RPAREN);
    }

    if (eatSemiColon) {
      _eat(TokenKind.SEMICOLON);
    }

    return new IncludeDirective(name.name, params, span);
  }

  RuleSet processRuleSet([SelectorGroup selectorGroup]) {
    if (selectorGroup == null) {
      selectorGroup = processSelectorGroup();
    }
    if (selectorGroup != null) {
      return new RuleSet(
          selectorGroup, processDeclarations(), selectorGroup.span);
    }
    return null;
  }

  /**
   * Look ahead to see if what should be a declaration is really a selector.
   * If it's a selector than it's a nested selector.  This support's Less'
   * nested selector syntax (requires a look ahead). E.g.,
   *
   *    div {
   *      width : 20px;
   *      span {
   *        color: red;
   *      }
   *    }
   *
   * Two tag name selectors div and span equivalent to:
   *
   *    div {
   *      width: 20px;
   *    }
   *    div span {
   *      color: red;
   *    }
   *
   * Return [:null:] if no selector or [SelectorGroup] if a selector was parsed.
   */
  SelectorGroup _nestedSelector() {
    Messages oldMessages = messages;
    _createMessages();

    var markedData = _mark;

    // Look a head do we have a nested selector instead of a declaration?
    SelectorGroup selGroup = processSelectorGroup();

    var nestedSelector = selGroup != null &&
        _peekKind(TokenKind.LBRACE) &&
        messages.messages.isEmpty;

    if (!nestedSelector) {
      // Not a selector so restore the world.
      _restore(markedData);
      messages = oldMessages;
      return null;
    } else {
      // Remember any messages from look ahead.
      oldMessages.mergeMessages(messages);
      messages = oldMessages;
      return selGroup;
    }
  }

  DeclarationGroup processDeclarations({bool checkBrace: true}) {
    var start = _peekToken.span;

    if (checkBrace) _eat(TokenKind.LBRACE);

    var decls = <TreeNode>[];
    var dartStyles = []; // List of latest styles exposed to Dart.

    do {
      var selectorGroup = _nestedSelector();
      while (selectorGroup != null) {
        // Nested selector so process as a ruleset.
        var ruleset = processRuleSet(selectorGroup);
        decls.add(ruleset);
        selectorGroup = _nestedSelector();
      }

      Declaration decl = processDeclaration(dartStyles);
      if (decl != null) {
        if (decl.hasDartStyle) {
          var newDartStyle = decl.dartStyle;

          // Replace or add latest Dart style.
          bool replaced = false;
          for (var i = 0; i < dartStyles.length; i++) {
            var dartStyle = dartStyles[i];
            if (dartStyle.isSame(newDartStyle)) {
              dartStyles[i] = newDartStyle;
              replaced = true;
              break;
            }
          }
          if (!replaced) {
            dartStyles.add(newDartStyle);
          }
        }
        decls.add(decl);
      }
    } while (_maybeEat(TokenKind.SEMICOLON));

    if (checkBrace) _eat(TokenKind.RBRACE);

    // Fixup declaration to only have dartStyle that are live for this set of
    // declarations.
    for (var decl in decls) {
      if (decl is Declaration) {
        if (decl.hasDartStyle && dartStyles.indexOf(decl.dartStyle) < 0) {
          // Dart style not live, ignore these styles in this Declarations.
          decl.dartStyle = null;
        }
      }
    }

    return new DeclarationGroup(decls, _makeSpan(start));
  }

  List<DeclarationGroup> processMarginsDeclarations() {
    var groups = <DeclarationGroup>[];

    var start = _peekToken.span;

    _eat(TokenKind.LBRACE);

    List<Declaration> decls = [];
    List dartStyles = []; // List of latest styles exposed to Dart.

    do {
      switch (_peek()) {
        case TokenKind.MARGIN_DIRECTIVE_TOPLEFTCORNER:
        case TokenKind.MARGIN_DIRECTIVE_TOPLEFT:
        case TokenKind.MARGIN_DIRECTIVE_TOPCENTER:
        case TokenKind.MARGIN_DIRECTIVE_TOPRIGHT:
        case TokenKind.MARGIN_DIRECTIVE_TOPRIGHTCORNER:
        case TokenKind.MARGIN_DIRECTIVE_BOTTOMLEFTCORNER:
        case TokenKind.MARGIN_DIRECTIVE_BOTTOMLEFT:
        case TokenKind.MARGIN_DIRECTIVE_BOTTOMCENTER:
        case TokenKind.MARGIN_DIRECTIVE_BOTTOMRIGHT:
        case TokenKind.MARGIN_DIRECTIVE_BOTTOMRIGHTCORNER:
        case TokenKind.MARGIN_DIRECTIVE_LEFTTOP:
        case TokenKind.MARGIN_DIRECTIVE_LEFTMIDDLE:
        case TokenKind.MARGIN_DIRECTIVE_LEFTBOTTOM:
        case TokenKind.MARGIN_DIRECTIVE_RIGHTTOP:
        case TokenKind.MARGIN_DIRECTIVE_RIGHTMIDDLE:
        case TokenKind.MARGIN_DIRECTIVE_RIGHTBOTTOM:
          // Margin syms processed.
          //   margin :
          //      margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S*
          //
          //      margin_sym : @top-left-corner, @top-left, @bottom-left, etc.
          var marginSym = _peek();

          _next();

          var declGroup = processDeclarations();
          if (declGroup != null) {
            groups.add(new MarginGroup(
                marginSym, declGroup.declarations, _makeSpan(start)));
          }
          break;
        default:
          Declaration decl = processDeclaration(dartStyles);
          if (decl != null) {
            if (decl.hasDartStyle) {
              var newDartStyle = decl.dartStyle;

              // Replace or add latest Dart style.
              bool replaced = false;
              for (var i = 0; i < dartStyles.length; i++) {
                var dartStyle = dartStyles[i];
                if (dartStyle.isSame(newDartStyle)) {
                  dartStyles[i] = newDartStyle;
                  replaced = true;
                  break;
                }
              }
              if (!replaced) {
                dartStyles.add(newDartStyle);
              }
            }
            decls.add(decl);
          }
          _maybeEat(TokenKind.SEMICOLON);
          break;
      }
    } while (!_maybeEat(TokenKind.RBRACE) && !isPrematureEndOfFile());

    // Fixup declaration to only have dartStyle that are live for this set of
    // declarations.
    for (var decl in decls) {
      if (decl.hasDartStyle && dartStyles.indexOf(decl.dartStyle) < 0) {
        // Dart style not live, ignore these styles in this Declarations.
        decl.dartStyle = null;
      }
    }

    if (decls.length > 0) {
      groups.add(new DeclarationGroup(decls, _makeSpan(start)));
    }

    return groups;
  }

  SelectorGroup processSelectorGroup() {
    List<Selector> selectors = [];
    var start = _peekToken.span;

    do {
      Selector selector = processSelector();
      if (selector != null) {
        selectors.add(selector);
      }
    } while (_maybeEat(TokenKind.COMMA));

    if (selectors.length > 0) {
      return new SelectorGroup(selectors, _makeSpan(start));
    }
    return null;
  }

  /**
   * Return list of selectors
   */
  Selector processSelector() {
    var simpleSequences = <SimpleSelectorSequence>[];
    var start = _peekToken.span;
    while (true) {
      // First item is never descendant make sure it's COMBINATOR_NONE.
      var selectorItem = simpleSelectorSequence(simpleSequences.isEmpty);
      if (selectorItem != null) {
        simpleSequences.add(selectorItem);
      } else {
        break;
      }
    }

    if (simpleSequences.isEmpty) return null;

    return new Selector(simpleSequences, _makeSpan(start));
  }

  /// Same as [processSelector] but reports an error for each combinator.
  ///
  /// This is a quick fix for parsing <compound-selectors> until the parser
  /// supports Selector Level 4 grammar:
  /// https://drafts.csswg.org/selectors-4/#typedef-compound-selector
  Selector processCompoundSelector() {
    return processSelector()
      ..simpleSelectorSequences.forEach((sequence) {
        if (!sequence.isCombinatorNone) {
          _error('compound selector can not contain combinator', sequence.span);
        }
      });
  }

  simpleSelectorSequence(bool forceCombinatorNone) {
    var start = _peekToken.span;
    var combinatorType = TokenKind.COMBINATOR_NONE;
    var thisOperator = false;

    switch (_peek()) {
      case TokenKind.PLUS:
        _eat(TokenKind.PLUS);
        combinatorType = TokenKind.COMBINATOR_PLUS;
        break;
      case TokenKind.GREATER:
        // Parse > or >>>
        _eat(TokenKind.GREATER);
        if (_maybeEat(TokenKind.GREATER)) {
          _eat(TokenKind.GREATER);
          combinatorType = TokenKind.COMBINATOR_DEEP;
        } else {
          combinatorType = TokenKind.COMBINATOR_GREATER;
        }
        break;
      case TokenKind.TILDE:
        _eat(TokenKind.TILDE);
        combinatorType = TokenKind.COMBINATOR_TILDE;
        break;
      case TokenKind.SLASH:
        // Parse /deep/
        _eat(TokenKind.SLASH);
        var ate = _maybeEat(TokenKind.IDENTIFIER);
        var tok = ate ? _previousToken : _peekToken;
        if (!(ate && tok.text == 'deep')) {
          _error('expected deep, but found ${tok.text}', tok.span);
        }
        _eat(TokenKind.SLASH);
        combinatorType = TokenKind.COMBINATOR_DEEP;
        break;
      case TokenKind.AMPERSAND:
        _eat(TokenKind.AMPERSAND);
        thisOperator = true;
        break;
    }

    // Check if WHITESPACE existed between tokens if so we're descendent.
    if (combinatorType == TokenKind.COMBINATOR_NONE && !forceCombinatorNone) {
      if (this._previousToken != null &&
          this._previousToken.end != this._peekToken.start) {
        combinatorType = TokenKind.COMBINATOR_DESCENDANT;
      }
    }

    var span = _makeSpan(start);
    var simpleSel = thisOperator
        ? new ElementSelector(new ThisOperator(span), span)
        : simpleSelector();
    if (simpleSel == null &&
        (combinatorType == TokenKind.COMBINATOR_PLUS ||
            combinatorType == TokenKind.COMBINATOR_GREATER ||
            combinatorType == TokenKind.COMBINATOR_TILDE)) {
      // For "+ &", "~ &" or "> &" a selector sequence with no name is needed
      // so that the & will have a combinator too.  This is needed to
      // disambiguate selector expressions:
      //    .foo&:hover     combinator before & is NONE
      //    .foo &          combinator before & is DESCDENDANT
      //    .foo > &        combinator before & is GREATER
      simpleSel = new ElementSelector(new Identifier("", span), span);
    }
    if (simpleSel != null) {
      return new SimpleSelectorSequence(simpleSel, span, combinatorType);
    }
  }

  /**
   * Simple selector grammar:
   *
   *    simple_selector_sequence
   *       : [ type_selector | universal ]
   *         [ HASH | class | attrib | pseudo | negation ]*
   *       | [ HASH | class | attrib | pseudo | negation ]+
   *    type_selector
   *       : [ namespace_prefix ]? element_name
   *    namespace_prefix
   *       : [ IDENT | '*' ]? '|'
   *    element_name
   *       : IDENT
   *    universal
   *       : [ namespace_prefix ]? '*'
   *    class
   *       : '.' IDENT
   */
  simpleSelector() {
    // TODO(terry): Natalie makes a good point parsing of namespace and element
    //              are essentially the same (asterisk or identifier) other
    //              than the error message for element.  Should consolidate the
    //              code.
    // TODO(terry): Need to handle attribute namespace too.
    var first;
    var start = _peekToken.span;
    switch (_peek()) {
      case TokenKind.ASTERISK:
        // Mark as universal namespace.
        var tok = _next();
        first = new Wildcard(_makeSpan(tok.span));
        break;
      case TokenKind.IDENTIFIER:
        first = identifier();
        break;
      default:
        // Expecting simple selector.
        // TODO(terry): Could be a synthesized token like value, etc.
        if (TokenKind.isKindIdentifier(_peek())) {
          first = identifier();
        } else if (_peekKind(TokenKind.SEMICOLON)) {
          // Can't be a selector if we found a semi-colon.
          return null;
        }
        break;
    }

    if (_maybeEat(TokenKind.NAMESPACE)) {
      var element;
      switch (_peek()) {
        case TokenKind.ASTERISK:
          // Mark as universal element
          var tok = _next();
          element = new Wildcard(_makeSpan(tok.span));
          break;
        case TokenKind.IDENTIFIER:
          element = identifier();
          break;
        default:
          _error('expected element name or universal(*), but found $_peekToken',
              _peekToken.span);
          break;
      }

      return new NamespaceSelector(
          first, new ElementSelector(element, element.span), _makeSpan(start));
    } else if (first != null) {
      return new ElementSelector(first, _makeSpan(start));
    } else {
      // Check for HASH | class | attrib | pseudo | negation
      return simpleSelectorTail();
    }
  }

  bool _anyWhiteSpaceBeforePeekToken(int kind) {
    if (_previousToken != null &&
        _peekToken != null &&
        _previousToken.kind == kind) {
      // If end of previous token isn't same as the start of peek token then
      // there's something between these tokens probably whitespace.
      return _previousToken.end != _peekToken.start;
    }

    return false;
  }

  /**
   * type_selector | universal | HASH | class | attrib | pseudo
   */
  simpleSelectorTail() {
    // Check for HASH | class | attrib | pseudo | negation
    var start = _peekToken.span;
    switch (_peek()) {
      case TokenKind.HASH:
        _eat(TokenKind.HASH);

        var hasWhiteSpace = false;
        if (_anyWhiteSpaceBeforePeekToken(TokenKind.HASH)) {
          _warning("Not a valid ID selector expected #id", _makeSpan(start));
          hasWhiteSpace = true;
        }
        if (_peekIdentifier()) {
          var id = identifier();
          if (hasWhiteSpace) {
            // Generate bad selector id (normalized).
            id.name = " ${id.name}";
          }
          return new IdSelector(id, _makeSpan(start));
        }
        return null;
      case TokenKind.DOT:
        _eat(TokenKind.DOT);

        bool hasWhiteSpace = false;
        if (_anyWhiteSpaceBeforePeekToken(TokenKind.DOT)) {
          _warning("Not a valid class selector expected .className",
              _makeSpan(start));
          hasWhiteSpace = true;
        }
        var id = identifier();
        if (hasWhiteSpace) {
          // Generate bad selector class (normalized).
          id.name = " ${id.name}";
        }
        return new ClassSelector(id, _makeSpan(start));
      case TokenKind.COLON:
        // :pseudo-class ::pseudo-element
        return processPseudoSelector(start);
      case TokenKind.LBRACK:
        return processAttribute();
      case TokenKind.DOUBLE:
        _error('name must start with a alpha character, but found a number',
            _peekToken.span);
        _next();
        break;
    }
  }

  processPseudoSelector(FileSpan start) {
    // :pseudo-class ::pseudo-element
    // TODO(terry): '::' should be token.
    _eat(TokenKind.COLON);
    var pseudoElement = _maybeEat(TokenKind.COLON);

    // TODO(terry): If no identifier specified consider optimizing out the
    //              : or :: and making this a normal selector.  For now,
    //              create an empty pseudoName.
    var pseudoName;
    if (_peekIdentifier()) {
      pseudoName = identifier();
    } else {
      return null;
    }

    // Functional pseudo?

    if (_peekToken.kind == TokenKind.LPAREN) {
      var name = pseudoName.name.toLowerCase();
      if (!pseudoElement && name == 'not') {
        _eat(TokenKind.LPAREN);

        // Negation :   ':NOT(' S* negation_arg S* ')'
        var negArg = simpleSelector();

        _eat(TokenKind.RPAREN);
        return new NegationSelector(negArg, _makeSpan(start));
      } else if (!pseudoElement && (name == 'host' || name == 'host-context')) {
        _eat(TokenKind.LPAREN);
        var selector = processCompoundSelector();
        _eat(TokenKind.RPAREN);
        var span = _makeSpan(start);
        return new PseudoClassFunctionSelector(pseudoName, selector, span);
      } else {
        // Special parsing for expressions in pseudo functions.  Minus is used
        // as operator not identifier.
        // TODO(jmesserly): we need to flip this before we eat the "(" as the
        // next token will be fetched when we do that. I think we should try to
        // refactor so we don't need this boolean; it seems fragile.
        tokenizer.inSelectorExpression = true;
        _eat(TokenKind.LPAREN);

        // Handle function expression.
        var span = _makeSpan(start);
        var expr = processSelectorExpression();

        tokenizer.inSelectorExpression = false;

        // Used during selector look-a-head if not a SelectorExpression is
        // bad.
        if (expr is! SelectorExpression) {
          _errorExpected("CSS expression");
          return null;
        }

        _eat(TokenKind.RPAREN);
        return (pseudoElement)
            ? new PseudoElementFunctionSelector(pseudoName, expr, span)
            : new PseudoClassFunctionSelector(pseudoName, expr, span);
      }
    }

    // TODO(terry): Need to handle specific pseudo class/element name and
    // backward compatible names that are : as well as :: as well as
    // parameters.  Current, spec uses :: for pseudo-element and : for
    // pseudo-class.  However, CSS2.1 allows for : to specify old
    // pseudo-elements (:first-line, :first-letter, :before and :after) any
    // new pseudo-elements defined would require a ::.
    return pseudoElement
        ? new PseudoElementSelector(pseudoName, _makeSpan(start))
        : new PseudoClassSelector(pseudoName, _makeSpan(start));
  }

  /**
   *  In CSS3, the expressions are identifiers, strings, or of the form "an+b".
   *
   *    : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+
   *
   *    num               [0-9]+|[0-9]*\.[0-9]+
   *    PLUS              '+'
   *    DIMENSION         {num}{ident}
   *    NUMBER            {num}
   */
  processSelectorExpression() {
    var start = _peekToken.span;

    var expressions = <Expression>[];

    Token termToken;
    var value;

    var keepParsing = true;
    while (keepParsing) {
      switch (_peek()) {
        case TokenKind.PLUS:
          start = _peekToken.span;
          termToken = _next();
          expressions.add(new OperatorPlus(_makeSpan(start)));
          break;
        case TokenKind.MINUS:
          start = _peekToken.span;
          termToken = _next();
          expressions.add(new OperatorMinus(_makeSpan(start)));
          break;
        case TokenKind.INTEGER:
          termToken = _next();
          value = int.parse(termToken.text);
          break;
        case TokenKind.DOUBLE:
          termToken = _next();
          value = double.parse(termToken.text);
          break;
        case TokenKind.SINGLE_QUOTE:
          value = processQuotedString(false);
          value = "'${_escapeString(value, single: true)}'";
          return new LiteralTerm(value, value, _makeSpan(start));
        case TokenKind.DOUBLE_QUOTE:
          value = processQuotedString(false);
          value = '"${_escapeString(value)}"';
          return new LiteralTerm(value, value, _makeSpan(start));
        case TokenKind.IDENTIFIER:
          value = identifier(); // Snarf up the ident we'll remap, maybe.
          break;
        default:
          keepParsing = false;
      }

      if (keepParsing && value != null) {
        var unitTerm;
        // Don't process the dimension if MINUS or PLUS is next.
        if (_peek() != TokenKind.MINUS && _peek() != TokenKind.PLUS) {
          unitTerm = processDimension(termToken, value, _makeSpan(start));
        }
        if (unitTerm == null) {
          unitTerm = new LiteralTerm(value, value.name, _makeSpan(start));
        }
        expressions.add(unitTerm);

        value = null;
      }
    }

    return new SelectorExpression(expressions, _makeSpan(start));
  }

  //  Attribute grammar:
  //
  //  attributes :
  //    '[' S* IDENT S* [ ATTRIB_MATCHES S* [ IDENT | STRING ] S* ]? ']'
  //
  //  ATTRIB_MATCHES :
  //    [ '=' | INCLUDES | DASHMATCH | PREFIXMATCH | SUFFIXMATCH | SUBSTRMATCH ]
  //
  //  INCLUDES:         '~='
  //
  //  DASHMATCH:        '|='
  //
  //  PREFIXMATCH:      '^='
  //
  //  SUFFIXMATCH:      '$='
  //
  //  SUBSTRMATCH:      '*='
  //
  //
  AttributeSelector processAttribute() {
    var start = _peekToken.span;

    if (_maybeEat(TokenKind.LBRACK)) {
      var attrName = identifier();

      int op;
      switch (_peek()) {
        case TokenKind.EQUALS:
        case TokenKind.INCLUDES: // ~=
        case TokenKind.DASH_MATCH: // |=
        case TokenKind.PREFIX_MATCH: // ^=
        case TokenKind.SUFFIX_MATCH: // $=
        case TokenKind.SUBSTRING_MATCH: // *=
          op = _peek();
          _next();
          break;
        default:
          op = TokenKind.NO_MATCH;
      }

      var value;
      if (op != TokenKind.NO_MATCH) {
        // Operator hit so we require a value too.
        if (_peekIdentifier()) {
          value = identifier();
        } else {
          value = processQuotedString(false);
        }

        if (value == null) {
          _error('expected attribute value string or ident', _peekToken.span);
        }
      }

      _eat(TokenKind.RBRACK);

      return new AttributeSelector(attrName, op, value, _makeSpan(start));
    }
    return null;
  }

  //  Declaration grammar:
  //
  //  declaration:  property ':' expr prio?
  //
  //  property:  IDENT [or IE hacks]
  //  prio:      !important
  //  expr:      (see processExpr)
  //
  // Here are the ugly IE hacks we need to support:
  //   property: expr prio? \9; - IE8 and below property, /9 before semi-colon
  //   *IDENT                   - IE7 or below
  //   _IDENT                   - IE6 property (automatically a valid ident)
  //
  Declaration processDeclaration(List dartStyles) {
    Declaration decl;

    var start = _peekToken.span;

    // IE7 hack of * before property name if so the property is IE7 or below.
    var ie7 = _peekKind(TokenKind.ASTERISK);
    if (ie7) {
      _next();
    }

    // IDENT ':' expr '!important'?
    if (TokenKind.isIdentifier(_peekToken.kind)) {
      var propertyIdent = identifier();

      var ieFilterProperty = propertyIdent.name.toLowerCase() == 'filter';

      _eat(TokenKind.COLON);

      Expressions exprs = processExpr(ieFilterProperty);

      var dartComposite = _styleForDart(propertyIdent, exprs, dartStyles);

      // Handle !important (prio)
      var importantPriority = _maybeEat(TokenKind.IMPORTANT);

      decl = new Declaration(
          propertyIdent, exprs, dartComposite, _makeSpan(start),
          important: importantPriority, ie7: ie7);
    } else if (_peekToken.kind == TokenKind.VAR_DEFINITION) {
      _next();
      var definedName;
      if (_peekIdentifier()) definedName = identifier();

      _eat(TokenKind.COLON);

      Expressions exprs = processExpr();

      decl = new VarDefinition(definedName, exprs, _makeSpan(start));
    } else if (_peekToken.kind == TokenKind.DIRECTIVE_INCLUDE) {
      // @include mixinName in the declaration area.
      var span = _makeSpan(start);
      var include = processInclude(span, eatSemiColon: false);
      decl = new IncludeMixinAtDeclaration(include, span);
    } else if (_peekToken.kind == TokenKind.DIRECTIVE_EXTEND) {
      var simpleSequences = <TreeNode>[];

      _next();
      var span = _makeSpan(start);
      var selector = simpleSelector();
      if (selector == null) {
        _warning("@extends expecting simple selector name", span);
      } else {
        simpleSequences.add(selector);
      }
      if (_peekKind(TokenKind.COLON)) {
        var pseudoSelector = processPseudoSelector(_peekToken.span);
        if (pseudoSelector is PseudoElementSelector ||
            pseudoSelector is PseudoClassSelector) {
          simpleSequences.add(pseudoSelector);
        } else {
          _warning("not a valid selector", span);
        }
      }
      decl = new ExtendDeclaration(simpleSequences, span);
    }

    return decl;
  }

  /** List of styles exposed to the Dart UI framework. */
  static const int _fontPartFont = 0;
  static const int _fontPartVariant = 1;
  static const int _fontPartWeight = 2;
  static const int _fontPartSize = 3;
  static const int _fontPartFamily = 4;
  static const int _fontPartStyle = 5;
  static const int _marginPartMargin = 6;
  static const int _marginPartLeft = 7;
  static const int _marginPartTop = 8;
  static const int _marginPartRight = 9;
  static const int _marginPartBottom = 10;
  static const int _lineHeightPart = 11;
  static const int _borderPartBorder = 12;
  static const int _borderPartLeft = 13;
  static const int _borderPartTop = 14;
  static const int _borderPartRight = 15;
  static const int _borderPartBottom = 16;
  static const int _borderPartWidth = 17;
  static const int _borderPartLeftWidth = 18;
  static const int _borderPartTopWidth = 19;
  static const int _borderPartRightWidth = 20;
  static const int _borderPartBottomWidth = 21;
  static const int _heightPart = 22;
  static const int _widthPart = 23;
  static const int _paddingPartPadding = 24;
  static const int _paddingPartLeft = 25;
  static const int _paddingPartTop = 26;
  static const int _paddingPartRight = 27;
  static const int _paddingPartBottom = 28;

  static const Map<String, int> _stylesToDart = const {
    'font': _fontPartFont,
    'font-family': _fontPartFamily,
    'font-size': _fontPartSize,
    'font-style': _fontPartStyle,
    'font-variant': _fontPartVariant,
    'font-weight': _fontPartWeight,
    'line-height': _lineHeightPart,
    'margin': _marginPartMargin,
    'margin-left': _marginPartLeft,
    'margin-right': _marginPartRight,
    'margin-top': _marginPartTop,
    'margin-bottom': _marginPartBottom,
    'border': _borderPartBorder,
    'border-left': _borderPartLeft,
    'border-right': _borderPartRight,
    'border-top': _borderPartTop,
    'border-bottom': _borderPartBottom,
    'border-width': _borderPartWidth,
    'border-left-width': _borderPartLeftWidth,
    'border-top-width': _borderPartTopWidth,
    'border-right-width': _borderPartRightWidth,
    'border-bottom-width': _borderPartBottomWidth,
    'height': _heightPart,
    'width': _widthPart,
    'padding': _paddingPartPadding,
    'padding-left': _paddingPartLeft,
    'padding-top': _paddingPartTop,
    'padding-right': _paddingPartRight,
    'padding-bottom': _paddingPartBottom
  };

  static const Map<String, int> _nameToFontWeight = const {
    'bold': FontWeight.bold,
    'normal': FontWeight.normal
  };

  static int _findStyle(String styleName) => _stylesToDart[styleName];

  DartStyleExpression _styleForDart(
      Identifier property, Expressions exprs, List dartStyles) {
    var styleType = _findStyle(property.name.toLowerCase());
    if (styleType != null) {
      return buildDartStyleNode(styleType, exprs, dartStyles);
    }
    return null;
  }

  FontExpression _mergeFontStyles(FontExpression fontExpr, List dartStyles) {
    // Merge all font styles for this class selector.
    for (var dartStyle in dartStyles) {
      if (dartStyle.isFont) {
        fontExpr = new FontExpression.merge(dartStyle, fontExpr);
      }
    }

    return fontExpr;
  }

  DartStyleExpression buildDartStyleNode(
      int styleType, Expressions exprs, List dartStyles) {
    switch (styleType) {
      /*
       * Properties in order:
       *
       *   font-style font-variant font-weight font-size/line-height font-family
       *
       * The font-size and font-family values are required. If other values are
       * missing; a default, if it exist, will be used.
       */
      case _fontPartFont:
        var processor = new ExpressionsProcessor(exprs);
        return _mergeFontStyles(processor.processFont(), dartStyles);
      case _fontPartFamily:
        var processor = new ExpressionsProcessor(exprs);

        try {
          return _mergeFontStyles(processor.processFontFamily(), dartStyles);
        } catch (fontException) {
          _error(fontException, _peekToken.span);
        }
        break;
      case _fontPartSize:
        var processor = new ExpressionsProcessor(exprs);
        return _mergeFontStyles(processor.processFontSize(), dartStyles);
      case _fontPartStyle:
        /* Possible style values:
         *   normal [default]
         *   italic
         *   oblique
         *   inherit
         */
        // TODO(terry): TBD
        break;
      case _fontPartVariant:
        /* Possible variant values:
         *   normal  [default]
         *   small-caps
         *   inherit
         */
        // TODO(terry): TBD
        break;
      case _fontPartWeight:
        /* Possible weight values:
         *   normal [default]
         *   bold
         *   bolder
         *   lighter
         *   100 - 900
         *   inherit
         */
        // TODO(terry): Only 'normal', 'bold', or values of 100-900 supoorted
        //              need to handle bolder, lighter, and inherit.  See
        //              https://github.com/dart-lang/csslib/issues/1
        var expr = exprs.expressions[0];
        if (expr is NumberTerm) {
          var fontExpr = new FontExpression(expr.span, weight: expr.value);
          return _mergeFontStyles(fontExpr, dartStyles);
        } else if (expr is LiteralTerm) {
          int weight = _nameToFontWeight[expr.value.toString()];
          if (weight != null) {
            var fontExpr = new FontExpression(expr.span, weight: weight);
            return _mergeFontStyles(fontExpr, dartStyles);
          }
        }
        break;
      case _lineHeightPart:
        if (exprs.expressions.length == 1) {
          var expr = exprs.expressions[0];
          if (expr is UnitTerm) {
            UnitTerm unitTerm = expr;
            // TODO(terry): Need to handle other units and LiteralTerm normal
            //              See https://github.com/dart-lang/csslib/issues/2.
            if (unitTerm.unit == TokenKind.UNIT_LENGTH_PX ||
                unitTerm.unit == TokenKind.UNIT_LENGTH_PT) {
              var fontExpr = new FontExpression(expr.span,
                  lineHeight: new LineHeight(expr.value, inPixels: true));
              return _mergeFontStyles(fontExpr, dartStyles);
            } else if (isChecked) {
              _warning("Unexpected unit for line-height", expr.span);
            }
          } else if (expr is NumberTerm) {
            var fontExpr = new FontExpression(expr.span,
                lineHeight: new LineHeight(expr.value, inPixels: false));
            return _mergeFontStyles(fontExpr, dartStyles);
          } else if (isChecked) {
            _warning("Unexpected value for line-height", expr.span);
          }
        }
        break;
      case _marginPartMargin:
        return new MarginExpression.boxEdge(exprs.span, processFourNums(exprs));
      case _borderPartBorder:
        for (var expr in exprs.expressions) {
          var v = marginValue(expr);
          if (v != null) {
            final box = new BoxEdge.uniform(v);
            return new BorderExpression.boxEdge(exprs.span, box);
          }
        }
        break;
      case _borderPartWidth:
        var v = marginValue(exprs.expressions[0]);
        if (v != null) {
          final box = new BoxEdge.uniform(v);
          return new BorderExpression.boxEdge(exprs.span, box);
        }
        break;
      case _paddingPartPadding:
        return new PaddingExpression.boxEdge(
            exprs.span, processFourNums(exprs));
      case _marginPartLeft:
      case _marginPartTop:
      case _marginPartRight:
      case _marginPartBottom:
      case _borderPartLeft:
      case _borderPartTop:
      case _borderPartRight:
      case _borderPartBottom:
      case _borderPartLeftWidth:
      case _borderPartTopWidth:
      case _borderPartRightWidth:
      case _borderPartBottomWidth:
      case _heightPart:
      case _widthPart:
      case _paddingPartLeft:
      case _paddingPartTop:
      case _paddingPartRight:
      case _paddingPartBottom:
        if (exprs.expressions.length > 0) {
          return processOneNumber(exprs, styleType);
        }
        break;
    }
    return null;
  }

  // TODO(terry): Look at handling width of thin, thick, etc. any none numbers
  //              to convert to a number.
  DartStyleExpression processOneNumber(Expressions exprs, int part) {
    var value = marginValue(exprs.expressions[0]);
    if (value != null) {
      switch (part) {
        case _marginPartLeft:
          return new MarginExpression(exprs.span, left: value);
        case _marginPartTop:
          return new MarginExpression(exprs.span, top: value);
        case _marginPartRight:
          return new MarginExpression(exprs.span, right: value);
        case _marginPartBottom:
          return new MarginExpression(exprs.span, bottom: value);
        case _borderPartLeft:
        case _borderPartLeftWidth:
          return new BorderExpression(exprs.span, left: value);
        case _borderPartTop:
        case _borderPartTopWidth:
          return new BorderExpression(exprs.span, top: value);
        case _borderPartRight:
        case _borderPartRightWidth:
          return new BorderExpression(exprs.span, right: value);
        case _borderPartBottom:
        case _borderPartBottomWidth:
          return new BorderExpression(exprs.span, bottom: value);
        case _heightPart:
          return new HeightExpression(exprs.span, value);
        case _widthPart:
          return new WidthExpression(exprs.span, value);
        case _paddingPartLeft:
          return new PaddingExpression(exprs.span, left: value);
        case _paddingPartTop:
          return new PaddingExpression(exprs.span, top: value);
        case _paddingPartRight:
          return new PaddingExpression(exprs.span, right: value);
        case _paddingPartBottom:
          return new PaddingExpression(exprs.span, bottom: value);
      }
    }
    return null;
  }

  /**
   * Margins are of the format:
   *
   *   top,right,bottom,left      (4 parameters)
   *   top,right/left, bottom     (3 parameters)
   *   top/bottom,right/left      (2 parameters)
   *   top/right/bottom/left      (1 parameter)
   *
   * The values of the margins can be a unit or unitless or auto.
   */
  BoxEdge processFourNums(Expressions exprs) {
    num top;
    num right;
    num bottom;
    num left;

    int totalExprs = exprs.expressions.length;
    switch (totalExprs) {
      case 1:
        top = marginValue(exprs.expressions[0]);
        right = top;
        bottom = top;
        left = top;
        break;
      case 2:
        top = marginValue(exprs.expressions[0]);
        bottom = top;
        right = marginValue(exprs.expressions[1]);
        left = right;
        break;
      case 3:
        top = marginValue(exprs.expressions[0]);
        right = marginValue(exprs.expressions[1]);
        left = right;
        bottom = marginValue(exprs.expressions[2]);
        break;
      case 4:
        top = marginValue(exprs.expressions[0]);
        right = marginValue(exprs.expressions[1]);
        bottom = marginValue(exprs.expressions[2]);
        left = marginValue(exprs.expressions[3]);
        break;
      default:
        return null;
    }

    return new BoxEdge.clockwiseFromTop(top, right, bottom, left);
  }

  // TODO(terry): Need to handle auto.
  marginValue(var exprTerm) {
    if (exprTerm is UnitTerm || exprTerm is NumberTerm) {
      return exprTerm.value;
    }
  }

  //  Expression grammar:
  //
  //  expression:   term [ operator? term]*
  //
  //  operator:     '/' | ','
  //  term:         (see processTerm)
  //
  Expressions processExpr([bool ieFilter = false]) {
    var start = _peekToken.span;
    var expressions = new Expressions(_makeSpan(start));

    var keepGoing = true;
    var expr;
    while (keepGoing && (expr = processTerm(ieFilter)) != null) {
      var op;

      var opStart = _peekToken.span;

      switch (_peek()) {
        case TokenKind.SLASH:
          op = new OperatorSlash(_makeSpan(opStart));
          break;
        case TokenKind.COMMA:
          op = new OperatorComma(_makeSpan(opStart));
          break;
        case TokenKind.BACKSLASH:
          // Backslash outside of string; detected IE8 or older signaled by \9 at
          // end of an expression.
          var ie8Start = _peekToken.span;

          _next();
          if (_peekKind(TokenKind.INTEGER)) {
            var numToken = _next();
            var value = int.parse(numToken.text);
            if (value == 9) {
              op = new IE8Term(_makeSpan(ie8Start));
            } else if (isChecked) {
              _warning(
                  "\$value is not valid in an expression", _makeSpan(start));
            }
          }
          break;
      }

      if (expr != null) {
        if (expr is List) {
          expr.forEach((exprItem) {
            expressions.add(exprItem);
          });
        } else {
          expressions.add(expr);
        }
      } else {
        keepGoing = false;
      }

      if (op != null) {
        expressions.add(op);
        if (op is IE8Term) {
          keepGoing = false;
        } else {
          _next();
        }
      }
    }

    return expressions;
  }

  static const int MAX_UNICODE = 0x10FFFF;

  //  Term grammar:
  //
  //  term:
  //    unary_operator?
  //    [ term_value ]
  //    | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor
  //
  //  term_value:
  //    NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
  //    TIME S* | FREQ S* | function
  //
  //  NUMBER:       {num}
  //  PERCENTAGE:   {num}%
  //  LENGTH:       {num}['px' | 'cm' | 'mm' | 'in' | 'pt' | 'pc']
  //  EMS:          {num}'em'
  //  EXS:          {num}'ex'
  //  ANGLE:        {num}['deg' | 'rad' | 'grad']
  //  TIME:         {num}['ms' | 's']
  //  FREQ:         {num}['hz' | 'khz']
  //  function:     IDENT '(' expr ')'
  //
  processTerm([bool ieFilter = false]) {
    var start = _peekToken.span;
    Token t; // token for term's value
    var value; // value of term (numeric values)

    var unary = "";
    switch (_peek()) {
      case TokenKind.HASH:
        this._eat(TokenKind.HASH);
        if (!_anyWhiteSpaceBeforePeekToken(TokenKind.HASH)) {
          String hexText;
          if (_peekKind(TokenKind.INTEGER)) {
            String hexText1 = _peekToken.text;
            _next();
            if (_peekIdentifier()) {
              hexText = '$hexText1${identifier().name}';
            } else {
              hexText = hexText1;
            }
          } else if (_peekIdentifier()) {
            hexText = identifier().name;
          }
          if (hexText != null) {
            return _parseHex(hexText, _makeSpan(start));
          }
        }

        if (isChecked) {
          _warning("Expected hex number", _makeSpan(start));
        }
        // Construct the bad hex value with a #<space>number.
        return _parseHex(" ${processTerm().text}", _makeSpan(start));
      case TokenKind.INTEGER:
        t = _next();
        value = int.parse("${unary}${t.text}");
        break;
      case TokenKind.DOUBLE:
        t = _next();
        value = double.parse("${unary}${t.text}");
        break;
      case TokenKind.SINGLE_QUOTE:
        value = processQuotedString(false);
        value = "'${_escapeString(value, single: true)}'";
        return new LiteralTerm(value, value, _makeSpan(start));
      case TokenKind.DOUBLE_QUOTE:
        value = processQuotedString(false);
        value = '"${_escapeString(value)}"';
        return new LiteralTerm(value, value, _makeSpan(start));
      case TokenKind.LPAREN:
        _next();

        GroupTerm group = new GroupTerm(_makeSpan(start));

        var term;
        do {
          term = processTerm();
          if (term != null && term is LiteralTerm) {
            group.add(term);
          }
        } while (term != null &&
            !_maybeEat(TokenKind.RPAREN) &&
            !isPrematureEndOfFile());

        return group;
      case TokenKind.LBRACK:
        _next();

        var term = processTerm();
        if (!(term is NumberTerm)) {
          _error('Expecting a positive number', _makeSpan(start));
        }

        _eat(TokenKind.RBRACK);

        return new ItemTerm(term.value, term.text, _makeSpan(start));
      case TokenKind.IDENTIFIER:
        var nameValue = identifier(); // Snarf up the ident we'll remap, maybe.

        if (!ieFilter && _maybeEat(TokenKind.LPAREN)) {
          var calc = processCalc(nameValue);
          if (calc != null) return calc;
          // FUNCTION
          return processFunction(nameValue);
        }
        if (ieFilter) {
          if (_maybeEat(TokenKind.COLON) &&
              nameValue.name.toLowerCase() == 'progid') {
            // IE filter:progid:
            return processIEFilter(start);
          } else {
            // Handle filter:<name> where name is any filter e.g., alpha, chroma,
            // Wave, blur, etc.
            return processIEFilter(start);
          }
        }

        // TODO(terry): Need to have a list of known identifiers today only
        //              'from' is special.
        if (nameValue.name == 'from') {
          return new LiteralTerm(nameValue, nameValue.name, _makeSpan(start));
        }

        // What kind of identifier is it, named color?
        var colorEntry = TokenKind.matchColorName(nameValue.name);
        if (colorEntry == null) {
          if (isChecked) {
            var propName = nameValue.name;
            var errMsg = TokenKind.isPredefinedName(propName)
                ? "Improper use of property value ${propName}"
                : "Unknown property value ${propName}";
            _warning(errMsg, _makeSpan(start));
          }
          return new LiteralTerm(nameValue, nameValue.name, _makeSpan(start));
        }

        // Yes, process the color as an RGB value.
        var rgbColor =
            TokenKind.decimalToHex(TokenKind.colorValue(colorEntry), 6);
        return _parseHex(rgbColor, _makeSpan(start));
      case TokenKind.UNICODE_RANGE:
        var first;
        var second;
        var firstNumber;
        var secondNumber;
        _eat(TokenKind.UNICODE_RANGE, unicodeRange: true);
        if (_maybeEat(TokenKind.HEX_INTEGER, unicodeRange: true)) {
          first = _previousToken.text;
          firstNumber = int.parse('0x$first');
          if (firstNumber > MAX_UNICODE) {
            _error("unicode range must be less than 10FFFF", _makeSpan(start));
          }
          if (_maybeEat(TokenKind.MINUS, unicodeRange: true)) {
            if (_maybeEat(TokenKind.HEX_INTEGER, unicodeRange: true)) {
              second = _previousToken.text;
              secondNumber = int.parse('0x$second');
              if (secondNumber > MAX_UNICODE) {
                _error(
                    "unicode range must be less than 10FFFF", _makeSpan(start));
              }
              if (firstNumber > secondNumber) {
                _error("unicode first range can not be greater than last",
                    _makeSpan(start));
              }
            }
          }
        } else if (_maybeEat(TokenKind.HEX_RANGE, unicodeRange: true)) {
          first = _previousToken.text;
        }

        return new UnicodeRangeTerm(first, second, _makeSpan(start));
      case TokenKind.AT:
        if (messages.options.lessSupport) {
          _next();

          var expr = processExpr();
          if (isChecked && expr.expressions.length > 1) {
            _error("only @name for Less syntax", _peekToken.span);
          }

          var param = expr.expressions[0];
          var varUsage =
              new VarUsage((param as LiteralTerm).text, [], _makeSpan(start));
          expr.expressions[0] = varUsage;
          return expr.expressions;
        }
        break;
    }

    return processDimension(t, value, _makeSpan(start));
  }

  /** Process all dimension units. */
  LiteralTerm processDimension(Token t, var value, SourceSpan span) {
    LiteralTerm term;
    var unitType = this._peek();

    switch (unitType) {
      case TokenKind.UNIT_EM:
        term = new EmTerm(value, t.text, span);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_EX:
        term = new ExTerm(value, t.text, span);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_LENGTH_PX:
      case TokenKind.UNIT_LENGTH_CM:
      case TokenKind.UNIT_LENGTH_MM:
      case TokenKind.UNIT_LENGTH_IN:
      case TokenKind.UNIT_LENGTH_PT:
      case TokenKind.UNIT_LENGTH_PC:
        term = new LengthTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_ANGLE_DEG:
      case TokenKind.UNIT_ANGLE_RAD:
      case TokenKind.UNIT_ANGLE_GRAD:
      case TokenKind.UNIT_ANGLE_TURN:
        term = new AngleTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_TIME_MS:
      case TokenKind.UNIT_TIME_S:
        term = new TimeTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_FREQ_HZ:
      case TokenKind.UNIT_FREQ_KHZ:
        term = new FreqTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      case TokenKind.PERCENT:
        term = new PercentageTerm(value, t.text, span);
        _next(); // Skip the %
        break;
      case TokenKind.UNIT_FRACTION:
        term = new FractionTerm(value, t.text, span);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_RESOLUTION_DPI:
      case TokenKind.UNIT_RESOLUTION_DPCM:
      case TokenKind.UNIT_RESOLUTION_DPPX:
        term = new ResolutionTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_CH:
        term = new ChTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_REM:
        term = new RemTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      case TokenKind.UNIT_VIEWPORT_VW:
      case TokenKind.UNIT_VIEWPORT_VH:
      case TokenKind.UNIT_VIEWPORT_VMIN:
      case TokenKind.UNIT_VIEWPORT_VMAX:
        term = new ViewportTerm(value, t.text, span, unitType);
        _next(); // Skip the unit
        break;
      default:
        if (value != null && t != null) {
          term = (value is Identifier)
              ? new LiteralTerm(value, value.name, span)
              : new NumberTerm(value, t.text, span);
        }
        break;
    }

    return term;
  }

  String processQuotedString([bool urlString = false]) {
    var start = _peekToken.span;

    // URI term sucks up everything inside of quotes(' or ") or between parens
    var stopToken = urlString ? TokenKind.RPAREN : -1;

    // Note: disable skipping whitespace tokens inside a string.
    // TODO(jmesserly): the layering here feels wrong.
    var inString = tokenizer._inString;
    tokenizer._inString = false;

    switch (_peek()) {
      case TokenKind.SINGLE_QUOTE:
        stopToken = TokenKind.SINGLE_QUOTE;
        _next(); // Skip the SINGLE_QUOTE.
        start = _peekToken.span;
        break;
      case TokenKind.DOUBLE_QUOTE:
        stopToken = TokenKind.DOUBLE_QUOTE;
        _next(); // Skip the DOUBLE_QUOTE.
        start = _peekToken.span;
        break;
      default:
        if (urlString) {
          if (_peek() == TokenKind.LPAREN) {
            _next(); // Skip the LPAREN.
            start = _peekToken.span;
          }
          stopToken = TokenKind.RPAREN;
        } else {
          _error('unexpected string', _makeSpan(start));
        }
        break;
    }

    // Gobble up everything until we hit our stop token.
    var stringValue = new StringBuffer();
    while (_peek() != stopToken && _peek() != TokenKind.END_OF_FILE) {
      stringValue.write(_next().text);
    }

    tokenizer._inString = inString;

    // All characters between quotes is the string.
    if (stopToken != TokenKind.RPAREN) {
      _next(); // Skip the SINGLE_QUOTE or DOUBLE_QUOTE;
    }

    return stringValue.toString();
  }

  // TODO(terry): Should probably understand IE's non-standard filter syntax to
  //              fully support calc, var(), etc.
  /**
   * IE's filter property breaks CSS value parsing.  IE's format can be:
   *
   *    filter: progid:DXImageTransform.MS.gradient(Type=0, Color='#9d8b83');
   *
   * We'll just parse everything after the 'progid:' look for the left paren
   * then parse to the right paren ignoring everything in between.
   */
  processIEFilter(FileSpan startAfterProgidColon) {
    // Support non-functional filters (i.e. filter: FlipH)
    var kind = _peek();
    if (kind == TokenKind.SEMICOLON || kind == TokenKind.RBRACE) {
      var tok = tokenizer.makeIEFilter(
          startAfterProgidColon.start.offset, _peekToken.start);
      return new LiteralTerm(tok.text, tok.text, tok.span);
    }

    var parens = 0;
    while (_peek() != TokenKind.END_OF_FILE) {
      switch (_peek()) {
        case TokenKind.LPAREN:
          _eat(TokenKind.LPAREN);
          parens++;
          break;
        case TokenKind.RPAREN:
          _eat(TokenKind.RPAREN);
          if (--parens == 0) {
            var tok = tokenizer.makeIEFilter(
                startAfterProgidColon.start.offset, _peekToken.start);
            return new LiteralTerm(tok.text, tok.text, tok.span);
          }
          break;
        default:
          _eat(_peek());
      }
    }
  }

  //  TODO(terry): Hack to gobble up the calc expression as a string looking
  //               for the matching RPAREN the expression is not parsed into the
  //               AST.
  //
  //  grammar should be:
  //
  //    <calc()> = calc( <calc-sum> )
  //    <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
  //    <calc-product> = <calc-value> [ '*' <calc-value> | '/' <number> ]*
  //    <calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )
  //
  String processCalcExpression() {
    var inString = tokenizer._inString;
    tokenizer._inString = false;

    // Gobble up everything until we hit our stop token.
    var stringValue = new StringBuffer();
    var left = 1;
    var matchingParens = false;
    while (_peek() != TokenKind.END_OF_FILE && !matchingParens) {
      var token = _peek();
      if (token == TokenKind.LPAREN)
        left++;
      else if (token == TokenKind.RPAREN) left--;

      matchingParens = left == 0;
      if (!matchingParens) stringValue.write(_next().text);
    }

    if (!matchingParens) {
      _error("problem parsing function expected ), ", _peekToken.span);
    }

    tokenizer._inString = inString;

    return stringValue.toString();
  }

  CalcTerm processCalc(Identifier func) {
    var start = _peekToken.span;

    var name = func.name;
    if (name == 'calc') {
      // TODO(terry): Implement expression parsing properly.
      String expression = processCalcExpression();
      var calcExpr = new LiteralTerm(expression, expression, _makeSpan(start));

      if (!_maybeEat(TokenKind.RPAREN)) {
        _error("problem parsing function expected ), ", _peekToken.span);
      }

      return new CalcTerm(name, name, calcExpr, _makeSpan(start));
    }

    return null;
  }

  //  Function grammar:
  //
  //  function:     IDENT '(' expr ')'
  //
  processFunction(Identifier func) {
    var start = _peekToken.span;
    var name = func.name;

    switch (name) {
      case 'url':
        // URI term sucks up everything inside of quotes(' or ") or between parens
        var urlParam = processQuotedString(true);

        // TODO(terry): Better error message and checking for mismatched quotes.
        if (_peek() == TokenKind.END_OF_FILE) {
          _error("problem parsing URI", _peekToken.span);
        }

        if (_peek() == TokenKind.RPAREN) {
          _next();
        }

        return new UriTerm(urlParam, _makeSpan(start));
      case 'var':
        // TODO(terry): Consider handling var in IE specific filter/progid.  This
        //              will require parsing entire IE specific syntax e.g.,
        //              param = value or progid:com_id, etc. for example:
        //
        //    var-blur: Blur(Add = 0, Direction = 225, Strength = 10);
        //    var-gradient: progid:DXImageTransform.Microsoft.gradient"
        //      (GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
        var expr = processExpr();
        if (!_maybeEat(TokenKind.RPAREN)) {
          _error("problem parsing var expected ), ", _peekToken.span);
        }
        if (isChecked &&
            expr.expressions.where((e) => e is OperatorComma).length > 1) {
          _error("too many parameters to var()", _peekToken.span);
        }

        var paramName = (expr.expressions[0] as LiteralTerm).text;

        // [0] - var name, [1] - OperatorComma, [2] - default value.
        var defaultValues = expr.expressions.length >= 3
            ? expr.expressions.sublist(2)
            : <Expression>[];
        return new VarUsage(paramName, defaultValues, _makeSpan(start));
      default:
        var expr = processExpr();
        if (!_maybeEat(TokenKind.RPAREN)) {
          _error("problem parsing function expected ), ", _peekToken.span);
        }

        return new FunctionTerm(name, name, expr, _makeSpan(start));
    }
  }

  Identifier identifier() {
    var tok = _next();

    if (!TokenKind.isIdentifier(tok.kind) &&
        !TokenKind.isKindIdentifier(tok.kind)) {
      if (isChecked) {
        _warning('expected identifier, but found $tok', tok.span);
      }
      return new Identifier("", _makeSpan(tok.span));
    }

    return new Identifier(tok.text, _makeSpan(tok.span));
  }

  // TODO(terry): Move this to base <= 36 and into shared code.
  static int _hexDigit(int c) {
    if (c >= 48 /*0*/ && c <= 57 /*9*/) {
      return c - 48;
    } else if (c >= 97 /*a*/ && c <= 102 /*f*/) {
      return c - 87;
    } else if (c >= 65 /*A*/ && c <= 70 /*F*/) {
      return c - 55;
    } else {
      return -1;
    }
  }

  HexColorTerm _parseHex(String hexText, SourceSpan span) {
    var hexValue = 0;

    for (var i = 0; i < hexText.length; i++) {
      var digit = _hexDigit(hexText.codeUnitAt(i));
      if (digit < 0) {
        _warning('Bad hex number', span);
        return new HexColorTerm(new BAD_HEX_VALUE(), hexText, span);
      }
      hexValue = (hexValue << 4) + digit;
    }

    // Make 3 character hex value #RRGGBB => #RGB iff:
    // high/low nibble of RR is the same, high/low nibble of GG is the same and
    // high/low nibble of BB is the same.
    if (hexText.length == 6 &&
        hexText[0] == hexText[1] &&
        hexText[2] == hexText[3] &&
        hexText[4] == hexText[5]) {
      hexText = '${hexText[0]}${hexText[2]}${hexText[4]}';
    } else if (hexText.length == 4 &&
        hexText[0] == hexText[1] &&
        hexText[2] == hexText[3]) {
      hexText = '${hexText[0]}${hexText[2]}';
    } else if (hexText.length == 2 && hexText[0] == hexText[1]) {
      hexText = '${hexText[0]}';
    }
    return new HexColorTerm(hexValue, hexText, span);
  }
}

class ExpressionsProcessor {
  final Expressions _exprs;
  int _index = 0;

  ExpressionsProcessor(this._exprs);

  // TODO(terry): Only handles ##px unit.
  FontExpression processFontSize() {
    /* font-size[/line-height]
     *
     * Possible size values:
     *   xx-small
     *   small
     *   medium [default]
     *   large
     *   x-large
     *   xx-large
     *   smaller
     *   larger
     *   ##length in px, pt, etc.
     *   ##%, percent of parent elem's font-size
     *   inherit
     */
    LengthTerm size;
    LineHeight lineHt;
    var nextIsLineHeight = false;
    for (; _index < _exprs.expressions.length; _index++) {
      var expr = _exprs.expressions[_index];
      if (size == null && expr is LengthTerm) {
        // font-size part.
        size = expr;
      } else if (size != null) {
        if (expr is OperatorSlash) {
          // LineHeight could follow?
          nextIsLineHeight = true;
        } else if (nextIsLineHeight && expr is LengthTerm) {
          assert(expr.unit == TokenKind.UNIT_LENGTH_PX);
          lineHt = new LineHeight(expr.value, inPixels: true);
          nextIsLineHeight = false;
          _index++;
          break;
        } else {
          break;
        }
      } else {
        break;
      }
    }

    return new FontExpression(_exprs.span, size: size, lineHeight: lineHt);
  }

  FontExpression processFontFamily() {
    var family = <String>[];

    /* Possible family values:
     * font-family: arial, Times new roman ,Lucida Sans Unicode,Courier;
     * font-family: "Times New Roman", arial, Lucida Sans Unicode, Courier;
     */
    var moreFamilies = false;

    for (; _index < _exprs.expressions.length; _index++) {
      Expression expr = _exprs.expressions[_index];
      if (expr is LiteralTerm) {
        if (family.length == 0 || moreFamilies) {
          // It's font-family now.
          family.add(expr.toString());
          moreFamilies = false;
        } else if (isChecked) {
          messages.warning('Only font-family can be a list', _exprs.span);
        }
      } else if (expr is OperatorComma && family.length > 0) {
        moreFamilies = true;
      } else {
        break;
      }
    }

    return new FontExpression(_exprs.span, family: family);
  }

  FontExpression processFont() {
    // Process all parts of the font expression.
    FontExpression fontSize;
    FontExpression fontFamily;
    for (; _index < _exprs.expressions.length; _index++) {
      // Order is font-size font-family
      if (fontSize == null) {
        fontSize = processFontSize();
      }
      if (fontFamily == null) {
        fontFamily = processFontFamily();
      }
      //TODO(terry): Handle font-weight, font-style, and font-variant. See
      //               https://github.com/dart-lang/csslib/issues/3
      //               https://github.com/dart-lang/csslib/issues/4
      //               https://github.com/dart-lang/csslib/issues/5
    }

    return new FontExpression(_exprs.span,
        size: fontSize.font.size,
        lineHeight: fontSize.font.lineHeight,
        family: fontFamily.font.family);
  }
}

/**
 * Escapes [text] for use in a CSS string.
 * [single] specifies single quote `'` vs double quote `"`.
 */
String _escapeString(String text, {bool single: false}) {
  StringBuffer result = null;

  for (int i = 0; i < text.length; i++) {
    var code = text.codeUnitAt(i);
    String replace = null;
    switch (code) {
      case 34 /*'"'*/ :
        if (!single) replace = r'\"';
        break;
      case 39 /*"'"*/ :
        if (single) replace = r"\'";
        break;
    }

    if (replace != null && result == null) {
      result = new StringBuffer(text.substring(0, i));
    }

    if (result != null) result.write(replace != null ? replace : text[i]);
  }

  return result == null ? text : result.toString();
}
