在Java环境中解析C++源代码

8
我有一个C++应用程序,也有它的源代码,且已经基于.NET框架构建。现在我需要一个工具(最好是免费的),以我的源代码作为输入,在经过一些预处理或必要的编程后,给出源代码元素的结构依赖关系的中间表示,如AST或调用图。我正在使用Java来检查这个C++源代码,所以如果解决方案在Java环境中,比如eclipse的插件之类的,会更好。是否有任何可用的工具可以满足我的需求?谢谢!

1
最坏的情况下,你可以使用C++工具:http://stackoverflow.com/a/2318476/839436 - Tom Kerr
Eclipse和NetBeans都有C++的开源插件,你可以从这些开始。 - Peter Lawrey
这只是一个实现C++解析器的“简单问题”。(不幸的是,C++是最难解析的结构之一。) - Hot Licks
6个回答

4

我成功使用NetBeans的CND模块在Java中解析了C++。虽然它仍然不太美观,但可能比使用原始ANTLR或其他工具更好。首先,为了简单起见(CND实际上不需要所有这些类),请从http://netbeans.org/downloads/zip.html下载“all-in-one”包并将其解压缩到当前目录或其他位置。接下来,这是一个我一直在玩弄的玩具C++头文件:

namespace foo {

int f(int p);

template<typename A> class bar {
    void run(A) { }
};

}

以下是使用CND解析的尝试:

import java.io.*;
import java.util.*;
import org.openide.filesystems.*;
import org.netbeans.modules.cnd.api.model.*;
import org.netbeans.modules.cnd.api.model.services.*;
import org.netbeans.modules.cnd.modelimpl.csm.*;

public class Foo {
    public static void main(String[] args) throws Exception {
        FileObject fo = FileUtil.toFileObject(new File(args[0]));
        CsmStandaloneFileProvider fp = CsmStandaloneFileProvider.getDefault();
        CsmModel model = CsmModelAccessor.getModel();
        CsmModelState modelState = CsmModelAccessor.getModelState();

        CsmFile cf = fp.getCsmFile(fo);
        cf.scheduleParsing(true);
        Collection<CsmOffsetableDeclaration> c = cf.getDeclarations();
        c = ((CsmNamespaceDefinition)c.toArray()[0]).getDeclarations();
        for (CsmOffsetableDeclaration d : c) {
            if (d instanceof CsmFunction) {
                CsmFunction f = (CsmFunction)d;
                System.out.print(f.getQualifiedName() + " " + f.getName() + "(");
                Collection<CsmParameter> pp = f.getParameters();
                for (CsmParameter p : pp) {
                    System.out.print(p.getType().getClassifierText());
                }
                System.out.println(")");
            } else if (d instanceof ClassImpl) {
                ClassImpl cls = (ClassImpl)d;
                System.out.println("Got template? " + cls.isTemplate());
                List<CsmTemplateParameter> lt = cls.getTemplateParameters();
                for (CsmTemplateParameter t : lt) {
                    System.out.println(t.getQualifiedName() + " " + t.getName());
                }
                Collection<CsmMember> cm = cls.getMembers();
                for (CsmMember m : cm) {
                    CsmFunction f = (CsmFunction)m;
                    System.out.print(f.getQualifiedName() + " " + f.getName() + "(");
                    Collection<CsmParameter> pp = f.getParameters();
                    for (CsmParameter p : pp) {
                        System.out.print(p.getType().getClassifierText());
                    }
                    System.out.println(")");
                }
            }
        }
    }
}

我们需要添加到classpath中的JAR文件数量相当大,必须有更好的处理方式,但目前这样做是可行的:

$ export CLASSPATH=netbeans/platform/modules/org-netbeans-modules-editor-mimelookup.jar:netbeans/platform/modules/org-netbeans-modules-queries.jar:netbeans/dlight/modules/org-netbeans-modules-dlight-libs-common.jar:netbeans/ide/modules/org-netbeans-modules-projectapi.jar:netbeans/platform/modules/org-netbeans-api-progress.jar:netbeans/platform/modules/org-openide-windows.jar:netbeans/platform/modules/org-openide-text.jar:netbeans/platform/modules/org-openide-awt.jar:netbeans/platform/lib/org-openide-modules.jar:netbeans/platform/modules/org-openide-nodes.jar:netbeans/platform/modules/org-netbeans-modules-masterfs.jar:netbeans/platform/core/org-openide-filesystems.jar:netbeans/platform/lib/org-openide-util.jar:netbeans/platform/lib/org-openide-util-lookup.jar:netbeans/platform/modules/org-openide-loaders.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-api-model.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-api-project.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-model-services.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-modelimpl.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-modelutil.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-utils.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-repository.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-repository-api.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-apt.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-source.jar:netbeans/cnd/modules/org-netbeans-modules-cnd-antlr.jar:.
$ javac Foo.java
$ java Foo Foo.h

然后输出以下内容:

foo::f f(int)
Got template? true
foo::bar::A A
foo::bar::run run(A)

顺便提一句,我们可以使用Eclipse CDT做类似的事情: 使用Java解析/读取C头文件


顺便说一句,今天我建议使用Java中的Clang:https://github.com/bytedeco/javacpp-presets/tree/master/llvm/samples/src/main/java/org/bytedeco/javacpp/samples/clang - Samuel Audet

4
你可能会对doxygen感兴趣,它是一款基于源代码生成文档的免费工具。你无需额外付出努力就可以生成调用图、继承图、协作图和许多其他有用的工具。 http://www.doxygen.nl/

1
你可以使用纯Java实现的Eclipse解析器,只需要两个jar文件。 我已经提供了如何使用的详细信息,请查看链接:
https://dev59.com/i2PVa4cB1Zd3GeqP2BHb#27496664 上面的链接还有一个项目,提供了Eclipse解析器的抽象结构,更加简单易懂(但并不适用于所有情况)。

0

Samuel Audet是正确的!但他缺少JAR文件。你需要添加以下JAR文件:org-netbeans-modules-cnd-indexing.jar,org-netbeans-modules-parsing-lucene.jar,org-netbeans-libs-lucene.jar和lucene-core-3.5.0.jar。


0

根据您的需求,Synopsis可能适合您:http://synopsis.fresco.org/

这是一个模块化工具,它解析源代码(C/C++/Python/IDL)并生成抽象语法图。该图可以通过API遍历(或将其传递给其他Synopsis模块以生成源文档,例如)。Synopsis提供了C++和Python API,不幸的是没有Java API - 但我认为它可以通过Jython(或JNI当然也可以;-))从Java中使用。


0

我认为你应该看看Xogastan。它可以将C++生成AST作为XML文档。Xogastan有很多生成选项。

Xogastan主页

问候,

编辑: 它与Java没有直接联系,但你可以将其用作外部工具,然后分析生成的XML。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接