试图生成一个简单的正式语法的所有句子

时间:2013-09-23 03:01:49

标签: python queue grammar formal-languages

我是python的新手并尝试在语法中生成所有可能的句子。 这是语法:

  #set of non terminals
  N = ('<subject>', '<predicate>', '<noun phrase>', '<noun>', '<article>', '<verb>',   '<direct object>')
  #set of teminals

  T = ('the', 'boy', 'dog', 'bit')
  #productions
  P = [ ('Sigma',           ['<subject>', '<predicate>']), \
  ('<subject>',       ['<noun phrase>']),            \
  ('<predicate>',     ['<verb>']),                   \
  ('<predicate>',     ['<verb>','<direct object>']), \
  ('<noun phrase>',   ['<article>','<noun>']),       \
  ('<direct object>', ['<noun phrase>']),            \
  ('<noun>',          ['boy']),                      \
  ('<noun>',          ['dog']),                      \
  ('<article>',       ['the']),                      \
  ('<verb>',          ['bit'])                       ]

这是我的尝试,我正在使用队列类来有条不紊地实现它,

# language defined by the previous grammar.
Q = Queue()
Q.enqueue(['Sigma'])
found = 0
while 0 < len(Q):
    print "One while loop done"
    # Get the next sentential form
    sf = Q.dequeue()
    sf1 = [y for y in sf]
    for production in P:
        for i in range(len(sf1)):
                if production[0] == sf1[i]:
                        sf[i:i+1] = [x for x in production[1]]
                        Q.enqueue(sf)
                        Q.printQ()

我进入了无限循环,而且我面临着浅深拷贝的一些问题,如果我改变一个sf副本,队列中的所有内容也会发生变化。任何帮助表示赞赏,任何指示,提示都会很棒

这是预期的输出:

       The dog bit the boy
       The boy bit the dog
       The boy bit the boy
       The dog bit the dog
       The dog bit
       The boy bit

2 个答案:

答案 0 :(得分:2)

  

我正面临着浅深拷贝的一些问题,如果我改变一个sf副本,队列中的所有内容也会发生变化

是。在Python中,列表是具有自己标识的对象。所以:

Q.enqueue(['Sigma'])

创建一个(单元素)列表并将对它的引用排入队列。

sf = Q.dequeue()

弹出从Q引用并将其分配给变量'sf'。

sf[i:i+1] = ...

对该列表进行更改('sf'所指的那个)。

Q.enqueue(sf)

将对同一列表的引用排入队列。

因此只涉及一个列表对象,而Q只包含多个引用。

相反,您可能希望Q中的每个条目都是对单独列表(句子形式)的引用,因此您必须为每次调用Q.enqueue创建一个新列表。

根据您的修复方式,代码中可能存在或可能不存在其他问题。考虑:

(1)每个句子都有多个推导,你只需要“找到”一个(例如,最左边的推导)。

(2)一般情况下,虽然不是在你的示例语法中,但是一个生产的RHS可能有多个非终端的出现(例如,如果是COND,那么STMT,否则STMT),并且这些出现不需要派生相同的子形式。

(3)一般来说,语法可以生成一组无限的句子。


顺便说一句,要在Python中复制一个列表,而不是说

copy = [x for x in original]

说起来更简单:

copy = original[:]

答案 1 :(得分:0)

我创建了一个简单的语法,允许在替代和选项方面指定不同的句子。可以解析用该语法描述的句子。使用Coco / R描述属性语法,其中有一个python版本(http://www.ssw.uni-linz.ac.at/Coco/#Others)。我对C#比较熟悉,所以我在这里创建了一个C#项目,可以作为一个例子:https://github.com/abeham/Sentence-Generator

例如,解析“(This | That)是一个[nice]句子”,用这个简单语法的解析器创建四个句子: *这是一个句子 *这是一个很好的句子 *那是一句话 *这是一个很好的句子

由于没有符号可供重复,因此只能使用该语法创建有限句子。

我知道已经存在一个已接受的答案,但我希望这个答案对于那些来到这里寻找通用解决方案的人来说也是有价值的。至少我没有在网上找到类似的东西,这就是我创建github项目的原因。