Reputation: 35
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".
Upvotes: 0
Views: 948
Reputation: 53307
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}?;
Upvotes: 0
Reputation: 4799
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.
Upvotes: 2