ANTLR以任何顺序命名函数参数/参数

问题描述:

我一直在寻找一种方法来命名函数参数/参数在ANTLR中以任何顺序出现。有谁知道是否有语法来忽略ANTLR解析器表达式中的顺序?ANTLR以任何顺序命名函数参数/参数

假设语言中有一个函数foo,可以使用两个命名参数:xy。由于它们被命名为参数,我希望他们能够以任何顺序被传递到函数:

foo(x=1, y=2) 

以及

foo(y=2, x=1) 

都应该是合法的。

我可以列出ANTLR中的所有参数排列,但我希望会有更优雅的解决方案,尤其是因为我有一些函数可能需要5个参数。

任何帮助将不胜感激!

+0

我可能会帮忙,但这个问题对我来说有点不清楚。你能举一个你想要解析的例子吗? – 2009-12-07 23:45:30

+0

谢谢Scott的慷慨提议,并且由于不清楚而感到抱歉。举个例子,希望有帮助! – Han 2009-12-08 16:05:33

我很确定ANTLR没有内置任何内容来处理这个问题。但是你可以简单地在你的语法中添加一些常规编程逻辑来重新组织参数。

这里有一个小的演示语法:

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;} 
     ; 

而且有点类来测试它:

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)"); 
    } 
} 

产生的输出:

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) 

明白...

如果你w蚂蚁硬线“富”,“X”和“Y”,在你的语法,请执行下列操作(不编译/测试,但应该给的想法)

foo : 
    { SomeType x=null, y=null; } 
    'foo' '(' 
     ( 'x' '=' {if (x != null) throw ...;} x=value 
     |  'y' '=' {if (y != null) throw ...;} y=value 
    )* 
    ')' 
    { if (x = null || y == null) throw ...; } 
    ; 

如果你想要更多的灵活性(支持其他功能),做一些像巴特的建议。