rascal - 嵌套的后代模式匹配
问题描述
我正在尝试查找所有方法调用和包含它们的类。如果我理解正确,模式匹配会执行回溯以以所有可能的方式进行匹配。
采取以下java代码。
package main;
public class Main {
public static void main(String[] args) {
System.out.println("hello world");
System.out.println("hello again");
}
}
我正在使用 createAstsFromDirectory 加载代码。
rascal>ast = createAstsFromDirectory(|home:///multiple-method-calls|, false);
我试图找到对 println 的两个调用。以下代码匹配一次:
void findCalls(set[Declaration] ast)
{
visit(ast)
{
case \class(_,_,_,/\methodCall(_,_,str methodName,_)):
println("<methodName>");
}
}
rascal>findCalls(ast);
println
ok
此代码匹配四次:
void findCalls(set[Declaration] ast)
{
visit(ast)
{
case /\class(_,_,_,/\methodCall(_,_,str methodName,_)):
println("<methodName>");
}
}
rascal>findCalls(ast);
println
println
println
println
ok
模式必须如何精确匹配两次?
相关问题,如何访问类名?尝试访问类名时,我收到一条错误消息。
void findCalls(set[Declaration] ast)
{
visit(ast)
{
case /\class(str className,_,_,/\methodCall(_,_,str methodName,_)):
println("<className> <methodName>");
}
}
findCalls(ast);
Main println
|project://personal-prof/src/Assignment13Rules.rsc|(3177,9,<141,16>,<141,25>): Undeclared variable: className
看起来第一个匹配项将 className 正确绑定到“Main”,但第二个匹配项没有。
解决方案
我想我会这样写:
void findCalls(set[Declaration] ast) {
for(/class(_, _, _, /methodCall(_,_,str methodName,_)) <- ast) {
println("<methodName>");
}
}
for 循环适用于它可以找到的每个类,通过它可以在内部找到的每个方法调用,因此对于您给出的示例来说是两次。
您的第二次尝试出错并且匹配太频繁:如果您将 a 嵌套/
在访问案例的顶部,则您访问树中的每个位置一次,然后再次遍历整个子树,包括根节点。所以你会接到两次电话。
您的第一次尝试出错了,因为访问的案例模式的顶层不会自行回溯,它会找到整个模式的第一个匹配项然后停止。所以嵌套/
只匹配一次,然后执行主体。
在 for 循环解决方案中,for 循环(与访问不同)将尝试所有可能的匹配,直到它停止,所以这就是要走的路。还有另一种更接近您的原始计划的解决方案:
void findCalls(set[Declaration] ast) {
visit (ast) {
case class(_, _, _, body) :
for (/methodCall(_,_,str methodName,_) <- body) {
println("<methodName>");
}
}
}
这也像 for 循环一样工作,它首先通过访问一一找到所有类,然后通过 for 循环遍历所有嵌套匹配。
最后,您还可以嵌套访问本身以获得正确答案:
void findCalls(set[Declaration] ast) {
visit (ast) {
case class(_, _, _, body) :
visit(body) {
case methodCall(_,_,str methodName,_): {
println("<methodName>");
}
}
}
}
WRT 到 className 的东西,似乎visit
和顶级深度匹配的组合在这样的情况下:case /<pattern>
Rasca 解释器中有一个错误,深度模式中变量绑定丢失。所以请避免这种模式(我认为您不需要它),如果您愿意,请在 github 上提交问题报告?
在 for 循环的情况下,这将按预期工作:
for(/class(str className, _, _, /methodCall(_,_,str methodName,_)) <- ast) {
println("<className>::<methodName>");
}
推荐阅读
- c++ - 在 MacOSX 登录时启动我的程序
- javascript - 如何在 RabbitMq node-amqplib 库中检查连接是否存在?
- c# - WPF:TextBlock AutomationProperties.HelpText 更改
- node.js - 部署到heroku,出现错误
- sql-server - 动态转置列和行
- qt - TreeView:模型的参考错误
- c++ - 比较大型数据集中的向量
- python - 如何解决:'str' 对象在 keras 中没有属性 'data_format'
- python - 在不使用 re 的情况下更改由下划线分隔的字符串中的特定字符的更好方法
- design-patterns - 反向装饰器模式