Lui*_*hys 2 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))
}
Run Code Online (Sandbox Code Playgroud)
这是我的尝试不起作用:
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")
}
Run Code Online (Sandbox Code Playgroud)
它失败了:
[4.1] failure: `END' expected but `b' found
blah2
^
Run Code Online (Sandbox Code Playgroud)
我刚刚开始这些,所以我不知道我在做什么.我认为问题可能在于".*".r正则表达式不做多行.如何更改它以便正确解析?
根据你的语法定义,".*".r <~ (divider | "END")你告诉解析器,a example应该跟a divider或a END.在解析blah1之后,解析器试图找到divider并失败,然后尝试END,再次失败,没有其他选项可用,所以END这里是生产值的最后一个选择,所以从解析器的角度来看,它预期END,但很快发现,下一个输入blah2来自第4行.
尝试接近您的实现,您的案例中的语法应该是:
examples ::= {divider example}
divider ::= Integer")"
example ::= {literal ["END"]}
Run Code Online (Sandbox Code Playgroud)
我认为解析"示例" List[String]更有意义,无论如何,这取决于你.
问题是你的example解析器,它应该是一个可重复的文字.
所以,
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"))
}
Run Code Online (Sandbox Code Playgroud)
正则表达式(?=[\\r\\n])意味着它是一个积极的前瞻,并匹配后面的字符\r或\n.
解析结果是:
[10.1]解析:列表(例子(0,列表(blah1,blah2,blah3)),例子(1,列表(blah4,blah5)))
如果要将其解析为String(而不是List[String]),只需添加转换函数,例如:^^ {_ mkString "\n"}