Reputation: 332
I have a special case where I am not able to write Antlr3 parser rule for that.
I have 5 parser rules, let say: a,b,c,d and e.
Conditions:
Possible cases:
Is Antlr provide any easy way to implement this? It is possible by implementing rule for each combination of rule.
Upvotes: 0
Views: 76
Reputation: 27966
A possible way to do this would be with context-dependent predicates. How you would implement would be language dependent but it might look something like:
statement : element*;
element : {!seen(a) && !seen(b)}? a {add(a);}
| {!seen(a) && !seen(b)}? b {add(b);}
| {!seen(c) c {add(c);}
....
Essentially this stops the parser considering an option after it's been seen once.
Here is a very simple example using Java:
@parser::header {
import java.util.EnumSet;
import java.util.List;
}
@parser::members {
public enum Val {A, B, C, D, E};
public EnumSet<Val> result = EnumSet.noneOf(Val.class);
}
statement : (a|b|c|d|e)+ EOF;
a : {!result.contains(Val.A) && !result.contains(Val.B)}? 'a' {result.add(Val.A);};
b : {!result.contains(Val.A) && !result.contains(Val.B)}? 'b' {result.add(Val.B);};
c : {!result.contains(Val.C)}? 'c' {result.add(Val.C);};
d : {!result.contains(Val.D)}? 'd' {result.add(Val.D);};
e : {!result.contains(Val.E)}? 'e' {result.add(Val.E);};
Upvotes: 3
Reputation: 53337
ANTLR4 doesn't allow to implement all those conditions you specified. Especially the condition that rules may appear in any order but only once is something that is barely supported by any parser.
However, you can use a two step approach. First, allow all rules to appear in any order. Done usually like this:
main: sub*;
sub: a | b | c;
After parsing you can do another step (usually you will have a semantic step anyway, which would qualify here too) and check the occurences in the generated parse tree. You can then throw a detailed error message telling the user what is not allowed (which is tricky, if not impossible, if you try to do that in parser rules). The approach laid out by @sprinter is ok too, but it will not give you any meaningful error message, but just tell you that rule element
had no viable alt (which can have many reasons, not only duplicate rules).
And with that second step you can easily apply any additional condition (specific orders, rules that must not go together etc., without having to change your grammar), which you cannot do in the parsing step (since you cannot lookahead rules).
Upvotes: 3