2009-12-07 6 views
0

Je cherchais un moyen d'avoir des arguments/paramètres de fonction nommés dans n'importe quel ordre dans ANTLR. Est-ce que quelqu'un sait s'il y a une syntaxe pour ignorer l'ordre dans une expression analyseur ANTLR?ANTLR a nommé des arguments/paramètres de fonction dans n'importe quel ordre

Dites qu'il existe une fonction foo dans le langage qui peut prendre deux paramètres nommés: x et y. Comme ils sont nommés paramètres, je les aime pour pouvoir être transmis dans la fonction dans l'ordre:

foo(x=1, y=2) 

ainsi que

foo(y=2, x=1) 

devrait être à la fois juridique.

Je pourrais juste énumérer toutes les permutations de paramètre dans ANTLR, mais j'espérais qu'il y aurait une solution plus élégante, particulièrement puisque j'ai quelques fonctions qui peuvent prendre 5 paramètres.

Toute aide serait grandement appréciée!

+0

Je pourrais être en mesure d'aider, mais la question est un peu floue pour moi. Pouvez-vous donner un exemple de ce que vous essayez d'analyser? –

+0

Merci Scott pour votre offre généreuse, et désolé pour ne pas être clair. Un exemple est posté, espérons que ça aide! – Han

Répondre

1

Je suis assez sûr qu'il n'y a rien construit dans ANTLR pour gérer cela. Mais vous pouvez simplement saupoudrer une logique de programmation régulière dans votre grammaire pour réorganiser les paramètres.

Voici une petite grammaire de démonstration:

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

Et une petite classe pour le tester:

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

qui produit la sortie:

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

Gotcha ...

Si vous w ant à câbler « foo », « x » et « y » dans votre grammaire, procédez comme suit (non compilé/testé, mais devrait donner l'idée)

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

Si vous voulez plus de flexibilité (pour soutenir d'autres fonctions), faites quelque chose comme la suggestion de Bart.

Questions connexes