2010-03-07 5 views
2

J'essaie de créer une grammaire pour multiplier et diviser des nombres dans lesquels le symbole '*' n'a pas besoin d'être inclus. J'en ai besoin pour sortir un AST. Donc, pour l'entrée comme ceci:ANTLR: multiplication en omettant le symbole '*'

1 2/3 4

Je veux l'AST soit

(* (/ (* 1 2) 3) 4)

J'ai frappé sur ce qui suit, qui utilise le code java pour créer les nœuds appropriés:

grammar TestProd; 

options { 
    output = AST; 
} 

tokens { 
    PROD; 
} 

DIV : '/'; 

multExpr: (INTEGER -> INTEGER) 
      ({div = null;} 
      div=DIV? b=INTEGER 
       -> 
       ^({$div == null ? (Object)adaptor.create(PROD, "*") : (Object)adaptor.create(DIV, "/")} 
       $multExpr $b))* 
    ; 

INTEGER: ('0' | '1'..'9' '0'..'9'*); 

WHITESPACE: (' ' | '\t')+ { $channel = HIDDEN; }; 

Cela fonctionne. Mais existe-t-il un moyen meilleur/plus simple?

Répondre

1

Voici une manière:

grammar Test; 

options { 
    backtrack=true; 
    output=AST; 
} 

tokens { 
    MUL; 
    DIV; 
} 

parse 
    : expr* EOF 
    ; 

expr 
    : (atom -> atom) 
    ('/' a=atom -> ^(DIV $expr $a) 
    | a=atom  -> ^(MUL $expr $a) 
    )* 
    ; 

atom 
    : Number 
    | '(' expr ')' -> expr 
    ; 

Number 
    : '0'..'9'+ 
    ; 

Space 
    : (' ' | '\t' | '\r' | '\n') {skip();} 
    ; 

Testé avec:

import org.antlr.runtime.*; 
import org.antlr.runtime.tree.Tree; 

public class Main { 
    public static void main(String[] args) throws Exception { 
     String source = "1 2/3 4"; 
     ANTLRStringStream in = new ANTLRStringStream(source); 
     TestLexer lexer = new TestLexer(in); 
     CommonTokenStream tokens = new CommonTokenStream(lexer); 
     TestParser parser = new TestParser(tokens); 
     TestParser.parse_return result = parser.parse(); 
     Tree tree = (Tree)result.getTree(); 
     System.out.println(tree.toStringTree()); 
    } 
} 

produit:

(MUL (DIV (MUL 1 2) 3) 4) 
+0

Je savais qu'il devait y avoir une meilleure façon ... semble maintenant évident. Merci, Bart! –

+0

@Dan, vous êtes les bienvenus! –