26

我试图在我的 ParserVisitor 中获取更具体的错误消息的行号(访问由 antlr 生成的解析树)。但是,我在这门课上只有 context ctx,我可以做类似ctx.getText()但不能做的事情getLine()。有没有办法做到这一点?

可以ctx.getPayload()在这里使用吗?如果是这样,怎么做?

编辑:我正在使用 ANTLR 4 创建 java 文件。

尝试以如下方法访问访问者中的行号:

@Override 
public Type visitStatAssign(@NotNull BasicParser.StatAssignContext ctx) {
...
// some semantic error detected
int lineNo = ...
System.err.("Semantic error at line " + lineNo); 
}

编辑 2:我的词法分析器和解析器规则是相当标准的,例如在词法分析器中:

INT : 'int' ;
CHAR : 'char' ;
BOOL : 'bool' ;
STRING : 'string' ; 

...在解析器规则 baseType 中:

baseType : INT | CHAR | BOOL | STRING ; 
4

3 回答 3

46

您可以使用ctx.start或获取规则中的第一个标记ctx.getStart()。然后getLine()在令牌上使用来获取行号(并getCharPositionInLine()获取列)。

于 2014-01-11T17:28:24.140 回答
16

您可以使用ctx.getSourceInterval()来获取规则使用的令牌范围。您可以使用TokenStream.get(int index)获取与源区间关联的token,然后从token中获取位置信息。

Interval sourceInterval = ctx.getSourceInterval();
Token firstToken = commonTokenStream.get(sourceInterval.a);
int line = firstToken.getLine();
于 2013-11-05T22:01:54.407 回答
7

如果您有 ParserRuleContext 对象,则可以按照@njlarsson 的建议直接获取行号:

ParserRuleContext ctx; 
int line = ctx.getStart().getLine();

但是,如果您只有一个 RuleContext 对象,则需要先将其类型转换为 ParserRuleContext:

RuleContext rctx;
ParserRuleContext ctx = (ParserRuleContext) rctx; 
int line = ctx.getStart().getLine();

注意: >> 我使用的是 ANTLR4 >> 在上面的代码片段中,为了简洁起见ctxrctx没有初始化。您需要使用适当的值初始化它们,例如ParserRuleContext ctx = parser.compilationUnit();

于 2019-11-19T09:36:24.053 回答