我在编写parboiled2解析器时遇到了一个棘手的问题,那就是我需要匹配一行的一部分,这是一个字符串,它的结尾有一个:字符标记。这很容易,只是字符串可以包含:字符。
目前,我已经得到了这样的消息,它将字符串视为一组以冒号结尾的字符串,并将它们连接起来,但这会消耗我不想要的尾随:,因为尾随:本身并不是字符串的一部分。
def address = rule { capture(oneOrMore(zeroOrMore(noneOf(":")) ~ ":")) }我觉得我应该在这里的某个地方使用&(":"),但是在匹配中间:字符时,我很难做到这一点。
成功匹配示例(作为较长字符串的一部分):
localhost: -> localhost1::: -> 1::::: -> ::不匹配:
:任何建议都是受欢迎的,即使是“你不能这么做”,这样我就可以停止绞尽脑汁了。
其上下文是在一个bind配置文件中解析HAProxy设置。给定以下(简化)案例类的有效字符串的一些示例如下:
case class Bind(endpoint: Endpoint, params: Seq[String])
case class Endpoint(address: Option[String], port: Option[Int])bind :80 -> Bind(Endpoint(None, Some(80)), Seq())bind localhost:80 -> Bind(Endpoint(Some("localhost"), Some(80)), Seq())bind localhost -> Bind(Endpoint(Some("localhost"), None), Seq())bind :80 param1 -> Bind(Endpoint(None, Some(80)), Seq("param1")))换句话说,如果有一个字符串,它需要在最终的:之前终止,因为这是一个端口的指示符。endpoint规则如下所示:
def endpoint = rule { optional(address) ~ optional(':' ~ int) ~> Endpoint }最终,端点的可匹配字符串被空格或行尾终止,因此有一种选择是捕捉到空间,然后单独解析字符串,但我希望在主解析器中这样做。
发布于 2015-01-28 07:18:29
我认为以下应适用于您的问题描述:
def noColons = rule { zeroOrMore(noneOf(":")) }
def colonWithNext = rule { ':' ~ &(noColons ~ ':') }
def address = rule { capture(oneOrMore(noColons).separatedBy(colonWithNext)) ~ ':' }您的代码的问题在于~组合器的使用,因为像A ~ B这样的表达式只匹配首先A匹配,然后B匹配,但如果B规则是规则A的一部分,则B匹配不匹配。这里不涉及回溯,parboiled2解析器只对替代方案进行回溯。
因此,在这种情况下,您必须确保消费':‘只有当有另一个跟随它。
https://stackoverflow.com/questions/28171606
复制相似问题