diff --git a/lib/Grammar.php b/lib/Grammar.php index 5a8bdb7..bcaf029 100644 --- a/lib/Grammar.php +++ b/lib/Grammar.php @@ -80,7 +80,7 @@ class Grammar { if (isset($json['injections'])) { $injections = []; foreach ($json['injections'] as $key => $injection) { - $injections[$key] = $this->parseJSONPattern($injection, $filename); + $injections[$key] = $this->parseJSONPattern($injection, $filename, true); } $injections = (count($injections) > 0) ? $injections : null; } @@ -88,7 +88,7 @@ class Grammar { } - protected function parseJSONPattern(array $pattern, string $filename): Pattern|Reference|null { + protected function parseJSONPattern(array $pattern, string $filename, bool $isInjection = false): Pattern|Reference|null { if (isset($pattern['include'])) { if ($pattern['include'][0] === '#') { return new RepositoryReference(substr($pattern['include'], 1), $this->_scopeName); @@ -108,7 +108,8 @@ class Grammar { 'patterns' => null, 'captures' => null, 'beginPattern' => false, - 'endPattern' => (isset($pattern['endPattern']) && $pattern['endPattern']) + 'endPattern' => (isset($pattern['endPattern']) && $pattern['endPattern']), + 'injection' => $isInjection ]; $modified = false; diff --git a/lib/Grammar/Pattern.php b/lib/Grammar/Pattern.php index 1fd4b55..d54ea23 100644 --- a/lib/Grammar/Pattern.php +++ b/lib/Grammar/Pattern.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace dW\Lit\Grammar; -use dW\Lit\Grammar; /** Contains patterns responsible for matching a portion of the document */ @@ -14,12 +13,13 @@ class Pattern extends Rule { protected ?array $_captures; protected ?string $_contentName; protected bool $_endPattern = false; + protected bool $_injection = false; protected ?string $_match; protected ?string $_name; protected ?array $_patterns; - public function __construct(?string $name = null, ?string $contentName = null, ?string $match = null, ?array $patterns = null, ?array $captures = null, bool $beginPattern = false, bool $endPattern = false) { + public function __construct(?string $name = null, ?string $contentName = null, ?string $match = null, ?array $patterns = null, ?array $captures = null, bool $beginPattern = false, bool $endPattern = false, bool $injection = false) { $this->_beginPattern = $beginPattern; $this->_name = $name; $this->_contentName = $contentName; @@ -27,5 +27,6 @@ class Pattern extends Rule { $this->_patterns = $patterns; $this->_captures = $captures; $this->_endPattern = $endPattern; + $this->_injection = $injection; } } \ No newline at end of file diff --git a/lib/Highlight.php b/lib/Highlight.php index 9b9557e..85db259 100644 --- a/lib/Highlight.php +++ b/lib/Highlight.php @@ -45,13 +45,12 @@ class Highlight { $scopeStack = [ $scopeName ]; foreach ($tokenList as $lineNumber => $tokens) { - continue; foreach ($tokens as $token) { $lastKey = count($token['scopes']) - 1; foreach ($token['scopes'] as $key => $scope) { $keyExists = array_key_exists($key, $scopeStack); if (!$keyExists || $scopeStack[$key] !== $scope) { - if ($keyExists && $scopeStack[$key] !== $scope) { + if ($keyExists) { $scopeStack = array_slice($scopeStack, 0, $key); $elementStack = array_slice($elementStack, 0, $key); } diff --git a/lib/Scope/Composite.php b/lib/Scope/Composite.php index aa61232..8514698 100644 --- a/lib/Scope/Composite.php +++ b/lib/Scope/Composite.php @@ -16,9 +16,7 @@ class Composite extends Node { public function getPrefix(array $scopes): ?int { - if ($this->matches($scopes)) { - return $this->_expressions[0]->getPrefix($scopes); - } + return ($this->matches($scopes)) ? $this->_expressions[0]->getPrefix($scopes) : null; } public function matches(array $scopes): bool { diff --git a/lib/Scope/Expression.php b/lib/Scope/Expression.php index 2846086..95eb1eb 100644 --- a/lib/Scope/Expression.php +++ b/lib/Scope/Expression.php @@ -25,9 +25,7 @@ class Expression extends Node { public function getPrefix(array $scopes): ?int { - if ($this->matches($scopes)) { - return $this->_child->getPrefix($scopes); - } + return ($this->matches($scopes)) ? $this->_child->getPrefix($scopes) : null; } public function matches(array $scopes): bool { diff --git a/lib/Scope/Group.php b/lib/Scope/Group.php index e28eb40..24fe0e9 100644 --- a/lib/Scope/Group.php +++ b/lib/Scope/Group.php @@ -16,9 +16,7 @@ class Group extends Node { public function getPrefix(array $scopes): ?int { - if ($this->matches($scopes)) { - return $this->_child->getPrefix($scopes); - } + return ($this->matches($scopes)) ? $this->_child->getPrefix($scopes) : null; } public function matches(array $scopes): bool { diff --git a/lib/Tokenizer.php b/lib/Tokenizer.php index 8060e62..2e07c98 100644 --- a/lib/Tokenizer.php +++ b/lib/Tokenizer.php @@ -102,9 +102,10 @@ class Tokenizer { protected function tokenizeLine(int $stopOffset): array { $tokens = []; + $injected = false; while (true) { - if ($this->activeInjection === null && $this->grammar->injections !== null) { + /*if ($this->activeInjection === null && $this->grammar->injections !== null) { foreach ($this->grammar->injections as $selector => $injection) { $selector = ScopeParser::parseSelector($selector); if ($selector->matches($this->scopeStack)) { @@ -116,12 +117,37 @@ class Tokenizer { } } } - } + }*/ // Grab the current rule list from the cache if available to prevent having to // splice in references repeatedly. $cacheIndex = array_search(end($this->ruleStack)->patterns, $this->ruleCacheIndexes); - $currentRules = ($cacheIndex !== false) ? $this->ruleCacheValues[$cacheIndex] : end($this->ruleStack)->patterns; + if ($cacheIndex !== false) { + $currentRules = $this->ruleCacheValues[$cacheIndex]; + } else { + $currentRules = end($this->ruleStack)->patterns; + + if ($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) { + $currentRules = [ ...$injection->patterns, ...$currentRules ]; + if ($prefix === Filter::PREFIX_LEFT) { + break; + } + } + if ($prefix === Filter::PREFIX_RIGHT || $prefix === Filter::PREFIX_BOTH) { + $currentRules = [ ...$currentRules, ...$injection->patterns ]; + } + + $injected = true; + break; + } + } + } + } $currentRulesCount = count($currentRules); $closestMatch = null; @@ -198,7 +224,18 @@ class Tokenizer { $this->ruleCacheIndexes[] = end($this->ruleStack)->patterns; $cacheIndex = count($this->ruleCacheIndexes) - 1; } - $this->ruleCacheValues[$cacheIndex] = $currentRules; + + if ($injected) { + $temp = $currentRules; + foreach ($temp as $k => $r) { + if ($r instanceof Pattern && $r->injection) { + unset($temp[$k]); + } + } + $this->ruleCacheValues[$cacheIndex] = array_values($temp); + } else { + $this->ruleCacheValues[$cacheIndex] = $currentRules; + } continue; } @@ -430,9 +467,9 @@ class Tokenizer { } // If what was just popped is the active injection then remove it, too. - if ($popped === $this->activeInjection) { + /*if ($popped === $this->activeInjection) { $this->activeInjection = null; - } + }*/ } // If the offset isn't at the end of the line then look for more matches. @@ -442,7 +479,7 @@ class Tokenizer { } - if ($this->activeInjection === null && $this->grammar->injections !== null) { + /*if ($this->activeInjection === null && $this->grammar->injections !== null) { foreach ($this->grammar->injections as $selector => $injection) { $selector = ScopeParser::parseSelector($selector); if ($selector->matches($this->scopeStack) && $selector->getPrefix($this->scopeStack) !== Filter::PREFIX_LEFT) { @@ -454,7 +491,7 @@ class Tokenizer { } } } - } + }*/ break; }