我正在尝试提出一种PEG语法,该语法将根据RFC 2396的以下BNF解析主机名
hostname = *( domainlabel "." ) toplabel [ "." ]
domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
toplabel = alpha | alpha *( alphanum | "-" ) alphanum
domainlabel
和toplabel
没有问题。
但似乎hostname
的规则无法用PEG表示。
这就是为什么我这么认为:
如果我们采用BNF中所写的语法,则*(domainlabel ".")
会消耗整个输入,因为toplabel [ "." ]
无法区分,所以h = (d '.')* t '.'?
d = [dt]
t = [t]
不知道何时停止。
简化的自包含插图:
t
这将解析d.d.t
,d.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?
答案 0 :(得分:1)
如果您只需要检查有效性,可以这样做:
/* Unchanged */
toplabel = alpha | alpha *( alphanum | "-" ) alphanum
/* Diff with above */
nontoplabel = digit | digit *( alphanum | "-" ) alphanum
/* Rephrase */
hostname = 1*( *( nontoplabel "." ) toplabel) [ "." ]
由于nontoplabel
和toplabel
可以通过第一个字符区分,因此最后一个表达式中不存在歧义。
转换是许多可能的正则表达式身份之一:
(a | b)* a ==> (b* a)+
您始终可以使用b
替换a|b
中的b-a
(使用-
作为设置差异运算符)。