How can I print the line number and of an offending tree node while walking the AST? What if I have '#include'(s) in my source language?

rajesh radhakrishnan

In C++ mode, here are the changes/additions that have to be done (using the example/cpp/treewalk example) MyASTNode.hh:

typedef ANTLR_USE_NAMESPACE(antlr)RefCount ANTLR_USE_NAMESPACE(std)string > RefString;

class MyASTNode : public ANTLR_USE_NAMESPACE(antlr)CommonAST {
private:
    int _line;
    RefString _filename;
    // stores all the different filenames (main file and include files)
    static  ANTLR_USE_NAMESPACE(std)map<RefString,RefString> _filenames;
public:
    MyASTNode();

    int getLine() const;
    const ANTLR_USE_NAMESPACE(std)string&  getFilename() const;

    void initialize(ANTLR_USE_NAMESPACE(antlr)RefToken t);

    static ANTLR_USE_NAMESPACE(antlr)RefAST factory();
};
MyASTNode.cc :
// selector, *parser, *lexer are in extern in Main.hpp (like cpp/includeFile example)

#include "Main.hpp"

// intialize static var
ANTLR_USE_NAMESPACE(std)map<RefString,RefString> MyASTNode::_filenames;

MyASTNode::MyASTNode() {}

int
MyASTNode::getLine() const
{ return _line; }

const ANTLR_USE_NAMESPACE(std)string&
MyASTNode::getFilename() const
{ return *(_filename); }

void
MyASTNode::initialize(ANTLR_USE_NAMESPACE(antlr)RefToken t) {
   ANTLR_USE_NAMESPACE(antlr)CommonAST::initialize(t);
   _line = t->getLine();

   RefString file_name(new
           string(((ANTLR_USE_NAMESPACE(antlr)CharScanner*)
             selector.getCurrentStream())->getFilename()));
   if (_filenames.find(file_name) == _filenames.end()) {// not found
      _filenames[file_name] = file_name;
      _filename = file_name;
   } else {
      _filename = _filenames[file_name];
   }
}

ANTLR_USE_NAMESPACE(antlr)RefAST
MyASTNode::factory()
{ return ANTLR_USE_NAMESPACE(antlr)RefAST(new MyASTNode); }
Main.cpp :
#include "MyASTNode.hpp"

LangParser *parser;
LangLexer *lexer;

int main() {
 lexer = new LangLexer(cin);
 string name(argv[1]);
 lexer->setFilename(name);

 parser = new LangParser(*lexer);

 parser->setASTNodeFactory(&MyASTNode::factory);
 parser->first_rule();

....


treewalk.g : // example grammar file

class LangWalker extends TreeParser;
....
expr:   #(ASSIGN expr expr)
        | ...
        | a:ID
          { 
           MyASTNode *q = static_cast<MyASTNode*>((ANTLR_USE_NAMESPACE(antlr)AST*)a);
           std::cout  a->getText()  " is at line "  q->getLine()
                 " at file "    q->getFilename()  std::endl; 
          }

I know the above answer is probably not presented in a very coherent way. But I hope you get the idea.

If you have any questions/comments/criticsm, pl do reply. :)

Also,

1. some of the grammar files in the examples/cpp directory don't have newline() call after WS_ . ie. WS_ : ' ' /* { newline(); } missing */

2. '-traceTreeParser' option for the treewalker generates wrong 'Tracer' constructor function. It generates,

Tracer traceInOut(this,"program");

//constructor in TreeParser.hpp line# 134
Tracer(TreeParser* p,const ANTLR_USE_NAMESPACE(std)string& t, RefAST a)

Hence my correction (I have a perl script that does this for me),

string s = "program";
Tracer traceInOut(this,s,_t); 
0 Comments  (click to add your comment)
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

About | Sitemap | Contact