diff --git a/lib/Scope/Exception.php b/lib/Scope/Exception.php new file mode 100644 index 0000000..ad55331 --- /dev/null +++ b/lib/Scope/Exception.php @@ -0,0 +1,36 @@ + 2) { + $last = array_pop($expected); + $expected = implode(', ', $expected) . ', or ' . $last; + } else { + $expected = implode(' or ', $expected); + } + } + } + + $found = ($found !== false) ? "\"$found\"" : 'end of input'; + parent::__construct(sprintf(self::MESSAGE, $expected, $found, $offset), 2112); + } +} \ No newline at end of file diff --git a/lib/Scope/Matchers/ScopeMatcher.php b/lib/Scope/Matchers/ScopeMatcher.php index bfdb7ad..fe08f8b 100644 --- a/lib/Scope/Matchers/ScopeMatcher.php +++ b/lib/Scope/Matchers/ScopeMatcher.php @@ -9,49 +9,31 @@ namespace dW\Highlighter\Scope; class ScopeMatcher extends Matcher { protected array $segments; - public function __construct(SegmentMatcher|TrueMatcher ...$matchers) { - $this->segments = $matchers; + public function __construct(string ...$segments) { + $this->segments = $segments; } public function matches(string $scope): bool { - $lastDotIndex = 0; - $nextDotIndex = 0; - $scopeLen = strlen($scope); - - for ($i = 0, $len = count($this->segments); $i < $len; $i++) { - $matcherSegment = $this->segments[$i]; - if ($lastDotIndex > $scopeLen) { - break; - } + $scopeSegments = explode('.', $scope); - $nextDotIndex = strpos($scope, '.', $lastDotIndex); - if ($nextDotIndex === false) { - $nextDotIndex = $scopeLen; + if (count($this->segments) !== count($scopeSegments)) { + return false; + } + + foreach ($this->segments as $index => $segment) { + if ($segment === '*') { + continue; } - $scopeSegment = substr($scope, $lastDotIndex, $nextDotIndex - $lastDotIndex); - if (!$matcherSegment->matches($scopeSegment)) { + if ($segment !== $scopeSegments[$index]) { return false; } - - $lastDotIndex = $nextDotIndex + 1; } - return ($i === count($this->segments)); + return true; } - public function getPrefix(string $scope): string|null|false { - $scopeSegments = explode('.', $scope); - if (count($scopeSegments) < count($this->segments)) { - return false; - } - - foreach ($this->segments as $index => $segment) { - if ($segment->matches($scopeSegments[$index])) { - if ($segment->prefix !== null) { - return $segment->prefix; - } - } - } + public function getPrefix(string $scope) { + return null; } } diff --git a/lib/Scope/Matchers/SegmentMatcher.php b/lib/Scope/Matchers/SegmentMatcher.php deleted file mode 100644 index cf32a32..0000000 --- a/lib/Scope/Matchers/SegmentMatcher.php +++ /dev/null @@ -1,23 +0,0 @@ -segment = $segment; - } - - public function matches(string $scope): bool { - return ($scope === $this->segment); - } - - public function getPrefix(string $scope): string|null|false { - return null; - } -} diff --git a/lib/Scope/Matchers/TrueMatcher.php b/lib/Scope/Matchers/TrueMatcher.php deleted file mode 100644 index e5228d3..0000000 --- a/lib/Scope/Matchers/TrueMatcher.php +++ /dev/null @@ -1,23 +0,0 @@ -scopeName = $scopeName; - } - - public function matches(string $scope): bool { - return true; - } - - public function getPrefix(string $scope): string|null|false { - return null; - } -} diff --git a/lib/Scope/Parser.php b/lib/Scope/Parser.php index b5ba6f7..6d32a1c 100644 --- a/lib/Scope/Parser.php +++ b/lib/Scope/Parser.php @@ -17,20 +17,7 @@ class Parser { public static function parse(string $selector): Matcher|false { self::$instance = new self($selector); - - $errorReporting = false; - if ((error_reporting() & \E_USER_ERROR)) { - $errorReporting = true; - ParseError::setHandler(); - } - - $result = self::parseSelector(); - - if ($errorReporting) { - ParseError::clearHandler(); - } - - return $result; + return self::parseSelector(); } @@ -100,7 +87,7 @@ class Parser { $result = self::parsePath($prefix); } else { // TODO: Take the effort to make this more descriptive - self::error([ 'Group', 'Path' ], $peek); + self::throw([ 'Group', 'Path' ], $peek); } if (self::$debug) { @@ -118,7 +105,7 @@ class Parser { $result = self::parseSelector(); $token = self::$instance->data->consume(); if ($token !== ')') { - self::error('")"', $token); + self::throw('")"', $token); } $result = ($prefix === null) ? $result : new GroupMatcher($prefix, $result); @@ -185,13 +172,13 @@ class Parser { $token = self::$instance->data->consume(); if ($token === false || !preg_match('/^(?:[A-Za-z0-9-_]+|\*)(?:\.(?:[A-Za-z0-9-+_]+|\*))*$/S', $token)) { // TODO: Take the effort to make this more descriptive - self::error('valid scope syntax', $token); + self::throw('valid scope syntax', $token); } $segments = explode('.', $token); - foreach ($segments as $index => $segment) { + /*foreach ($segments as $index => $segment) { $segments[$index] = ($segment !== '*') ? new SegmentMatcher($segment) : new TrueMatcher(); - } + }*/ $result = new ScopeMatcher(...$segments); @@ -231,10 +218,11 @@ class Parser { protected static function debugResult($result) { printf("%s Result: %s\n", debug_backtrace()[1]['function'], - str_replace([ '::__set_state(array', __NAMESPACE__ ], '', var_export($result, true))); + // Removes bullshit from printed classes for easier reading + str_replace([ '::__set_state(array', __NAMESPACE__, '))' ], [ '', '', ')' ], var_export($result, true))); } - protected static function error(array|string $expected, string|bool $found) { - ParseError::trigger($expected, $found, self::$instance->data->offset()); + protected static function throw(array|string $expected, string|bool $found) { + throw new Exception($expected, $found, self::$instance->data->offset()); } }