ANTLR4 - label assigned to a block which is not a set

3.8k views Asked by At

I am getting the errors label assigned to a block which is not a set. This error occurs for my labels: child, left, right, first, and last. What I am doing is assigning a label to a group of alternatives; shouldn't this be supported?

Fragment of my grammar:

expr:
      unaryExpr '(' child=(stat | expr | NUMBER) ')'                                                #labelUnaryExpr
    | binaryExpr '(' left=(stat | expr | constant) ',' right=(stat | expr | constant) ')'           #labelBinaryExpr
    | multipleExpr '(' first=(stat | expr | constant) (',' rest=(stat | expr | constant))+ ')'      #labelMultipleExpr
    ;   
1

There are 1 answers

4
GRosenberg On BEST ANSWER

The problem is that alternate elements can be of different types: TerminalNodes, the various rule Contexts, and Lists of both. NUMBER and expr are clearly different types. So assignment to a single label (single variable type) is not generally possible.

Extract the alternatives out as subrules:

....
| multipleExpr '(' first=altExpr (',' rest+=altExpr)+ ')'
;

altExpr   : stat | expr | constant ;

In this particular case, you don't necessarily need labels, since the altExpr's will be captured in a List in the multipleExpr context class -- the first element of the list will always be the first encountered altExpr.

Look at the relevant context class in the generated parser to see how the labels are realized as variables.

And, when constructing labeled lists, the += assignment op is required.

Updated:

The listener will have a method

enterMultipleExpr(YourParser.MultipleExprContext ctx);

The YourParser embedded class MultipleExprContext will have a method

    public List<AltExprContext> altExpr() {
        return getRuleContexts(AltExpr.class);
    }

so ctx.altExpr() returns the list. If you implement the labels, the context will also have the public variables:

public AltExprContext first;
public List<AltExprContext> rest;

Again, look at the relevant context class in the generated parser to see what generated accessors you have to work with.