如何在ParserVisitor中获取行号?

28

我正在尝试在我的ParserVisitor(访问antlr生成的语法树)中获取行号以获得更具体的错误信息。然而,在这个类中我只有上下文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 ; 

你能贴一些代码吗?你正在使用哪个版本的ANTLR? - user987339
你使用树形语法吗?你能发一下吗? - user987339
1
你所说的树形语法是什么意思?抱歉,这是我第一次发布! - i_have_no_idea_what_i'm_doing
你需要编写一个词法分析器,将输入转换为标记流。这是由词法规则定义的。还有一个树形语法分析器,将您的标记转换为语义树。这是由解析规则定义的。词法规则+解析规则=语法规则。 - user987339
树形语法在这里无关紧要吧?解析器访问者只是遍历由其生成的树。解析程序中的行号不会受到这些影响,对吧? - i_have_no_idea_what_i'm_doing
3个回答

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

谢谢。我正在使用JavaScript目标运行时,而ctx.start确实具有该行值。 - yoshi

16

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

Interval sourceInterval = ctx.getSourceInterval();
Token firstToken = commonTokenStream.get(sourceInterval.a);
int line = firstToken.getLine();

1
当我尝试这样做时,没有commonTokenStream。 - john k
1
@johnktejik,commonTokenStreamAntlr-v3中可用,您可以使用Antlr-v4 - Ram

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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接