By specifying the grammar rule "appear in any order, but not more than once",
Let's say I have three characters A, B, C.
In ANTLR, how can I point out that in sentence A, B and C can appear at most once and that they can appear in any order. (For example, ABC, BCA are both legal)
I tried
(A | B | C) *
knowing that he would only care about a part of "any order", but could not figure out how to say that he could only appear once.
Edited: I've tried using boolean flags which worked but seems too hairy - there should be an easier way, huh?
myrule;
{
boolean aSeen = false;
boolean bSeen = false;
boolean cSeen = false;
}
:
( A { if (aSeen) throw RuntimeException("alraedy seen") else aSeen = true; }
| B { if (bSeen) throw RuntimeException("alraedy seen") else bSeen = true; }
| C { if (cSeen) throw RuntimeException("alraedy seen") else cSeen = true; }
)*
;
source to share
Since you mentioned that there can be many, many permutations, I would prefer to keep a simple grammar and process it in a visitor or listener, for example:
public class ValuesListener : ValuesBaseListener
{
bool isASeen = false; // "seen flag here"
public override void ExitA(ValuesParser.AContext context)
{
if (isASeen) // already parsed this once
<throw exception to stop and inform user>
else // first time parsing this, so process and set flag so it won't happen again
{
isASeen = true; // never gets reset during this tree walk
<perform normal processing here>
}
}
}
Then your grammar might be something like
myrule: someothertoken myRuleOptions* ;
myRuleOptions
: A
| B
| C
| ...etc.
My mind? There are ways to do this with predicates as suggested above, but for readability and technical support by engineers inexperienced in ANTLR4 but very proficient in the target language, I would consider this approach. In my environment, I often hand over ANTLR projects to engineers who just follow a pattern I set up and who don't really understand ANTLR. They are easier to follow.
source to share