Reputation: 262
Having a syntax definition like:
syntax ClassDeclaration = classDecl: "class" Identifier ClassBody ;
...
syntax ClassBody = classBody : "{" ClassBodyDeclaration* "}" ;
syntax ClassBodyDeclaration = ClassMemberDeclaration
| InstanceInitializer
| StaticInitializer
| ConstructorDeclaration
;
...
Using a visitor, I am able to pattern match the class body using:
visit(unit) {
case classDecl(name, ClassBody body): { // a block "A" here }
...
}
Question: in a situation like this, how can I pattern match the list of class body declarations from the "body" variable within the "A" block? I tried comprehension, but I got that "body" is not an enumerable type.
Upvotes: 0
Views: 164
Reputation: 1038
The simplest way is to give the ClassBodyDeclaration*
a name, like:
syntax ClassBody = classBody : "{" ClassBodyDeclaration* decls "}";
You can then use a comprehension to access each declaration, using code like declList = [ d | d <- body.decls ]
to extract them into a list, for instance.
Another alternative is to use Rascal's concrete syntax matching functionality, which doesn't require modifying the grammar. You can match the declarations in the body using the following code:
list[ClassBodyDeclaration] declList = [ ];
if ((ClassBody)`{ <ClassBodyDeclaration* decls> }` := body) {
declList = [ d | d <- decls ];
}
Finally, as mentioned in another response, you can do what Rascal calls a deep match, matching all occurrences of ClassBodyDeclaration
within body:
declList = [ d | /ClassBodyDeclaration d := body ];
This is fine unless, for some reason, you could have classes nested inside of other classes, in which case you wouldn't get only those class body declarations that are part of the current class but you would also get all those owned by the nested classes as well.
Upvotes: 2
Reputation: 6696
How about this solution:
visit(unit) {
case classDecl(name, classBody(ClassBodyDeclaration* body)): { // a block "A" here }
...
}
Or:
visit(unit) {
case (ClassDecl) `class <Identifier name> { <ClassBodyDeclaration* body> }` : {
...
}
}
Upvotes: 2
Reputation: 65
If you have no control over the grammar you could also use a deep match in a comprehension like so: declList = [ cbd | /ClassBodyDeclaration cbd := body]
.
This matches all ClassBodyDeclaration
contained in body
. The :=
is the match operator.
Upvotes: 2