使用 ANTLR4 确定文件中某个位置的上下文

Determining context at a position in file using ANTLR4

我正在尝试在 JavaScript 中为 VS Code 编写语言扩展,但我似乎遗漏了一些东西。

我的语言有 Lexer.g4 和 Parser.g4,可以使用它们生成树。

我的问题是 VS Code API 为我提供了一个文档和该文档中的一个位置(行 #,字符 #)。从我为 ANTLR4 查看的任何示例中,我似乎无法找到任何生成的函数,这些函数在文件中占据一个位置并返回该位置的树节点。

我想知道,比如光标在函数名上。

我是否应该遍历整个树并检查标记的位置以查看它们是否包含我在编辑器中的位置?或者也许我没有使用正确的工具来完成这项工作?我觉得我可能遗漏了一些更基本的东西。

是的,您必须遍历解析树才能找到给定位置的上下文。这是一个非常简单的任务,您可以在我的 ANLTR4 exension for vscode 中看到它的实际操作。有多个函数返回对给定位置有用的东西。比如这个:

/**
 * Returns the parse tree which covers the given position or undefined if none could be found.
 */
function parseTreeFromPosition(root: ParseTree, column: number, row: number): ParseTree | undefined {
    // Does the root node actually contain the position? If not we don't need to look further.
    if (root instanceof TerminalNode) {
        let terminal = (root as TerminalNode);
        let token = terminal.symbol;
        if (token.line != row)
            return undefined;

        let tokenStop = token.charPositionInLine + (token.stopIndex - token.startIndex + 1);
        if (token.charPositionInLine <= column && tokenStop >= column) {
            return terminal;
        }
        return undefined;
    } else {
        let context = (root as ParserRuleContext);
        if (!context.start || !context.stop) { // Invalid tree?
            return undefined;
        }

        if (context.start.line > row || (context.start.line == row && column < context.start.charPositionInLine)) {
            return undefined;
        }

        let tokenStop = context.stop.charPositionInLine + (context.stop.stopIndex - context.stop.startIndex + 1);
        if (context.stop.line < row || (context.stop.line == row && tokenStop < column)) {
            return undefined;
        }

        if (context.children) {
            for (let child of context.children) {
                let result = parseTreeFromPosition(child, column, row);
                if (result) {
                    return result;
                }
            }
        }
        return context;

    }
}