如何将源代码转换为基于XML的AST表示形式?

7

我想获取Java和C代码AST的XML表示。3个月前,我提过这个问题, 但解决方案对我来说不太舒适。

  • srcml似乎是解决此问题的好方法,但它不支持行号和列号,而我需要该功能。
  • 关于elsa:引用:“正在努力将Elsa AST导出为XML文档;我们期望能够在下一个公共发布版本中进行宣传。”
  • dms...不理解那个。
  • 特别是对于Java,有javaml支持行号。但sourceforge页面没有列出任何文件。
问题:是否有可用的软件支持将ast转换为支持行号(和列)的xml [特别是对于java和c / c ++]?是否有javaml和srcml的替代方案?
附言:我不想使用解析器生成器。我希望找到一个可以在控制台上使用的工具,输入:./my-xml-generator Test.java [或类似的内容] ... 或者一个java实现也很好。

你想做什么,需要使用XML吗? - Ira Baxter
2
srcML 现在支持行号和列号。从网站上来看:“具有文件和目录感知的元数据,例如语言、文件位置和版本信息。” 我广泛使用了 srcML,并可以验证它具有行号和列信息。 - David Shepherd
5个回答

3

对于1000行输入的Java代码,生成的XML文档有多大? - Ira Baxter

2
你对 DMS 不理解什么?
它是存在的。
它拥有编译器精确的C,C++,Java,C#,COBOL(和许多其他语言)的解析器/前端
它会自动为其解析的内容构建完整的抽象语法树(AST)。每个AST节点都标记了表示该节点起始位置的文件/行/列信息,而 DMS 的 API 调用可以计算出最终列号。
它还内置了一个选项,可以从 AST 生成 XML,其中包含节点类型、源位置(如上所述)及任何相关字面值。命令行调用如下:
 run DMSDomainParser ++XML  <path_to_your_file>

您可以查看Java的XML结果,了解此类XML结果的情况。
您可能真的不想要您所希望的。1000个C程序可能有100K行的#include文件内容。一行代码会产生5-10个节点。DMS XML输出简洁,每个节点只占用一行,因此您需要处理大约1百万行的XML,每行60个字符--> 6000万个字符。这是一个很大的文件,您可能不想使用基于XML的工具来处理它。
DMS本身提供了大量的基础设施来操作其构建的AST:遍历、模式匹配(针对源代码形式编码的模式)、源到源转换、控制流、数据流、指向分析、全局调用图等等。您会发现复制所有这些机器非常困难,并且您可能需要它们才能做任何有趣的事情。
结论:最好直接使用像DMS这样的工具来操作AST,而不是与XML作斗争。
完整披露:我是DMS的架构师。

1

srcml支持行号和列号。这里有一个使用名为input.java的Java文件的示例(请记住,srcml支持包括C/C++在内的多种语言),其中包含以下内容:

public class HelloWorld {
    public static void main(String[] args) {
        // Prints "Hello, World" to the terminal window.
        System.out.println("Hello, World");
    }
}

然后使用启用保留此额外位置信息的命令运行srcml:

srcml input.java --position

它以嵌入行号和列号的XML格式生成以下AST:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit xmlns="http://www.srcML.org/srcML/src" xmlns:pos="http://www.srcML.org/srcML/position" revision="0.9.5" language="Java" filename="input.java" pos:tabs="8"><class><specifier pos:line="1" pos:column="1">public<pos:position pos:line="1" pos:column="7"/></specifier> class <name pos:line="1" pos:column="14">HelloWorld<pos:position pos:line="1" pos:column="24"/></name> <block pos:line="1" pos:column="25">{
    <function><specifier pos:line="2" pos:column="5">public<pos:position pos:line="2" pos:column="11"/></specifier> <specifier pos:line="2" pos:column="12">static<pos:position pos:line="2" pos:column="18"/></specifier> <type><name pos:line="2" pos:column="19">void<pos:position pos:line="2" pos:column="23"/></name></type> <name pos:line="2" pos:column="24">main<pos:position pos:line="2" pos:column="28"/></name><parameter_list pos:line="2" pos:column="28">(<parameter><decl><type><name><name pos:line="2" pos:column="29">String<pos:position pos:line="2" pos:column="35"/></name><index pos:line="2" pos:column="35">[]<pos:position pos:line="2" pos:column="37"/></index></name></type> <name pos:line="2" pos:column="38">args<pos:position pos:line="2" pos:column="42"/></name></decl></parameter>)<pos:position pos:line="2" pos:column="43"/></parameter_list> <block pos:line="2" pos:column="44">{
    <comment type="line" pos:line="3" pos:column="9">// Prints "Hello, World" to the terminal window.</comment>
    <expr_stmt><expr><call><name><name pos:line="4" pos:column="9">System<pos:position pos:line="4" pos:column="15"/></name><operator pos:line="4" pos:column="15">.<pos:position pos:line="4" pos:column="16"/></operator><name pos:line="4" pos:column="16">out<pos:position pos:line="4" pos:column="19"/></name><operator pos:line="4" pos:column="19">.<pos:position pos:line="4" pos:column="20"/></operator><name pos:line="4" pos:column="20">println<pos:position pos:line="4" pos:column="27"/></name></name><argument_list pos:line="4" pos:column="27">(<argument><expr><literal type="string" pos:line="4" pos:column="28">"Hello, World"<pos:position pos:line="4" pos:column="42"/></literal></expr></argument>)<pos:position pos:line="4" pos:column="43"/></argument_list></call></expr>;<pos:position pos:line="4" pos:column="44"/></expr_stmt>
    }<pos:position pos:line="5" pos:column="6"/></block></function>
}<pos:position pos:line="6" pos:column="2"/></block></class></unit>

参考资料: srcml v0.9.5 的文档(请参见 srcml --help)。我经常使用 srcml,包括使用此功能获取位置信息。


1

1
据我所知,GCC-XML仅转储类型定义数据,而不是函数体的代码。 - Ira Baxter

0

仅适用于Java,您可以使用 BeautyJ

您可以使用 -xml.* 选项来启动它并针对您的文件进行分析。例如:

java /your/dir/BeautyJ/lib/beautyj.jar beautyj -xml.out= -xml.doctype your_file.java

...然后您将获得该文件(以及包含的文件)的XML表示形式。

顺便说一句:"-xml.out="选项指定输出文件。以这种方式使用,带有尾随"=",它会输出到STDOUT。这不是错误。


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