Regex 使用解析器组合器整理文本行

Regex 使用解析器组合器整理文本行,regex,scala,parser-combinators,Regex,Scala,Parser Combinators,我正在尝试使用解析器组合器解析文本文件。我想在名为Example的类中捕获索引和文本。下面是一个在输入文件上显示表单的测试: object Test extends ParsComb with App { val input = """ 0) blah1 blah2 blah3 1) blah4 blah5 END """ println(parseAll(examples, input)) } 以下是我的尝试,但没有成功: import scala.util.parsing.comb

我正在尝试使用解析器组合器解析文本文件。我想在名为
Example
的类中捕获索引和文本。下面是一个在输入文件上显示表单的测试:

object Test extends ParsComb with App {
  val input = """
0)
blah1
blah2
blah3
1)
blah4
blah5
END
"""
  println(parseAll(examples, input))
}
以下是我的尝试,但没有成功:

import scala.util.parsing.combinator.RegexParsers

case class Example(index: Int, text: String)

class ParsComb extends RegexParsers {
  def examples: Parser[List[Example]] = rep(divider~example) ^^ 
                                          {_ map {case d ~ e => Example(d,e)}}
  def divider:  Parser[Int]           = "[0-9]+".r <~ ")"    ^^ (_.toInt)
  def example:  Parser[String]        = ".*".r <~ (divider | "END") 
}

我只是从这些开始,所以我不知道我在做什么。我认为问题可能在于
“*”.r
regex没有执行多行操作。如何更改此项以使其正确解析?

您的解析器无法处理换行符,您的
示例
解析器将删除下一个
分隔符
,并且您的
示例
正则表达式匹配
分隔符
和“END”字符串

试试这个:

object ParsComb extends RegexParsers { 
  def examples: Parser[List[Example]] = rep(divider~example) <~ """END\n?""".r ^^ {_ map {case d ~ e => Example(d,e)}} 
  def divider: Parser[Int] = "[0-9]+".r <~ ")\n" ^^ (_.toInt) 
  def example: Parser[String] = rep(str) ^^ {_.mkString}
  def str: Parser[String] = """.*\n""".r ^? { case s if simpleLine(s) => s}

  val div = """[0-9]+\)\n""".r
  def simpleLine(s: String) = s match {
    case div() => false
    case "END\n" => false
    case _ => true
  }

  def apply(s: String) = parseAll(examples, s)
}
  • 错误消息是什么意思
根据您的语法定义,
“*”。r
我认为问题可能在于“*”.r正则表达式不起作用
多行

没错。使用dotall修饰符(奇怪地称为“s”):


def示例:Parser[String]=“(?s)。*”.r谢谢-稍后我会玩一玩,以确保我了解发生了什么!谢谢,回答得很好-请将更多内容发布到StackOverflow!
object ParsComb extends RegexParsers { 
  def examples: Parser[List[Example]] = rep(divider~example) <~ """END\n?""".r ^^ {_ map {case d ~ e => Example(d,e)}} 
  def divider: Parser[Int] = "[0-9]+".r <~ ")\n" ^^ (_.toInt) 
  def example: Parser[String] = rep(str) ^^ {_.mkString}
  def str: Parser[String] = """.*\n""".r ^? { case s if simpleLine(s) => s}

  val div = """[0-9]+\)\n""".r
  def simpleLine(s: String) = s match {
    case div() => false
    case "END\n" => false
    case _ => true
  }

  def apply(s: String) = parseAll(examples, s)
}
scala> ParsComb(input)
res3: ParsComb.ParseResult[List[Example]] =
[10.1] parsed: List(Example(0,blah1
blah2
blah3
), Example(1,blah4
blah5
))
examples ::= {divider example}
divider  ::= Integer")"
example  ::= {literal ["END"]}
class ParsComb extends RegexParsers {
  def examples: Parser[List[Example]] = rep(divider ~ example) ^^ { _ map { case d ~ e => Example(d, e) } }
  def divider: Parser[Int] = "[0-9]+".r <~ ")" ^^ (_.toInt)
  def example: Parser[List[String]] = rep("[\\w]*(?=[\\r\\n])".r <~ opt("END"))
}
def example:  Parser[String]        = "(?s).*".r <~ (divider | "END")