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 { class ScopeMatcher extends Matcher {
protected array $segments; protected array $segments;
public function __construct(SegmentMatcher|TrueMatcher ...$matchers) { public function __construct(string ...$segments) {
$this->segments = $matchers; $this->segments = $segments;
} }
public function matches(string $scope): bool { public function matches(string $scope): bool {
$lastDotIndex = 0; $scopeSegments = explode('.', $scope);
$nextDotIndex = 0;
$scopeLen = strlen($scope);
for ($i = 0, $len = count($this->segments); $i < $len; $i++) {
$matcherSegment = $this->segments[$i];
if ($lastDotIndex > $scopeLen) {
break;
}
$nextDotIndex = strpos($scope, '.', $lastDotIndex); if (count($this->segments) !== count($scopeSegments)) {
if ($nextDotIndex === false) { return false;
$nextDotIndex = $scopeLen; }
foreach ($this->segments as $index => $segment) {
if ($segment === '*') {
continue;
} }
$scopeSegment = substr($scope, $lastDotIndex, $nextDotIndex - $lastDotIndex); if ($segment !== $scopeSegments[$index]) {
if (!$matcherSegment->matches($scopeSegment)) {
return false; return false;
} }
$lastDotIndex = $nextDotIndex + 1;
} }
return ($i === count($this->segments)); return true;
} }
public function getPrefix(string $scope): string|null|false { public function getPrefix(string $scope) {
$scopeSegments = explode('.', $scope); return null;
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;
}
}
}
} }
} }

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 { public static function parse(string $selector): Matcher|false {
self::$instance = new self($selector); self::$instance = new self($selector);
return self::parseSelector();
$errorReporting = false;
if ((error_reporting() & \E_USER_ERROR)) {
$errorReporting = true;
ParseError::setHandler();
}
$result = self::parseSelector();
if ($errorReporting) {
ParseError::clearHandler();
}
return $result;
} }
@ -100,7 +87,7 @@ class Parser {
$result = self::parsePath($prefix); $result = self::parsePath($prefix);
} else { } else {
// TODO: Take the effort to make this more descriptive // TODO: Take the effort to make this more descriptive
self::error([ 'Group', 'Path' ], $peek); self::throw([ 'Group', 'Path' ], $peek);
} }
if (self::$debug) { if (self::$debug) {
@ -118,7 +105,7 @@ class Parser {
$result = self::parseSelector(); $result = self::parseSelector();
$token = self::$instance->data->consume(); $token = self::$instance->data->consume();
if ($token !== ')') { if ($token !== ')') {
self::error('")"', $token); self::throw('")"', $token);
} }
$result = ($prefix === null) ? $result : new GroupMatcher($prefix, $result); $result = ($prefix === null) ? $result : new GroupMatcher($prefix, $result);
@ -185,13 +172,13 @@ class Parser {
$token = self::$instance->data->consume(); $token = self::$instance->data->consume();
if ($token === false || !preg_match('/^(?:[A-Za-z0-9-_]+|\*)(?:\.(?:[A-Za-z0-9-+_]+|\*))*$/S', $token)) { if ($token === false || !preg_match('/^(?:[A-Za-z0-9-_]+|\*)(?:\.(?:[A-Za-z0-9-+_]+|\*))*$/S', $token)) {
// TODO: Take the effort to make this more descriptive // TODO: Take the effort to make this more descriptive
self::error('valid scope syntax', $token); self::throw('valid scope syntax', $token);
} }
$segments = explode('.', $token); $segments = explode('.', $token);
foreach ($segments as $index => $segment) { /*foreach ($segments as $index => $segment) {
$segments[$index] = ($segment !== '*') ? new SegmentMatcher($segment) : new TrueMatcher(); $segments[$index] = ($segment !== '*') ? new SegmentMatcher($segment) : new TrueMatcher();
} }*/
$result = new ScopeMatcher(...$segments); $result = new ScopeMatcher(...$segments);
@ -231,10 +218,11 @@ class Parser {
protected static function debugResult($result) { protected static function debugResult($result) {
printf("%s Result: %s\n", printf("%s Result: %s\n",
debug_backtrace()[1]['function'], 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) { protected static function throw(array|string $expected, string|bool $found) {
ParseError::trigger($expected, $found, self::$instance->data->offset()); throw new Exception($expected, $found, self::$instance->data->offset());
} }
} }

Loading…
Cancel
Save