28

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 ; 
5
  • Can you post some code. Which version of ANTLR are you using?
    – user987339
    Commented Nov 5, 2013 at 11:07
  • Are you using tree grammar? Can you post it?
    – user987339
    Commented Nov 5, 2013 at 11:22
  • 1
    What exactly do you mean by tree grammar? Sorry this is my first time posting! Commented Nov 5, 2013 at 11:28
  • You have to write a part for lexical analysis which converts your input into stream of tokens. This is defined by lexical rules. And tree grammar which converts your tokens into semantic tree. This is defined with parser rules. lexical rules + Parser rules = grammar rules.
    – user987339
    Commented Nov 5, 2013 at 11:35
  • Surely the tree grammar is irrelevant here? The parser visitor just goes over the tree generated by it. Wouldn't the line number in the parsed program be independent of these? Commented Nov 5, 2013 at 11:58

3 Answers 3

51

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).

1
  • Thanks. I am using the Javascript target runtime, and ctx.start sure has the line value.
    – yoshi
    Commented Apr 26, 2016 at 10:32
16

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();
2
  • 1
    there is no commonTokenStream when I try this
    – john k
    Commented Mar 8, 2018 at 7:41
  • 1
    @johnktejik, commonTokenStream is available in Antlr-v3, you may using Antlr-v4
    – Ram
    Commented Mar 26, 2018 at 12:19
7

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.