SimpleSelector? processPseudoSelector()

in lib/parser.dart [1526:1602]


  SimpleSelector? 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.
    Identifier pseudoName;
    if (_peekIdentifier()) {
      pseudoName = identifier();
    } else {
      return null;
    }
    var name = pseudoName.name.toLowerCase();

    // Functional pseudo?
    if (_peekToken.kind == TokenKind.LPAREN) {
      if (!pseudoElement && name == 'not') {
        _eat(TokenKind.LPAREN);

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

        _eat(TokenKind.RPAREN);
        return NegationSelector(negArg, _makeSpan(start));
      } else if (!pseudoElement &&
          (name == 'host' ||
              name == 'host-context' ||
              name == 'global-context' ||
              name == '-acx-global-context')) {
        _eat(TokenKind.LPAREN);
        var selector = processCompoundSelector();
        if (selector == null) {
          _errorExpected('a selector argument');
          return null;
        }
        _eat(TokenKind.RPAREN);
        var span = _makeSpan(start);
        return 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) {
          _eat(TokenKind.RPAREN);
          return (pseudoElement)
              ? PseudoElementFunctionSelector(pseudoName, expr, span)
              : PseudoClassFunctionSelector(pseudoName, expr, span);
        } else {
          _errorExpected('CSS expression');
          return null;
        }
      }
    }

    // Treat CSS2.1 pseudo-elements defined with pseudo class syntax as pseudo-
    // elements for backwards compatibility.
    return pseudoElement || _legacyPseudoElements.contains(name)
        ? PseudoElementSelector(pseudoName, _makeSpan(start),
            isLegacy: !pseudoElement)
        : PseudoClassSelector(pseudoName, _makeSpan(start));
  }