我想使用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)== C中,我只想匹配==
我怎么只匹配根元素?
答案 0 :(得分:1)
您可以任意嵌套模式,并使用它来匹配函数调用,包括函数名称和要匹配的第一个参数的形状。
例如:
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 IMHO中并不是代码异味,因为这就是这段代码的全部重点,您想要略微不同地对待两种相似的模式,并且第一个示例文档明确地不嵌套控制流。换句话说:嵌套模式比嵌套控制流?
更清晰答案 1 :(得分:0)
我使用此字段,因为注释字段中的空间有限。
我喜欢嵌套模式的此功能,但是我没有找到匹配的简单案例。我尝试了以下模式:
visit(body) {
case \functionCall("methodA", [arg, *_]): println("match");
case \functionCall(SomeId("methodA", [arg, *_])): println("match");
case \functionCall(SomeId("methodA"), [arg, *_]): println("match");
case \functionCall(IdExpresssion("methodA", [arg, *_])): println("match");
case \functionCall(IdExpresssion("methodA"), [arg, *_]): println("match");
case \functionCall(name("methodA", [arg, *_])): println("match");
case \functionCall(name("methodA"), [arg, *_]): println("match");
}
iprint(body)给出以下结果:
compoundStatement(
[
compoundStatement(
[
expressionStatement(
.... some expressions and declarations
for(
... for statement
compoundStatement(
[
... inside for loop
expressionStatement(
functionCall(
idExpression(
name(
"methodA",
src=|project://Instrumentation/example.c|(11195,10)),
src=|project://Instrumentation/example.c|(11195,10),
decl=|cpp+problem://Attempt%20to%20use%20symbol%20failed:%20methodA|,
typ=problemType("Failure to determine type of expression")),
[equals(
idExpression(
name(
"beforeTest",
src=|project://Instrumentation/example.c|(11207,20)),
src=|project://Instrumentation/example.c|(11207,20),
decl=|cpp+variable:///test1()/beforeTest|,
typ=problemType("Type depends on an unresolved name")),
idExpression(
name(
"afterTest",
src=|project://Instrumentation/example.c|(11231,19)),
src=|project://Instrumentation/example.c|(11231,19),
decl=|cpp+variable:///test1()/afterTest|,
typ=problemType("Type depends on an unresolved name")),
src=|project://Instrumentation/example.c|(11207,43),
typ=problemType("Type depends on an unresolved name"))],
src=|project://Instrumentation/example.c|(11195,57),
typ=problemBinding()),
src=|project://Instrumentation/example.c|(11195,58)),
expressionStatement(
... more expressions and declaratios in for loop
],
src=|project://Instrumentation/example.c|(10148,1349))ok
如何制作与MethodA匹配的模式?