RFC 2396(关于URI)的语法如何用PEG表示?

时间:2017-02-08 04:21:30

标签: parsing uri grammar peg

我正在尝试提出一种PEG语法,该语法将根据RFC 2396的以下BNF解析主机名

  hostname      = *( domainlabel "." ) toplabel [ "." ]
  domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
  toplabel      = alpha | alpha *( alphanum | "-" ) alphanum

domainlabeltoplabel没有问题。

但似乎hostname的规则无法用PEG表示。

这就是为什么我这么认为:

如果我们采用BNF中所写的语法,则*(domainlabel ".")会消耗整个输入,因为toplabel [ "." ]无法区分,所以h = (d '.')* t '.'? d = [dt] t = [t] 不知道何时停止。

简化的自包含插图:

t

这将解析d.d.td.d.d并在t.上失败,这是完全可以预料到的,但无法解析两者都有效的d.d.t.t.案例。

如果我们添加前瞻,那么它会消耗d.d.t.d.t.t.,但会在h = (!(t '.'?)d '.')* t '.'? d = [dt] t = [t] 上失败。

    let newListOfParticles = Array(
        repeatElement(
            defaultParticle,
            count: self.numberOfParticles
        )
    )

所以我没有想法,有没有办法在PEG中表达这个BNF?

1 个答案:

答案 0 :(得分:1)

如果您只需要检查有效性,可以这样做:

/* Unchanged */
toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
/* Diff with above */
nontoplabel   = digit | digit *( alphanum | "-" ) alphanum
/* Rephrase */
hostname      = 1*( *( nontoplabel "." ) toplabel) [ "." ]

由于nontoplabeltoplabel可以通过第一个字符区分,因此最后一个表达式中不存在歧义。

转换是许多可能的正则表达式身份之一:

(a | b)* a ==> (b* a)+

您始终可以使用b替换a|b中的b-a(使用-作为设置差异运算符)。