【问题标题】:Preprocessing Scala parser Reader input预处理 Scala 解析器 Reader 输入
【发布时间】:2012-11-12 20:40:10
【问题描述】:

我有一个包含对象的文本表示的文件。我编写了一个组合器解析器语法来解析文本并返回对象。在文本中,“#”是注释分隔符:从该字符到行尾的所有内容都将被忽略。空行也被忽略。我想一次处理一行文本,以便处理非常大的文件。

我不想用通用注释和空行逻辑弄乱我的解析器语法。我想删除这些作为预处理步骤。通过行将文件转换为迭代器,我可以执行以下操作:

Source.fromFile("file.txt").getLines.map(_.replaceAll("#.*", "").trim).filter(!_.isEmpty)

如何将这样的表达式的输出传递给组合器解析器?我不知道如何用这样的过滤表达式创建Reader 对象。 Java FileReader 接口不能那样工作。

有没有办法做到这一点,或者我应该把我的注释和空行逻辑放在解析器语法中?如果是后者,是否有一些 util.parsing 包已经为我做了这个?

【问题讨论】:

    标签: parsing scala combinators


    【解决方案1】:

    最简单的方法是在PagedSeq 上使用fromLines 方法:

    import scala.collection.immutable.PagedSeq
    import scala.io.Source
    import scala.util.parsing.input.PagedSeqReader
    
    val lines = Source.fromFile("file.txt").getLines.map(
      _.replaceAll("#.*", "").trim
    ).filterNot(_.isEmpty)
    
    val reader = new PagedSeqReader(PagedSeq.fromLines(lines))
    

    现在您有了一个scala.util.parsing.input.Reader,您可以将其插入您的解析器。无论如何,这基本上是在解析 java.io.Reader 时发生的情况——它立即被包裹在 PagedSeqReader 中。

    【讨论】:

      【解决方案2】:

      这不是你写的最漂亮的代码,但你可以通过一个新的Source 如下:

      val SEP = System.getProperty("line.separator")
      def lineMap(fileName : String, trans : String=>String) : Source = {
        Source.fromIterable(
          Source.fromFile(fileName).getLines.flatMap(
            line => trans(line) + SEP
          ).toIterable
        )
      }
      

      解释:flatMap 将在 characters 上生成一个迭代器,您可以将其转换为 Iterable,您可以使用它来构建新的 Source。您需要额外的SEP,因为默认情况下getLines 会删除它(使用\n 可能无法正常工作,因为Source 无法正确分隔行)。

      如果您也想应用过滤,即删除一些行,您可以尝试:

      // whenever `trans` returns `None`, the line is dropped.
      def lineMapFilter(fileName : String, trans : String=>Option[String]) : Source = {
        Source.fromIterable(
          Source.fromFile(fileName).getLines.flatMap(
            line => trans(line).map(_ + SEP).getOrElse("")
          ).toIterable
        )
      }
      

      举个例子:

      lineMapFilter("in.txt", line => if(line.isEmpty) None else Some(line.reverse))
      

      ...将删除空行并反转非空行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-22
        • 1970-01-01
        • 2019-04-29
        • 1970-01-01
        • 2011-04-14
        • 1970-01-01
        相关资源
        最近更新 更多