You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Antlr PLSQL Parser获取表达式的字符位置

如何在ANTLR PL/SQL Parser中获取特定表达式的字符位置?

我正在使用ANTLR PL/SQL Parser处理来自Oracle Forms的SQL代码,已经生成了所需的Java类,主代码运行正常(代码如下),能获取语法错误数量和解析树子节点,但不知道如何获取特定表达式的字符位置,已知ANTLR具备该能力,特此求助。

CharStream charStream = CharStreams.fromString("CREATE FUNCTION totalCustomers \r\n"
                + "RETURN number IS \r\n"
                + "   total number(2) := 0; \r\n"
                + "BEGIN \r\n"
                + "   SELECT count(*) into total \r\n"
                + "   FROM customers; \r\n"
                + "   RETURN total; \r\n"
                + "END; ");

PlSqlLexer plSqlLexer = new PlSqlLexer(charStream); // 注:原代码中charStream2应为charStream
        
CommonTokenStream commonTokenStream = new CommonTokenStream(plSqlLexer);
        
PlSqlParser plSqlParser = new PlSqlParser(commonTokenStream);

PlSqlParser.Create_function_bodyContext sql_scriptContext = plSqlParser.create_function_body();

解决方案:利用ANTLR上下文对象的位置方法

ANTLR生成的所有解析树上下文类(比如Create_function_bodyContext、各类子节点上下文)都继承自ParserRuleContext,该类提供了获取起始和结束位置的核心方法:

  • getStart():返回对应规则/表达式的起始Token
  • getStop():返回对应规则/表达式的结束Token

每个Token对象包含以下关键位置信息:

  • getLine():行号(从1开始计数)
  • getCharPositionInLine():行内列号(从0开始计数)
  • getStartIndex():在原始字符流中的起始偏移量(从0开始)
  • getStopIndex():在原始字符流中的结束偏移量(包含该位置字符)

示例:获取count(*)的字符位置

以你的代码为例,若要获取SELECT count(*) ...中count(*)的位置,可按以下步骤操作:

// 从根上下文定位到SELECT语句节点
PlSqlParser.Select_statementContext selectStmtCtx = sql_scriptContext.select_statement();

// 从SELECT语句定位到函数调用节点(对应count(*))
PlSqlParser.Function_callContext funcCallCtx = selectStmtCtx.select_list()
    .select_list_element()
    .expression()
    .function_call();

// 获取起始位置信息
Token startToken = funcCallCtx.getStart();
int startLine = startToken.getLine();
int startCol = startToken.getCharPositionInLine();
int startOffset = startToken.getStartIndex();

// 获取结束位置信息
Token stopToken = funcCallCtx.getStop();
int endLine = stopToken.getLine();
int endCol = stopToken.getCharPositionInLine();
int endOffset = stopToken.getStopIndex();

// 输出结果
System.out.println("count(*) 位置信息:");
System.out.println("起始行:" + startLine + ",起始列:" + startCol);
System.out.println("结束行:" + endLine + ",结束列:" + endCol);
System.out.println("字符偏移范围:[" + startOffset + ", " + endOffset + "]");

额外提示

  • 若需要更细粒度的位置(比如count(*)中的*),可以继续深入子节点(比如funcCallCtx.getChild(...)),重复上述位置获取步骤
  • 可以通过charStream.getText(startOffset, endOffset)获取对应位置的原始文本,验证位置是否正确
  • 解析树节点的层级关系可参考ANTLR生成的PlSqlParser.java文件中的上下文类定义,或使用ANTLR可视化工具查看解析树结构

内容的提问来源于stack exchange,提问作者Alena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:31:19