【问题标题】:Is there a good Python library that can parse C++? [closed]是否有可以解析 C++ 的优秀 Python 库? [关闭]
【发布时间】:2010-11-29 12:28:29
【问题描述】:

Google 没有发现任何似乎相关的内容。

我有一堆现有的、可工作的 C++ 代码,我想使用 python 来抓取它并找出类之间的关系等。

编辑:只是想指出:我认为我不需要或不想解析 C++ 的每一点;我只需要足够聪明的东西来处理类、函数和成员变量声明,并跳过函数定义。

【问题讨论】:

  • 如果没有完整的 C++ 解析器,您几乎无法做到这一点。
  • 如果您可以接受它不捕获 0.1% 的边缘情况,那么您很可能能够摆脱正则表达式解析。我很确定很多文本编辑器都这样做是为了语法高亮/解析。例如,Sublime Text 带有包括 C++ 在内的多种语言的正则表达式解析文件(参见 C++.tmLanguage)。

标签: c++ python


【解决方案1】:

不是这样的答案,只是为了演示正确解析 C++ 的难度。我最喜欢的演示:

template<bool> struct a_t;

template<> struct a_t<true> {
    template<int> struct b {};
};

template<> struct a_t<false> {
    enum { b };
};

typedef a_t<sizeof(void*)==sizeof(int)> a;

enum { c, d };
int main() {
    a::b<c>d; // declaration or expression?
}

这是完全有效的、符合标准的 C++,但注释行的确切含义取决于您的实现。如果sizeof(void*)==sizeof(int)(在 32 位平台上典型),则它是 a::b&lt;c&gt; 类型的局部变量 d 的声明。如果条件不成立,则它是一个无操作表达式((a::b &lt; c) &gt; d)。为a::b 添加一个构造函数实际上会让你通过副作用的存在/不存在来暴露差异。

【讨论】:

  • 邪恶,是的,但可以解析就好了。我已经更新了 stackoverflow.com/a/17393852/120163">this SO answer 解析此代码:
  • C++:对人类来说很难,对计算机来说更难。
  • @Dave:C++:对人类来说很难,对计算机来说较少。如果不冻结我的大脑一半,我无法亲自解析这个。我的解析器处理得很好;没有半个大脑可以冷冻。
【解决方案2】:

众所周知,C++ 难以解析。大多数尝试正确执行此操作的人最终都会拆开编译器。事实上,这(部分)是 LLVM 开始的原因:Apple 需要一种可以解析 C++ 以在 XCode 中使用的方法,该方法与编译器解析它的方式相匹配。

这就是为什么有像 GCC_XML 这样的项目可以与 python xml 库结合使用的原因。

一些似乎在解析 C++ 方面做得很好的非编译器项目是:

  • Eclipse CDT
  • OpenGrok
  • 氧气

【讨论】:

  • +1 - gcc-xml 是要走的路,除非您想要像 EDG 前端这样的付费(且昂贵)解决方案。
  • 请注意,gcc-xml 不会解析所有内容。具体来说,函数体不被解析。
  • 你也应该考虑 swig ,我在github.com/kamanashisroy/swig csv 模块玩得很开心。
【解决方案3】:

多年来我一直在使用pygccxml,它是一个非常好的围绕 GCC-XML 的 Python 包装器。这是一个功能非常齐全的包,构成了一些常用代码生成工具的基础,例如来自同一作者的py++

【讨论】:

    【解决方案4】:

    您不会找到用于执行此操作的嵌入式 Python 库。解析 C++ 很繁琐,而且很少有人编写不属于编译器的解析器。你可以在here找到一个很好的问题总结。

    最好的选择可能是 clang,因为它的 C++ 支持是 well-established。尽管这不是 Python 解决方案,但听起来好像可以在 Python 包装器中重复使用,因为它在开发中强调封装和良好的设计。

    【讨论】:

    • 繁琐?非常难。
    【解决方案5】:

    Pycparser 是一个完整的 ANSI C 解析器。 也许你可以将它扩展到 c++ :-)

    【讨论】:

    【解决方案6】:

    如果您以兼容的方式格式化了您的 cmets,doxygen 的工作非常出色。如果你安装了graphviz,它甚至会绘制继承图。

    例如,在下面运行 doxygen:

    /// <summary>
    /// A summary of my class
    /// </summary>
    public class MyClass
    {
    protected:
        int m_numOfWidgets; /// Keeps track of the number of widgets stored
    
    public:
        /// <summary>
        /// Constructor for the class.
        /// </summary>
        /// <param paramName="numOfWidgets">Specifies how many widgets to start with</param>
        MyClass(int numOfWidgets)
        {
            m_numOfWidgets = numOfWidgets;
        }
    
        /// <summary>
        /// Increments the number of widgets stored by the amount supplied.
        /// </summary>
        /// <param paramName="numOfWidgets">Specifies how many widgets to start with</param>
        /// <returns>The number of widgets stored</returns>
        IncreaseWidgets(int numOfWidgetsToAdd)
        {
            m_numOfWidgets += numOfWidgets;
            return m_numOfWidgets;
        }
    };
    

    会将所有这些 cmets 转换为 .html 文件中的条目。对于更复杂的设计,结果会更加有益 - 通常比尝试浏览源代码要容易得多。

    【讨论】:

    • Doxygen 是一款适用于 c++ 程序的出色软件!在其他人编写的程序上使用它,它可以更容易地弄清楚发生了什么。
    • 这样做是以 xml 样式的丑陋 cmets 为代价的
    【解决方案7】:

    This page 显示了一个用 Antlr 编写的 C++ 语法,而你 can generate Python code 来自它。

    似乎也有人在 pyparsing 中使用 C++ 解析器,但我无法找出是谁或它的当前状态。

    【讨论】:

    • 不可能在 ANTLR 中拥有一个完全可用的 C++ 语法,或者实际上任何其他语法描述语言。 C++ 语法不是上下文无关的。由于模板元编程之类的东西,有效地解析 C++ 需要编写图灵完备语言的解释器,以便能够区分变量声明和表达式。
    • @Pavel:如果您有一个不错的解析器,那么您可以使用上下文无关语法规则拥有一个完美的 C++ 解析器。您不必在解析过程中解析名称和类型;请参阅 DMS Toolkit 答案,了解完整的 C++ 解析器,它完全可以完成您所说的无法完成的工作。
    • @Ira:在某些情况下,如果你不解析类型,你就不知道什么是东西。例如,考虑:a&lt;sizeof(int)&gt;::b&lt;c&gt;d,其中a 是另一个具有特化的类模板,其中一个将b 定义为另一个类模板,第二个将b 定义为枚举成员。根据选择的专业化(即int的大小),整个事情要么是变量d的声明:a&lt;sizeof(int)&gt;::b&lt;c&gt;d,要么是一个表达式:a&lt;sizeof(int)&gt;::b &lt; c &gt; d。所以现在我们有了完全符合 ISO C++ 代码,它也依赖于实现。
    • 现在,如果该代码在类模板中,并且 sizeof(int)sizeof(T) 替换 - 或者一些更复杂的编译时表达式最终依赖于模板参数 - 你'必须完全评估该表达式才能产生明确的输出。由于该表达式可以使用本书中的所有 TMP 技巧,因此您必须编写代码来完全处理 C++ 模板实例化、完成特化、函数重载规则(考虑 a&lt;sizeof(foo(T()))&gt;)等等。如果您只是报告歧义 - 好吧,那不是“完整的 C++ 解析器”......
    • @Pavel:C++ 的纯 解析器 可以很好地构建 AST,而无需进行任何名称/类型解析。您是正确的,因为 AST 必须捕获纯语法规则无法区分的歧义(而 DMS 可以做到这一点)。可以解决解析树中的歧义,以通过稍后的传递生成最终干净的 AST(这就是 DMS 的做法)。优点是纯解析和符号表解析作为单独的模块化通道保存,这使得构建工作的“完整 C++ 解析器”变得更加容易。 ANTLR 版本将这些东西纠缠在一起,使其过于复杂而不可靠。
    【解决方案8】:

    没有(免费)好的库可以用任何语言解析 C++。
    您的最佳选择可能是Dehydra g++ 插件、clangElsa

    【讨论】:

      【解决方案9】:

      这是一个声称可以解析 c++ 标头的 SourceForge 项目。正如其他评论者指出的那样,没有通用的解决方案,但是您这听起来足以满足您的需求。 (我只是遇到了类似的需求,自己还没有尝试过。)

      http://sourceforge.net/projects/cppheaderparser/

      【讨论】:

        【解决方案10】:

        Clang 项目提供了仅用于解析 C++ 代码的库。

        使用 Clang 和 GCC,您可以生成代码的 XML 表示

        如果您更喜欢 Pythonian 解决方案,您也可以搜索 C++ yacc 语法并使用 py-ply(Yacc for Python),但这似乎是需要更多工作的解决方案

        【讨论】:

          【解决方案11】:

          pyparsing wiki 展示了这个示例 - 它所做的只是解析结构声明,因此这可能会让您大致了解问题的严重程度。

          我建议您(或者更好的是,您的雇主)花 200 美元购买Enterprise Architect from sparxsystems。该软件的价格非常强大,并且包含非常好的代码逆向工程功能。你将在自己的时间里花费更多的时间来完成大约 2% 的工作。在这种情况下,“购买”胜过“制造”。

          【讨论】:

            【解决方案12】:

            Ctypes 使用gcc-xml 进行代码生成。 cpptypes 也可能这样做。即使没有,您也可以使用 gcc-xml 从您的 C++ 文件生成 XML,然后使用内置或第三方 Python XML 解析器之一解析 xml。

            【讨论】:

              【解决方案13】:

              我会密切关注gcc.gnu.org/wiki/plugins,因为插件似乎是要走的路。 gcc-python-plugin 似乎也有一个很好的实现。

              【讨论】:

                猜你喜欢
                • 2011-12-03
                • 1970-01-01
                • 2010-10-02
                • 2010-09-21
                • 2010-11-03
                • 2012-10-05
                • 2013-04-24
                • 2010-12-30
                • 2010-11-29
                相关资源
                最近更新 更多