Scala Parser Combinators:在流中解析

时间:2013-09-25 20:03:03

标签: scala parser-combinators

我在scala中使用本机解析器组合器库,我想用它来解析许多大文件。我已经设置了组合器,但是我要解析的文件太大而无法一次性读入内存。我希望能够通过我的解析器从输入文件流式传输并将其读回磁盘,这样我就不需要将它全部存储在内存中。我当前的系统看起来像这样:

val f = Source.fromFile("myfile")
parser.parse(parser.document.+, f.reader).get.map{_.writeToFile}
f.close

这会在解析时读取整个文件,我想避免使用它。

4 个答案:

答案 0 :(得分:5)

使用scala的解析器组合器没有简单或内置的方法来实现这一点,它提供了实现parsing expression grammars的工具。

|||(最长匹配)等运算符与流解析模型在很大程度上不兼容,因为它们需要广泛的回溯功能。为了完成你想要做的事情,你需要重新制定你的语法,这样就不需要回溯,永远。这通常比听起来要难得多。

正如其他人所提到的,你最好的选择是调查一个初步阶段,在这个阶段你输入(例如按行),这样你就可以一次处理一部分流。

答案 1 :(得分:0)

一种简单的方法是从Iterator对象中抓取Source,然后像这样走过这些行:

val source = Source.fromFile("myFile")
val lines = source.getLines
for (line <- lines) {
    // Do magic with the line-value
}
source.close // Close the file

但是你需要能够在你的解析器中逐一使用这些行。

来源:https://groups.google.com/forum/#!topic/scala-user/LPzpXo3sUVE

答案 2 :(得分:0)

您可以尝试作为解析包一部分的StreamReader类。

你可以使用它:

val f = StreamReader( fromFile("myfile","UTF-8").reader() )

parseAll( parser, f )

答案 3 :(得分:0)

作为上面提到的一张海报的最长匹配与使用source.subSequence(0,source.length)的正则表达式相结合意味着甚至StreamReader也无济于事。

我所拥有的最好的kludgy答案是使用getLines,正如其他人所提到的那样,并且chunk作为接受的答案提到。我的特殊输入要求我一次分块2行。你可以从你构建的块中构建一个迭代器,使其稍微不那么难看。