无法使用正则表达式和Scala解析器组合解析复杂的语言

时间:2012-02-22 06:42:38

标签: parsing scala parser-combinators

我试图为某种语言编写解析器作为我研究的一部分。目前,我无法使用以下方式使用以下代码:

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,但似乎没有任何效果。前瞻或后瞻甚至如何影响解析器组合?我不是解析或正则表达式的专家,所以欢迎所有帮助!

1 个答案:

答案 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

对于前瞻和后视,它根本不会影响解析器组合器。正则表达式匹配,或者它没有 - 这是所有解析器组合者关心的。