I'm pretty sure there is nothing built in ANTLR to handle this. But you can simple sprinkle some regular programming logic in your grammar to reorganize the parameters.
Here's a little demo grammar:
grammar NF;
@parser::header {
package antlrdemo;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Arrays;
}
@lexer::header {
package antlrdemo;
}
parse : concat+
;
concat : 'concat' '(' k1=Key '=' v1=Value ',' k2=Key '=' v2=Value ',' k3=Key '=' v3=Value ')' {
HashMap<String, String> params = new HashMap<String, String>();
params.put($k1.text, $v1.text);
params.put($k2.text, $v2.text);
params.put($k3.text, $v3.text);
HashSet<String> expected = new HashSet<String>(Arrays.asList(new String[]{"a", "b", "c"}));
if(!params.keySet().equals(expected)) {
throw new RuntimeException("No soup for you!");
}
System.out.println(params.get("a")+params.get("b")+ params.get("c"));
}
;
Key : ('a'..'z')+
;
Value : ('a'..'z' | 'A'..'Z' | '0'..'9')+
;
Space : (' ' | '\t' | '\r' | '\n'){$channel = HIDDEN;}
;
And a little class to test it:
package antlrdemo;
import org.antlr.runtime.*;
public class NFDemo {
static void test(String source) throws RecognitionException {
ANTLRStringStream in = new ANTLRStringStream(source);
NFLexer lexer = new NFLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
NFParser parser = new NFParser(tokens);
System.out.print(source+" -> ");
parser.parse();
}
public static void main(String[] args) throws RecognitionException {
test("concat(a=1, b=2, c=3)");
test("concat(b=2, c=3, a=1)");
test("concat(c=3, a=1, b=2)");
test("concat(c=3, a=1, x=2)");
}
}
which produces the output:
concat(a=1, b=2, c=3) -> 123
concat(b=2, c=3, a=1) -> 123
concat(c=3, a=1, b=2) -> 123
concat(c=3, a=1, x=2) -> Exception in thread "main" java.lang.RuntimeException: No soup for you!
at antlrdemo.NFParser.concat(NFParser.java:137)
at antlrdemo.NFParser.parse(NFParser.java:70)
at antlrdemo.NFDemo.test(NFDemo.java:13)
at antlrdemo.NFDemo.main(NFDemo.java:20)