Аргументы / параметры именованных функций ANTLR в любом порядке

Я искал способ, чтобы аргументы / параметры именованных функций появлялись в ANTLR в любом порядке. Кто-нибудь знает, есть ли синтаксис для игнорирования порядка в выражении парсера ANTLR?

Скажем, в языке есть функция foo, которая может принимать два именованных параметра: x и y. Поскольку они являются именованными параметрами, я бы хотел, чтобы их можно было передавать в функцию в любом порядке:

foo(x=1, y=2)

а также

foo(y=2, x=1)

оба должны быть законными.

Я мог бы просто перечислить все перестановки параметров в ANTLR, но я надеялся, что будет более элегантное решение, тем более что у меня есть некоторые функции, которые могут принимать 5 параметров.

Любая помощь будет принята с благодарностью!


person Han    schedule 07.12.2009    source источник
comment
Возможно, я смогу помочь, но вопрос для меня немного непонятен. Вы можете привести пример того, что пытаетесь разобрать?   -  person Scott Stanchfield    schedule 08.12.2009
comment
Спасибо, Скотт, за ваше щедрое предложение, и извините за неясность. Пример размещен, надеюсь, что это поможет!   -  person Han    schedule 08.12.2009


Ответы (2)


Я почти уверен, что в 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)
person Bart Kiers    schedule 08.12.2009

Попался...

Если вы хотите закрепить «foo», «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 ...; }
    ;

Если вам нужна большая гибкость (для поддержки других функций), сделайте что-нибудь вроде предложения Барта.

person Scott Stanchfield    schedule 08.12.2009