protected function selectorSingle(&$out)
{
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
$parts = [];
if ($this->literal('*', false)) {
$parts[] = '*';
}
for (;;) {
// see if we can stop early
if ($this->match('\\s*[{,]', $m)) {
$this->count--;
break;
}
$s = $this->seek();
// self
if ($this->literal('&', false)) {
$parts[] = Compiler::$selfSelector;
continue;
}
if ($this->literal('.', false)) {
$parts[] = '.';
continue;
}
if ($this->literal('|', false)) {
$parts[] = '|';
continue;
}
if ($this->match('\\\\\\S', $m)) {
$parts[] = $m[0];
continue;
}
// for keyframes
if ($this->unit($unit)) {
$parts[] = $unit;
continue;
}
if ($this->keyword($name)) {
$parts[] = $name;
continue;
}
if ($this->interpolation($inter)) {
$parts[] = $inter;
continue;
}
if ($this->literal('%', false) && $this->placeholder($placeholder)) {
$parts[] = '%';
$parts[] = $placeholder;
continue;
}
if ($this->literal('#', false)) {
$parts[] = '#';
continue;
}
// a pseudo selector
if ($this->match('::?', $m) && $this->mixedKeyword($nameParts)) {
$parts[] = $m[0];
foreach ($nameParts as $sub) {
$parts[] = $sub;
}
$ss = $this->seek();
if ($this->literal('(') && ($this->openString(')', $str, '(') || true) && $this->literal(')')) {
$parts[] = '(';
if (!empty($str)) {
$parts[] = $str;
}
$parts[] = ')';
} else {
$this->seek($ss);
}
continue;
}
$this->seek($s);
// attribute selector
if ($this->literal('[') && ($this->openString(']', $str, '[') || true) && $this->literal(']')) {
$parts[] = '[';
if (!empty($str)) {
$parts[] = $str;
}
$parts[] = ']';
continue;
}
$this->seek($s);
break;
}
$this->eatWhiteDefault = $oldWhite;
if (count($parts) === 0) {
return false;
}
$out = $parts;
return true;
}