Dustin Wilson
3 years ago
18 changed files with 382 additions and 281 deletions
@ -0,0 +1,28 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2021 Dustin Wilson et al. |
||||
|
* See LICENSE file for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace dW\Lit\Scope; |
||||
|
|
||||
|
class Composite extends Node { |
||||
|
protected array $expressions = []; |
||||
|
protected bool $frozen = false; |
||||
|
|
||||
|
|
||||
|
public function __construct(Selector $parent) { |
||||
|
$this->_parent = \WeakReference::create($parent); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function add(Expression ...$expressions): bool { |
||||
|
if ($this->frozen) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
$this->expressions = $expressions; |
||||
|
$this->frozen = true; |
||||
|
return true; |
||||
|
} |
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2021 Dustin Wilson et al. |
||||
|
* See LICENSE file for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace dW\Lit\Scope; |
||||
|
|
||||
|
class Expression extends Node { |
||||
|
protected Filter|Group|Path $_child; |
||||
|
protected bool $frozen = false; |
||||
|
protected bool $_negate = false; |
||||
|
protected ?string $_operator; |
||||
|
|
||||
|
|
||||
|
public function __construct(Composite $parent, ?string $operator = null) { |
||||
|
$this->_operator = $operator; |
||||
|
$this->_parent = \WeakReference::create($parent); |
||||
|
|
||||
|
if ($operator === '-') { |
||||
|
$this->negate = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function __set(string $name, $value) { |
||||
|
if ($name !== 'child') { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set undefined property $name in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
} |
||||
|
|
||||
|
if ($this->frozen) { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set readonly $name property in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$this->frozen = true; |
||||
|
$this->_child = $value; |
||||
|
} |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2021 Dustin Wilson et al. |
||||
|
* See LICENSE file for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace dW\Lit\Scope; |
||||
|
|
||||
|
class Filter extends Node { |
||||
|
protected Group|Path $_child; |
||||
|
protected bool $frozen = false; |
||||
|
protected string $_operator; |
||||
|
protected string $_side; |
||||
|
|
||||
|
|
||||
|
public function __construct(Selector $parent, string $side) { |
||||
|
$this->_parent = \WeakReference::create($parent); |
||||
|
$this->_side = $side; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function __set(string $name, $value) { |
||||
|
if ($name !== 'child') { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set undefined property $name in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
} |
||||
|
|
||||
|
if ($this->frozen) { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set readonly $name property in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$this->frozen = true; |
||||
|
$this->_child = $value; |
||||
|
} |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2021 Dustin Wilson et al. |
||||
|
* See LICENSE file for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace dW\Lit\Scope; |
||||
|
|
||||
|
class Group extends Node { |
||||
|
protected Selector $_child; |
||||
|
protected bool $frozen = false; |
||||
|
|
||||
|
|
||||
|
public function __construct(Expression $parent) { |
||||
|
$this->_parent = \WeakReference::create($parent); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function __set(string $name, $value) { |
||||
|
if ($name !== 'child') { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set undefined property $name in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
} |
||||
|
|
||||
|
if ($this->frozen) { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set readonly $name property in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$this->frozen = true; |
||||
|
$this->_child = $value; |
||||
|
} |
||||
|
} |
@ -1,37 +0,0 @@ |
|||||
<?php |
|
||||
/** @license MIT |
|
||||
* Copyright 2021 Dustin Wilson et al. |
|
||||
* See LICENSE file for details */ |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
namespace dW\Lit\Scope; |
|
||||
|
|
||||
class AndMatcher extends Matcher { |
|
||||
protected array $matchers = []; |
|
||||
|
|
||||
public function __construct(Matcher ...$matchers) { |
|
||||
$this->matchers = $matchers; |
|
||||
} |
|
||||
|
|
||||
public function add(Matcher $matcher) { |
|
||||
$this->matchers[] = $matcher; |
|
||||
} |
|
||||
|
|
||||
public function matches(string ...$scopes): bool { |
|
||||
foreach ($this->matchers as $m) { |
|
||||
if (!$m->matches(...$scopes)) { |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public function getPrefix(string ...$scopes): string|null|false { |
|
||||
if ($this->matches(...$scopes)) { |
|
||||
return $this->matches[0]->getPrefix(...$scopes); |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
} |
|
@ -1,27 +0,0 @@ |
|||||
<?php |
|
||||
/** @license MIT |
|
||||
* Copyright 2021 Dustin Wilson et al. |
|
||||
* See LICENSE file for details */ |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
namespace dW\Lit\Scope; |
|
||||
|
|
||||
class GroupMatcher extends Matcher { |
|
||||
protected ?string $prefix; |
|
||||
protected Matcher $selector; |
|
||||
|
|
||||
public function __construct(?string $prefix, Matcher $selector) { |
|
||||
$this->prefix = ($prefix !== null) ? $prefix[0] : null; |
|
||||
$this->selector = $selector; |
|
||||
} |
|
||||
|
|
||||
public function matches(string ...$scopes): bool { |
|
||||
return $this->selector->matches(...$scopes); |
|
||||
} |
|
||||
|
|
||||
public function getPrefix(string ...$scopes): string|null|false { |
|
||||
if ($this->selector->matches(...$scopes)) { |
|
||||
return $this->prefix; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
<?php |
|
||||
/** @license MIT |
|
||||
* Copyright 2021 Dustin Wilson et al. |
|
||||
* See LICENSE file for details */ |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
namespace dW\Lit\Scope; |
|
||||
|
|
||||
class NegateMatcher extends Matcher { |
|
||||
protected Matcher $matcher; |
|
||||
|
|
||||
public function __construct(Matcher $matcher) { |
|
||||
$this->matcher = $matcher; |
|
||||
} |
|
||||
|
|
||||
public function matches(string ...$scopes): bool { |
|
||||
return !($this->matcher->matches(...$scopes)); |
|
||||
} |
|
||||
|
|
||||
public function getPrefix(string ...$scopes) { |
|
||||
return null; |
|
||||
} |
|
||||
} |
|
@ -1,40 +0,0 @@ |
|||||
<?php |
|
||||
/** @license MIT |
|
||||
* Copyright 2021 Dustin Wilson et al. |
|
||||
* See LICENSE file for details */ |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
namespace dW\Lit\Scope; |
|
||||
|
|
||||
class OrMatcher extends Matcher { |
|
||||
protected array $matchers = []; |
|
||||
|
|
||||
public function __construct(Matcher ...$matchers) { |
|
||||
$this->matchers = $matchers; |
|
||||
} |
|
||||
|
|
||||
public function add(Matcher $matcher) { |
|
||||
$this->matchers[] = $matcher; |
|
||||
} |
|
||||
|
|
||||
public function matches(string ...$scopes): bool { |
|
||||
foreach ($this->matchers as $m) { |
|
||||
if ($m->matches(...$scopes)) { |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public function getPrefix(string ...$scopes): string|null|false { |
|
||||
foreach ($this->matchers as $m) { |
|
||||
$prefix = $m->getPrefix(...$scopes); |
|
||||
if ($prefix !== null) { |
|
||||
return $prefix; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
} |
|
@ -1,37 +0,0 @@ |
|||||
<?php |
|
||||
/** @license MIT |
|
||||
* Copyright 2021 Dustin Wilson et al. |
|
||||
* See LICENSE file for details */ |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
namespace dW\Lit\Scope; |
|
||||
|
|
||||
class PathMatcher extends Matcher { |
|
||||
protected ?string $prefix; |
|
||||
protected array $matchers; |
|
||||
|
|
||||
public function __construct(?string $prefix, ScopeMatcher ...$matchers) { |
|
||||
$this->prefix = ($prefix !== null) ? $prefix[0] : null; |
|
||||
$this->matchers = $matchers; |
|
||||
} |
|
||||
|
|
||||
public function matches(string ...$scopes): bool { |
|
||||
$count = 0; |
|
||||
$matcher = $this->matchers[$count]; |
|
||||
foreach ($scopes as $scope) { |
|
||||
if ($matcher->matches($scope)) { |
|
||||
$matcher = $this->matchers[++$count] ?? null; |
|
||||
} |
|
||||
if ($matcher === null) { |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public function getPrefix(string ...$scopes): string|null|false { |
|
||||
if ($this->matches($scopes)) { |
|
||||
return $this->prefix; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,39 +0,0 @@ |
|||||
<?php |
|
||||
/** @license MIT |
|
||||
* Copyright 2021 Dustin Wilson et al. |
|
||||
* See LICENSE file for details */ |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
namespace dW\Lit\Scope; |
|
||||
|
|
||||
class ScopeMatcher extends Matcher { |
|
||||
protected array $segments; |
|
||||
|
|
||||
public function __construct(string ...$segments) { |
|
||||
$this->segments = $segments; |
|
||||
} |
|
||||
|
|
||||
public function matches(string $scope): bool { |
|
||||
$scopeSegments = explode('.', $scope); |
|
||||
|
|
||||
if (count($this->segments) !== count($scopeSegments)) { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
foreach ($this->segments as $index => $segment) { |
|
||||
if ($segment === '*') { |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
if ($segment !== $scopeSegments[$index]) { |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public function getPrefix(string $scope) { |
|
||||
return null; |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,56 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2021 Dustin Wilson et al. |
||||
|
* See LICENSE file for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace dW\Lit\Scope; |
||||
|
|
||||
|
class Path extends Node { |
||||
|
protected int $_anchor; |
||||
|
|
||||
|
protected array $frozen = [ |
||||
|
'add' => false, |
||||
|
'anchor' => false |
||||
|
]; |
||||
|
|
||||
|
protected array $scopes = []; |
||||
|
|
||||
|
const ANCHOR_NONE = 0; |
||||
|
const ANCHOR_START = 1; |
||||
|
const ANCHOR_END = 2; |
||||
|
const ANCHOR_BOTH = 3; |
||||
|
|
||||
|
|
||||
|
public function __construct(Expression $parent) { |
||||
|
$this->_parent = \WeakReference::create($parent); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function add(Scope ...$scopes): bool { |
||||
|
if ($this->frozen['add']) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
$this->scopes = $scopes; |
||||
|
$this->frozen['add'] = true; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function __set(string $name, $value) { |
||||
|
if ($name !== 'anchor') { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set undefined property $name in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
} |
||||
|
|
||||
|
if ($this->frozen['anchor']) { |
||||
|
$trace = debug_backtrace(); |
||||
|
trigger_error("Cannot set readonly $name property in {$trace[0]['file']} on line {$trace[0]['line']}", E_USER_NOTICE); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$this->frozen['anchor'] = true; |
||||
|
$this->_anchor = $value; |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2021 Dustin Wilson et al. |
||||
|
* See LICENSE file for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace dW\Lit\Scope; |
||||
|
|
||||
|
class Scope extends Node { |
||||
|
protected bool $_anchorToPrevious; |
||||
|
protected array $atoms = []; |
||||
|
protected bool $frozen = false; |
||||
|
|
||||
|
|
||||
|
public function __construct(Path $parent, bool $anchorToPrevious = false) { |
||||
|
$this->_anchorToPrevious = $anchorToPrevious; |
||||
|
$this->_parent = \WeakReference::create($parent); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function add(string ...$atoms): bool { |
||||
|
if ($this->frozen) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
$this->atoms = $atoms; |
||||
|
$this->frozen = true; |
||||
|
return true; |
||||
|
} |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2021 Dustin Wilson et al. |
||||
|
* See LICENSE file for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace dW\Lit\Scope; |
||||
|
|
||||
|
class Selector extends Node { |
||||
|
protected array $composites = []; |
||||
|
protected bool $frozen = false; |
||||
|
|
||||
|
|
||||
|
public function __construct(?Group $parent = null) { |
||||
|
$this->_parent = ($parent === null) ? null : \WeakReference::create($parent); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function add(Composite ...$composites): bool { |
||||
|
if ($this->frozen) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
$this->composites = $this->composites; |
||||
|
$this->frozen = true; |
||||
|
return true; |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue