将ABNF规则转换为REGEX

eni9jsuy  于 2023-05-23  发布在  其他
关注(0)|答案(3)|浏览(121)

我需要将下面提到的ABNF规则(mlaer)转换为REGEX

mlaer       =  1*( lebal "." ) lebal
   lebal       =  gid-tel *(rts-hdl)

   rts-hdl    =  *( alpha / digit / "-" ) gid-tel
   gid-tel    =  alpha / digit
   alpha       =  %x41-5A  ; 'A'-'Z'
   alpha       =/ %x61-7A  ; 'a'-'z'
   digit       =  %x30-39  ; '0'-'9'

有没有什么工具或东西可以自动完成这件事?

t2a7ltrp

t2a7ltrp1#

应该注意的是,在一般意义上,不可能将ABNF转换为REGEX。
这是因为正则表达式创建regular language,而ABNF规范创建context-free language
正则语言可以通过finite state machine(也用于regex匹配)进行解析,而上下文无关语言可以通过pushdown automata进行解析,pushdown automata是有限状态机的超集(下推自动机可以使用bison/yacc工具实现)。
旁注:正则表达式不能验证正则表达式字符串本身。这是因为允许有括号/圆括号,而括号/圆括号匹配不能用正则表达式来执行,而是用上下文无关语法来执行。
因此,从ABNF到正则表达式的转换仅适用于一部分情况。我猜如果ABNF不是递归的或者不包含任何循环定义的话就是这种情况。这是上述自动翻译工具的(隐含的)限制。

ktecyv1j

ktecyv1j2#

不确定是否有任何工具可以自动做到这一点,但它不是太难。
gid-tel

[A-Za-z0-9]

rts-hdl

[A-Za-z0-9-]*[A-Za-z0-9]

lebal

[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])*

注意,以这种形式编写的lebal将导致NFA引擎在某些类型的输入上运行很长时间。应改写为:

[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?

mlaer

([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?

可以使用字符串连接来构造复杂的正则表达式。这将使您能够编写干净的代码。虽然lebal的情况需要修改语法,以便在NFA引擎上工作良好。

fivyi3re

fivyi3re3#

对于较小的ABNF this在线工具written in PHP为我工作。在您的情况下,它返回:

gid-tel: ^([A-Z][a-z0-9])$
rts-hdl: ^(([A-Z][-a-z0-9])*([A-Z][a-z0-9]))$
lebal: ^([A-Z][a-z0-9])((([A-Z][-a-z0-9])*([A-Z][a-z0-9])))*$
mlaer: ^(([A-Z][a-z0-9])((([A-Z][-a-z0-9])*([A-Z][a-z0-9])))*\.)+([A-Z][a-z0-9])((([A-Z][-a-z0-9])*([A-Z][a-z0-9])))*$

但是对于更大的ABNF,比如E-Mail地址,它只输出空白。因此,我目前正在寻找其他工具,并发现一个weird, small script in Perl和一个written in Ruby几乎17年前,最后一次提交到7年前。后者看起来很有希望,因为它实际上为URI ABNF提供了一个RegEx,但我仍然需要让它工作。

相关问题