是否有适用于Linux的C / C ++语法识别搜索/替换命令行工具?

时间:2018-12-19 10:45:27

标签: awk sed refactoring automated-refactoring

我经常使用sed或awk之类的工具替换文本文件的内容。 但是,在替换C / C ++源代码中的语法元素时,我发现与它们一起工作非常困难。例如,在函数调用中获取参数或为其添加参数。

假设我对名为addSymbol的函数进行了以下调用:

addSymbol(Position(441,243),4,7,bigFont,smallFont);

我想执行以下操作:

-获取Position构造函数调用的参数(441和243)

-获取addSymbol函数调用的第二个参数-它是'4'

现在,在我的awk脚本中获取Position参数看起来像这样:

pos=gensub(/.*Position\(([^,]*),([^,]*)\).*/,"\\1,\\2",$0);

使用awk或sed进行解析,仅通过计算括号和逗号看起来很困难,因为它们/正则表达式可以使用: 1.他们逐行读取文件。但是源代码中的任何内容都可能会分成多行,这使得解析起来非常困难,但是它是完全有效的C / C ++代码

  1. 它们没有范围和括号级别的概念。在此示例中,我不能简单地计算逗号的数量,因为第一个逗号是构造函数调用的一部分,与第一个函数参数相关,因此不应该计算在内 该工具将必须跟踪当前的括号级别,并仅计算该级别的参数

  2. 它们没有上下文的概念。该代码可能包含注释或字符串文字,在解析语法元素时必须将其忽略。该工具将必须跟踪当前上下文并忽略注释或字符串文字中的内容。

  3. 必须忽略参数前后的空格。它们使正则表达式更加复杂,但是在解析源代码时则无所谓。

换句话说,我知道这样的工具很难解析:

addSymbol(Position(441,243),"some,string",4/*was 5, before*/,7,bigFont,smallFont);

是否有专门用于解析源代码的工具?可以在其中编写脚本的地方,我可以想象它看起来像这样:

functionCall = getFunctionCall("addSymbol");
symCount = functionCall.getArg(1);
firstArg = functionCall.getArg(0);
if (firstArg.name == "Position" && firstArg.argsCount==2) { //we are looking for "Position constrictor call with 2 arguments"
    pos_x=firstArg.getArg(0)
    pos_y=firstArg.getArg(1)
}

//if we want to remove an argument and output the edited string
functionCall.removeArg(0);
functionCall.print();

我不是在寻找复杂的东西,它会分析包含的文件,宏或模板,或者跟踪对变量的引用。对单个.c / .cpp文件进行操作就足够了。

这种工具不应是新工具,因为毕竟在编译过程中解析源代码时,它应与编译器以相同的方式工作。

我寻找了诸如cscope和ctags之类的程序,但它们看起来更加复杂,需要所有包含的文件才能解析整个项目。

有没有简单的工具,例如awk或sed,但专门用于解析源代码元素?

2 个答案:

答案 0 :(得分:1)

不是命令行级别,但是程序转换系统(PTS)可以执行这种操作。您以重写规则的形式给它脚本。

我们的DMS软件再造工具包是一个handles full C++17的PTS,可让您编写转换规则。 DMS的解析机制可以处理空格,换行符,格式,注释,数字基数,字符集等所有复杂问题,这些事情看起来很愚蠢,但却妨碍了实际工作的完成。我们还投入了大量精力处理预处理器的条件,宏和包含文件。

对于您的特定示例,以下脚本似乎合适。

 domain Cpp~ISO14882c2017; -- making it clear which dialect to use

 rule NuclearEdit(x:exp,y:exp,symcount:exp, arg3:exp, arg4:exp): statement->statement
 =  "addSymbol(Position(\x,\y),\arg2,\arg3,\arg4);"
 -> "addSymbol(\symcount,\arg3,\arg4);" .

那比程序脚本要容易得多。

您可以告诉DMS解析C ++源文件,应用规则脚本,然后漂亮地打印答案。它将保留尚未应用转换的布局,注释,数字基数等。

这是一个非常小的示例。 DMS已用于大型(数百万行C ++代码)系统上,可以大规模进行API重构。

答案 1 :(得分:0)

Facebook的sgrep tool可以执行查找部分,但不能进行替换部分。但是我不相信他们的C ++前端。世界上有两个很好的C ++前端,分别是Edison Group和Semantic Designs,而Facebook则两者都不使用。