ANTLR API问题; 示例+解决方法提供; 需要解释

我使用ANTLRWorks创建了以下Lexer。 (另见http://bkiers.blogspot.com/2011/03/2-introduction-to-antlr.html#intro )

// CSVLexer.g lexer grammar CSVLexer; @lexer::header { package graphica.parsers; } Comma : ',' ; LineBreak : '\r'? '\n' | '\r' ; SimpleValue : ~(',' | '\r' | '\n' | '"')+ ; QuotedValue : '"' ('""' | ~'"')* '"' ; 

我使用以下Java类来测试Lexer。

  /** * * @author Nilo */ import org.antlr.runtime.*; public class CSVLexerTest { public static void main(String[] args) throws Exception { // the input source String source = "val1, value2, value3, value3.2" + "\n" + "\"line\nbreak\",ABAbb,end"; // create an instance of the lexer CSVLexer lexer = new CSVLexer(new ANTLRStringStream(source)); // wrap a token-stream around the lexer CommonTokenStream tokens = new CommonTokenStream(lexer); // traverse the tokens and print them to see if the correct tokens are created // tokens.toString(); int n = 1; for (Object o : tokens.getTokens()) { CommonToken token = (CommonToken) o; System.out.println("token(" + n + ") = " + token.getText().replace("\n", "\\n")); n++; } } } 

上面的类(来自同一个教程)不会产生任何输出。 但是,如果我在令牌循环之前插入tokens.toString(),则按预期打印输出。

注意:我在Windows 7上使用ANTLWorks 1.4.3,ANTLR 3.4,JDK 1.7 / 64bit

问题:我不明白这一点。 请解释。 应该有一种方法可以在没有tokens.toString()的情况下使其工作

CommonTokenStream扩展了BufferedTokenStream ,它具有List tokens ,当调用getTokens()时返回该getTokens() 。 但是这个List tokens只在特定时间被填充。 在3.3和3.4中,它不会发生在getTokens() ,其中3.2 确实填充了tokens列表。

ANTLR 3.2(以及之前)

 public List getTokens() { if ( p == -1 ) { fillBuffer(); } return tokens; } protected void fillBuffer() { // fill `tokens` } 

ANTLR 3.3(以及之后)

 public List getTokens() { return tokens; } public void fill() { // fill `tokens` } 

注意3.2的填充方法是如何受到保护的,在3.3+中它是公共的,因此以下工作原理:

 import org.antlr.runtime.*; public class CSVLexerTest { public static void main(String[] args) throws Exception { // the input source String source = "val1, value2, value3, value3.2" + "\n" + "\"line\nbreak\",ABAbb,end"; // create an instance of the lexer CSVLexer lexer = new CSVLexer(new ANTLRStringStream(source)); // wrap a token-stream around the lexer and fill the tokens-list CommonTokenStream tokens = new CommonTokenStream(lexer); tokens.fill(); // traverse the tokens and print them to see if the correct tokens are created // tokens.toString(); int n = 1; for (Object o : tokens.getTokens()) { CommonToken token = (CommonToken) o; System.out.println("token(" + n + ") = " + token.getText().replace("\n", "\\n")); n++; } } } 

产生输出:

 token(1) = val1 token(2) = , token(3) = value2 token(4) = , token(5) = value3 token(6) = , token(7) = value3.2 token(8) = \n token(9) = "line\nbreak" token(10) = , token(11) = ABAbb token(12) = , token(13) = end token(14) =