You are here

private function Parser::parseSimpleSelector in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 vendor/symfony/css-selector/Parser/Parser.php \Symfony\Component\CssSelector\Parser\Parser::parseSimpleSelector()

Parses next simple node (hash, class, pseudo, negation).

Parameters

TokenStream $stream:

bool $insideNegation:

Return value

array

Throws

SyntaxErrorException

1 call to Parser::parseSimpleSelector()
Parser::parserSelectorNode in vendor/symfony/css-selector/Parser/Parser.php
Parses next selector or combined node.

File

vendor/symfony/css-selector/Parser/Parser.php, line 178

Class

Parser
CSS selector parser.

Namespace

Symfony\Component\CssSelector\Parser

Code

private function parseSimpleSelector(TokenStream $stream, $insideNegation = false) {
  $stream
    ->skipWhitespace();
  $selectorStart = count($stream
    ->getUsed());
  $result = $this
    ->parseElementNode($stream);
  $pseudoElement = null;
  while (true) {
    $peek = $stream
      ->getPeek();
    if ($peek
      ->isWhitespace() || $peek
      ->isFileEnd() || $peek
      ->isDelimiter(array(
      ',',
      '+',
      '>',
      '~',
    )) || $insideNegation && $peek
      ->isDelimiter(array(
      ')',
    ))) {
      break;
    }
    if (null !== $pseudoElement) {
      throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector');
    }
    if ($peek
      ->isHash()) {
      $result = new Node\HashNode($result, $stream
        ->getNext()
        ->getValue());
    }
    elseif ($peek
      ->isDelimiter(array(
      '.',
    ))) {
      $stream
        ->getNext();
      $result = new Node\ClassNode($result, $stream
        ->getNextIdentifier());
    }
    elseif ($peek
      ->isDelimiter(array(
      '[',
    ))) {
      $stream
        ->getNext();
      $result = $this
        ->parseAttributeNode($result, $stream);
    }
    elseif ($peek
      ->isDelimiter(array(
      ':',
    ))) {
      $stream
        ->getNext();
      if ($stream
        ->getPeek()
        ->isDelimiter(array(
        ':',
      ))) {
        $stream
          ->getNext();
        $pseudoElement = $stream
          ->getNextIdentifier();
        continue;
      }
      $identifier = $stream
        ->getNextIdentifier();
      if (in_array(strtolower($identifier), array(
        'first-line',
        'first-letter',
        'before',
        'after',
      ))) {

        // Special case: CSS 2.1 pseudo-elements can have a single ':'.
        // Any new pseudo-element must have two.
        $pseudoElement = $identifier;
        continue;
      }
      if (!$stream
        ->getPeek()
        ->isDelimiter(array(
        '(',
      ))) {
        $result = new Node\PseudoNode($result, $identifier);
        continue;
      }
      $stream
        ->getNext();
      $stream
        ->skipWhitespace();
      if ('not' === strtolower($identifier)) {
        if ($insideNegation) {
          throw SyntaxErrorException::nestedNot();
        }
        list($argument, $argumentPseudoElement) = $this
          ->parseSimpleSelector($stream, true);
        $next = $stream
          ->getNext();
        if (null !== $argumentPseudoElement) {
          throw SyntaxErrorException::pseudoElementFound($argumentPseudoElement, 'inside ::not()');
        }
        if (!$next
          ->isDelimiter(array(
          ')',
        ))) {
          throw SyntaxErrorException::unexpectedToken('")"', $next);
        }
        $result = new Node\NegationNode($result, $argument);
      }
      else {
        $arguments = array();
        $next = null;
        while (true) {
          $stream
            ->skipWhitespace();
          $next = $stream
            ->getNext();
          if ($next
            ->isIdentifier() || $next
            ->isString() || $next
            ->isNumber() || $next
            ->isDelimiter(array(
            '+',
            '-',
          ))) {
            $arguments[] = $next;
          }
          elseif ($next
            ->isDelimiter(array(
            ')',
          ))) {
            break;
          }
          else {
            throw SyntaxErrorException::unexpectedToken('an argument', $next);
          }
        }
        if (empty($arguments)) {
          throw SyntaxErrorException::unexpectedToken('at least one argument', $next);
        }
        $result = new Node\FunctionNode($result, $identifier, $arguments);
      }
    }
    else {
      throw SyntaxErrorException::unexpectedToken('selector', $peek);
    }
  }
  if (count($stream
    ->getUsed()) === $selectorStart) {
    throw SyntaxErrorException::unexpectedToken('selector', $stream
      ->getPeek());
  }
  return array(
    $result,
    $pseudoElement,
  );
}