2010-06-30 11 views
0

Je suis en train d'écrire un code qui fonctionnera comme des calendriers google fonction Ajout rapide. Vous connaissez celui où vous pouvez entrer l'une des choses suivantes: 1) 24th sep 2010, Johns anniversaire 2) L'anniversaire de John, 24/9/10 3) 24 Septembre 2010, l'anniversaire de John Doe 4) 24-9 -2010: John fait l'anniversaire 5) John fait l'anniversaire 24 septembre 2010lexical analyser ou d'une série d'expressions régulières pour analyser des textes non structurés sous forme structurée

Et il peut comprendre que nous voulons un événement sur une date 24/9/2010 ont le reste du matériel comme texte d'événement.

Je veux faire est python.

Je pense à une conception où j'écris des expressions régulières qui peuvent correspondre à tous les cas énumérés ci-dessus et extraire la date. Mais je suis sur il y a une manière plus intelligente d'aborder ce problème. Comme je ne suis clairement pas formé à l'analyse lexicale ou aux nombreux types de parsers. Je cherche ce qui est un bon moyen d'aborder ce problème.

Répondre

2

REMARQUE: le code python n'est pas correct! C'est juste un pseudo-code approximatif de ce à quoi ça pourrait ressembler.

expressions régulières sont bonnes à la recherche et l'extraction des données de texte dans un format fixe (par exemple une date de JJ/MM/AAAA).

Une paire lexer/analyseur est bonne à des données de traitement dans un cadre structuré, mais le format quelque peu variable. Lexers a divisé le texte en jetons. Ces jetons sont des unités d'information d'un type donné (nombre, chaîne, etc.). Les parseurs prennent cette série de jetons et font quelque chose en fonction de l'ordre des jetons.

En regardant les données, vous disposez d'une structure de base (sujet, verbe, objet) dans différentes combinaisons pour la relation (personne, « anniversaire », date):

Je 29/9/10 et gérer 24-9-2010 en tant que simple jeton utilisant une regex, le renvoyant comme type de date. Vous pourriez probablement faire la même chose pour les autres dates, avec une carte pour convertir Septembre et sep à 9.

Vous pouvez ensuite retourner le tout le reste sous forme de chaînes (séparés par des espaces).

Vous avez alors:

  1. Date '' string 'anniversaire'
  2. string 'anniversaire' '' Date
  3. Date
  4. 'anniversaire' 'de' chaîne de chaîne
  5. date
  6. ' : 'string string 'anniversaire'
  7. string
  8. 'anniversaire' Date

NOTE:' birthda y « », ', « : » et « de » ici sont des mots clés, donc:

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 

Tous sauf 3 Utilisez la forme possessive de la personne ('s si le dernier caractère est une consonne, s si elle est une voyelle).Cela peut être difficile, comme « Alexis » pourrait être la forme plurielle de « Alexi », mais puisque vous restreignez où les formes plurielles peuvent être, il est facile de détecter:

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 

Maintenant, le nom peut être soit first-name ou first-name last-name (oui, je sais que le Japon les remplace, mais du point de vue du traitement, le problème ci-dessus n'a pas besoin de différencier les noms et prénoms). Ce qui suit traitera ces deux formes:

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 

Enfin, vous pouvez traiter les formulaires 1-5 en utilisant quelque chose comme ceci:

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