静态解析:判断两个Javascript函数是否相同

时间:2011-05-16 19:34:28

标签: javascript parsing static-analysis

我正在寻找一种方法,使用两个JavaScript函数的静态分析来判断它们是否相同。让我定义“相同”的多个定义。

等级1:除了可能的不同空格外,功能相同,例如TABS,CR,LF和SPACES。

等级2 这些函数可能有不同的空格,如第1级,但也可能有不同的变量名。

等级3 ???


对于第一级,我想我可以从包含两个JS函数定义的每个字符串中删除所有(非文字,可能很难)空格,然后比较字符串。

对于第二级,我想我需要使用类似SpiderMonkey's parser之类的东西来生成两个解析树,然后编写一个比较器来遍历树并允许变量具有不同的名称。


[编辑]威利汉姆,请在下面说明一点。我的意思是相同的。现在,我正在寻找一些实用的策略,特别是关于使用解析树。

3 个答案:

答案 0 :(得分:3)

<强>重新编辑:

为了阐述我对确定相同功能的建议,可以建议以下流程:

第1级:删除任何不属于字符串文字的空格;在每个{;}之后插入换行符并进行比较。如果相等;功能是相同的,如果不是:

第2级:将所有不依赖于同一范围内定义的其他变量状态的变量声明和赋值移动到声明它们的范围的开头(或者如果不想实际解析JS;大括号的开始);并按行长排序;将所有变量名称处理为4个字符长,并且在绑定长度的情况下回退到按字母顺序忽略变量名称。按字母顺序重新排序所有集合,并重命名所有变量vSNN,其中v是文字,S是嵌套大括号的数量,NN是遇到变量的顺序。

比较;如果相等,则功能相同,如果不相同:

级别3:将所有字符串文字替换为"sNN",其中"s是文字的,NN是遇到字符串的顺序。相比;如果相等,则功能相同,如果不相同:

第4级:根据字母顺序使用具有最高优先级的函数的名称来规范化已知相同的任何函数的名称(在下面的示例中,对p_strlen()的任何调用都将替换为c_strlen()。如果需要,按照级别1重复重新排序。比较;如果相等,则功能相同,否则;功能几乎肯定不相同。


原始回答:

我想你会发现你的意思是“相同”,而不是“相同”。

正如您所发现的那样,差异至关重要:

如果按照某种规范化方式(删除非文字空格,将变量重命名和重新排序为规范化顺序,用占位符替换字符串文字,......),则两个函数相同,它们与字面意思相比较相等。

如果在为任何给定输入值调用时,它们给出相同的返回值,则两个函数相同。在一般情况下,考虑一种编程语言,它计算了零终止字符串(混合Pascal / C字符串,如果你愿意的话)。函数p_strlen(str)可能会查看字符串的字符数并返回该字符串。函数c_strlen(str)可以计算字符串中的字符数并返回该字符。

虽然这些函数肯定不相同,但它们是相同的:对于任何给定(有效)的输入值,它们将给出相同的值。


我的观点是:

确定两个函数是否相同(您似乎想要实现的)是一个(中等)微不足道的问题,如您所描述的那样。

确定两个函数是否真正相同(您可能实际想要实现的)是非平凡的;事实上,它很简单,很可能与Halting Problem有关,而不是静态分析可以做到的事情。


编辑:当然,相同的功能也是一样的;但是以完全分析的高度特异性且很少有用的方式。

答案 1 :(得分:1)

你对1级的态度似乎是合理的。

对于2级,如何对每个函数进行一些基本变量替换,然后对1级进行approch?从头开始,对于您遇到的每个变量声明,将它们重命名为var1, var2, ... varX

如果函数以不同的顺序声明变量,这没有用... var ivar j可以在两个函数中以相同的方式使用,但是以不同的顺序声明。然后你可能会像你提到的那样对解析树进行比较。

答案 2 :(得分:1)

查看我公司的(语义设计)Smart Differencer工具。该系列工具根据感兴趣的语言(在您的情况下,JavaScript)的编译器级别详细语法解析源代码,构建AST,然后比较AST(有效地忽略空格和注释)。文字值是标准化的,因此它们如何“拼写”并不重要; 10E17具有与1E18相同的归一化值。

如果两棵树是相同的,它会告诉你“没有差异”。如果它们因标识符的一致重命名而不同,则该工具将告诉您一致重命名及其发生的块。其他差异报告为语言元素(标识符,语句,块,类,...)插入,删除,复制或移动。目标是报告可能解释差异的一小部分增量。您可以在网站上查看多种语言的示例。

你实际上不能超越这个;确定两个函数是否计算相同的答案,原则上你必须解决暂停问题。您可能能够检测到作为可交换列表元素的两个语言元素在哪里可以无效地进行转换;我们正在努力解决这个问题。您可能能够应用规范化重写来规范化某些表单(例如,将所有多个声明映射到一系列词法排序的单个声明)。您可能能够将源代码转换为其等效的数据流集,并进行图形同构匹配(来自麻省理工学院的程序员的学徒在1980年提出要做到这一点,但我不认为他们曾经到过那里)。 / p>

所有工作都要比你预期的要多。