Zarwan
Zarwan

Reputation: 5787

Change rule associated with a node at runtime in ANTLR4

I have a rule called "variable" which is just associated with non-keyword text. During runtime I compile a list of strings that should be associated with the rule "special" which is also just normal text however it is defined below variable, hence is never actually reached as everything will match to variable first.

During runtime how can I use this list to change any tokens matching "variable" that are also in the list to match "special"?

Example:

Grammar

parent:
  variable |
  special;

variable:
  ID;

special:
  ID;

Text to be parsed: "one two three four"
Result: variable, variable, variable, variable

Later I calculate that I want "four" to be associated with special. So the result should change to: variable, variable, variable, special

This should happen without the text actually changing. I tried looking into listeners and visitors but I'm not sure how I would actually modify the rule associated with a node. I also found this example that seems similar but it's in ANTLR3: Dynamically create lexer rule

Upvotes: 0

Views: 652

Answers (1)

GRosenberg
GRosenberg

Reputation: 5991

The perhaps most direct way of qualifying a token at run-time is to use a predicate to selectively falsify a rule. This can be done in either in the parser or lexer. Using your proto-grammar, and rearranging a bit:

@members {
    ArrayList<String> keyList = .... // get dynamic list of keywords

    public boolean inList(String id) {
        return keyList.contains(id) ;
    }
}

parent   : special   // dynamic keywords
         | variable  // everything else
         ;
special  : ID { inList($ID.getText()) }? ;
variable : ID ;

The predicate falsifies the special rule for any ID token not in the list of dynamic keywords.

Upvotes: 1

Related Questions