2#include "tokenizeString.h"
3#include "encodedTokenAttributes.h"
7#include <unordered_set>
12StateStackImpl* StateStackImpl::NULL_STATE =
nullptr;
15static StackNodeArena* g_activeArena =
nullptr;
17StackNodeArena* tmlGetActiveArena() {
return g_activeArena; }
18void tmlSetActiveArena(StackNodeArena* arena) { g_activeArena = arena; }
20void StackNodeArena::clear() {
21 for (StateStackImpl* s : stacks) delete s;
22 for (AttributedScopeStack* a : scopes) delete a;
27void StackNodeArena::sweepKeeping(
const std::vector<StateStackImpl*>& roots) {
31 std::unordered_set<const StateStackImpl*> liveStacks;
32 std::unordered_set<const AttributedScopeStack*> liveScopes;
34 auto markScopes = [&](AttributedScopeStack* a) {
35 while (a && liveScopes.insert(a).second) a = a->parent;
38 for (StateStackImpl* root : roots) {
39 StateStackImpl* s = root;
40 while (s && liveStacks.insert(s).second) {
41 markScopes(s->nameScopesList);
42 markScopes(s->contentNameScopesList);
47 std::vector<StateStackImpl*> keptStacks;
48 keptStacks.reserve(liveStacks.size());
49 for (StateStackImpl* s : stacks) {
50 if (liveStacks.count(s)) keptStacks.push_back(s);
53 stacks.swap(keptStacks);
55 std::vector<AttributedScopeStack*> keptScopes;
56 keptScopes.reserve(liveScopes.size());
57 for (AttributedScopeStack* a : scopes) {
58 if (liveScopes.count(a)) keptScopes.push_back(a);
61 scopes.swap(keptScopes);
66BalancedBracketSelectors::BalancedBracketSelectors(
67 const std::vector<std::string>& balancedBracketSelectors,
68 const std::vector<std::string>& unbalancedBracketSelectors)
71 if (balancedBracketSelectors.empty() && unbalancedBracketSelectors.empty()) {
79bool BalancedBracketSelectors::matchesAlways()
const {
80 return _allowAny && _unbalancedBracketMatchers.empty();
83bool BalancedBracketSelectors::matchesNever()
const {
84 return !_allowAny && _balancedBracketMatchers.empty();
87bool BalancedBracketSelectors::match(
const std::vector<std::string>& scopes)
const {
95AttributedScopeStack::AttributedScopeStack(
96 AttributedScopeStack* parent_,
97 const ScopeName& scopeName_,
98 EncodedTokenAttributes tokenAttributes_)
99 : parent(parent_), scopeName(scopeName_), tokenAttributes(tokenAttributes_) {
100 if (g_activeArena) g_activeArena->scopes.push_back(
this);
103AttributedScopeStack::~AttributedScopeStack() {
107AttributedScopeStack* AttributedScopeStack::createRoot(
108 const std::string& scopeName,
109 EncodedTokenAttributes tokenAttributes) {
110 return new AttributedScopeStack(
nullptr, scopeName, tokenAttributes);
113AttributedScopeStack* AttributedScopeStack::createRootAndLookUpScopeName(
114 const std::string& scopeName,
115 EncodedTokenAttributes tokenAttributes,
118 BasicScopeAttributes rawMetadata = grammar->getMetadataForScope(scopeName);
120 ScopeStack scopeStack(
nullptr, scopeName);
121 StyleAttributes* rootStyle = grammar->getThemeProvider()->themeMatch(&scopeStack);
125 rawMetadata.languageId,
126 rawMetadata.tokenType,
128 rootStyle ? rootStyle->fontStyle : static_cast<int>(
FontStyle::
NotSet),
129 rootStyle ? rootStyle->foregroundId : 0,
130 rootStyle ? rootStyle->backgroundId : 0
135 return new AttributedScopeStack(
nullptr, scopeName, scopeTokenAttributes);
138AttributedScopeStack* AttributedScopeStack::push(
140 const std::string& scopeName) {
142 if (scopeName.empty()) {
146 BasicScopeAttributes rawMetadata = grammar->getMetadataForScope(scopeName);
148 std::vector<ScopeName> names = this->getScopeNames();
149 names.push_back(scopeName);
150 ScopeStack* scopeStack = ScopeStack::from(names);
151 StyleAttributes* themeData = grammar->getThemeProvider()->themeMatch(scopeStack);
154 this->tokenAttributes,
155 rawMetadata.languageId,
156 rawMetadata.tokenType,
158 themeData ? themeData->fontStyle : static_cast<int>(
FontStyle::
NotSet),
159 themeData ? themeData->foregroundId : 0,
160 themeData ? themeData->backgroundId : 0
165 ScopeStack* p = scopeStack->parent;
170 return new AttributedScopeStack(
this, scopeName, scopeTokenAttributes);
173AttributedScopeStack* AttributedScopeStack::pushAttributed(
174 const std::string& scopePath,
177 if (scopePath.empty()) {
182 if (scopePath.find(
' ') == std::string::npos) {
184 return _pushAttributed(
this, scopePath, grammar);
188 std::vector<std::string> scopes;
189 std::string currentScope;
190 for (
char c : scopePath) {
192 if (!currentScope.empty()) {
193 scopes.push_back(currentScope);
194 currentScope.clear();
200 if (!currentScope.empty()) {
201 scopes.push_back(currentScope);
204 AttributedScopeStack* result =
this;
205 for (
const std::string& scope : scopes) {
206 result = _pushAttributed(result, scope, grammar);
211AttributedScopeStack* AttributedScopeStack::_pushAttributed(
212 AttributedScopeStack* target,
213 const std::string& scopeName,
216 if (scopeName.empty()) {
220 BasicScopeAttributes rawMetadata = grammar->getMetadataForScope(scopeName);
222 std::vector<ScopeName> names = target->getScopeNames();
223 names.push_back(scopeName);
224 ScopeStack* scopeStack = ScopeStack::from(names);
225 StyleAttributes* themeData = grammar->getThemeProvider()->themeMatch(scopeStack);
228 target->tokenAttributes,
229 rawMetadata.languageId,
230 rawMetadata.tokenType,
232 themeData ? themeData->fontStyle : static_cast<int>(
FontStyle::
NotSet),
233 themeData ? themeData->foregroundId : 0,
234 themeData ? themeData->backgroundId : 0
239 ScopeStack* p = scopeStack->parent;
244 return new AttributedScopeStack(target, scopeName, metadata);
247std::vector<std::string> AttributedScopeStack::getScopeNames()
const {
248 std::vector<std::string> result;
249 const AttributedScopeStack* current =
this;
251 result.push_back(current->scopeName);
252 current = current->parent;
254 std::reverse(result.begin(), result.end());
258bool AttributedScopeStack::equals(AttributedScopeStack* a, AttributedScopeStack* b) {
259 if (a == b)
return true;
260 if (!a || !b)
return false;
263 if (a->scopeName != b->scopeName || a->tokenAttributes != b->tokenAttributes) {
270 return a ==
nullptr && b ==
nullptr;
275StateStackImpl::StateStackImpl(
276 StateStackImpl* parent_,
280 bool beginRuleCapturedEOL_,
281 const std::string* endRule_,
282 AttributedScopeStack* nameScopesList_,
283 AttributedScopeStack* contentNameScopesList_)
286 _enterPos(enterPos_),
287 _anchorPos(anchorPos_),
288 beginRuleCapturedEOL(beginRuleCapturedEOL_),
289 endRule(endRule_ ? new std::string(*endRule_) : nullptr),
290 nameScopesList(nameScopesList_),
291 contentNameScopesList(contentNameScopesList_) {
293 depth = parent ? parent->depth + 1 : 1;
294 if (g_activeArena) g_activeArena->stacks.push_back(
this);
297StateStackImpl::~StateStackImpl() {
302StateStack* StateStackImpl::clone() {
303 return new StateStackImpl(
308 beginRuleCapturedEOL,
311 contentNameScopesList
315bool StateStackImpl::equals(StateStack* other) {
316 if (
this == other)
return true;
317 if (!other)
return false;
319 StateStackImpl* otherImpl =
dynamic_cast<StateStackImpl*
>(other);
320 if (!otherImpl)
return false;
324 if (_enterPos != otherImpl->_enterPos)
return false;
326 bool thisHasEndRule = (endRule !=
nullptr);
327 bool otherHasEndRule = (otherImpl->endRule !=
nullptr);
328 if (thisHasEndRule != otherHasEndRule)
return false;
329 if (thisHasEndRule && *endRule != *otherImpl->endRule)
return false;
331 if (!AttributedScopeStack::equals(nameScopesList, otherImpl->nameScopesList))
return false;
332 if (!AttributedScopeStack::equals(contentNameScopesList, otherImpl->contentNameScopesList))
return false;
335 if (parent ==
nullptr && otherImpl->parent ==
nullptr)
return true;
336 if (parent ==
nullptr || otherImpl->parent ==
nullptr)
return false;
338 return parent->equals(otherImpl->parent);
341void StateStackImpl::reset() {
343 StateStackImpl* el =
this;
351StateStackImpl* StateStackImpl::push(
355 bool beginRuleCapturedEOL,
356 const std::string* endRule,
357 AttributedScopeStack* nameScopesList,
358 AttributedScopeStack* contentNameScopesList) {
360 return new StateStackImpl(
365 beginRuleCapturedEOL,
368 contentNameScopesList
372StateStackImpl* StateStackImpl::pop() {
376StateStackImpl* StateStackImpl::safePop() {
383Rule* StateStackImpl::getRule(Grammar* grammar) {
384 return grammar->getRule(this->ruleId);
387StateStackImpl* StateStackImpl::withContentNameScopesList(AttributedScopeStack* contentNameScopesList) {
388 if (this->contentNameScopesList == contentNameScopesList) {
391 return this->parent->push(
395 this->beginRuleCapturedEOL,
397 this->nameScopesList,
398 contentNameScopesList
402StateStackImpl* StateStackImpl::withEndRule(
const std::string& endRule) {
403 if (this->endRule && *this->endRule == endRule) {
406 return new StateStackImpl(
411 this->beginRuleCapturedEOL,
413 this->nameScopesList,
414 this->contentNameScopesList
418bool StateStackImpl::hasSameRuleAs(StateStackImpl* other) {
419 StateStackImpl* el =
this;
420 while (el && el->_enterPos == other->_enterPos) {
429std::string StateStackImpl::toString()
const {
430 std::string result =
"StateStack[";
431 const StateStackImpl* current =
this;
433 result +=
"Rule#" + std::to_string(
ruleIdToNumber(current->ruleId));
434 if (current->parent) result +=
", ";
435 current = current->parent;
443LineTokens::LineTokens(
444 bool emitBinaryTokens,
445 const std::string& lineText,
446 const std::vector<TokenTypeMatcher>& tokenTypeMatchers,
447 BalancedBracketSelectors* balancedBracketSelectors)
448 : _emitBinaryTokens(emitBinaryTokens),
450 _tokenTypeMatchers(tokenTypeMatchers),
451 _balancedBracketSelectors(balancedBracketSelectors),
452 _lastTokenEndIndex(0) {
455void LineTokens::produce(StateStackImpl* stack,
int endIndex) {
456 produceFromScopes(stack->contentNameScopesList, endIndex);
459void LineTokens::produceFromScopes(AttributedScopeStack* scopesList,
int endIndex) {
460 if (_lastTokenEndIndex >= endIndex) {
464 if (_emitBinaryTokens) {
465 _binaryTokens.push_back(_lastTokenEndIndex);
466 _binaryTokens.push_back(scopesList->tokenAttributes);
467 _lastTokenEndIndex = endIndex;
470 token.startIndex = _lastTokenEndIndex;
471 token.endIndex = endIndex;
472 token.scopes = scopesList->getScopeNames();
473 _tokens.push_back(token);
474 _lastTokenEndIndex = endIndex;
478std::vector<IToken> LineTokens::getResult(StateStackImpl* stack,
int lineLength) {
480 if (!_tokens.empty() && _tokens.back().startIndex == lineLength - 1) {
485 if (_tokens.empty()) {
486 _lastTokenEndIndex = -1;
487 produce(stack, lineLength);
488 if (!_tokens.empty()) {
489 _tokens.back().startIndex = 0;
496std::vector<uint32_t> LineTokens::getBinaryResult(StateStackImpl* stack,
int lineLength) {
497 return _binaryTokens;
503 const ScopeName& rootScopeName,
504 IRawGrammar* grammar,
506 const EmbeddedLanguagesMap* embeddedLanguages,
507 const TokenTypeMap* tokenTypes,
508 BalancedBracketSelectors* balancedBracketSelectors_,
509 IGrammarRepository* grammarRepository,
510 IThemeProvider* themeProvider,
512 : _rootScopeName(rootScopeName),
515 _grammarRepository(grammarRepository),
516 _themeProvider(themeProvider),
518 _injections(nullptr),
519 balancedBracketSelectors(balancedBracketSelectors_),
522 _ruleId2desc.push_back(
nullptr);
524 _basicScopeAttributesProvider =
new BasicScopeAttributesProvider(
529 _grammar = initGrammar(grammar,
nullptr);
533 for (
const auto& pair : *tokenTypes) {
536 TokenTypeMatcher matcher;
537 matcher.type = pair.second;
538 _tokenTypeMatchers.push_back(matcher);
547void Grammar::dispose() {
548 for (
size_t i = 0; i < _ruleId2desc.size(); i++) {
549 auto* rule = _ruleId2desc[i];
555 _ruleId2desc.clear();
557 if (_basicScopeAttributesProvider) {
558 delete _basicScopeAttributesProvider;
559 _basicScopeAttributesProvider =
nullptr;
563 _injections =
nullptr;
565 if (balancedBracketSelectors) {
566 delete balancedBracketSelectors;
567 balancedBracketSelectors =
nullptr;
571OnigScanner* Grammar::createOnigScanner(
const std::vector<std::string>& sources) {
572 return _onigLib->createOnigScanner(sources);
575OnigString* Grammar::createOnigString(
const std::string& str) {
576 return _onigLib->createOnigString(str);
579BasicScopeAttributes Grammar::getMetadataForScope(
const std::string& scope) {
580 return _basicScopeAttributesProvider->getBasicScopeAttributes(&scope);
583Rule* Grammar::getRule(RuleId ruleId) {
585 if (
id >= 0 &&
id <
static_cast<int>(_ruleId2desc.size())) {
586 return _ruleId2desc[id];
591RuleId Grammar::registerRule(Rule* rule) {
592 int id = ++_lastRuleId;
593 if (_ruleId2desc.size() <=
static_cast<size_t>(
id)) {
594 _ruleId2desc.resize(
id + 1,
nullptr);
596 _ruleId2desc[id] = rule;
600RuleId Grammar::allocateRuleId() {
601 int id = ++_lastRuleId;
602 if (_ruleId2desc.size() <=
static_cast<size_t>(
id)) {
603 _ruleId2desc.resize(
id + 1,
nullptr);
608void Grammar::setRule(RuleId ruleId, Rule* rule) {
610 if (
id >= 0 &&
id <
static_cast<int>(_ruleId2desc.size())) {
611 _ruleId2desc[id] = rule;
615IRawGrammar* Grammar::getExternalGrammar(
const std::string& scopeName, IRawRepository* repository) {
616 auto it = _includedGrammars.find(scopeName);
617 if (it != _includedGrammars.end()) {
621 if (_grammarRepository) {
622 IRawGrammar* rawIncludedGrammar = _grammarRepository->lookup(scopeName);
623 if (rawIncludedGrammar) {
624 IRawRule* base = (repository && repository->baseRule) ? repository->baseRule : nullptr;
625 _includedGrammars[scopeName] = initGrammar(rawIncludedGrammar, base);
626 return _includedGrammars[scopeName];
635std::vector<Injection> Grammar::getInjections() {
636 if (_injections ==
nullptr) {
637 _injections =
new std::vector<Injection>(_collectInjections());
643static bool scopesAreMatching(
const std::string& thisScopeName,
const std::string& scopeName) {
644 if (thisScopeName.empty()) {
647 if (thisScopeName == scopeName) {
650 size_t len = scopeName.length();
651 return thisScopeName.length() > len &&
652 thisScopeName.substr(0, len) == scopeName &&
653 thisScopeName[len] ==
'.';
657static bool nameMatcher(
const std::vector<std::string>& identifiers,
658 const std::vector<std::string>& scopes) {
659 if (scopes.size() < identifiers.size()) {
662 size_t lastIndex = 0;
663 for (
const auto& identifier : identifiers) {
665 for (
size_t i = lastIndex; i < scopes.size(); i++) {
666 if (scopesAreMatching(scopes[i], identifier)) {
680static void collectInjections(std::vector<Injection>& result,
681 const std::string& selector,
684 IRawGrammar* grammarDef) {
690 auto matchers = createMatchers<std::vector<std::string>>(selector, nameMatcher);
693 RuleId ruleId = RuleFactory::getCompiledRuleId(rule, grammar, grammarDef->repository);
696 for (
const auto& matcherWithPriority : matchers) {
698 injection.debugSelector = selector;
699 injection.matcher = matcherWithPriority.matcher;
700 injection.ruleId = ruleId;
701 injection.grammar = grammarDef;
702 injection.priority = matcherWithPriority.priority;
703 result.push_back(injection);
707std::vector<Injection> Grammar::_collectInjections() {
708 std::vector<Injection> result;
711 IRawGrammar* grammar = _grammar;
717 if (grammar->injections) {
718 for (
const auto& pair : *grammar->injections) {
719 const std::string& expression = pair.first;
720 IRawRule* rule = pair.second;
721 collectInjections(result, expression, rule,
this, grammar);
726 if (_grammarRepository) {
727 std::vector<std::string> injectionScopeNames = _grammarRepository->injections(_rootScopeName);
728 for (
const auto& injectionScopeName : injectionScopeNames) {
729 IRawGrammar* injectionGrammar = getExternalGrammar(injectionScopeName,
nullptr);
730 if (injectionGrammar) {
731 const std::string* selector = injectionGrammar->injectionSelector;
732 if (selector && !selector->empty()) {
735 IRawRule* injectionRule = (injectionGrammar->repository && injectionGrammar->repository->selfRule)
736 ? injectionGrammar->repository->selfRule
738 collectInjections(result, *selector, injectionRule,
this, injectionGrammar);
745 std::sort(result.begin(), result.end(), [](
const Injection& a,
const Injection& b) {
746 return a.priority < b.priority;
752ITokenizeLineResult Grammar::tokenizeLine(
753 const std::string& lineText,
754 StateStack* prevState,
757 StateStackImpl* prevStateImpl =
dynamic_cast<StateStackImpl*
>(prevState);
758 TokenizeResult r = _tokenize(lineText, prevStateImpl,
false, timeLimit);
760 ITokenizeLineResult result;
761 result.tokens = r.lineTokens->getResult(r.ruleStack, r.lineLength);
762 result.ruleStack = r.ruleStack;
763 result.stoppedEarly = r.stoppedEarly;
769ITokenizeLineResult2 Grammar::tokenizeLine2(
770 const std::string& lineText,
771 StateStack* prevState,
774 StateStackImpl* prevStateImpl =
dynamic_cast<StateStackImpl*
>(prevState);
775 TokenizeResult r = _tokenize(lineText, prevStateImpl,
true, timeLimit);
777 ITokenizeLineResult2 result;
778 result.tokens = r.lineTokens->getBinaryResult(r.ruleStack, r.lineLength);
779 result.ruleStack = r.ruleStack;
780 result.stoppedEarly = r.stoppedEarly;
786Grammar::TokenizeResult Grammar::_tokenize(
787 const std::string& lineText,
788 StateStackImpl* prevState,
789 bool emitBinaryTokens,
794 _rootId = RuleFactory::getCompiledRuleId(
795 _grammar->repository->selfRule,
803 if (!prevState || prevState == StateStackImpl::NULL_STATE) {
806 BasicScopeAttributes rawDefaultMetadata =
807 _basicScopeAttributesProvider->getDefaultAttributes();
808 StyleAttributes* defaultStyle = _themeProvider->getDefaults();
812 rawDefaultMetadata.languageId,
813 rawDefaultMetadata.tokenType,
815 defaultStyle->fontStyle,
816 defaultStyle->foregroundId,
817 defaultStyle->backgroundId
820 Rule* rootRule = getRule(_rootId);
821 std::string* rootScopeName = rootRule ? rootRule->getName(
nullptr,
nullptr) :
nullptr;
823 AttributedScopeStack* scopeList;
825 scopeList = AttributedScopeStack::createRootAndLookUpScopeName(
830 delete rootScopeName;
832 scopeList = AttributedScopeStack::createRoot(
"unknown", defaultMetadata);
835 prevState =
new StateStackImpl(
850 std::string lineTextWithNewline = lineText +
"\n";
851 OnigString* onigLineText = createOnigString(lineTextWithNewline);
852 int lineLength = onigLineText->content().length();
854 LineTokens* lineTokens =
new LineTokens(
858 balancedBracketSelectors
861 StackElement resultStack = tokenizeString(
872 disposeOnigString(onigLineText);
874 TokenizeResult result;
875 result.lineLength = lineLength;
876 result.lineTokens = lineTokens;
877 result.ruleStack = resultStack.stack;
878 result.stoppedEarly = resultStack.stoppedEarly;
885Grammar* createGrammar(
886 const ScopeName& scopeName,
887 IRawGrammar* grammar,
889 const EmbeddedLanguagesMap* embeddedLanguages,
890 const TokenTypeMap* tokenTypes,
891 BalancedBracketSelectors* balancedBracketSelectors,
892 IGrammarRepository* grammarRepository,
893 IThemeProvider* themeProvider,
902 balancedBracketSelectors,
909IRawGrammar* initGrammar(IRawGrammar* grammar, IRawRule* base) {
911 if (!grammar->repository) {
912 grammar->repository =
new IRawRepository();
916 IRawRule* selfRule =
new IRawRule();
919 if (grammar->patterns && !grammar->patterns->empty()) {
920 selfRule->patterns =
new std::vector<IRawRule*>(*grammar->patterns);
923 grammar->patterns->clear();
926 selfRule->name =
new std::string(grammar->scopeName);
928 grammar->repository->selfRule = selfRule;
931 grammar->repository->baseRule = base ? base : selfRule;
RuleId ruleIdFromNumber(int id)
Convert an integer to a RuleId.
int ruleIdToNumber(RuleId id)
Convert a RuleId to its integer value.
FontStyle
Font styling attributes (italic, bold, underline, strikethrough)
@ NotSet
Type not determined or not applicable.
int32_t EncodedTokenAttributes
Compact 32-bit encoding of a token's attributes.