La bibliothèque Python pyparsing vous permet de définir des grammaires faciles à lire et à modifier avec un bulletin de définition hiérarchique. J'ai remarqué qu'il peut être décrit sans utiliser d'instructions if, et j'ai écrit la grammaire en japonais pour les classes, les méthodes et les noms de variables. Comparé à la description en anglais avec le même contenu, j'ai senti que le code en japonais était plus facile à comprendre au premier coup d'œil. Il est peut-être exagéré de traduire des classes et des méthodes en japonais, mais je ne pensais pas pouvoir le faire avec le japonais en Python. Utilise Python 3.7, pyparsing 2.4.6. (Distribution Anaconda)
En supposant trois types de listes de membres de l'organisation, j'ai défini la grammaire de l'analyseur qui les lit en japonais. Kanji est utilisé pour les noms de variables (nom de grammaire, nom d'expression) autres que les mots réservés Python, les noms de fonctions, les noms de classes et de fonctions importés et l'analyse des cibles. Le code est une pile ascendante de phrases de haut en bas. On peut voir que l'expression de droite de la phrase suivante décrite à la fin est la grammaire de niveau supérieur, et il existe trois types de membres de l'organisation.
Membre de l'association=Membre de soutien|Membre étudiant|Membre individuel
J'ai écrit de bas en haut, mais en écrivant, j'ai d'abord décidé cette dernière définition, puis j'ai écrit la définition inférieure correspondant à la partie, puis j'ai pris la méthode de décomposition de cette dernière phrase en détails. Définissez une expression qui correspond au premier jeton de chaque ligne de la liste pour créer une branche entre les trois types de membres les plus importants. En d'autres termes, la première correspondance de la chaîne de caractères à analyser dépend du nom de l'entreprise ou du nom de l'école. Les membres individuels sont autres que cela. (Extrayez le code ci-dessous)
Nom de la compagnie=Match en arrière('Compagnie')
Membre de soutien= (Nom de la compagnie+Représentant+Numéro de membre)('Membre de soutien')
nom de l'école=Match en arrière('Université') |Match en arrière('Collège technique') |Match en arrière('Université校')
Membre étudiant= (nom de l'école+Prénom et nom+Lecture du prénom et du nom+Numéro de membre)('Membre étudiant')
De plus, comme 〇✖ Co., Ltd., la mise en correspondance du nom de la société et du nom de l'école en supposant des chaînes de caractères continues sans délimiteurs est effectuée par une correspondance de suffixe des expressions régulières comme décrit ci-dessus. Au début, je pensais à la description suivante, mais cela n'a pas fonctionné à cause du problème dit gourmand, dans lequel l'expression précédente, la chaîne kanji (Word), était mangée, par exemple, par 'Co., Ltd.'. J'ai aussi essayé le match le plus long, mais cela n'a pas fonctionné. Dans pyparsing, les jetons sont consommés par la gauche, il n'y a donc aucun problème avec la correspondance de préfixe.
"""L'après-match provoque des problèmes de suralimentation"""
Nom de la compagnie=Joindre(Chaîne Kanji+ oneOf('GK Co., Ltd.'))('Nom de la compagnie')
"""Le préfixe ne cause pas de problèmes de suralimentation"""
Nom de la compagnie=Joindre('Co., Ltd.' +Chaîne Kanji)
Afin de conserver le format d'une liste de phrases utilisant des expressions régulières, une fonction (expression lambda) qui renvoie un suffixe Regex est fournie. Il est plus efficace de définir la fonction de correspondance de suffixe de sorte que plusieurs chaînes de caractères puissent être passées, telles que «Godo Kaisha Co., Ltd.», mais c'est une forme dans laquelle plusieurs caractères sont décrits dans la description de la grammaire avec un seul argument. Lors de la définition de la grammaire avec pyparsing, afin d'éviter le problème de suralimentation mentionné précédemment, en plus de la solution de contournement avec les expressions régulières, il est possible d'arrêter la consommation en modifiant le type de caractère de l'entrée avant et après, en insérant un délimiteur, etc. .. En thérapie symptomatique, il faut beaucoup de temps pour résoudre le problème. (En fait, j'ai perdu deux jours si ce n'était pas comme ça)
Vous trouverez ci-dessous le code complet, avec des données données et testées dans la partie principale, y compris la gestion simple des exceptions. Cependant, il semble que pe.loc n'indique pas toujours correctement le premier emplacement d'erreur, probablement en raison du retour en arrière. Au début, vous pouvez rédiger des descriptions grammaticales, mais si vous en écrivez, vous comprendrez. Dans l'image, la chaîne de caractères à analyser est injectée dans le code écrit dans la grammaire, et seuls ceux qui correspondent à une expression sont filtrés.
parse_OrgMemberRecordReg.py
#by T.Hayashi
#tested with Python3.7, pyparsing 2.4.6
#don't use full-width space as delimitter in this script.
from pyparsing import (
Combiner comme combiner,
Mot comme colonne,
nums sous forme de nombres,
__version__comme version,
Regex ,
pyparsing_unicode as uni,
ParseException)
#Les japonais suivants
def Définir la grammaire():
Match en arrière= lambda s : Regex(r'.*'+s)
entier=Colonne(Nombres)
Chaîne Kanji=Colonne(uni.Japanese.Kanji.alphas)
Ligne Kana=Colonne(uni.Japanese.Hiragana.alphas)
Numéro de membre=entier('Numéro de membre')
Prénom et nom=Chaîne Kanji('Prénom et nom')
Lecture du prénom et du nom=Ligne Kana('Lecture du prénom et du nom')
Nom de la compagnie=Joindre('Co., Ltd.' +Chaîne Kanji)
Nom de la compagnie=Nom de la compagnie|Match en arrière('Compagnie')
Représentant=Chaîne Kanji('Représentant')
Membre de soutien= (Nom de la compagnie+Représentant+Numéro de membre)('Membre de soutien')
nom de l'école=Match en arrière('Université') |Match en arrière('Collège technique') |Match en arrière('Université校')
Membre étudiant= (nom de l'école+Prénom et nom+Lecture du prénom et du nom+Numéro de membre)('Membre étudiant')
Membre individuel= (Prénom et nom+Lecture du prénom et du nom+Numéro de membre)('Membre individuel')
Membre de l'association=Membre de soutien|Membre étudiant|Membre individuel
retour membre de l'association
test def(gram,instr):
try:
r=gram.parseString(instr)
name=r.getName()
print(name,r.get(name))
print()
except ParseException as pe:
print(f'error at {pe.loc} of {instr}')
print(instr)
#loc : char position.
print(' '*(pe.loc-2)+'^')
#print('Explain:\n',ParseException.explain(pe))
print('version pyparsing:',Numéro de version)
grammaire=grammaireを定義()
tester(grammaire,'Taro Yamada Yamada Taro 3456')
tester(grammaire,'Fictive East University Saburo Kawasaki Saburo Kawasaki 5127')
tester(grammaire,'Fictitious Trading Co., Ltd. Totaro 0015') #Correspondance de préfixe
tester(grammaire,'Fictitious Trading Co., Ltd. Taro Kaiyama 0010') #Match en arrière
tester(grammaire,'Collège national de technologie du nord-nord-ouest Ichiro Ito Ichiro Ito 900')
#Confirmation d'erreur L'école secondaire n'est pas dans la définition
tester(grammaire,'Kita Tohoku Lycée Suzuki Saburo Suzuki Saburo 1000')
#Confirmation d'erreur: l'entreprise est manquante
tester(grammaire,'Stock Trading fictif Totaro 0015')
#Confirmation d'erreur Kanji pour la lecture
tester(grammaire,'Ichitaro Yamada Ichitaro Yamada 3456')
Voici le résultat de l'exécution.
version pyparsing: 2.4.6
Membre individuel['Yamada Taro', 'Yamada Taro', '3456']
Membre étudiant['Université fictive de l'Est', 'Saburo Kawasaki', 'Kawasaki Saburo', '5127']
Membre de soutien['Fictitious Trading Co., Ltd.', 'Totaro', '0015']
Membre de soutien['Fictitious Trading Co., Ltd.', 'Taro Umiyama', '0010']
Membre étudiant['Collège technique nord-nord-ouest', 'Ichiro Ito', 'Ichirou Ito', '900']
erreur à 6 du lycée Kita Tohoku Suzuki Saburo Suzuki Saburo 1000
Kita Tohoku Lycée Suzuki Saburo Suzuki Saburo 1000
^
erreur à 7 de Stock Fictitious Trading Totaro 0015
Stock Trading fictif Totaro 0015
^
erreur à 9 d'Ichitaro Yamada Ichitaro Yamada 3456
Ichitaro Yamada Ichitaro Yamada 3456
^
Avec une liste de définitions de type BNF (forme Backus-Naur), j'ai pu définir une grammaire plus facile à comprendre qu'un programme normal. Je pensais que si j'utilisais le japonais, diverses choses inattendues se produiraient, mais sans cela, j'étais surpris que Python puisse faire autant. Ce à quoi je faisais attention était de ne pas provoquer le problème de la suralimentation et d'éviter de saisir des espaces invisibles pleine largeur lors de la saisie du code. La définition et le débogage de grammaires plus volumineuses pour fonctionner correctement peuvent être difficiles à tracer et peuvent ne pas être aussi faciles qu'un programme Python ordinaire, selon la façon dont vous les écrivez. Pour cette raison, dans le cas d'un étudiant qui fait des corrections à plusieurs reprises en regardant les exceptions et les comportements inattendus, il est nécessaire d'essayer fortement d'écrire le code correct autant que possible dès le début par rapport à un programme normal. .. .. Remarque: je l'ai appelé le problème de la suralimentation, mais ce n'est pas un terme général et je l'ai nommé provisoirement ici.