2013-08-01 73 views
2

我正在嘗試實現一個DSL的預處理器,模仿代碼/額外的CPP示例。但是,我沒有使用令牌工廠。是否需要?調用emit(token)不會將令牌插入令牌流中,如預期的那樣。ANTLR4:如何注入令牌

這裏的詞法分析器:

// string-delimited path 
SPATH  : '"' (~[\n\r])*? '"' 
       { 
       emit(); // inject the current token 
       // launch another lexer on the include file, get tokens, 
       // emit them all at once here 
       List<CommonToken> tokens = Preprocessor.include(getText()); 
       if (null != tokens) { 
        for (CommonToken tok : tokens) { 
        emit(tok); 
        } 
       } 
       } 
     ; 

這裏的方法包括:

@SuppressWarnings("unchecked") 
public static List<CommonToken> include(String filename) { 
    List<CommonToken> tokens = null; 
    try (FileReader fr = openFile(filename.substring(1, filename.length() - 1)); 
      BufferedReader br = new BufferedReader(fr)) { 
     ANTLRInputStream input = new ANTLRInputStream(br); 
     PreprocessorLexer lexer = new PreprocessorLexer(input); 

     tokens = (List<CommonToken>) lexer.getAllTokens(); 

    } catch (IOException ioe) { 
     log.error("Can't load ~{}~", ioe.getLocalizedMessage()); 
    } 
    return tokens; 
} 

回答

3

你需要重寫Lexer.nextToken提供此功能。在您的詞法分析器中,保留尚未由nextToken返回的注入令牌的Deque<Token>。當隊列爲空時,nextToken的實現應根據超類的實現返回下一個標記。

下面是一些示例代碼。我沒有試圖編譯或運行它,因此它可能不完美。

private final Deque<Token> pendingTokens = new ArrayDeque<>(); 

@Override 
public Token nextToken() { 
    Token pending = pendingTokens.pollFirst(); 
    if (pending != null) { 
     return pending; 
    } 

    Token next = super.nextToken(); 
    pending = pendingTokens.pollFirst(); 
    if (pending != null) { 
     pendingTokens.addLast(next); 
     return pending; 
    } 

    return next; 
} 
+0

如何在不替換它的情況下發射當前令牌? emit()給出了一個令牌,它的toString()返回[@ 56,110:123 =''strategy.ccl'',<0>,7:15]不是<0>令牌號碼,表示一個不可靠的令牌? – user2643128

+0

從lexer規則中刪除emit(),允許適當地發出當前令牌。 – user2643128

+0

從Token中縮短nextToken()next ...返回下一個;返回super.nextToken();也有幫助。 – user2643128