AFAIK,ANTLR v2.x 缓冲令牌的创建。 parser takes a TokenBuffer,在its turn takes a TokenStream。当解析器需要更多令牌时,然后通过其nextToken() method 轮询此TokenStream。
换句话说,如果您将输入源作为文件提供,ANTLR 不会读取整个文件并为其创建令牌,而是仅在需要时创建(并丢弃)令牌。
请注意,我从未使用过 ANTLR 2.x,所以我可能是错的。你观察到不同的东西吗?如果是这样,您如何向 ANTLR 提供源代码:作为文件还是作为大字符串?如果是后者,我建议改为提供文件。
编辑
假设您要解析一个文件,该文件由带有数字的行组成,由空格分隔(您想忽略它)。您还希望解析器逐行处理文件,因为一次收集所有数字会导致内存问题。
您可以通过让您的主解析器规则 parse 返回每行的数字列表来做到这一点。如果到达 EOF(文件结尾),您只需返回 null 而不是列表。
使用 ANTLR 2.7.6 的演示:
文件:My.g
class MyParser extends Parser;
parse returns [java.util.List<Integer> numbers]
{
numbers = new java.util.ArrayList<Integer>();
}
: (n:Number {numbers.add(Integer.valueOf(n.getText()));})+ LineBreak
| EOF {numbers = null;}
;
class MyLexer extends Lexer;
Number
: ('0'..'9')+
;
LineBreak
: ('\r')? '\n'
;
Space
: (' ' | '\t') {$setType(Token.SKIP);}
;
文件:Main.java
import antlr.*;
public class Main {
public static void main(String[] args) throws Exception {
MyLexer lexer = new MyLexer(new java.io.StringReader("1 2 3\n4 5 6 7 8\n9 10\n"));
MyParser parser = new MyParser(new TokenBuffer(lexer));
int line = 0;
java.util.List<Integer> numbers = null;
while((numbers = parser.parse()) != null) {
line++;
System.out.println("line " + line + " = " + numbers);
}
}
}
要运行演示:
*尼克斯
java -cp antlr-2.7.6.jar antlr.Tool My.g
javac -cp antlr-2.7.6.jar *.java
java -cp .:antlr-2.7.6.jar Main
或开启:
窗口
java -cp antlr-2.7.6.jar antlr.Tool My.g
javac -cp antlr-2.7.6.jar *.java
java -cp .;antlr-2.7.6.jar Main
这将产生以下输出:
line 1 = [1, 2, 3]
line 2 = [4, 5, 6, 7, 8]
line 3 = [9, 10]
警告
任何尝试此代码的人,请注意这使用的是 ANTLR 2.7.6。除非您有非常令人信服的理由使用此版本,否则强烈建议使用 ANTLR 的最新稳定版本(在撰写本文时为 v3.3)。