您需要的是一个
程序转换系统。这些工具通常允许您表达对源代码的更改,使用源级模式编写,本质上是说:
if you see *this*, replace it by *that*
但是,操作抽象语法树使匹配和替换过程比字符串处理更可靠。
这些工具必须具有所需源语言的解析器。源语言为C ++,这使得这个过程相当困难。
Clang有点符合要求;毕竟它可以解析C ++。OP对象无法在没有所有环境上下文的情况下执行此操作。就OP输入(格式正确)程序片段(语句等)到解释器中而言,Clang可能会[I自己没有太多经验]难以专注于片段是什么(语句?表达式?声明?...)。最后,Clang并不真正是PTS;其树修改程序不是源到源转换。对于方便性很重要,但可能不会阻止OP使用它;表面语法重写规则很方便,但您始终可以用更多的努力替换过程树操作。当有多个规则时,这开始变得非常重要。
GCC with Melt在与Clang相同的方式下有点符合要求。我认为Melt使GCC在这种工作中最好也只是稍微好一点。YMMV。
我们的
DMS软件重构工具包与其
完整的C++14 [编辑于2018年7月:C++17]前端绝对符合要求。DMS已被用于对大规模C++代码库进行大规模转换。
DMS可以在不预先告知语法类别的情况下
解析任意(良好形式的)C++片段,并使用其模式解析机制返回正确语法非终端类型的AST。[您可能会得到多个解析结果,如歧义,需要决定如何解决,有关更多讨论,请参见
为什么不能用LR(1)解析器解析C++?]如果您愿意在解析时放弃宏展开,并坚持预处理指令(它们也会被解析)与代码片段有良好的结构关系(#if foo{#endif不允许),则可以在不使用“环境”的情况下执行此操作,但这对于交互输入的代码片段不太可能是真正的问题。
然后,DMS提供完整的过程化AST库来操作已解析的树(搜索、检查、修改、构建、替换),然后可以从修改后的树重新生成表面源代码,给出OP文本以馈送给解释器。
在这种情况下,它的优点在于OP可以直接将大部分修改作为源到源语法规则编写。对于他的示例,他可以向DMS提供一个重写规则(未经测试但非常接近正确):
rule replace_Draw(A:primary,B1:expression,B2:expression):
primary->primary
"\A->Draw(\B1, \B2)" -- pattern
rewrites to
"MyFunc(\A, \B1, \B2)"
DMS将接受任何包含左侧“...Draw...”模式的解析AST,并在替换A、B1和B2匹配项后,用右侧替换该子树。引号是元引号,用于区分C++文本和规则语法文本;反斜杠是元转义符,在元引号内用于命名元变量。有关规则语法中可用内容的更多详细信息,请参见
DMS Rewrite Rules。
如果OP提供了这样一组规则,就可以要求DMS应用整个规则集。
所以我认为这对于OP来说完全可以胜任。这是一个相当重量级的机制,用于“添加”到他想提供给第三方的软件包中;DMS及其C++前端几乎不是“小”程序。但现代计算机具有大量资源,因此我认为问题在于OP需要多么严重地做到这一点。
Draw
的重复调用 (A->Draw(...)->...->Draw(...)
)? - Alexander FetermanA->Draw(B); C->Draw(D)
或者func(A->Draw(B), C->Draw(D))
。由于Draw
返回一个整数值,所以不会发生重复调用所示模式的情况。 - Eldritch CheeseA->Draw(B1, B2)
的过程中,可以进行宏扩展吗? - serge-sans-paille