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?
Created May 4, 2012
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);