2010-03-07 125 views
2

我正在嘗試創建一個用於乘和除數字的語法,其中不需要包含'*'符號。我需要它輸出一個AST。因此,對於這樣的輸入:ANTLR:乘法省略'*'符號

1 2/3 4

我希望AST是

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

我已經打在下文中,它使用Java代碼來創建相應的節點:

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

這工作。但有沒有更好/更簡單的方法?

回答

1

這裏有一個辦法:

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

測試了:

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()); 
    } 
} 
生產

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

我知道必須有一個更好的辦法......現在似乎是顯而易見的。謝謝,巴特! – 2010-03-08 01:54:08

+0

@丹,不客氣! – 2010-03-08 07:09:30