Getting the line number in the ParserVisitor?

I'm trying to get line numbers for more specific error messages in my ParserVisitor (visits the parse tree generated by antlr). However, all I have in this class is the context ctx, and I can do things like ctx.getText() but not getLine(). Is there a way to do this?

Can ctx.getPayload() be used here? If so, how?

Edit: I'm using ANTLR 4 to create java files.

Trying to access the line number in a visitor in a method such as this:

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

Edit 2: My lexer and parser rules are fairly standard, for example in the lexer:

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

...is in the parser rule baseType:

baseType : INT | CHAR | BOOL | STRING ; 

Upvotes: 28

Views: 15893

Answers (3)

anjandash
anjandash

Reputation: 827

If you have a ParserRuleContext Object, you can get the line number directly as suggested by @njlarsson:

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

However, if you have just a RuleContext Object, you need to Type Cast it to ParserRuleContext first:

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

Note: >> I'm using ANTLR4 >> In the code snippets above, ctx and rctx are not initialized for brevity. You need to initialize them with appropriate values e.g. ParserRuleContext ctx = parser.compilationUnit();

Upvotes: 7

Sam Harwell
Sam Harwell

Reputation: 99949

You can use ctx.getSourceInterval() to get the range of tokens consumed by the rule. You can use TokenStream.get(int index) to get the token associated with the source interval, and then get the position information from the token.

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

Upvotes: 16

njlarsson
njlarsson

Reputation: 2340

You can get the first token in the rule with ctx.start or ctx.getStart(). Then use getLine() on the token to get the line number (and getCharPositionInLine() to get the column).

Upvotes: 51

Related Questions