2009-12-07 74 views
0

我一直在尋找一種方法來命名函數參數/參數在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

回答

1

我很確定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) 
1

明白...

如果你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 ...; } 
    ; 

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