我经常使用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 ++代码
它们没有范围和括号级别的概念。在此示例中,我不能简单地计算逗号的数量,因为第一个逗号是构造函数调用的一部分,与第一个函数参数相关,因此不应该计算在内 该工具将必须跟踪当前的括号级别,并仅计算该级别的参数
它们没有上下文的概念。该代码可能包含注释或字符串文字,在解析语法元素时必须将其忽略。该工具将必须跟踪当前上下文并忽略注释或字符串文字中的内容。
必须忽略参数前后的空格。它们使正则表达式更加复杂,但是在解析源代码时则无所谓。
换句话说,我知道这样的工具很难解析:
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,但专门用于解析源代码元素?
答案 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则两者都不使用。