实现NLTK递归下降解析器时无结果输出,请求原因排查
问题原因分析
你的递归下降解析器无输出,本质是语法规则与句子结构完全不匹配,具体错误点如下:
终端符号定义错误:所有非终结符的多选项规则里,单词之间没加竖线
|分隔。比如N -> 'dog' 'Somebody''chair''back''coffee'会被NLTK解析成一个包含连续字符串的规则,而非多个可选单词。正确写法应该是每个单词用|分开,比如N -> 'dog' | 'Somebody' | 'chair' | 'back' | 'coffee'。V、P、DT规则都存在这个问题。S规则与句子结构不兼容:你定义的
S -> NP VP PP要求所有句子必须包含PP(介词短语),但sentence2("A sleepy yellow dog stretched his back")和sentence3("Somebody downstairs made coffee")都没有PP部分,导致这两个句子无法匹配S的规则,直接解析失败。未定义非终结符VBD:VP规则里有
VP -> VBD,但语法中完全没有VBD的产生式,解析器遇到这个分支时无法找到匹配规则,会直接放弃该路径。词汇归类错误:
- "his"被错误归到P(介词),它是物主代词,应该新增PR类别或者归到NP;
- "downstairs"被归到P,实际是副词,应该归到RB或者新增ADV类别,导致sentence3里的"downstairs"无法匹配任何规则。
冗余无效代码:开头定义的
nt1、nt2、prod1、prod2没有被使用,虽然不影响运行,但属于无用代码,建议删除。
修正后的示例代码
from nltk import CFG from nltk.parse import RecursiveDescentParser # 修正后的语法规则 grammar = CFG.fromstring(""" S -> NP VP | NP VP PP NP -> DT JJ JJ N | DT JJ N | N | PR N VP -> V NP | V RB PP -> P NP N -> 'dog' | 'Somebody' | 'chair' | 'back' | 'coffee' V -> 'stretched' | 'slept' | 'made' P -> 'by' PR -> 'his' DT -> 'The' | 'the' | 'A' JJ -> 'cheerful' | 'black' | 'sleepy' | 'yellow' RB -> 'quietly' | 'downstairs' """) rd = RecursiveDescentParser(grammar) sentence1 = "The cheerful black dog slept quietly by the chair".split() sentence2 = "A sleepy yellow dog stretched his back".split() sentence3 = "Somebody downstairs made coffee".split() for a in rd.parse(sentence1): print(a) for a in rd.parse(sentence2): print(a) for a in rd.parse(sentence3): print(a)
修正说明:
- 给所有多选项规则添加
|分隔符; - 扩展S规则,允许
S -> NP VP的结构,适配sentence2和sentence3; - 删除未定义的VBD分支,调整VP规则;
- 新增PR类别处理"his",将"downstairs"移到RB类别;
- 给NP新增
DT JJ N和PR N的规则,适配sentence2的结构。
内容的提问来源于stack exchange,提问作者YoYoCowboy
相关产品推荐
相关产品推荐

