我试图为某种语言编写解析器作为我研究的一部分。目前,我无法使用以下方式使用以下代码:
private def _uw: Parser[UW] = _headword ~ _modifiers ~ _attributes ^^ {
case hw ~ mods ~ attrs => new UW(hw, mods, attrs)
}
private def _headword[String] = "\".*\"".r | "[^(),]*".r
private def _modifiers: Parser[List[UWModifier]] = opt("(" ~> repsep(_modifier, ",") <~ ")") ^^ {
case Some(mods) => mods
case None => List[UWModifier]()
}
private def _modifier: Parser[UWModifier] = ("[^><]*".r ^^ (RelTypes.toRelType(_))) ~ "[><]".r ~ _uw ^^ {
case (rel: RelType) ~ x ~ (uw: UW) => new UWModifier(rel, uw)
}
private def _attributes: Parser[List[UWAttribute]] = rep(_attribute) ^^ {
case Nil => List[UWAttribute]()
case attrs => attrs
}
private def _attribute: Parser[UWAttribute] = ".@" ~> "[^>.]*".r ^^ (new UWAttribute(_))
上面的代码只包含该语言的一部分,为了节省时间和空间,我不太了解整个语言的细节。 _uw方法应该解析一个由三部分组成的字符串,尽管第一部分必须存在于字符串中。
_uw应该能够正确解析这些测试字符串:
test0
test1.@attr
"test2"
"test3".@attr
test4..
test5..@attr
"test6..".@attr
"test7.@attr".@attr
test8(urel>uw)
test9(urel>uw).@attr
"test10..().@"(urel>uw).@attr
test11(urel1>uw1(urel2>uw2,urel3>uw3),urel4>uw4).@attr1.@attr2
因此,如果词条以"
开头和结尾,则双引号内的所有内容都被视为词条的一部分。所有以.@
开头的单词,如果不在双引号内,都是词条的属性。
E.g。在test5中,解析器应将test5.
解析为词条,并将attr
解析为属性。只是。@被省略,之前的所有点都应该包含在词条中。
因此,在词条之后,可以有属性和/或修饰符。顺序是严格的,因此属性总是在修饰符之后。如果有属性但没有修饰符,则.@
之前的所有内容都被视为词条的一部分。
主要问题是"[^@(]*".r
。我尝试了各种创造性的替代品,例如"(^[\\w\\.]*)((\\.\\@)|$)".r
,但似乎没有任何效果。前瞻或后瞻甚至如何影响解析器组合?我不是解析或正则表达式的专家,所以欢迎所有帮助!
答案 0 :(得分:1)
我认为"[^@(]*".r
与您的问题无关。我明白这一点:
private def _headword[String] = "\".*\"".r | "[^(),]*".r
这是_uw
中的第一件事(顺便说一下,不建议在Scala中使用下划线),所以当它尝试解析test5..@attr
时,第二个正则表达式将匹配所有它!
scala> "[^(),]*".r findFirstIn "test5..@attr"
res0: Option[String] = Some(test5..@attr)
因此剩余的解析器将不会有任何剩余。另外,_headword
中的第一个正则表达式也存在问题,因为.*
会接受引号,这意味着这样的内容变得有效:
"test6 with a " inside of it..".@attr
对于前瞻和后视,它根本不会影响解析器组合器。正则表达式匹配,或者它没有 - 这是所有解析器组合者关心的。