一,首先看书中提到的三个函数:
peek 函数:
def peek(word_list):
if word_list:
word = word_list[0]
return word[0]
else:
return None
输入的参数是上一节所创建的函数返回的列表,当列表为空时, peek 返回 None 。
当列表不为空时,返回 word_list[0][0],即列表第一个元组的第一项。
match 函数:
def match(word_list, expecting):
if word_list:
word = word_list.pop(0)
if word[0] == expecting:
return word
else:
return None
else:
return None
同上,当输入参数为空列表时,match 返回 None 。
当列表不为空时,查看列表第一个元组的第一项是否为所期望的单词,
是则从列表中删除并返回第一个元组,不是则返回 None 。
skip 函数:
def skip(word_list, word_type):
while peek(work_list) == word_type:
match(word_list, word_type)
skip 函数通过调用其他两个函数实现。
首先判断第一个元组中储存的用户输入是否为所期望的类型,是则进行循环,
循环中将此元组删除并返回。否则不循环,即“跳过”。
解析句子的代码:
class ParserError(Exception):
pass
class Sentence(object):
def __init__(self, subject, verb, object):
# remember we take ('noun','princess') tuples and convert them
self.subject = subject[1]
self.verb = verb[1]
self.object = object[1]
def peek(word_list):
if word_list:
word = word_list[0]
return word[0]
else:
return None
def match(word_list, expecting):
if word_list:
word = word_list.pop(0)
if word[0] == expecting:
return word
else:
return None
else:
return None
def skip(word_list, word_type):
while peek(work_list) == word_type:
match(word_list, word_type)
def parse_verb(word_list):
skip(word_list, 'stops')
if peek(word_list) == 'verb':
return match(word_list, 'verb')
else:
raise ParserError("Expected a verb next.")
def parse_object(word_list):
skip(word_list, 'stops')
next = peek(word_list)
if next == 'noun':
return match(word_list, 'noun')
elif next == 'direction':
return match(word_list, 'direction')
else:
raise ParserError("Expected a noun or direction next.")
def parse_subject(word_list, subj):
verb = parse_verb(word_list)
obj = parse_object(word_list)
return Sentence(subj, verb, obj)
def parse_sentence(word_list):
skip(word_list, 'stops')
start = peek(word_list)
if start == 'noun':
subj = match(word_list, 'noun')
return parse_subject(word_list, subj)
elif start == 'verb':
#assume the subject is the player then
return parse_subject(word_list, ('noun', 'player'))
else:
raese ParseError("Must start with subject, object, or verb not: %s" % start)
以下进行解析:
1~2 行:自定义异常类 ParserError ,通过继承基类 Exception 得到。
5~11 行:自定义类 Sentence ,用于储存分类后的用户输入的句子的词汇。
14~36 行:定义三个工具函数 peek, match, skip便于以后调用。
39~45 行:函数 parse_verb ,首先跳过无用的关键词(即类型为 'stop' 的词汇),
之后如果列表中第一个元组中存储的是 'verb' 类型,则从列表中删除
并返回,否则抛出异常。
48~57 行:函数 parse_object , 功能同函数 parse_verb 类似,只不过是对 'noun'
和 'direction' 类型进行处理。
60~64 行:函数 parse_subject, 通过调用函数 parse_verb 和 parse_object ,
接收一个参数作为用户输入的主语,对用户输入进行处理,返回类 Sentence。
67~79 行:函数 parse_sentence, 这个函数相当于引擎,用来完成整个过程的调度。
除去无用关键词后,首先查看用户输入的第一个单词,如果是名词,则将
其作为主语,再通过调用 Sentence 类将用户输入中的主谓宾储存起来,
若第一个词为动词,则将 'player' 作为主语,再调用 Sentence 类。否则
抛出异常。
以下是测试方案:
from nose.tools import *
from ex49.lexicon import *
def test_parse_verb():
assert_raises(ParserError, parse_verb, [('noun', 'door')])
assert_equal(parse_verb([('verb', 'go')]), ('verb','go'))
def test_parse_object():
assert_raises(ParserError, parse_object, [('verb', 'go')])
assert_equal(parse_object([('noun', 'bear')]), ('noun', 'bear'))
def tesst_parse_sentence():
assert_raises(ParserError, parse_sentence, [('direction', 'north')])
def test_Sentence():
sentence=Sentence(('noun','player'),('verb', 'go'),('noun', 'bear'))
assert_equal(sentence.subject, 'player')
assert_equal(sentence.verb, 'go')
assert_equal(sentence.object, 'bear')