2013-10-05 100 views
1

我遇到了ANTLR輸出的一個小問題。 伊夫一個真的小的語法看起來像這樣:ANTLR輸出及其順序

test : states; 
states : '.states' state+; 
state : stateID=ID { 
    System.out.println("state: " + $stateID.text); 
     | stateID=ID '{' state* '}' { 
    System.out.println("SubState: " + $stateID.text);}; 

我想分析看起來像這樣的內容:

a{ 
    b 
    c{ 
     d 
    } 
} 

好了,問題是,第一個記號,我會得到的是「 b',然後是'd',然後是'c'。 但我的意圖是將其解析爲我的數據結構,我需要知道他們的父母。 我通過這個命令得知的是,c是d的父親,但是b怎麼辦? 如果我重寫了例子來這種形式:

a{ 
    c{ 
     d 
    } 
    b 
} 

一切都很好。那麼有沒有辦法知道誰是b的父母,而沒有限制在最後一個例子中寫出它?

回答

1

在ANTLR 4中,不再推薦使用語法操作。解析器可能以非預期的順序訪問和測試不同的規則和替代方案,因此除非添加錯誤處理代碼,否則最好讓進程正常運行,然後檢查結果。

所以你讓解析器創建它的樹,然後編寫一個自定義的偵聽器,它會在每一步發出你的println調用。例如,假設您正在使用名爲Foo的語法,以便ANTLR自動生成一個FooBaseListener類。

所以,首先你會是這樣的:

public class PrintingFooListener extends FooBaseListener { 
    @Override 
    public void enterState(FooParser.StateContext ctx) 
    { 
     // It is possible to get all sorts of token/subrule/text 
     // information from the ctx input, especially if you labeled 
     // the parser/lexer rules. 

     System.out.println("I entered State"); 
    } 
} 

然後使用ParseTreeWalker實用工具類通過解析樹與您的拖訪客瀏覽:

// Assume lexing, etc. already done before this point 
ParserRuleContext<Token> tree = parser.myMainRule(); // Do parse 

ParseTreeWalker walker = new ParseTreeWalker(); // Premade utility class 
PrintingFooListener listener = new PrintingFooListener(); // Your customized subclass 
walker.walk(listener, tree); 
+0

你不需要創建一個'ParseTreeWalker'的實例。只需使用'ParseTreeWalker.DEFAULT.walk(監聽器,樹);' –