match - 匹配部分 AST 的根元素
问题描述
我想使用 Clair 和 Rascal 重构一些 C 代码。我搜索具有特定名称的函数。如果我找到这样的功能,我想用另一个功能替换它。我需要在四个功能之间进行选择。要选择的函数取决于找到的函数的参数。我需要匹配表达式的根元素。
我可以使用访问模式进行匹配。我试过了
visit(body) {
case \functionCall(func, args): {
if ("myName" == func.name.\value) {
visit(args[0]) {
case \equals(_, _): println("Equals");
case \notEquals(_, _): println("Not equals");
}
}
}
}
这并不能保证我匹配根元素。在 (A != B) == CI 只想匹配 ==
我怎样才能只匹配根元素?
解决方案
您可以任意嵌套模式并使用它来匹配函数调用,包括函数名称和要匹配的第一个参数的形状。
例如:
case functionCall(someId("my name", [e:\equals(_, _), *_]) => newFunctionCall(e)
case functionCall(someId("my name", [e:\notEquals(_, _), *_]) => newFunctionCall(e)
[..]
请注意,只要第一个参数是 equals 或 nonEquals 表达式,这里匹配任意长度的参数列表的列表模式。
因此,您可以为第一个参数的每个案例重复一个顶级案例,如上,或嵌套一个开关并使用“插入”,如下所示:
case functionCall(someId("my name", [arg, *_]) :
switch(arg) {
case equals(_, _) : insert newFunctionCall(arg);
...
}
我更喜欢第一种情况,因为它更具声明性。Rascal 应该在内部考虑到常见的东西以提高效率。两种模式非常相似的事实并不是 Rascal 恕我直言的代码异味,因为这就是这段代码的全部意义所在,您希望稍微不同地对待两种相似的模式,第一个示例文档明确地没有嵌套控制流。换句话说:嵌套模式比嵌套控制流更清晰
推荐阅读
- java - 有没有使用 selenium webdriver 绕过 cookie iframe 的解决方案?
- discord.js - 无法读取未定义 discord.js v12 的属性“角色”
- c# - 根据 Type 变量传递泛型类型
- c# - .Net assembly for db migration can't be registered if com-interop is set under project properties build in vs
- c++ - Why doesn't address change in forked process?
- amazon-cloudfront - AWS CloudFront - bypass cache depending on the presence of a certain header or cookie?
- r - Issue copying filenames into a new folder in R
- python - Iterating through multiple numpy arrays simultaneously
- javascript - Changing state value in async event function
- pdf - 将ftz文件转换为pdf