[antlr-interest] Problems with treeParser in V2 with c++ target

Joachim Mårtensson joachimm at etek.chalmers.se
Mon May 7 12:55:44 PDT 2007


Hello,
I am trying to learn how to use Antlr with C++ as a target, and I thought
I should try out something relatively easy. Basically I thought I should
extend the calc example in the cpp folder to work like the expression
parser in the Antlr (beta) book, however I am running into problems.

$./out "(4+5*8);"
 ( + 4 ( * 5 8 ) )
<AST>: unexpected AST node: 4
expr:0value is 0 <- my debug output

I find this hard to figure out, I am guessing that I am setting up the
ParseTree in the wrong way or something but I cannot figure out how.

Thanks in advance
Joachim

my treeGrammar file looks like this.
header
{
    #include <map>;
    #include <string>;
    #include <iostream>;

}

options {
    language="Cpp";
}
class CalcTreeWalker extends TreeParser;

{
    public:
     std::map<std::string, double> idMem;
}

prog returns [double ret]
{
    ret = 0.0;
    double total = 0;
}
: (total = stat {ret += total;})+ ;

stat returns [double st]
{
     st = 0;
}
    :   #(ASSIGN c:ID st = expr) { idMem[c->getText()]= st;}
    |   st = expr { std::cout << "expr:"<< st;} ;
expr returns [double r]
{
    double a,b;
    r=0;
}
    :   #(PLUS a=expr b=expr)    {r = a+b;}
    |   #(MINUS a=expr b=expr)    {r = a-b;}
    |   #(STAR a=expr b=expr)    {r = a*b;}
    |   i:INT            {r = atof(i->getText().c_str());}
    |   k:ID {if (idMem.count(k->getText()) > 0) r = idMem[k->getText()];
else r = 0;}
    ;

-------------
and the Parser and Lexer looks like this.
-------------

options {
    language="Cpp";
}

class CalcParser extends Parser;
options {
    //genHashLines = true;        // include line number information
    buildAST = true;            // uses CommonAST by default
    k = 2;
}

prog: (stat)+ ;

stat: expr SEMI!
    | ID ASSIGN^ expr SEMI! ;

expr
    : mexpr ((PLUS^|MINUS^) mexpr)*
    ;

mexpr
    :    atom (STAR^ atom)*
    ;


atom: INT
    | ID
    | LPAREN! expr RPAREN!
    ;

class CalcLexer extends Lexer;

WS_    :    (' '
    |    '\t'
    |    '\n'
    |    '\r')
        { _ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; }
    ;

LPAREN:    '('
    ;

RPAREN:    ')'
    ;
LBRACKET: '[' ;
RBRACKET: ']' ;
ASSIGN: '=' ;
STAR:    '*'
    ;
ID
    	:	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
    	;


STRING_LITERAL	: 	'"'	(~'"')* '"' ;

MINUS: '-' ;

PLUS:    '+'
    ;

SEMI:    ';'
    ;

protected
DIGIT
    :    '0'..'9'
    ;

INT    :    (DIGIT)+
    ;

-------------------
I use the following code to set up the parser and tree. (almost identical
to the Main file in the cpp/calc example folder)

-------------------
/* Calculate an expression read from stdin or from the arguments passed to
 * the program (using stringstream's)
 */
#include <iostream>
#include <sstream>
#include <map>;
#include "antlr/AST.hpp"
#include "CalcLexer.hpp"
#include "CalcParser.hpp"
#include "CalcTreeWalker.hpp"

int main( int argc, char* argv[] )
{
	ANTLR_USING_NAMESPACE(std)
	ANTLR_USING_NAMESPACE(antlr)
	try
	{
		ostringstream expr;
		istringstream input_string;
		istream *input = &cin;
		const char *filename = "<cin>";

		if( argc > 1 )
		{
			// write the argv strings to a ostringstream...
			for( int i = 1; i < argc; i++ )
			{
				if( i > 1 && i != (argc-1))
					expr << ' ';
				expr << argv[i];
			}
			input_string.str(expr.str());
			input = &input_string;
			filename = "<arguments>";
		}

		CalcLexer lexer(*input);
		lexer.setFilename(filename);

		CalcParser parser(lexer);
		parser.setFilename(filename);

		ASTFactory ast_factory;
		parser.initializeASTFactory(ast_factory);
		parser.setASTFactory(&ast_factory);

		// Parse the input expression
		parser.prog();
		RefAST t = parser.getAST();
		if( t )
		{
	  	// Print the resulting tree out in LISP notation
			cout << t->toStringTree() << endl;
			CalcTreeWalker walker;

	  	// Traverse the tree created by the parser
			walker.initializeASTFactory(ast_factory);
            walker.setASTFactory(&ast_factory);
			double r = walker.prog(t);

            for(map<string, double>::const_iterator it =
walker.idMem.begin(); it != walker.idMem.end(); ++it)
            {
                cout << "first: " << it->first << "second:\t" <<
it->second << endl;
            }
			cout << "value is " << r << endl;
		}
		else
			cout << "No tree produced" << endl;

	}
	catch(ANTLRException& e)
	{
		cerr << "Parse exception: " << e.toString() << endl;
		return -1;
	}
	catch(exception& e)
	{
		cerr << "exception: " << e.what() << endl;
		return -1;
	}
	return 0;
}





More information about the antlr-interest mailing list