Need to parse SQL query to C++ code in project, so I had to learn antlr these days.
Let’s write a small sample file “Calc.g” for antlr3:
grammar Calc;
options {
language = Cpp;
}
@lexer::header {
#include
#include
Then add "antlr-3.5.2-complete.jar" (run "mvn package" on source code path of antlr3 will generate this jar) to CLASSPATH and run:
java org.antlr.Tool Calc.g
It will generate many code files: CalcLexer.[hpp/cpp], CalcParser.[hpp/cpp], Calc.tokens. Now we could compile all generated C++ codes:
g++ CalcLexer.cpp CalcParser.cpp Test.cpp -I$(ANTLR3_SRC_PATH)/runtime/Cpp/include/ -I./ -o Test
("ANTLR3_SRC_PATH" is where the antlr3 source code are
But this step lead compiler errors for g++:
CalcParser.cpp: In member function ‘void CalcParser::stat()’:
CalcParser.cpp:436:67: error: invalid conversion from ‘const CommonTokenType* {aka const antlr3::CommonToken >*}’ to ‘antlr3::Traits::CommonTokenType* {aka antlr3::CommonToken >*}’ [-fpermissive]
ID2 = this->matchToken(ID, &FOLLOW_ID_in_stat106);
^
CalcParser.cpp: In member function ‘int CalcParser::atom()’:
CalcParser.cpp:836:70: error: invalid conversion from ‘const CommonTokenType* {aka const antlr3::CommonToken >*}’ to ‘antlr3::Traits::CommonTokenType* {aka antlr3::CommonToken >*}’ [-fpermissive]
INT4 = this->matchToken(INT, &FOLLOW_INT_in_atom276);
^
CalcParser.cpp:854:67: error: invalid conversion from ‘const CommonTokenType* {aka const antlr3::CommonToken >*}’ to ‘antlr3::Traits::CommonTokenType* {aka antlr3::CommonToken >*}’ [-fpermissive]
ID5 = this->matchToken(ID, &FOLLOW_ID_in_atom288);
^
The reason is 'ID' and 'INT' should be declare as "const CommonTokenType*", rather than "CommonTokenType*". The fix has already be commited to antlr3 and be contained in master branch of git tree. Therefore I checkout the master branch of antlr3 instead of "3.5.2" tag, re-package the jar of antlr3, re-generate the code for "Calc.g", and the compiler errors disappeared.
The target executable file is "Test", now we can use it to parse our "code":
echo "a=3
b=4
3+a*b" | ./Test
15
The result '15' is correct.