如何构建最新版ANTLR4 C++语法解析器?
构建最新版ANTLR4 C++ C++解析器遇到编译错误
背景
已从官方ANTLR语法仓库下载C++语法文件(包含CPP14Parser、CPP14Lexer及CPPParser相关文件),旧版本(指定GitHub提交)可通过自行编写的CMakeLists.txt正常构建,但最新版编译时出现大量错误,查阅的文档已过时。
旧版本可工作的操作流程
1. CMakeLists.txt配置
cmake_minimum_required(VERSION 3.14) project(CPPparser) set(CMAKE_CXX_STANDARD 17) include_directories( ${PROJECT_SOURCE_DIR}/generated/ ${PROJECT_SOURCE_DIR}/cppruntime/src/ ${PROJECT_SOURCE_DIR}/src/ ) set(src_dir ${PROJECT_SOURCE_DIR}/generated/CPP14Lexer.cpp ${PROJECT_SOURCE_DIR}/generated/CPP14Parser.cpp ${PROJECT_SOURCE_DIR}/generated/CPP14Visitor.cpp ${PROJECT_SOURCE_DIR}/generated/CPP14BaseVisitor.cpp ) file(GLOB antlr4-cpp-src ${PROJECT_SOURCE_DIR}/cppruntime/src/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/atn/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/dfa/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/internal/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/misc/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/support/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/tree/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/tree/pattern/*.cpp ${PROJECT_SOURCE_DIR}/cppruntime/src/tree/xpath/*.cpp ) add_library (antlr4-cpp-runtime ${antlr4-cpp-src}) add_executable(CPPparser ${src_dir} src/main.cpp) target_link_libraries(CPPparser antlr4-cpp-runtime)
2. 目录结构
/src:存放main.cpp/generated:存放通过antlr4 -Dlanguage=Cpp -visitor生成的文件/cppruntime:存放官方ANTLR运行时
3. 编译命令
mkdir build && cd build cmake .. make
新版本编译错误信息
: error: expected class-name before ‘{’ token 12 | class CPP14Parser : public CPP14ParserBase { | ^ /home/user/CPnew/generated/CPP14Parser.h:118:3: error: ‘CPP14Parser::~CPP14Parser()’ marked ‘override’, but does not override 118 | ~CPP14Parser() override; | ^ /home/user/CPnew/generated/CPP14Parser.h:120:15: error: ‘std::string CPP14Parser::getGrammarFileName() const’ marked ‘override’, but does not override 120 | std::string getGrammarFileName() const override; | ^~~~~~~~~~~~~~~~~~ /home/user/CPnew/generated/CPP14Parser.h:122:27: error: ‘const antlr4::atn::ATN& CPP14Parser::getATN() const’ marked ‘override’, but does not override 122 | const antlr4::atn::ATN& getATN() const override; | ^~~~~~ /home/user/CPnew/generated/CPP14Parser.h:124:35: error: ‘const std::vector<std::__cxx11::basic_string<char> >& CPP14Parser::getRuleNames() const’ marked ‘override’, but does not override 124 | const std::vector<std::string>& getRuleNames() const override; | ^~~~~~~~~~~~ /home/user/CPnew/generated/CPP14Parser.h:126:34: error: ‘const antlr4::dfa::Vocabulary& CPP14Parser::getVocabulary() const’ marked ‘override’, but does not override 126 | const antlr4::dfa::Vocabulary& getVocabulary() const override; | ^~~~~~~~~~~~~ /home/user/CPnew/generated/CPP14Parser.h:128:34: error: ‘antlr4::atn::SerializedATNView CPP14Parser::getSerializedATN() const’ marked ‘override’, but does not override 128 | antlr4::atn::SerializedATNView getSerializedATN() const override; | ^~~~~~~~~~~~~~~~ /home/user/CPnew/generated/CPP14Parser.h:3895:8: error: ‘bool CPP14Parser::sempred(antlr4::RuleContext*, size_t, size_t)’ marked ‘override’, but does not override 3895 | bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override; | ^~~~~~~ /home/user/CPnew/cppruntime/src/CPP14ParserBase.cpp:5:6: error: ‘CPP14ParserBase’ has not been declared 5 | bool CPP14ParserBase::IsPureSpecifierAllowed() | ^~~~~~~~~~~~~~~ /home/user/CPnew/cppruntime/src/CPP14ParserBase.cpp: In function ‘bool IsPureSpecifierAllowed()’: /home/user/CPnew/cppruntime/src/CPP14ParserBase.cpp:9:18: error: invalid use of ‘this’ in non-member function 9 | auto x = this->getRuleContext(); // memberDeclarator | ^~~~
main.cpp代码
#include <iostream> #include "CPP14Lexer.h" #include "CPP14Parser.h" using namespace antlr4; int main(int argc, const char* argv[]) { const char* filepath = argv[1]; std::ifstream ifs; ifs.open(filepath); ANTLRInputStream input(ifs); CPP14Lexer lexer(&input); CommonTokenStream tokens(&lexer); CPP14Parser parser(&tokens); tree::ParseTree* tree = parser.translationunit(); if (parser.getNumberOfSyntaxErrors() > 0) { std::cout<<"File syntax error"<<std::endl; return 0; } tokens.fill(); for (auto t : tokens.getTokens()) { std::cout<<t->toString()<<std::endl; } std::cout << tree->toStringTree(&parser) << std::endl << std::endl; ifs.close(); return 0; }
解决建议
- 匹配ANTLR版本:确保使用的语法文件(CPP14.g4等)与ANTLR运行时版本完全一致。最新版语法文件可能依赖了运行时的新特性或接口变更,旧版运行时不兼容。
- 正确生成代码:使用最新版ANTLR工具生成C++代码,命令应为
antlr4 -Dlanguage=Cpp -visitor -no-listener CPP14.g4(根据需要调整参数),确保生成的代码与当前运行时匹配。 - 调整CMakeLists.txt:
- 确保ANTLR运行时的头文件路径正确,最新版运行时的头文件可能位于
cppruntime/include/antlr4-runtime/而非cppruntime/src/,需更新include_directories:include_directories( ${PROJECT_SOURCE_DIR}/generated/ ${PROJECT_SOURCE_DIR}/cppruntime/include/ ${PROJECT_SOURCE_DIR}/src/ ) - 链接运行时库时,优先使用官方提供的CMake配置,而非手动收集源文件。可以通过
find_package(ANTLR REQUIRED)来导入官方运行时的CMake目标。
- 确保ANTLR运行时的头文件路径正确,最新版运行时的头文件可能位于
- 处理CPP14ParserBase依赖:错误提示
CPP14ParserBase未声明,说明生成的代码中该基类的头文件未被正确包含,或生成时未生成该基类文件。检查语法文件中是否有parserBaseClass定义,确保生成代码时包含了基类的头文件,且该文件在generated目录中,CMake能正确找到。 - 检查C++标准:最新版ANTLR4 C运行时可能需要更高的C标准(如C++20),尝试将
CMAKE_CXX_STANDARD设置为20。
内容的提问来源于stack exchange,提问作者EggDi
相关产品推荐
相关产品推荐

