我正在使用scala组合子分析字符串,我想要这样的字符串"Ph"或"Ph."或"Ph.D"或"Ph.D"将被成功解析,其中,就目前而言,前三个已成功解析,但当我执行println(parseAll(name, "Ph.D."))
时,我看到以下内容:
[1.6] failure: string matching regex `p{IsLatin}+' expected but end of source found
Ph.D.
^
我的直觉是,因为nameSepSubset
是nameSep
使用的规则,所以rep1(nameSub ~ nameSep)
消耗了"Ph.D."中的所有内容,因此不产生对nameSub ~ nameSepSubset
的输入。除了rep1
,还有其他运算符或定义语法的其他方法可以解决这个问题吗?
语法:
lazy val nameSub = """[a-zA-Z]+""".r
lazy val nameSepSubset = (
rep1(" ")
||| "." ~ rep1(" ")
||| ".")
lazy val nameSep = (
nameSepSubset
||| rep(" ") ~ "," ~ rep(" ")
||| rep(" ") ~> "-" <~ rep(" ")
||| "'")
lazy val name = (rep1(nameSub ~ nameSep) ~ nameSub ~ nameSepSubset
||| nameSub ~ nameSepSubset)
一个解决方案可以是使用名称的递归定义来重新定义名称规则:
lazy val name = nameSub ~ nameSep ~ name //(1)
||| nameSub ~ nameSepSubset /*(2)*/ ||| "" /*(3)*/
你可以看到合法的输出是:
来自规则(2)的nameSub ~ nameSepSubset
,其等价于可从规则(3)导出的nameSub ~ nameSepSubset ~ ""
或
nameSub ~ nameSep ~ nameSub ~ nameSepSub
或
nameSub ~ nameSep ~ nameSub ~ nameSep ~ nameSub ~ nameSepSub
或