我用NLTK写了这个简单的程序,它应该打印出语法树。但是,即使正在创建RecursiveDescentParser
,它也不打印任何内容。我的问题是什么?我是否错误地定义了语法?我尝试迭代解析器的方式有问题吗?提前谢谢。
import nltk
'''The price of peace is rising.'''
grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> V NP | V NP PP
PP -> P NP
V -> "is" | "rising"
NP -> Det N | Det N PP
Det -> "the" | "of"
N -> "price" | "peace"
P -> "in" | "on" | "by" | "with"
""")
sentence = "the price of peace is rising"
wordArray = sentence.split()
print(wordArray)
parser = nltk.RecursiveDescentParser(grammar)
for tree in parser.parse(wordArray):
print(tree)
答案 0 :(得分:0)
首先,始终以一口大小开始编写语法。
让我们从简单的句子Peace is rising
开始。
我们想要结构S -> NP VP
,其中:
VP是一个不及物动词短语,在这种特殊情况下,is rising
附带辅助is
,而rise
附带-ing
渐进变形。< / p>
NP只是一个名词。
[代码]:
import nltk
your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V
V -> "rising"
AUX -> "is"
NP -> N
N -> "peace"
""")
parser = nltk.RecursiveDescentParser(your_grammar)
sentence = "peace is rising".split()
for tree in parser.parse(sentence):
print (list(tree))
[OUT]:
[Tree('NP', [Tree('N', ['peace'])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]
现在使用NP -> DT NP | N
import nltk
your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V
V -> "rising"
AUX -> "is"
NP -> N | DT NP
N -> "peace" | "price"
DT -> "the"
""")
parser = nltk.RecursiveDescentParser(your_grammar)
sentence = "the price is rising".split()
for tree in parser.parse(sentence):
print (list(tree))
[OUT]:
[Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('N', ['price'])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]
最后,我们可以在NP中添加PP构造,NP -> NP PP
和PP -> P NP
:
import nltk
your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V
V -> "rising"
AUX -> "is"
NP -> N | DT NP | NP PP
N -> "peace" | "price"
DT -> "the"
PP -> P NP
P -> "of"
""")
parser = nltk.RecursiveDescentParser(your_grammar)
sentence = "the price of peace is rising".split()
for tree in parser.parse(sentence):
print (list(tree))
在最佳结果中为我们提供了最佳解析。
[OUT]:
[Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('NP', [Tree('N', ['price'])]), Tree('PP', [Tree('P', ['of']), Tree('NP', [Tree('N', ['peace'])])])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]
但它也带有一些讨厌的递归循环错误,看起来像这样:
File "/usr/local/lib/python3.5/site-packages/nltk/tree.py", line 158, in __getitem__
return self[index[0]][index[1:]]
File "/usr/local/lib/python3.5/site-packages/nltk/tree.py", line 156, in __getitem__
return self[index[0]]
File "/usr/local/lib/python3.5/site-packages/nltk/tree.py", line 150, in __getitem__
if isinstance(index, (int, slice)):
RecursionError: maximum recursion depth exceeded in __instancecheck__
这是因为nltk.RecursiveDescentParser
尝试递归地查找解析,因为NP -> NP PP
和PP -> P NP
规则可以无限重复。如果您想知道原因,请尝试将其作为StackOverflow上的单独问题; P
一个简单的解决方案是使用try-except
:
try:
for tree in parser.parse(sentence):
print (list(tree))
except RecursionError:
exit()
但那太丑了!相反,您可以使用ChartParser
:
import nltk
your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V
V -> "rising"
AUX -> "is"
NP -> N | DT NP | NP PP
N -> "peace" | "price"
DT -> "the"
PP -> P NP
P -> "of"
""")
parser = nltk.ChartParser(your_grammar)
sentence = "the price of peace is rising".split()
for tree in parser.parse(sentence):
print (list(tree))
[OUT]:
[Tree('NP', [Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('N', ['price'])])]), Tree('PP', [Tree('P', ['of']), Tree('NP', [Tree('N', ['peace'])])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]
[Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('NP', [Tree('N', ['price'])]), Tree('PP', [Tree('P', ['of']), Tree('NP', [Tree('N', ['peace'])])])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]