首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有用于模式匹配和-rewriting源代码的软件吗?

有用于模式匹配和-rewriting源代码的软件吗?
EN

Stack Overflow用户
提问于 2009-01-06 04:27:24
回答 4查看 2.1K关注 0票数 7

我有一些旧的软件(用的语言不是死的,但对我来说是死的;-),它为源代码实现了一个基本的模式匹配和-rewriting系统。我正在考虑复活这段代码,把它翻译成一种现代语言,并将这个项目作为一个重构的强大工具进行开源。在我更进一步之前,我想知道这样的事情是否已经存在(我的google-fu今晚正在对此吹毛求疵)。

下面是它的工作原理:

  • 模式匹配部分使用绑定变量的模板匹配跨越多行代码的源代码模式,
  • 模式重写部分使用模板重写匹配的代码,从匹配的模板插入绑定变量的内容。
  • 匹配和重写模板通过简单(无条件)重写规则关联(1:1)。

该软件操作于输入应用程序的抽象语法树( AST ),并输出修改后的AST,然后将其重新生成新的源代码。

例如,假设我们找到了一堆真正应该是for -循环的while-循环。以下模板将与while循环模式匹配:

代码语言:javascript
复制
Template oldLoopPtrn
    int @cnt@ = 0;
    while (@cnt@ < @max@)
    {
        … @body@
        ++@cnt@;
    }
End_Template

下面的模板将指定输出重写模式:

代码语言:javascript
复制
Template newLoopPtrn
    for(int @cnt@ = 0; @cnt@ < @max@; @cnt@++)
    {
        @body@
    }
End_Template

一条简单的规则把他们联系起来

代码语言:javascript
复制
Rule oldLoopPtrn --> newLoopPtrn

所以像这样的代码

代码语言:javascript
复制
int i=0;
while(i<arrlen)
{
    printf("element %d: %f\n",i,arr[i]);
    ++i;
}

自动重写为如下所示

代码语言:javascript
复制
for(int i = 0; i < arrlen; i++)
{
    printf("element %d: %f\n",i,arr[i]);
}

我所见过的最接近的东西是一些代码重构工具,但它们似乎是针对对选定片段的交互式重写,而不是大规模的自动更改。

我相信这种工具可以为重构充电,并且可以在多种语言(甚至HTML/CSS)上工作。我还相信,转换和完善代码库将是一个巨大的项目,我根本无法在任何合理的时间内单独完成。

所以,像这样的东西已经存在了吗?如果没有,有什么明显的特性(除了重写规则条件)需要考虑?

编辑:我非常喜欢这个系统的一个特性,即模板模式非常明显,易于阅读,因为它们是用与目标源代码相同的语言编写的,而不是以某种深奥的变异regex/BNF格式编写的。

EN

回答 4

Stack Overflow用户

发布于 2010-03-21 21:00:19

我正在考虑复活这段代码,把它翻译成一种现代语言,并将这个项目作为一个重构的强大工具进行开源。

我认为拥有这样一个免费的工具将是非常棒的。

但有一种商业产品可供使用:DMS软件重组工具包

DMS软件重组工具包是一套用于自动化定制源代码程序分析、修改或翻译或生成软件系统的工具,包含任意语言的混合(“域”)。DMS的“软件”一词非常广泛,涵盖任何正式的符号,包括编程语言、标记语言、硬件描述语言、设计符号、数据描述等。该工具包是实现设计维护系统™的第一步,这是一个面向21世纪软件工程环境的雄心勃勃的愿景,支持在语义和捕获设计的驱动下逐步构建和维护大型应用系统。

另外,对于C源代码,有一个科奇内尔工具:

Coccinelle是一个程序匹配和转换引擎,它提供了语言SmPL (Semantic ),用于在C代码中指定所需的匹配和转换。Coccinelle最初的目标是在Linux中执行附带进化。这种演化包括客户端代码中响应库API中的演化所需的更改,并可能包括修改,例如重命名函数、添加值与上下文相关的函数参数以及重新组织数据结构。除了附带进化之外,Coccinelle还成功地(被我们和其他人)用于查找和修复系统代码中的bug。

票数 3
EN

Stack Overflow用户

发布于 2009-01-06 04:38:14

血栓素是基于规则的,而不是基于模式的,因此它有更多的功能,但可能是一个更陡峭的学习曲线。

票数 2
EN

Stack Overflow用户

发布于 2012-06-03 08:12:33

在TXL中,如下所示:

代码语言:javascript
复制
include "c.grm"

rule main
    replace [declaration_or_statement*]
        int cnt [id] = 0;
        while (cnt < max [shift_expression] )
        {
                body [declaration_or_statement*]
        }
    deconstruct * body
        ++cnt;
    by
        for (int cnt = 0; cnt < max; cnt++)
        {
                body
        }
end rule

对于这一投入:

代码语言:javascript
复制
int main () {
  int i=0;
  while(i < arrlen) {
    printf("element %d: %f\n",i,arr[i]);
    ++i;
  }
}

它产生这样的结果:

代码语言:javascript
复制
int main () {
    for (int i = 0; i < arrlen; i++) {
        printf ("element %d: %f\n", i, arr [i]);
        ++i;
    }
}

对于上面的Coccinelle示例中显示的拆分情况,您可以为规则添加一个类似的保护。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/415455

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档