不能遍历AST的节点,同时为每个节点分配一个ID

时间:2014-11-04 17:26:06

标签: rascal

这是一个简单的个人尝试,以了解Rascal内部的情况。必须有更好的(如果还没有支持)解决方案。 这是代码:

fileLoad = |home:///PHPAnalysis/systems/ApilTestScripts/simple1.php|;
fileAST=loadPHPFile(fileLoad,true,false);

//assign a simple id to each node
public map[value,int] assignID12(node N)
{
    myID=();
    visit(N)
    {
        case node M:
        {
            name=getName(M);
            myID[name] =999;

        }
    }
return myID;
}

ids=assignID12(fileAST);

给了我

|stdin:///|(92,4,<1,92>,<1,96>): Expected str, but got value 

loadPHPFile返回一个类型为:list [Stmt]的节点,其中每个Stmt是程序中可能出现的多种语句之一(在我的例子中是PHP)。没有说明为什么我这样做,为什么上面的代码不起作用?尤其令人沮丧,因为在线文档中可以找到一个非常简单的例子。请参阅:http://tutor.rascal-mpl.org/Recipes/Basic/Basic.html#/Recipes/Common/CountConstructors/CountConstructors.html

2 个答案:

答案 0 :(得分:0)

我启动了一个新的控制台,它似乎工作。当然,我将map [value,int]的返回类型更改为map [str,int],就像它最初在示例中一样。

我遇到的问题是我之前可能错误地定义了这个功能。虽然我很快解决了一个明显的问题,但它一直给我错误。我意识到在Rascal中,当你启动一个控制台并导入某些定义时,它(似乎)不可能覆盖这些定义。解释器不断参考您提供的第一个定义。这可能只是执行类型检查的解释器,并防止无意识和/或不兼容的分配。这对变量有意义(在典型的程序意义上),但在函数(或方法)上强制执行它似乎并不是最好的主意。我觉得它变得很麻烦,因为用户通常必须在他/她对功能定义感到满意之前进行一些迭代。只是我的意见......

答案 1 :(得分:0)

您很可能已将范围中的名称ids定义为类型map[str,int],这将是错误的直接来源。您可以在函数labelScript中查看脚本https://github.com/cwi-swat/php-analysis/blob/master/src/lang/php/analysis/cfg/LabelState.rsc以查看如何在PHP AiR中完成此操作(因此您不需要自己编写此代码)。这将给你一个脚本,其中所有的表达式和语句都有一个指定的ID,以及标签状态,它只跟踪这个标签操作中使用的一些信息(主要是生成一个唯一ID的计数器)。 / p>

对于早期的响应,最好的做法是在您可以导入的模块中提供定义。如果这样做,将会拾取对类型等的任何更改(如果模块已经导入,则会自动进行更改,因为如果模块已更改,或者下次导入模块时,Rascal将为您重新导入模块)。但是,如果您直接在控制台中定义某些内容,则不会发生这种情况。将控制台视为一个您不断添加的大型模块。由于我们可以有函数的重载,如果你再次定义函数,你实际上是定义了函数的新替代方法,但这可能不像你期望的那样工作。