2015-04-29 34 views
3

使用監聽器迭代令牌時,我想知道如何使用ParserRuleContext來查看令牌流中的下一個令牌或接下來的幾個令牌?在監聽器中使用ParserRuleContext遍歷令牌 - ANTLR4

在下面的代碼我想在所有的令牌當前令牌直到EOF後偷看:

@Override 
public void enterSemicolon(JavaParser.SemicolonContext ctx) { 

    Token tok, semiColon = ctx.getStart(); 
    int currentIndex = semiColon.getStartIndex(); 
    int reqInd = currentIndex+1; 
    TokenSource tokSrc= semiColon.getTokenSource(); 
    CharStream srcStream = semiColon.getInputStream(); 
    srcStream.seek(currentIndex); 

    while(true){ 

     tok = tokSrc.nextToken() ; 
     System.out.println(tok); 
     if(tok.getText()=="<EOF>"){break;} 
     srcStream.seek(reqInd++); 
    } 
} 

但輸出我得到的是:

  . 
      . 
      . 
      . 
      . 
[@-1,131:130='',<-1>,13:0] 
[@-1,132:131='',<-1>,13:0] 
[@-1,133:132='',<-1>,13:0] 
[@-1,134:133='',<-1>,13:0] 
[@-1,135:134='',<-1>,13:0] 
[@-1,136:135='',<-1>,13:0] 
[@-1,137:136='',<-1>,13:0] 
[@-1,138:137='',<-1>,13:0] 
[@-1,139:138='',<-1>,13:0] 
[@-1,140:139='',<-1>,13:0] 
[@-1,141:140='',<-1>,13:0] 
[@-1,142:141='',<-1>,13:0] 
[@-1,143:142='',<-1>,13:0] 
[@-1,144:143='',<-1>,13:0] 
[@-1,145:144='',<-1>,13:0] 
[@-1,146:145='',<-1>,13:0] 
[@-1,147:146='',<-1>,13:0] 
[@-1,148:147='',<-1>,13:0] 
[@-1,149:148='',<-1>,13:0] 
[@-1,150:149='',<-1>,13:0] 
[@-1,151:150='',<-1>,13:0] 
[@-1,152:151='',<-1>,13:0] 
[@-1,153:152='',<-1>,13:0] 
[@-1,154:153='',<-1>,13:0] 
[@-1,155:154='',<-1>,13:0] 
[@-1,156:155='',<-1>,13:0] 
[@-1,157:156='',<-1>,13:0] 
[@-1,158:157='',<-1>,13:0] 
[@-1,159:158='',<-1>,13:0] 
[@-1,160:159='',<-1>,13:0] 
[@-1,161:160='<EOF>',<-1>,13:0] 
[@-1,137:136='',<-1>,13:0] 
[@-1,138:137='',<-1>,13:0] 
[@-1,139:138='',<-1>,13:0] 
[@-1,140:139='',<-1>,13:0] 
[@-1,141:140='',<-1>,13:0] 
[@-1,142:141='',<-1>,13:0] 
[@-1,143:142='',<-1>,13:0] 
[@-1,144:143='',<-1>,13:0] 
[@-1,145:144='',<-1>,13:0] 
[@-1,146:145='',<-1>,13:0] 
[@-1,147:146='',<-1>,13:0] 
[@-1,148:147='',<-1>,13:0] 
[@-1,149:148='',<-1>,13:0] 
[@-1,150:149='',<-1>,13:0] 
[@-1,151:150='',<-1>,13:0] 
[@-1,152:151='',<-1>,13:0] 
[@-1,153:152='',<-1>,13:0] 
[@-1,154:153='',<-1>,13:0] 
[@-1,155:154='',<-1>,13:0] 
[@-1,156:155='',<-1>,13:0] 
[@-1,157:156='',<-1>,13:0] 
[@-1,158:157='',<-1>,13:0] 
[@-1,159:158='',<-1>,13:0] 
[@-1,160:159='',<-1>,13:0] 
[@-1,161:160='<EOF>',<-1>,13:0] 
      . 
      . 
      . 
      . 

我們看到,雖然我能夠遍歷所有的令牌直到EOF,我無法獲得令牌的實際內容或類型。我想知道是否有一種使用偵聽器遍歷的方法。

回答

0

硬是一定的,但

tok = tokSrc.nextToken() ; 

似乎重新運行詞法分析器,起始於一個假定的正確的令牌邊界,但無需重置詞法分析器。詞法分析器拋出錯誤可能解釋觀察到的行爲。

不過,更好的方法是簡單地恢復現有令牌流:

public class Walker implements YourJavaListener { 

    CommonTokenStream tokens; 

    public Walker(JavaParser parser) { 
     tokens = (CommonTokenStream) parser.getTokenStream() 
    } 

然後訪問流,以獲得所需的令牌:

@Override 
public void enterSemicolon(JavaParser.SemicolonContext ctx) { 
    TerminalNode semi = ctx.semicolon(); // adjust as needed for your impl. 
    Token tok = semi.getSymbol(); 
    int idx = tok.getTokenIndex(); 

    while(tok.getType() != IntStream.EOF) { 
     System.out.println(tok); 
     tok = tokens.get(idx++); 
    } 
} 

一個完全不同的方法,可能有助於您的最終目的是直接從父上下文獲取有限的令牌集:

ParserRuleContext pctx = ctx.getParent(); 
List<TerminalNode> nodes = pctx.getTokens(pctx.getStart(), pctx.getStop()); 
+0

備註:在ANTLRv4中沒有簽名的方法'ParserRuleContext :: getTokens(Token,Token)'。 – Quepas