配置
ANTLR4 不提供 Linux 下的二进制文件,所以需要ANTLR4手动生成C++的代码,首先下载runtime库:https://www.antlr.org/download/antlr4-cpp-runtime-4.9.1-source.zip。这个链接是4.9.1版本的ANTLR4库,需要其他版本的库就直接改链接就可以了。
解压后命名为runtime-cpp,进入runtime-cpp文件夹,执行以下指令:
cd antlr/runtime/Cpp
mkdir build && cd build
cmake ..
make -j20 && make install
若出现依赖的问题,则安装好依赖即可(需要的依赖: build-essential、make、cmake、g++、git、uuid-dev、pkg-config)
编译完后,头文件放在 /usr/local/include/antlr4-runtime
,链接库放在 /usr/local/lib
。
使用
我们写一个简单的hello.g4代码:
grammar hello; // 定义文法的名字
s : 'hello' ID ; // 匹配关键字hello和标志符
ID : [a-z]+ ; // 标志符由小写字母组成
WS : [ \t\r\n]+ -> skip ; // 跳过空格、制表符、回车符和换行符
然后在文件目录下运行
antlr4 -Dlanguage=Cpp NC.g4
运行之后会生成一些.cpp .h文件
然后我们新建main.cpp文件
/*main.cpp*/
#include <iostream>
#include "antlr4-runtime.h"
#include "helloLexer.h"
#include "helloParser.h"
#pragma execution_character_set("utf-8")
#pragma comment(lib, "antlr4-runtime.lib") //安装方法中静态库引用
using namespace antlr4;
// 递归遍历解析树节点并获取文本内容
std::string getTextFromNode(tree::ParseTree* node) {
std::string text = "";
for (size_t i = 0; i < node->children.size(); i++) {
tree::ParseTree* child = node->children[i];
if (child != nullptr) {
text += getTextFromNode(child) + " & ";
}
}
if (auto terminalNode = dynamic_cast<tree::TerminalNode*>(node)) {
text += terminalNode->getText();
}
return text;
}
int main(int argc, const char* argv[]) {
ANTLRInputStream input(std::cin);
helloLexer lexer(&input);
CommonTokenStream tokens(&lexer);
helloParser parser(&tokens);
// 开始解析输入
helloParser::SContext* tree = parser.s();
// 调用方法遍历解析树根节点并获取文本内容
std::string treeText = getTextFromNode(tree);
// 输出解析内容
std::cout << "解析结果: " << std::endl;
std::cout << treeText << std::endl;
return 0;
}
再编写makefile文件:
CC = g++
ANTLR_INCLUDE_DIR = /usr/local/include/antlr4-runtime #头文件目录
ANTLR_LIB_DIR = /usr/local/lib #库文件目录
CXXFLAGS = -I$(ANTLR_INCLUDE_DIR) $(shell find $(ANTLR_INCLUDE_DIR) -type d | sed 's/^/-I/') #用来找头文件目录及其子目录
LDFLAGS = -L$(ANTLR_LIB_DIR) $(shell find $(ANTLR_LIB_DIR) -type d | sed 's/^/-L/') -lantlr4-runtime #用来找库文件目录及其子目录
SRCS = main.cpp helloBaseListener.cpp helloLexer.cpp helloListener.cpp helloParser.cpp #所有.cpp文件
OBJS = $(SRCS:.cpp=.o)
TARGET = helloworld #目标文件:hellowolrd
$(TARGET): $(OBJS)
$(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
%.o: %.cpp
$(CC) $(CXXFLAGS) -c -o $@ $<
clean:
rm -f $(OBJS) $(TARGET)
然后在目录下运行make指令,看见输出如下
sungjoeng@LAPTOP-0G9E5KJ7:~/antlr4Project/hello$ make
g++ -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime/tree -I/usr/local/include/antlr4-runtime/tree/pattern -I/usr/local/include/antlr4-runtime/tree/xpath -I/usr/local/include/antlr4-runtime/.idea -I/usr/local/include/antlr4-runtime/internal -I/usr/local/include/antlr4-runtime/support -I/usr/local/include/antlr4-runtime/atn -I/usr/local/include/antlr4-runtime/dfa -I/usr/local/include/antlr4-runtime/misc -c -o main.o main.cpp
g++ -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime/tree -I/usr/local/include/antlr4-runtime/tree/pattern -I/usr/local/include/antlr4-runtime/tree/xpath -I/usr/local/include/antlr4-runtime/.idea -I/usr/local/include/antlr4-runtime/internal -I/usr/local/include/antlr4-runtime/support -I/usr/local/include/antlr4-runtime/atn -I/usr/local/include/antlr4-runtime/dfa -I/usr/local/include/antlr4-runtime/misc -c -o helloBaseListener.o helloBaseListener.cpp
g++ -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime/tree -I/usr/local/include/antlr4-runtime/tree/pattern -I/usr/local/include/antlr4-runtime/tree/xpath -I/usr/local/include/antlr4-runtime/.idea -I/usr/local/include/antlr4-runtime/internal -I/usr/local/include/antlr4-runtime/support -I/usr/local/include/antlr4-runtime/atn -I/usr/local/include/antlr4-runtime/dfa -I/usr/local/include/antlr4-runtime/misc -c -o helloLexer.o helloLexer.cpp
g++ -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime/tree -I/usr/local/include/antlr4-runtime/tree/pattern -I/usr/local/include/antlr4-runtime/tree/xpath -I/usr/local/include/antlr4-runtime/.idea -I/usr/local/include/antlr4-runtime/internal -I/usr/local/include/antlr4-runtime/support -I/usr/local/include/antlr4-runtime/atn -I/usr/local/include/antlr4-runtime/dfa -I/usr/local/include/antlr4-runtime/misc -c -o helloListener.o helloListener.cpp
g++ -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime/tree -I/usr/local/include/antlr4-runtime/tree/pattern -I/usr/local/include/antlr4-runtime/tree/xpath -I/usr/local/include/antlr4-runtime/.idea -I/usr/local/include/antlr4-runtime/internal -I/usr/local/include/antlr4-runtime/support -I/usr/local/include/antlr4-runtime/atn -I/usr/local/include/antlr4-runtime/dfa -I/usr/local/include/antlr4-runtime/misc -c -o helloParser.o helloParser.cpp
g++ -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime -I/usr/local/include/antlr4-runtime/tree -I/usr/local/include/antlr4-runtime/tree/pattern -I/usr/local/include/antlr4-runtime/tree/xpath -I/usr/local/include/antlr4-runtime/.idea -I/usr/local/include/antlr4-runtime/internal -I/usr/local/include/antlr4-runtime/support -I/usr/local/include/antlr4-runtime/atn -I/usr/local/include/antlr4-runtime/dfa -I/usr/local/include/antlr4-runtime/misc -o hellowolrd main.o helloBaseListener.o helloLexer.o helloListener.o helloParser.o -L/usr/local/lib -L/usr/local/lib -L/usr/local/lib/pkgconfig -L/usr/local/lib/cmake -L/usr/local/lib/cmake/GTest -L/usr/local/lib/python3.10 -L/usr/local/lib/python3.10/dist-packages -lantlr4-runtime
这个时候我们可以看到目录下多了一个helloworld程序,终端运行helloworld,输入hello hahaha可以看到如下输出:
sungjoeng@LAPTOP-0G9E5KJ7:~/antlr4Project/hello$ ./helloworld
hello hahaha
解析结果:
hello & hahaha &
此时代码成功运行!