ПРИМЕЧАНИЕ: код Python здесь не правильный!Это всего лишь приблизительный псевдокод того, как он может выглядеть.
Регулярные выражения хороши для поиска и извлечения данных из текста в фиксированном формате (например, дата ДД / ММ / ГГГГ).
Пара лексер / парсер хороша для обработки данных в структурированном, но несколько изменяемом формате.Лексеры разбивают текст на токены.Эти токены являются единицами информации данного типа (число, строка и т. Д.).Парсеры берут эту серию токенов и делают что-то в зависимости от порядка токенов.
Глядя на данные, у вас есть базовая (субъект, глагол, объект) структура в различных комбинациях для отношения (персона, 'birthday ', date):
Я бы обработал 29/9/10 и 24-9-2010 как один токен, используя регулярное выражение, возвращая его как тип даты.Вероятно, вы могли бы сделать то же самое для других дат, используя карту для преобразования сентября и сентября в 9.
Затем вы можете вернуть все остальное в виде строк (разделенных пробелами).
Вызатем имеют:
- дата ', строка' день рождения '
- строка' день рождения ',' дата
- дата 'день рождения' 'строки' строка
- date ':' string string 'birthday'
- string string 'birthday' date
ПРИМЕЧАНИЕ: 'birthday', ',', ':' and 'из 'здесь есть ключевые слова, поэтому:
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
, если это гласный).Это может быть сложно, так как «Алексис» может быть формой множественного числа «Алекси», но поскольку вы ограничиваете, где могут быть формы множественного числа, это легко обнаружить:
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