2
我想獲得文本中給定位置的最可能令牌列表(行和列號)以確定必須填充的內容用於完成自動代碼。這可以通過使用ANTLR 4 API輕鬆實現。根據ANTLR4中的行號和列號獲取最可能的令牌類型
我想獲得給定位置的令牌的可能列表,因爲用戶可能正在寫入/編輯文本中間的某個位置,這仍然保證了可能的令牌列表。
請給我一些指導,因爲我無法找到關於此主題的在線資源。
我想獲得文本中給定位置的最可能令牌列表(行和列號)以確定必須填充的內容用於完成自動代碼。這可以通過使用ANTLR 4 API輕鬆實現。根據ANTLR4中的行號和列號獲取最可能的令牌類型
我想獲得給定位置的令牌的可能列表,因爲用戶可能正在寫入/編輯文本中間的某個位置,這仍然保證了可能的令牌列表。
請給我一些指導,因爲我無法找到關於此主題的在線資源。
通過行號獲取令牌的一種方法是爲您的語法創建一個ParseTreeListener
,使用它來遍歷給定的ParseTree並按行號索引TerminalNodes。我不知道C#,但這是我在Java中完成的。邏輯應該是相似的。
public class MyLineIndexer extends MyGrammarParserBaseListener {
protected MultiMap<Integer, TerminalNode> filelineTokenIndex;
@Override
public void visitTerminal(@NotNull TerminalNode node) {
// map every token to its file line for searching later...
if (node.getSymbol() != null) {
List<TerminalNode> tokens;
Integer line = node.getSymbol().getLine();
if (!filelineTokenIndex.containsKey(line)) {
tokens = new ArrayList<>();
filelineTokenIndex.put(line, tokens);
} else {
tokens = filelineTokenIndex.get(line);
}
tokens.add(node);
}
super.visitTerminal(node);
}
}
然後步行解析樹通常的方式...
ParseTree parseTree = ... ; // parse it how you want to
MyLineIndexer indexer = new MyLineIndexer();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(indexer, parseTree);
獲取令牌在一條線,現在的範圍是相當簡單的,高效的假設你有一個令牌的合理數量線。例如,您可以添加另一種方法是這樣的監聽器:
public TerminalNode findTerminalNodeAtCaret(int caretPos, int caretLine) {
if (caretPos <= 0) return null;
if (this.filelineTokenIndex.containsKey(caretLine)) {
List<TerminalNode> nodes = filelineTokenIndex.get(caretLine);
if (nodes.size() == 0) return null;
int tokenEndPos, tokenStartPos;
for (TerminalNode n : nodes) {
if (n.getSymbol() != null) {
tokenEndPos = n.getSymbol().getCharPositionInLine() + n.getText().length();
tokenStartPos = n.getSymbol().getCharPositionInLine();
// If the caret is within this token, return this token
if (caretPos >= tokenStartPos && caretPos <= tokenEndPos) {
return n;
}
}
}
}
return null;
}
您還需要確保你的解析器允許「寬鬆」的解析。在輸入語言結構時,它可能不是有效的。你的解析器規則應該允許這個。