| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- <?php
- namespace Gt\CssXPath;
- class SelectorListSplitter {
- /** @return array<int, string> */
- public function split(string $selectorList):array {
- $selectorList = trim($selectorList);
- if($selectorList === "") {
- return [];
- }
- $parts = [];
- $current = "";
- $quote = null;
- $bracketDepth = 0;
- $parenDepth = 0;
- $length = strlen($selectorList);
- for($i = 0; $i < $length; $i++) {
- $char = $selectorList[$i];
- if($this->handleQuotedState($char, $current, $quote)) {
- continue;
- }
- if($this->openQuoteIfNeeded($char, $current, $quote)) {
- continue;
- }
- $this->trackDepth($char, $bracketDepth, $parenDepth);
- if($this->isTopLevelComma($char, $bracketDepth, $parenDepth)) {
- $this->appendCurrentPart($parts, $current);
- $current = "";
- continue;
- }
- $current .= $char;
- }
- $this->appendCurrentPart($parts, $current);
- return $parts;
- }
- private function handleQuotedState(
- string $char,
- string &$current,
- ?string &$quote
- ):bool {
- if($quote === null) {
- return false;
- }
- $current .= $char;
- if($char === $quote) {
- $quote = null;
- }
- return true;
- }
- private function openQuoteIfNeeded(
- string $char,
- string &$current,
- ?string &$quote
- ):bool {
- if($char !== "'" && $char !== '"') {
- return false;
- }
- $quote = $char;
- $current .= $char;
- return true;
- }
- private function trackDepth(
- string $char,
- int &$bracketDepth,
- int &$parenDepth
- ):void {
- match($char) {
- "[" => $bracketDepth++,
- "]" => $bracketDepth = max(0, $bracketDepth - 1),
- "(" => $parenDepth++,
- ")" => $parenDepth = max(0, $parenDepth - 1),
- default => null,
- };
- }
- private function isTopLevelComma(
- string $char,
- int $bracketDepth,
- int $parenDepth
- ):bool {
- return $char === ","
- && $bracketDepth === 0
- && $parenDepth === 0;
- }
- /** @param array<int, string> $parts */
- private function appendCurrentPart(array &$parts, string $current):void {
- $trimmed = trim($current);
- if($trimmed !== "") {
- $parts[] = $trimmed;
- }
- }
- }
|