Parsing Scala解析器组合器:按行解析

Parsing Scala解析器组合器:按行解析,parsing,scala,parser-combinators,Parsing,Scala,Parser Combinators,使用Scala parser combinators库是否可以按行而不是字符进行解析?我希望我的自定义解析器具有签名 (in: Reader[String]) => ParserResult[T] 因此,in.first中的字符串将是一行文本,in.rest中的字符串将是剩余的行 我假设我需要对解析器进行子类化,并将Elem类型定义为String。然后实现Reader[String]将输入拆分为行。我想知道这是正确的方法吗?还有其他解决方案吗?下面的代码可以做到这一点: import s

使用Scala parser combinators库是否可以按行而不是字符进行解析?我希望我的自定义解析器具有签名

(in: Reader[String]) => ParserResult[T]
因此,in.first中的字符串将是一行文本,in.rest中的字符串将是剩余的行


我假设我需要对解析器进行子类化,并将Elem类型定义为String。然后实现Reader[String]将输入拆分为行。我想知道这是正确的方法吗?还有其他解决方案吗?

下面的代码可以做到这一点:

import scala.util.parsing.combinator.Parsers
import scala.util.parsing.input.{Position, Reader}

object Main {
  def main(args: Array[String]): Unit = CVParser("one\ntwo\nthree")
}

object CVParser {
  def apply(in: String): Any = impl.parse(in)

  private object impl extends Parsers {
    override type Elem = String

    def parse(in: String): ParseResult[String~String~String] = {
      val reader = new ByLineReader(in.split(System.lineSeparator).toList, 1)
      grammar(reader)
    }

    // private

    private val grammar = SampleParser ~ SampleParser ~ SampleParser

    private class ByLineReader(lines: List[String], lineNo: Int) extends Reader[String] {
      override def first: String = lines.headOption getOrElse ""
      override def rest: Reader[String] =
        if (!lines.isEmpty) new ByLineReader(lines.tail, lineNo + 1)
        else new ByLineReader(lines, lineNo)
      override def pos: Position = new Position {
        def line: Int = lineNo
        def column: Int = 0
        def lineContents: String = first
      }
      override def atEnd: Boolean = lines.size == 1
    }

    private object SampleParser extends Parser[String] {
      def apply(in: Input): ParseResult[String] = {
        println(in.first + "\n---------")
        Success(in.first, in.rest)
      }
    }
  }
}
产出:

one
---------
two
---------
three
---------
现在,接受一行文本的新解析器可以使用常用的解析器组合符来编写和组合,如~,~>,