3

ANTLR 生成的 java 解析器是否能够流式传输任意大的文件?

我尝试使用 UnbufferedCharStream 构建 Lexer 并将其传递给解析器。由于在 UnbufferedCharStream 上调用 size,我得到了 UnsupportedOperationException,并且异常包含一个解释,即您不能在 UnbufferedCharStream 上调用 size。

    new Lexer(new UnbufferedCharStream( new CharArrayReader("".toCharArray())));
    CommonTokenStream stream = new CommonTokenStream(lexer);
    Parser parser = new Parser(stream);

我基本上有一个使用 pig 从 hadoop 导出的文件。它有大量由'\n'分隔的行。每列由一个'\t'分割。这很容易在 java 中解析,因为我使用缓冲读取器来读取每一行。然后我用 '\t' 分割得到每一列。但我也想进行某种模式验证。第一列应该是格式正确的日期,然后是一些价格列,然后是一些十六进制列。

当我查看生成的解析器代码时,我可以这样称呼它

    parser.lines().line()

这会给我一个列表,从概念上讲我可以迭代。但是,当我得到它时,列表的大小似乎是固定的。这意味着解析器可能已经解析了整个文件。

API 的另一部分是否允许您流式传输非常大的文件?就像在读取文件时使用访问者或监听器被调用的某种方式一样?但它不能将整个文件保存在内存中。它不适合。

4

1 回答 1

5

你可以这样做:

InputStream is = new FileInputStream(inputFile);//input file is the path to your input file
ANTLRInputStream input = new ANTLRInputStream(is);
GeneratedLexer lex = new GeneratedLexer(input);
lex.setTokenFactory(new CommonTokenFactory(true));
TokenStream tokens = new UnbufferedTokenStream<CommonToken>(lex);
GeneratedParser parser = new GeneratedParser(tokens);
parser.setBuildParseTree(false);//!!
parser.top_level_rule();

如果文件很大,忘记监听器或访问者 - 我将直接在语法中创建对象。只需将它们全部放在某种结构中(即 HashMap、Vector...)并根据需要进行检索。避免了创建解析树的这种方式(这确实需要大量内存)。

于 2014-09-30T12:17:46.740 回答