[antlr-interest] Newbie: How to debug in C++?
me 262
me262c at gmail.com
Mon Apr 2 12:02:30 PDT 2007
Hi,
I tried to convert Alex Miller's examples into C++ (MSVC7)
http://tech.puredanger.com/2007/01/13/implementing-a-scripting-language-with-antlr-part-1-lexer/
The lexer went OK, the Parser is missing DumpASTVisitor in C++, but
otherwise OK too. The script.g however got a lot of error in
ScriptWalker.hpp. Here is the *.g file for C++ (you can find the java
version on Alex's blog, part 2).
A Main.cpp for testing is also attached.
It would not compile at all. Can someone point out what went wrong here?
Thanks
/* ############################## L E X E R ############################ */
options {
language="Cpp";
}
class ScriptLexer extends Lexer;
options {
k=1; // Only 1 lookahead character required
}
// Define string values - either simple unquoted or complex quoted
STRING : ('a'..'z'|'A'..'Z'|'0'..'9'|'_')+
| ('"' (~'"')* '"');
// Ignore all whitespace
WS :
(' '
| '\t'
| '\r' '\n' { newline(); }
| '\n' { newline(); }
)
{ $setType(antlr::Token::SKIP); } ;
// Single-line comment
LINE_COMMENT : '#' (~('\n'|'\r'))* ('\n'|'\r'('\n')?)?
{ $setType(antlr::Token::SKIP); newline(); } ;
// Punctuation
LBRACE : '{';
RBRACE : '}';
EQUALS : '=';
SEMI : ';';
/* ############################## P A R S E R ############################ */
class ScriptParser extends Parser;
options {
buildAST=true; // Automatically build the AST while parsing
k=2; // Need lookahead of two for props without keys (to check for the =)
}
tokens {
SCRIPT; // Imaginary token inserted at the root of the script
BLOCK; // Imaginary token inserted at the root of a block
COMMAND; // Imaginary token inserted at the root of a command
PROPERTY; // Imaginary token inserted at the root of a property
}
/**
* Parse a script, which consists of 0 or more blocks. The AST
produced will contain an imaginary
* SCRIPT node at the root with child block ASTs.
*/
script : (block)*
{#script = #([SCRIPT, "SCRIPT"], #script);}; // Magic to insert the
imgainary SCRIPT node
/**
* Parse a block, which consists of a block name then 0 or more
commands in { }. The AST produced
* will contain an imaginary BLOCK node at the root with children
which are the block name followed
* by an AST for each child command. The { } are not included in the AST.
*/
block : (STRING LBRACE! (command)* RBRACE!)
{#block = #([BLOCK, "BLOCK"], #block);};
/**
* Parse a command, which consists of a command name, followed by 0
or more command properties and
* terminated with a semicolon.
*/
command : (STRING (property)* SEMI!)
{#command = #([COMMAND, "COMMAND"], #command);};
/**
* Parse a property definition, which consists either of an unkeyed value
* or as a key-value pair. The AST produced will contain an
imaginary PROPERTY token node at the root
* with either one child (for a non-keyed value) or two children if
there is a key and a value.
* The = is not included in the AST.
*/
property : ( (STRING EQUALS!)? STRING)
{#property = #([PROPERTY, "PROPERTY"], #property);};
/* ############################## T R E E W A L K E R
############################ */
class ScriptWalker extends TreeParser;
{
/**
* Helper method to remove quotes from a quoted string.
* @param value The value to remove quotes from
* @return The value with surrounding quotes (if any) removed
*/
std::string removeQuotes(std::string &value) {
// if(value != null && value.startsWith("\"")) {
// return value.substring(1, value.length()-1);
// }
return value;
}
}
/**
* Look for SCRIPT node with child BLOCK ASTs and return a Script object
* @return Script object, never null
*/
script returns [Script script]
{
script = new Script();
}
: #( SCRIPT (block[script] )* );
/**
* Look for BLOCK node with child COMMAND ASTs and add any block
found to the blocks list.
* @param blocks The blocks being collected
*/
block [Script script]
{
Block block = null;
}
: #( BLOCK
(
b:STRING
{
block = new Block(removeQuotes(b->getText()));
}
(command[block])*
)
)
{ script->addBlock(block); }
;
/**
* Look for COMMAND node with child command name and properties and
add the command
* info to the block.
* @param block The block being parsed
*/
command [Block block]
{
Command command = null;
}
: #( COMMAND
(
c:STRING
{
command = new Command(removeQuotes(c->getText()));
block->addCommand(command);
}
(property[command])*
)
);
/**
* Look for PROPERTY node with child (optional) key and value and add
the property
* to the current CommandInfo.
* @param command The current command
*/
property [Command command]
: #( PROPERTY
(
p1:STRING (p2:STRING)?
{
if(p2 == null) {
command->addProperty(removeQuotes(p1->getText()));
} else {
command->addProperty(removeQuotes(p1->getText()),
removeQuotes(p2->getText()));
}
}
)
);
//--------------------------------------------------------------------------------
// The main.cpp
//--------------------------------------------------------------------------------
/* Calculate an expression read from stdin or from the arguments passed to
* the program (using stringstream's)
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "antlr/CommonAST.hpp"
#include "antlr/AST.hpp"
#include "ScriptLexer.hpp"
#include "ScriptParser.hpp"
#include "ScriptWalker.hpp"
using namespace std;
string getTokenType(int tokenType)
{
switch(tokenType) {
case ScriptLexerTokenTypes::STRING: return "STRING";
case ScriptLexerTokenTypes::LBRACE: return "LBRACE";
case ScriptLexerTokenTypes::RBRACE: return "RBRACE";
case ScriptLexerTokenTypes::EQUALS: return "EQUALS";
case ScriptLexerTokenTypes::SEMI: return "SEMI";
default: return "OTHER";
}
}
int main( int argc, char* argv[] )
{
ANTLR_USING_NAMESPACE(std)
ANTLR_USING_NAMESPACE(antlr)
try
{
ifstream in(argv[1],ios::in);
ScriptLexer lexer(in);
/*
RefToken token = lexer.nextToken();
while(token->getType() != ScriptLexerTokenTypes::EOF_) {
cout << "\t" + getTokenType(token->getType()) + "\t\t" +
token->getText()<<endl;
token = lexer.nextToken();
}
*/
ScriptParser parser(lexer);
ASTFactory ast_factory;
parser.initializeASTFactory(ast_factory);
parser.setASTFactory(&ast_factory);
parser.script();
RefAST ast = (RefAST) parser.getAST();
/*
DumpASTVisitor visitor;
visitor.visit(ast);
*/
}
catch(ANTLRException& e)
{
cerr << "Parse exception: " << e.toString() << endl;
return -1;
}
catch(exception& e)
{
cerr << "exception: " << e.what() << endl;
return -1;
}
return 0;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: script.g
Type: application/octet-stream
Size: 4751 bytes
Desc: not available
Url : http://www.antlr.org/pipermail/antlr-interest/attachments/20070402/c6a7a416/attachment.obj
-------------- next part --------------
/* Calculate an expression read from stdin or from the arguments passed to
* the program (using stringstream's)
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "antlr/CommonAST.hpp"
#include "antlr/AST.hpp"
#include "ScriptLexer.hpp"
#include "ScriptParser.hpp"
#include "ScriptWalker.hpp"
using namespace std;
string getTokenType(int tokenType)
{
switch(tokenType) {
case ScriptLexerTokenTypes::STRING: return "STRING";
case ScriptLexerTokenTypes::LBRACE: return "LBRACE";
case ScriptLexerTokenTypes::RBRACE: return "RBRACE";
case ScriptLexerTokenTypes::EQUALS: return "EQUALS";
case ScriptLexerTokenTypes::SEMI: return "SEMI";
default: return "OTHER";
}
}
int main( int argc, char* argv[] )
{
ANTLR_USING_NAMESPACE(std)
ANTLR_USING_NAMESPACE(antlr)
try
{
ifstream in(argv[1],ios::in);
ScriptLexer lexer(in);
/*
RefToken token = lexer.nextToken();
while(token->getType() != ScriptLexerTokenTypes::EOF_) {
cout << "\t" + getTokenType(token->getType()) + "\t\t" + token->getText()<<endl;
token = lexer.nextToken();
}
*/
ScriptParser parser(lexer);
ASTFactory ast_factory;
parser.initializeASTFactory(ast_factory);
parser.setASTFactory(&ast_factory);
parser.script();
RefAST ast = (RefAST) parser.getAST();
/*
DumpASTVisitor visitor;
visitor.visit(ast);
*/
}
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