编程语言
首页 > 编程语言> > python – BNF可以处理前向消费吗?

python – BNF可以处理前向消费吗?

作者:互联网

最近我发现了python模块pyparsing,这是一个通过编写语法而不是解析器来解析数据的好工具.我对无上下文语法的想法不熟悉,所以请纠正这个问题中的任何错误假设.

Pyparsing可以实现BNF(Backus–Naur Form)无上下文语法.这个语法可以是递归的,但是它可以有前瞻性的前瞻吗?自从我偶然发现this question以来,我一直想知道这个问题的答案.让我举一个具体的例子.考虑字符串:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

让语法看起来像:

<number> :: __<digit>__
<block>  :: <number>(x) (<number> <number> <number> .... x times)

即,读取第一个数字标记,将其保存为x,然后使用下一个x数字并将它们组合在一起.解析后的行应如下所示:

 [[1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]]

我写了一个简单的python MWE而不是使用pyparsing所以我很清楚我正在尝试做什么:

A = range(1,31)

B, sub_b = [], []
consume  = 0

for a in A:
    if consume: 
        sub_b.append(a)
        consume -= 1
    else:
        if sub_b: B.append(sub_b)
        sub_b = [a,]
        consume = a
B.append(sub_b)
print B

两个(相关的)问题:这可以用BNF无上下文语法完成吗?如果是/否我怎么能用pyparsing做呢?

解决方法:

在没有上下文的语法中,或者在常规语法中,没有关于参数化大小的东西.像消耗这样的数值参数不是CFG模型的一部分,可以证明以不同的方式获得效果是不可能的.但是,您可以为任何固定长度编写作品,因此您可以为长度为1,长度为2,长度为3的块编写作品:

<block3> :: <number> <number> <number>

或者,类似地,将长度匹配为前缀或甚至作为后缀:

<block3a> :: 3 <number> <number> <number>
<block3b> :: <number> <number> <number> 3

所以要做你想做的事,你只需要一个包含那种规则的语法,对于你可能需要的所有N.

给定的CFG将仅包括有限数量的这些产品.在数学上不可能编写可以处理无限参数化大小的CFG(以BNF或任何其他形式),无论是作为前缀还是作为后缀.实际上,您可以根据需要随时使用新产品更新您的CFG.例如,读取数字N并为您的语法创建规则块N(如果它尚不存在).但是没有单一的CFG可以捕获无限制的参数化尺寸.

编辑,因为您还询问了上下文相关的语法:它仍然不会这样做.问题是使用整数运算,而不是语法的类. Chomsky层次结构中的任何形式语言都是根据有限数量的符号(标记)定义的,并且因为它们是无限多个整数,所以它们不能被赋予不同的含义(请注意,您的解析过程依赖于整数运算).

如果你要将长度预处理成一个多个星的序列(* * * 4 7 10),那么CFG解析器是微不足道的:

<group> :: * <group> <number>
<group> :: * <number>

这就是所谓的a ^ n b ^ n语言.您也可以使用符号“十”等符号.但是,如果没有预处理,唯一的解决方案(以及您的程序或图灵机在实践中所做的)是在您的语法中解释数字符号.例如,将“21”解析为十个十一.我怀疑这可以在CFG中完成(问题是处理任意长的数字而没有单独的规则,数百万,数十亿等),但我不太确定.无论哪种方式,它只是一个有趣的学术练习,因为使用真正的整数是如此容易.我相信人们已经用整数研究了形式语言的属性,但我不能说清楚.

标签:python,context-free-grammar,pyparsing,bnf
来源: https://codeday.me/bug/20190613/1233697.html