From 502711359641004c736caf3482f97c86ba851c64 Mon Sep 17 00:00:00 2001 From: Dustin Wilson Date: Sun, 15 Aug 2021 22:23:52 -0500 Subject: [PATCH] Started injections, broken lol --- lib/Scope/Path.php | 6 ++++++ lib/Scope/Selector.php | 12 ----------- lib/Tokenizer.php | 47 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/lib/Scope/Path.php b/lib/Scope/Path.php index c9d1b9b..06ff378 100644 --- a/lib/Scope/Path.php +++ b/lib/Scope/Path.php @@ -34,6 +34,12 @@ class Path extends Node { $index = 0; $cur = $this->_scopes[$index]; foreach ($scopes as $s) { + if (is_string($s)) { + $s = Parser::parseScope($s); + } elseif (!$s instanceof Scope) { + throw new \Exception('Argument $scopes must be an array of strings or instances of '. __NAMESPACE__. "\\Scope.\n"); + } + if ($cur->matches($s)) { $cur = $this->_scopes[++$index] ?? null; } diff --git a/lib/Scope/Selector.php b/lib/Scope/Selector.php index 9c1d41a..2120d6c 100644 --- a/lib/Scope/Selector.php +++ b/lib/Scope/Selector.php @@ -16,23 +16,11 @@ class Selector extends Node { public function getPrefix(array $scopes): ?int { - foreach ($scopes as $s) { - if (!$s instanceof Scope) { - throw new \Exception("Argument \$scopes must be an array of Scope instances.\n"); - } - } - $matches = $this->matches($scopes, $match); return ($matches) ? $match->getPrefix($scopes) : null; } public function matches(array $scopes, ?Composite &$match = null): bool { - foreach ($scopes as $s) { - if (!$s instanceof Scope) { - throw new \Exception("Argument \$scopes must be an array of Scope instances.\n"); - } - } - foreach ($this->_composites as $composite) { if ($composite->matches($scopes)) { $match = $composite; diff --git a/lib/Tokenizer.php b/lib/Tokenizer.php index d9e068a..d6bfbab 100644 --- a/lib/Tokenizer.php +++ b/lib/Tokenizer.php @@ -5,17 +5,21 @@ declare(strict_types=1); namespace dW\Lit; -use dW\Lit\Scope\Parser as ScopeParser; use dW\Lit\Grammar\{ Pattern, Reference }; +use dW\Lit\Scope\{ + Filter, + Parser as ScopeParser +}; class Tokenizer { protected \Generator $data; protected Grammar $grammar; protected int $offset = 0; + protected ?Pattern $activeInjection = null; protected array $ruleStack; protected array $scopeStack; protected $debug = false; @@ -65,14 +69,31 @@ class Tokenizer { protected function tokenizeLine(string $line): array { $tokens = []; + $lineLength = strlen($line); + + if ($this->activeInjection === null && $this->grammar->injections !== null) { + foreach ($this->grammar->injections as $selector => $injection) { + $selector = ScopeParser::parseSelector($selector); + if ($selector->matches($this->scopeStack)) { + $prefix = $selector->getPrefix($this->scopeStack); + if ($prefix === Filter::PREFIX_LEFT || $prefix === Filter::PREFIX_BOTH) { + $this->scopeStack[] = $injection; + $this->activeInjection = $injection; + break; + } + } + } + } while (true) { $currentRules = end($this->ruleStack)->patterns; $currentRulesCount = count($currentRules); + for ($i = 0; $i < $currentRulesCount; $i++) { while (true) { $rule = $currentRules[$i]; + // If the rule is a Pattern and matches the line at the offset then tokenize the // matches. if ($rule instanceof Pattern && preg_match($rule->match, $line, $match, PREG_OFFSET_CAPTURE, $this->offset)) { @@ -200,7 +221,12 @@ class Tokenizer { } // And remove the rule from the rule stack, too. - array_pop($this->ruleStack); + $popped = array_pop($this->ruleStack); + // If what was just popped is the active injection then remove it, too. + if ($popped === $this->activeInjection) { + $this->activeInjection = null; + } + break 2; } // Otherwise, if the rule is a Reference then retrieve its patterns, splice into @@ -219,6 +245,23 @@ class Tokenizer { } } + if ($this->activeInjection === null && $this->grammar->injections !== null) { + foreach ($this->grammar->injections as $selector => $injection) { + $selector = ScopeParser::parseSelector($selector); + if ($selector->matches($this->scopeStack)) { + $prefix = $selector->getPrefix($this->scopeStack); + if ($prefix !== Filter::PREFIX_LEFT) { + $this->ruleStack[] = $injection; + $this->activeInjection = $injection; + + if ($this->offset < $lineLength) { + continue 2; + } + } + } + } + } + break; }