Browse Source

Scope parser is functioning okay enough

main
Dustin Wilson 3 years ago
parent
commit
d0928d7c4d
  1. 24
      lib/Scope/Data.php
  2. 2
      lib/Scope/Exception.php
  3. 17
      lib/Scope/Matchers/AndMatcher.php
  4. 16
      lib/Scope/Matchers/CompositeMatcher.php
  5. 8
      lib/Scope/Matchers/GroupMatcher.php
  6. 6
      lib/Scope/Matchers/NegateMatcher.php
  7. 8
      lib/Scope/Matchers/OrMatcher.php
  8. 2
      lib/Scope/Matchers/PathMatcher.php
  9. 92
      lib/Scope/Parser.php

24
lib/Scope/Data.php

@ -14,7 +14,7 @@ class Data {
public function __construct(string $data) { public function __construct(string $data) {
$this->data = $data; $this->data = $data;
$this->endPosition = strlen($data) - 1; $this->endPosition = strlen($data);
} }
public function consume(int $length = 1): string|bool { public function consume(int $length = 1): string|bool {
@ -39,19 +39,6 @@ class Data {
return $this->consumeWhile($match, 1); return $this->consumeWhile($match, 1);
} }
public function consumeUntil(string $match, $limit = null): string|bool {
if ($this->_position === $this->endPosition) {
return false;
}
$length = strcspn($this->data, $match, $this->_position, $limit);
if ($length === 0) {
return '';
}
return $this->consume($length);
}
public function consumeWhile(string $match, $limit = null): string|bool { public function consumeWhile(string $match, $limit = null): string|bool {
if ($this->_position === $this->endPosition) { if ($this->_position === $this->endPosition) {
return false; return false;
@ -83,6 +70,15 @@ class Data {
return $output; return $output;
} }
public function unconsumeTo(int $position = 1): bool {
if ($position < 0 || $position > $this->endPosition) {
return false;
}
$this->_position = $position;
return true;
}
public function __get(string $name) { public function __get(string $name) {
if ($name === 'position') { if ($name === 'position') {
return $this->_position; return $this->_position;

2
lib/Scope/Exception.php

@ -9,7 +9,7 @@ namespace dW\Highlighter\Scope;
class Exception extends \Exception { class Exception extends \Exception {
const MESSAGE = '%s expected; found %s'; const MESSAGE = '%s expected; found %s';
public function __construct(string $expected, string $found) { public function __construct(string $expected, string|bool $found) {
$strlen = strlen($expected); $strlen = strlen($expected);
if ($strlen > 1) { if ($strlen > 1) {
$temp = []; $temp = [];

17
lib/Scope/Matchers/AndMatcher.php

@ -0,0 +1,17 @@
<?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 AndMatcher extends Matcher {
protected Matcher $left;
protected Matcher $right;
public function __construct(Matcher $left, Matcher $right) {
$this->left = $left;
$this->right = $right;
}
}

16
lib/Scope/Matchers/CompositeMatcher.php

@ -7,5 +7,19 @@ declare(strict_types=1);
namespace dW\Highlighter\Scope; namespace dW\Highlighter\Scope;
class CompositeMatcher extends Matcher { class CompositeMatcher extends Matcher {
public function __construct(Matcher $left, string $operator, Matcher $right) {} protected Matcher $matcher;
public function __construct(Matcher $left, string $operator, Matcher $right) {
switch ($operator) {
case '|':
$this->matcher = new OrMatcher($left, $right);
break;
case '&':
$this->matcher = new AndMatcher($left, $right);
break;
case '-':
$this->matcher = new AndMatcher($left, new NegateMatcher($right));
break;
}
}
} }

8
lib/Scope/Matchers/GroupMatcher.php

@ -7,5 +7,11 @@ declare(strict_types=1);
namespace dW\Highlighter\Scope; namespace dW\Highlighter\Scope;
class GroupMatcher extends Matcher { class GroupMatcher extends Matcher {
public function __construct(string $prefix, Matcher $selector) {} protected string|null $prefix;
protected Matcher $selector;
public function __construct(string|null $prefix, Matcher $selector) {
$this->prefix = ($prefix !== null) ? $prefix[0] : null;
$this->selector = $selector;
}
} }

6
lib/Scope/Matchers/NegateMatcher.php

@ -7,5 +7,9 @@ declare(strict_types=1);
namespace dW\Highlighter\Scope; namespace dW\Highlighter\Scope;
class NegateMatcher extends Matcher { class NegateMatcher extends Matcher {
public function __construct(Matcher $groupOrPath) {} protected Matcher $matcher;
public function __construct(Matcher $matcher) {
$this->matcher = $matcher;
}
} }

8
lib/Scope/Matchers/OrMatcher.php

@ -7,5 +7,11 @@ declare(strict_types=1);
namespace dW\Highlighter\Scope; namespace dW\Highlighter\Scope;
class OrMatcher extends Matcher { class OrMatcher extends Matcher {
public function __construct(Matcher $left, Matcher $right) {} protected Matcher $left;
protected Matcher $right;
public function __construct(Matcher $left, Matcher $right) {
$this->left = $left;
$this->right = $right;
}
} }

2
lib/Scope/Matchers/PathMatcher.php

@ -11,7 +11,7 @@ class PathMatcher extends Matcher {
protected array $matchers; protected array $matchers;
public function __construct(string|null $prefix, Matcher ...$matchers) { public function __construct(string|null $prefix, Matcher ...$matchers) {
$this->prefix = $prefix; $this->prefix = ($prefix !== null) ? $prefix[0] : null;
$this->matchers = $matchers; $this->matchers = $matchers;
} }
} }

92
lib/Scope/Parser.php

@ -30,16 +30,10 @@ class Parser {
$s2 = self::parseSelector(); $s2 = self::parseSelector();
if ($s2 !== false) { if ($s2 !== false) {
$s3 = self::parseSpace(); $s3 = self::parseSpace();
if ($s3 !== false) { $result = $s2;
$result = $s2;
}
} }
} }
if (self::$debug === true) {
echo "------------------------------\n";
}
if ($result === false && self::$instance->lastExceptionData !== []) { if ($result === false && self::$instance->lastExceptionData !== []) {
throw new Exception(self::$instance->lastExceptionData['expected'], self::$instance->lastExceptionData['found']); throw new Exception(self::$instance->lastExceptionData['expected'], self::$instance->lastExceptionData['found']);
} }
@ -53,6 +47,7 @@ class Parser {
} }
$result = false; $result = false;
$position = self::$instance->data->position;
$s1 = self::parseExpression(); $s1 = self::parseExpression();
if ($s1 !== false) { if ($s1 !== false) {
@ -77,11 +72,12 @@ class Parser {
} }
if ($result === false) { if ($result === false) {
self::$instance->data->unconsumeTo($position);
$result = self::parseExpression(); $result = self::parseExpression();
} }
if (self::$debug === true) { if (self::$debug === true) {
echo "parseComposite Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -142,7 +138,7 @@ class Parser {
} }
if (self::$debug === true) { if (self::$debug === true) {
echo "parseExpression Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -174,29 +170,27 @@ class Parser {
} }
} }
if ($prefix !== null) { $s2 = self::$instance->data->consumeIf('(');
$s2 = self::$instance->data->consumeIf('('); if ($s2 === '' || $s2 === false) {
if ($s2 === '' || $s2 === false) { $s2 = false;
$s2 = false; self::fail('(');
self::fail('('); }
}
if ($s2 !== false) { if ($s2 !== false) {
$s3 = self::parse(); $s3 = self::parseSpace();
if ($s3 !== false) { if ($s3 !== false) {
$s4 = self::parseSelector(); $s4 = self::parseSelector();
if ($s4 !== false) { if ($s4 !== false) {
$s5 = self::parseSpace(); $s5 = self::parseSpace();
if ($s5 !== false) { if ($s5 !== false) {
$s6 = self::$instance->data->consumeIf(')'); $s6 = self::$instance->data->consumeIf(')');
if ($s6 === '' || $s6 === false) { if ($s6 === '' || $s6 === false) {
$s6 = false; $s6 = false;
self::fail(')'); self::fail(')');
} }
if ($s6 !== false) { if ($s6 !== false) {
$result = new GroupMatcher($prefix, $s4); $result = new GroupMatcher($prefix, $s4);
}
} }
} }
} }
@ -204,7 +198,7 @@ class Parser {
} }
if (self::$debug === true) { if (self::$debug === true) {
echo "parseGroup Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -241,7 +235,7 @@ class Parser {
$s3 = [$s2]; $s3 = [$s2];
do { do {
$s4 = false; $s6 = false;
$s5 = self::parseSpace(); $s5 = self::parseSpace();
if ($s5 !== false) { if ($s5 !== false) {
$s6 = self::parseScope(); $s6 = self::parseScope();
@ -249,13 +243,13 @@ class Parser {
$s3[] = $s6; $s3[] = $s6;
} }
} }
} while ($s4 !== false); } while ($s6 !== false);
$result = new PathMatcher($prefix, ...$s3); $result = new PathMatcher($prefix, ...$s3);
} }
if (self::$debug === true) { if (self::$debug === true) {
echo "parsePath Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -313,7 +307,7 @@ class Parser {
} }
if (self::$debug === true) { if (self::$debug === true) {
echo "parseSegment Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -325,6 +319,7 @@ class Parser {
} }
$result = false; $result = false;
$position = self::$instance->data->position;
$s1 = self::parseComposite(); $s1 = self::parseComposite();
if ($s1 !== false) { if ($s1 !== false) {
@ -346,8 +341,13 @@ class Parser {
} }
} }
if ($result === false) {
self::$instance->data->unconsumeTo($position);
$result = self::parseComposite();
}
if (self::$debug === true) { if (self::$debug === true) {
echo "parseSelector Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -384,7 +384,7 @@ class Parser {
} }
if (self::$debug === true) { if (self::$debug === true) {
echo "parseScope Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -401,7 +401,7 @@ class Parser {
} }
if (self::$debug === true) { if (self::$debug === true) {
echo "parseSpace Result: " . var_export($result, true) . "\n"; self::debugResult($result);
} }
return $result; return $result;
@ -409,12 +409,16 @@ class Parser {
protected static function debug() { protected static function debug() {
/*if (self::$debugCount === 2500) {
die();
}*/
$message = <<<DEBUG $message = <<<DEBUG
------------------------------ ------------------------------
%s %s
Method: %s Method: %s
Position: %s Position: %s
Char: '%s' Char: %s
DEBUG; DEBUG;
@ -430,10 +434,16 @@ class Parser {
self::$debugCount++, self::$debugCount++,
ltrim($methodTree, '->'), ltrim($methodTree, '->'),
self::$instance->data->position, self::$instance->data->position,
self::$instance->data->peek() var_export(self::$instance->data->peek(), true)
); );
} }
protected static function debugResult($result) {
printf("%s Result: %s\n",
debug_backtrace()[1]['function'],
var_export($result, true));
}
protected static function fail(string $expected) { protected static function fail(string $expected) {
self::$instance->lastExceptionData = [ self::$instance->lastExceptionData = [
'expected' => $expected, 'expected' => $expected,

Loading…
Cancel
Save