Browse Source

Removed Segment and True scope matchers, reverted to throwing exceptions

main
Dustin Wilson 3 years ago
parent
commit
93ea83aedd
  1. 36
      lib/Scope/Exception.php
  2. 46
      lib/Scope/Matchers/ScopeMatcher.php
  3. 23
      lib/Scope/Matchers/SegmentMatcher.php
  4. 23
      lib/Scope/Matchers/TrueMatcher.php
  5. 32
      lib/Scope/Parser.php

36
lib/Scope/Exception.php

@ -0,0 +1,36 @@
<?php
/** @license MIT
* Copyright 2021 Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace dW\Highlighter\Scope;
class Exception extends \Exception {
const MESSAGE = '%s expected; found %s at offset %s';
public function __construct(array|string $expected, string|bool $found, int $offset) {
if (!is_string($expected)) {
$expectedLen = count($expected);
if ($expectedLen === 1) {
$expected = ($expected[0] !== false) ? $expected[0] : 'end of input';
} else {
$temp = [];
for ($i = 0; $i < $strlen; $i++) {
$temp[] = ($expected[$i] !== false) ? "{$expected[$i]}" : 'end of input';
}
$expected = $temp;
if ($expectedLen > 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);
}
}

46
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;
}
}

23
lib/Scope/Matchers/SegmentMatcher.php

@ -1,23 +0,0 @@
<?php
/** @license MIT
* Copyright 2021 Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace dW\Highlighter\Scope;
class SegmentMatcher extends Matcher {
protected string $segment;
public function __construct(string $segment) {
$this->segment = $segment;
}
public function matches(string $scope): bool {
return ($scope === $this->segment);
}
public function getPrefix(string $scope): string|null|false {
return null;
}
}

23
lib/Scope/Matchers/TrueMatcher.php

@ -1,23 +0,0 @@
<?php
/** @license MIT
* Copyright 2021 Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace dW\Highlighter\Scope;
class TrueMatcher extends Matcher {
protected string $scopeName;
public function __construct(string $scopeName) {
$this->scopeName = $scopeName;
}
public function matches(string $scope): bool {
return true;
}
public function getPrefix(string $scope): string|null|false {
return null;
}
}

32
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());
}
}

Loading…
Cancel
Save