Rodrigo Bonifacio
Rodrigo Bonifacio

Reputation: 262

Pattern Matching syntax definition

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

Answers (3)

Mark Hills
Mark Hills

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

Jurgen Vinju
Jurgen Vinju

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

Jouke Stoel
Jouke Stoel

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

Related Questions