2011-05-17 1 views
2

J'ai écrit une grammaire ANTLR3 subdivisée en règles plus petites pour augmenter la lisibilité. Par exemple:Comment éviter les intermédiaires et les noeuds AST inutiles avec ANTLR3?

messageSequenceChart: 
    'msc' mscHead bmsc 'endmsc' end 
; 

# Where mscHead is a shortcut to : 
mscHead: 
    mscName mscParameterDecl? timeOffset? end 
    mscInstInterface? mscGateInterface 
; 

Je sais que la fonctionnalité intégrée de construction ANTLR AST permet à l'utilisateur de déclarer les nœuds AST intermédiaires qui ne seront pas en finale AST. Mais que faire si vous construisez l'AST à la main?

messageSequenceChart returns [msc::MessageSequenceChart* n = 0]: 
    'msc' mscHead bmsc'endmsc' end 
    { 
    $n = new msc::MessageSequenceChart(/* mscHead subrules accessors like $mscHead.mscName.n ? */ 
             $bmsc.n); 
    } 
; 

mscHead: 
    mscName mscParameterDecl? timeOffset? end 
; 

La documentation ne parle pas d'une telle chose. Il semble donc que je devrais créer des nœuds pour toutes les règles intermédiaires afin de pouvoir accéder au résultat de leurs sous-règles.

Est-ce que quelqu'un connaît une meilleure solution?

Merci.

Répondre

2

Vous pouvez résoudre ce problème en laissant votre sous-règle (s) renvoient plusieurs valeurs et un accès seulement ceux qui vous intéresse.

La démonstration ci-dessous montre comment le faire. Bien qu'il ne soit pas en C, je suis convaincu que vous serez en mesure de le régler pour l'adapter à vos besoins:

grammar Test; 

parse 
    : sub EOF {System.out.printf("second=\%s\n", $sub.second);} 
    ; 

sub returns [String first, String second, String third] 
    : a=INT b=INT c=INT 
    { 
     $first = $a.text; 
     $second = $b.text; 
     $third = $c.text; 
    } 
    ; 

INT 
    : '0'..'9'+ 
    ; 

SPACE 
    : ' ' {$channel=HIDDEN;} 
    ; 

Et si votre parse l'entrée "12 34 56" avec l'analyseur généré, second=34 est imprimé à la console, comme vous pouvez le voir après l'exécution:

import org.antlr.runtime.*; 

public class Main { 
    public static void main(String[] args) throws Exception { 
    TestLexer lex = new TestLexer(new ANTLRStringStream("12 34 56")); 
    TokenStream tokens = new TokenRewriteStream(lex); 
    TestParser parser = new TestParser(tokens); 
    parser.parse(); 
    } 
} 

Ainsi, un raccourci de la règle parse comme $sub.INT, ou $sub.$a pour accéder à l'un des trois INT jetons, dans pas possible, malheureusement.

+0

Génial! Ça marche ! : D Vous m'avez fait économiser beaucoup de temps! –

+0

@Julio, c'est bon d'entendre ça, et je vous en prie. –

+0

Un autre problème! http://stackoverflow.com/questions/6047127/ignore-tokens-in-the-token-characters Je crois en toi: p –

Questions connexes