[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to obtain the line number of AST node?



On Fri, 24 Nov 2006, Niklas Matthies wrote:

I'm a bit puzzled as I could not find a way to get the line number
of the AST nodes. The token classes have getLine() since they derive
from Token, but after AST translation some AST nodes do not contain
any tokens. AST node classes are derived from Node, which does not
have getLine() so the line number seems to be forgotten in the
translatation. What to do now?

Yes, that's a deficiency I encountered as well. Even when all nodes
contain tokens, you get wrong positional info unless _all_ original
tokens are retained in the AST.

This is kind of contradictory to the idea of the AST translation, which I like very much compared to the "traditional" compiler generators (like CUP + JFlex).

Furthermore, determining position info for the nodes by writing an
analysis which propagates the information from the leaf nodes (tokens)
up to the other nodes can be quite tedious, because you have to write
dedicated code for each node type.

I cooked a bit ugly hack, but it works well for me at the moment. I suppose it might solve the issue for some other people too so here it is. This is not a general solution to the problem, use at your own peril :)

I make a new Node-class after the sablecc is run and put this extension there:

    public Node() { startLine = parser.Parser.last_line; }

    private int startLine;
    public int getStartLine() { return startLine;}

Since Node is always similar (unless sablecc version changes) and does not depend on the syntax, this can be a simple copy operation. Parser.java needs to be adjusted accordingly and this is a bit trickier. Since my stuff needs to work only on my university's Solaris system this is done by putting the following in build.xml:

        <exec executable="sed" output="protoparser">
          <arg line="-e 's/private\ int\ last_line/public\ static\ int\ last_line/g' classes/parser/Parser.java"/>
        </exec>
        <move tofile="classes/parser/Parser.java">
        <fileset dir=".">
        <include name="protoparser"/>
        </fileset>
        </move>

Sed simply replaces "private int last_line" with "public static int last_line" and creates a new file which then replaces the original. This is fine for me, but will not work in every situation. Naturally there can be only one instance of Parser at a given moment and this does not help getting line number information over multiple lines, but in my case these are not required.

--
// Antti Virtanen -//- http://lokori.iki.fi/ -//- 050-4004278