模式匹配语法定义

时间:2016-10-20 15:44:04

标签: rascal

具有如下语法定义:

syntax ClassDeclaration = classDecl: "class" Identifier ClassBody ;
...
syntax ClassBody = classBody : "{" ClassBodyDeclaration* "}" ;

syntax ClassBodyDeclaration = ClassMemberDeclaration 
                           | InstanceInitializer 
                           | StaticInitializer 
                           | ConstructorDeclaration 
                           ;

... 

使用访问者,我可以使用以下方式匹配类主体:

visit(unit) {
  case classDecl(name,  ClassBody body): { // a block "A" here }
  ...
}

问题:在这样的情况下,我如何模式匹配“A”块中“body”变量的类体声明列表?我尝试了理解,但我认为“身体”不是一个可枚举的类型。

3 个答案:

答案 0 :(得分:2)

最简单的方法是给ClassBodyDeclaration*一个名字,如:

syntax ClassBody = classBody : "{" ClassBodyDeclaration* decls "}";

然后,您可以使用理解来访问每个声明,例如使用declList = [ d | d <- body.decls ]之类的代码将它们提取到列表中。

另一种选择是使用Rascal的具体语法匹配功能,它不需要修改语法。您可以使用以下代码匹配正文中的声明:

list[ClassBodyDeclaration] declList = [ ];

if ((ClassBody)`{ <ClassBodyDeclaration* decls> }` := body) {
    declList = [ d | d <- decls ];
}

最后,正如另一个回复中所提到的,你可以做Rascal所谓的深度匹配,匹配正文中所有出现的ClassBodyDeclaration

declList = [ d | /ClassBodyDeclaration d := body ];

除非出于某种原因,你可以将类嵌套在其他类中,否则这样就可以了。在这种情况下,你不会只获得属于当前类的那些类体声明,但你也可以得到所有类嵌套类所拥有的那些。

答案 1 :(得分:2)

如果你无法控制语法,你也可以在理解中使用深度匹配:declList = [ cbd | /ClassBodyDeclaration cbd := body]。 这与ClassBodyDeclaration中包含的所有body相匹配。 :=是匹配运算符。

答案 2 :(得分:2)

这个解决方案怎么样:

file_PATH = "y:/file_A.txt"

if os.path.exists(file_PATH):
    file_to_use = "y:/file_A.txt"
else:
    file_to_use = "d:/file_B.txt"

或者:

visit(unit) {
  case classDecl(name,  classBody(ClassBodyDeclaration* body)): { // a block "A" here }
  ...
}