如何构建提供的antlr语法?

问题描述 投票:0回答:1

我想使用 cpp 构建一个 cpp 解析器,并且我正在使用 ANTLR4。我注意到官方 github antlr 语法 github 中有一个“语法”部分,我已经下载了它。打开里面的CPP文件时,我注意到有一个CPP14Parser和一个CPP14Lexer,还有另一个CPP文件,里面有一个CPPParser。我已经浏览了这些文档好几天了,但它似乎已经过时了。我尝试过运行antlr-4,但后来在尝试编译它时不断出现错误。但是,我编写的 CMakeLists.txt 和 main(基本上是所有其他文件)确实可以在旧版本上工作,其中的内容更干净我成功构建的版本。有人可以教我如何构建最新版本的当前语法吗?如果需要更多具体背景,请告诉我!预先感谢!

编辑: 我所做的步骤如下所示,我安装了旧版本的CPP14.g4(如上面的描述中所写),并写了我自己写的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)

我将 main.cpp 写在 /src 文件夹中,/generate 具有在运行 antlr4 -Dlanguage=Cpp -visitor 后生成的文件,/cppruntime 用于来自官方 antlr github 的运行时。所以我将在 ubuntu 上运行以下命令

mkdir build && cd build
cmake ..
make

它确实工作得很好,但是,当我尝试使用相同的步骤编译 github 上提供的最新文件时,在运行 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;
}

TLDR:如果可能的话,请指导我如何构建最新版本的antlr语法。 抱歉,如果我没有说清楚或犯了任何愚蠢的错误,这是我的第一个问题。

c++ parsing antlr antlr4 grammar
1个回答
0
投票

第 1 步——克隆存储库

$ git clone https://github.com/antlr/grammars-v4.git
Cloning into 'grammars-v4'...
remote: Enumerating objects: 50618, done.
remote: Counting objects: 100% (1907/1907), done.
remote: Compressing objects: 100% (1285/1285), done.
remote: Total 50618 (delta 686), reused 1618 (delta 510), pack-reused 48711
Receiving objects: 100% (50618/50618), 47.50 MiB | 23.79 MiB/s, done.
Resolving deltas: 100% (27107/27107), done.
Updating files: 100% (9413/9413), done.

第 2 步——导航到 cpp 并检查 desc.xml 以查看目标是否可用于语法

$ cd grammars-v4/cpp/
$ cat desc.xml
<?xml version="1.0" encoding="UTF-8" ?>
<desc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../_scripts/desc.xsd">
   <targets>Cpp;CSharp;Dart;Go;Java;JavaScript;Python3;Antlr4ng</targets>
</desc>

desc.xml 描述了构建的目标以及正在“工作”的目标。有时可以看到可用于目标的目标文件,但它们可能无法构建,或者语法太慢而无法在实践中使用。

对于 cpp 语法,列出了 Cpp 目标,因此该目标“有效”。

第 3 步 -- 将目标支持文件复制到包含语法的目录中

$ cp Cpp/* .

您必须将文件复制到目录中。否则,你会得到编译错误。

第 4 步——使用提供的 Python 脚本转换语法

$ python transformGrammar.py
Altering .\CPP14Lexer.g4
Writing ...
Altering .\CPP14Parser.g4
Writing ...

语法包含“动作”,这是特定于目标的代码,专门针对Java。您必须将

this.
转换为 C++ 语法,
this->

$ grep this *.g4
CPP14Lexer.g4:This: 'this';
CPP14Parser.g4: * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
CPP14Parser.g4: * The above copyright notice and this permission notice shall be included in all copies or
CPP14Parser.g4:        | { this->IsPureSpecifierAllowed() }? pureSpecifier
CPP14Parser.g4:        | { this->IsPureSpecifierAllowed() }? virtualSpecifierSeq pureSpecifier

第 5 步——编写驱动程序并为语法构建脚本

存储库中的语法仅包含语法。它不包含任何驱动程序代码,因为人们希望以多种不同的方式打包解析器。您需要自己编写这段代码。此外,您还需要一个构建脚本来以可重复、无错误的方式进行构建。这就是人们使用 CMake 的原因。

除此之外,您可以运行以下命令来编译代码。您仍然需要编写驱动程序。

a) 克隆 antlr4 存储库

pushd ../../
$ git clone https://github.com/antlr/antlr4.git
Cloning into 'antlr4'...
remote: Enumerating objects: 134889, done.
remote: Counting objects: 100% (158/158), done.
remote: Compressing objects: 100% (82/82), done.
remote: Total 134889 (delta 62), reused 110 (delta 47), pack-reused 134731
Receiving objects: 100% (134889/134889), 68.26 MiB | 23.52 MiB/s, done.
Resolving deltas: 100% (79495/79495), done.
Updating files: 100% (2273/2273), done.
$ popd

b) 运行antlr4工具生成解析器源代码

$ antlr4 -Dlanguage=Cpp CPP14Lexer.g4 CPP14Parser.g4

c) 使用 GNU 编译器进行编译

$ g++ -std='c++17' -pthread -c -I../../antlr4/runtime/Cpp/runtime/src/ -g *.cpp
© www.soinside.com 2019 - 2024. All rights reserved.