package org.intellij.plugins.markdown.lang.lexer;
import com.intellij.lexer.LexerBase;
import com.intellij.psi.tree.IElementType;
import org.intellij.markdown.ast.ASTNode;
import org.intellij.markdown.ast.ASTNodeKt;
import org.intellij.markdown.ast.visitors.RecursiveVisitor;
import org.intellij.plugins.markdown.lang.MarkdownElementType;
import org.intellij.plugins.markdown.lang.parser.MarkdownParserManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class MarkdownToplevelLexer extends LexerBase {
private CharSequence myBuffer;
private int myBufferStart;
private int myBufferEnd;
private List<IElementType> myLexemes;
private List<Integer> myStartOffsets;
private List<Integer> myEndOffsets;
private int myLexemeIndex;
@Override
public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int initialState) {
myBuffer = buffer;
myBufferStart = startOffset;
myBufferEnd = endOffset;
final ASTNode parsedTree = MarkdownParserManager.parseContent(buffer.subSequence(startOffset, endOffset));
myLexemes = new ArrayList<>();
myStartOffsets = new ArrayList<>();
myEndOffsets = new ArrayList<>();
ASTNodeKt.accept(parsedTree, new LexerBuildingVisitor());
myLexemeIndex = 0;
}
@Override
public int getState() {
return myLexemeIndex;
}
@Nullable
@Override
public IElementType getTokenType() {
if (myLexemeIndex >= myLexemes.size()) {
return null;
}
return myLexemes.get(myLexemeIndex);
}
@Override
public int getTokenStart() {
if (myLexemeIndex >= myLexemes.size()) {
return myBufferEnd;
}
return myBufferStart + myStartOffsets.get(myLexemeIndex);
}
@Override
public int getTokenEnd() {
if (myLexemeIndex >= myLexemes.size()) {
return myBufferEnd;
}
return myBufferStart + myEndOffsets.get(myLexemeIndex);
}
@Override
public void advance() {
myLexemeIndex++;
}
@NotNull
@Override
public CharSequence getBufferSequence() {
return myBuffer;
}
@Override
public int getBufferEnd() {
return myBufferEnd;
}
private class LexerBuildingVisitor extends RecursiveVisitor {
@Override
public void visitNode(@NotNull ASTNode node) {
if (node.getStartOffset() == node.getEndOffset()) {
return;
}
final List<ASTNode> children = node.getChildren();
if (children.isEmpty()) {
myLexemes.add(MarkdownElementType.platformType(node.getType()));
myStartOffsets.add(node.getStartOffset());
myEndOffsets.add(node.getEndOffset());
}
else {
super.visitNode(node);
}
}
}
}