注意:这里的python代码不正确!这只是它看起来的粗略伪代码。
正则表达式擅长从文本中以固定格式(例如 DD/MM/YYYY 日期)查找和提取数据。
词法分析器/解析器对擅长以结构化但有些可变的格式处理数据。词法分析器将文本拆分为标记。这些标记是给定类型(数字、字符串等)的信息单元。解析器采用这一系列标记并根据标记的顺序执行某些操作。
查看数据,您有一个基本的(主语、动词、宾语)结构,关系(人、“生日”、日期)的不同组合:
我将使用正则表达式将 29/9/10 和 24-9-2010 作为单个令牌处理,并将其作为日期类型返回。您可能可以对其他日期执行相同的操作,使用地图将 9 月和 9 月转换为 9。
然后,您可以将其他所有内容作为字符串返回(由空格分隔)。
然后你有:
- 日期','字符串'生日'
- 字符串 '生日' ',' 日期
- date 'birthday' 'of' 字符串 string
- 日期':'字符串字符串'生日'
- 字符串字符串“生日”日期
注意:'birthday'、','、':' 和 'of' 这里是关键字,所以:
class Lexer:
DATE = 1
STRING = 2
COMMA = 3
COLON = 4
BIRTHDAY = 5
OF = 6
keywords = { 'birthday': BIRTHDAY, 'of': OF, ',': COMMA, ':', COLON }
def next_token():
if have_saved_token:
have_saved_token = False
return saved_type, saved_value
if date_re.match(): return DATE, date
str = read_word()
if str in keywords.keys(): return keywords[str], str
return STRING, str
def keep(type, value):
have_saved_token = True
saved_type = type
saved_value = value
除了 3 之外,所有的都使用人称的所有格形式('s
如果最后一个字符是辅音,s
如果它是元音)。这可能很棘手,因为 'Alexis' 可能是 'Alexi' 的复数形式,但由于您限制了复数形式的位置,因此很容易检测到:
def parseNameInPluralForm():
name = parseName()
if name.ends_with("'s"): name.remove_from_end("'s")
elif name.ends_with("s"): name.remove_from_end("s")
return name
现在,名称可以是first-name
或first-name last-name
(是的,我知道日本交换了这些,但从处理的角度来看,上述问题不需要区分名字和姓氏)。下面将处理这两种形式:
def parseName():
type, firstName = Lexer.next_token()
if type != Lexer.STRING: raise ParseError()
type, lastName = Lexer.next_token()
if type == Lexer.STRING: # first-name last-name
return firstName + ' ' + lastName
else:
Lexer.keep(type, lastName)
return firstName
最后,您可以使用以下方式处理表格 1-5:
def parseBirthday():
type, data = Lexer.next_token()
if type == Lexer.DATE: # 1, 3 & 4
date = data
type, data = Lexer.next_token()
if type == Lexer.COLON or type == Lexer.COMMA: # 1 & 4
person = parsePersonInPluralForm()
type, data = Lexer.next_token()
if type != Lexer.BIRTHDAY: raise ParseError()
elif type == Lexer.BIRTHDAY: # 3
type, data = Lexer.next_token()
if type != Lexer.OF: raise ParseError()
person = parsePerson()
elif type == Lexer.STRING: # 2 & 5
Lexer.keep(type, data)
person = parsePersonInPluralForm()
type, data = Lexer.next_token()
if type != Lexer.BIRTHDAY: raise ParseError()
type, data = Lexer.next_token()
if type == Lexer.COMMA: # 2
type, data = Lexer.next_token()
if type != Lexer.DATE: raise ParseError()
date = data
else:
raise ParseError()
return person, date