Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I skip a parsing rule using ANTLR 4?

In the lexer, tokens can be skipped, keeping them out of the parser, like so:

Whitespace : [ \t\r\n]+ -> skip ;

Is there an equivalent to -> skip for the parser? That is, once a parser rule is matched, is there a way to keep it out of the parse tree? Hypothetically, it might look something like this:

document : prolog? -> skip 
           misc* element misc* 
         ;

(Example taken from The Definitive ANTLR Book, p 225.)

like image 222
james.garriss Avatar asked Jan 28 '15 18:01

james.garriss


1 Answers

Not skip, but you can significantly qualify how a rule is matched using a predicate.

@members {
    boolean once = true;
    public boolean once() {
        if (once) {
            once = false;
            return true;
        }
        return false;
    }
}

Consider the possibility of a subrule match only once:

example1 : { once() }? prolog misc* element misc* 
         | misc* element misc* 
         ;

Allow only a single chance to match a subrule:

example2 : prolog { once() }? misc* element misc* 
         | misc* element misc* 
         ;

Match a subrule only one time:

example3 : prolog misc* element misc* { once() }?
         | misc* element misc* 
         ;

Update

Antlr3 has a postfix '!' operator that silently elides its element from the tree. Antlr4 has no direct equivalent.

The idiomatic workaround is to just totally ignore the existence of the element in the parse tree when walking. The visitor won't care if the element is present or not unless you explicitly write the code to do so.

Nonetheless, you can emulate the elide operator by demoting the prolog rule to a token rule that puts the matched token on the hidden channel (just in case you want to look at it later). Depending on the complexity of the prolog rule, rule demotion won't always be an option.

like image 178
GRosenberg Avatar answered Oct 21 '22 23:10

GRosenberg