C/C++-语法感知 search/replace 命令行工具是否适用于 linux?

Is there a C/C++-grammar-aware search/replace command line tool for linux?

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

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

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

我想做以下事情:

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

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

现在,在我的 awk 脚本中获取位置参数如下所示:

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

用 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 这样的简单工具,但专门用于解析源代码元素?

不是命令行级别,而是程序转换系统 (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 大规模重构。

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