0
votes

Is there a good way to have Antlr4 identify the version of a grammar used to parse input?

If I have two grammars, GA and GB, where GA is a subset of GB where GB imports GA is there a way to have Antlr4 report if the parsed input was parsed using GA or GB?

I could simply try parsing it with GB first and if that failed try parsing it with GA but I was wondering if there was a more efficient way to have Antlr keep track of what rules where used and say, "I successfully parsed this but only used rules from the GA grammar".

2

2 Answers

2
votes

The right approach would be to correlate each rule (or only key rules) to a parser version.

First of all you are going to need a field to track current version:

@members {
    int currentVersion = 1;
}

Now, let's suppose you have a rule RULE_ONE which correlates with version one and RULE_TWO which correlates with version two.
Each time a rule correlated with a higher version is accepted the currentVersion field should be changed:

RULE_ONE
      {currentVersion = Math.max(1, currentVersion);} //1 is the parser version
    : some_token
    ;

RULE_TWO
      {currentVersion = Math.max(2, currentVersion);} //2 is the parser version
    : some_token
    ;

Thus, when parsing is done, you can get the maximum version which has been used.

0
votes

Not exactly what you are asking, but in my MySQL grammar I have to support multiple server versions, which I do by using semantic predicates. That means, I can use a single grammar and enable/disable certain paths depending on a serverVersion field I have in my parser. This is how it looks like:

alterDatabase:
    DATABASE_SYMBOL schemaRef (
        createDatabaseOption+
        | {serverVersion < 80000}? UPGRADE_SYMBOL DATA_SYMBOL DIRECTORY_SYMBOL NAME_SYMBOL
    )
;

and works very well. I can use this approach even in the lexer (but there with validating semantic predicates, for performance reasons), which allows me to switch keywords on and off, like this:

CONTRIBUTORS_SYMBOL: C O N T R I B U T O R S {serverVersion < 50700}?;