in src/grammar.ts [1043:1194]
function scanNext(): void {
if (DebugFlags.InDebugMode) {
console.log('');
console.log(`@@scanNext ${linePos}: |${lineText.content.substr(linePos).replace(/\n$/, '\\n')}|`);
}
const r = matchRuleOrInjections(grammar, lineText, isFirstLine, linePos, stack, anchorPosition);
if (!r) {
if (DebugFlags.InDebugMode) {
console.log(' no more matches.');
}
// No match
lineTokens.produce(stack, lineLength);
STOP = true;
return;
}
const captureIndices: IOnigCaptureIndex[] = r.captureIndices;
const matchedRuleId: number = r.matchedRuleId;
const hasAdvanced = (captureIndices && captureIndices.length > 0) ? (captureIndices[0].end > linePos) : false;
if (matchedRuleId === -1) {
// We matched the `end` for this rule => pop it
const poppedRule = <BeginEndRule>stack.getRule(grammar);
if (DebugFlags.InDebugMode) {
console.log(' popping ' + poppedRule.debugName + ' - ' + poppedRule.debugEndRegExp);
}
lineTokens.produce(stack, captureIndices[0].start);
stack = stack.setContentNameScopesList(stack.nameScopesList);
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, poppedRule.endCaptures, captureIndices);
lineTokens.produce(stack, captureIndices[0].end);
// pop
const popped = stack;
stack = stack.pop()!;
anchorPosition = popped.getAnchorPos();
if (!hasAdvanced && popped.getEnterPos() === linePos) {
// Grammar pushed & popped a rule without advancing
if (DebugFlags.InDebugMode) {
console.error('[1] - Grammar is in an endless loop - Grammar pushed & popped a rule without advancing');
}
// See https://github.com/Microsoft/vscode-textmate/issues/12
// Let's assume this was a mistake by the grammar author and the intent was to continue in this state
stack = popped;
lineTokens.produce(stack, lineLength);
STOP = true;
return;
}
} else {
// We matched a rule!
const _rule = grammar.getRule(matchedRuleId);
lineTokens.produce(stack, captureIndices[0].start);
const beforePush = stack;
// push it on the stack rule
const scopeName = _rule.getName(lineText.content, captureIndices);
const nameScopesList = stack.contentNameScopesList.push(grammar, scopeName);
stack = stack.push(matchedRuleId, linePos, anchorPosition, captureIndices[0].end === lineLength, null, nameScopesList, nameScopesList);
if (_rule instanceof BeginEndRule) {
const pushedRule = <BeginEndRule>_rule;
if (DebugFlags.InDebugMode) {
console.log(' pushing ' + pushedRule.debugName + ' - ' + pushedRule.debugBeginRegExp);
}
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, pushedRule.beginCaptures, captureIndices);
lineTokens.produce(stack, captureIndices[0].end);
anchorPosition = captureIndices[0].end;
const contentName = pushedRule.getContentName(lineText.content, captureIndices);
const contentNameScopesList = nameScopesList.push(grammar, contentName);
stack = stack.setContentNameScopesList(contentNameScopesList);
if (pushedRule.endHasBackReferences) {
stack = stack.setEndRule(pushedRule.getEndWithResolvedBackReferences(lineText.content, captureIndices));
}
if (!hasAdvanced && beforePush.hasSameRuleAs(stack)) {
// Grammar pushed the same rule without advancing
if (DebugFlags.InDebugMode) {
console.error('[2] - Grammar is in an endless loop - Grammar pushed the same rule without advancing');
}
stack = stack.pop()!;
lineTokens.produce(stack, lineLength);
STOP = true;
return;
}
} else if (_rule instanceof BeginWhileRule) {
const pushedRule = <BeginWhileRule>_rule;
if (DebugFlags.InDebugMode) {
console.log(' pushing ' + pushedRule.debugName);
}
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, pushedRule.beginCaptures, captureIndices);
lineTokens.produce(stack, captureIndices[0].end);
anchorPosition = captureIndices[0].end;
const contentName = pushedRule.getContentName(lineText.content, captureIndices);
const contentNameScopesList = nameScopesList.push(grammar, contentName);
stack = stack.setContentNameScopesList(contentNameScopesList);
if (pushedRule.whileHasBackReferences) {
stack = stack.setEndRule(pushedRule.getWhileWithResolvedBackReferences(lineText.content, captureIndices));
}
if (!hasAdvanced && beforePush.hasSameRuleAs(stack)) {
// Grammar pushed the same rule without advancing
if (DebugFlags.InDebugMode) {
console.error('[3] - Grammar is in an endless loop - Grammar pushed the same rule without advancing');
}
stack = stack.pop()!;
lineTokens.produce(stack, lineLength);
STOP = true;
return;
}
} else {
const matchingRule = <MatchRule>_rule;
if (DebugFlags.InDebugMode) {
console.log(' matched ' + matchingRule.debugName + ' - ' + matchingRule.debugMatchRegExp);
}
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, matchingRule.captures, captureIndices);
lineTokens.produce(stack, captureIndices[0].end);
// pop rule immediately since it is a MatchRule
stack = stack.pop()!;
if (!hasAdvanced) {
// Grammar is not advancing, nor is it pushing/popping
if (DebugFlags.InDebugMode) {
console.error('[4] - Grammar is in an endless loop - Grammar is not advancing, nor is it pushing/popping');
}
stack = stack.safePop();
lineTokens.produce(stack, lineLength);
STOP = true;
return;
}
}
}
if (captureIndices[0].end > linePos) {
// Advance stream
linePos = captureIndices[0].end;
isFirstLine = false;
}
}