[PYTHON] J'ai écrit un analyseur japonais en japonais en utilisant pyparsing.

Aperçu

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)

Description et exemple d'exécution

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) greedyeater.jpg

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
       ^

À la fin

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.

Recommended Posts

J'ai écrit un analyseur japonais en japonais en utilisant pyparsing.
J'ai écrit python en japonais
Un mémo que j'ai écrit un tri rapide en Python
J'ai écrit une classe en Python3 et Java
J'ai écrit un modèle de conception dans l'édition Kotlin Prototype
J'ai écrit FizzBuzz en python en utilisant la machine à vecteurs de support (bibliothèque LIVSVM).
J'ai écrit un modèle de conception dans l'édition Kotlin Factory
J'ai écrit un modèle de conception dans l'édition Kotlin Builder
J'ai écrit un modèle de conception dans l'édition Kotlin Singleton
J'ai écrit un modèle de conception dans l'édition Kotlin Adapter
J'ai écrit un modèle de conception en kotlin, édité par Iterator
J'ai écrit un modèle de conception dans l'édition de modèle kotlin
Je comprends Python en japonais!
J'ai créé un lecteur de flux rapide en utilisant feedparser en Python
J'ai écrit un script pour obtenir un site populaire au Japon
J'ai écrit un script qui divise l'image en deux
J'ai écrit un code qui dépasse le taux de récupération de 100% dans la prédiction des courses de chevaux en utilisant LightGBM (partie 2)
J'ai fait un Line-bot avec Python!
J'obtiens une KeyError dans pyclustering.xmeans
J'ai écrit Fizz Buzz en Python
J'ai écrit Gray Scale avec Pytorch
J'ai écrit la file d'attente en Python
J'ai écrit la pile en Python
J'ai écrit une fonction pour charger le script d'extension Git en Python
J'ai écrit un script pour extraire les liens de pages Web en Python
[Python] J'ai écrit une API REST en utilisant AWS API Gateway et Lambda.
J'ai écrit un code pour convertir quaternion en angle de graissage de type z-y-x avec Python
Je veux imprimer dans la notation d'inclusion
J'ai fait un programme de gestion de la paie en Python!
J'ai essayé de jouer au jeu ○ ✕ en utilisant TensorFlow
Débutant: j'ai créé un lanceur à l'aide d'un dictionnaire
Tri sélect écrit en C
Scraping de sites Web à l'aide de JavaScript en Python
[Python] J'ai écrit de force une courte fonction de génération de bruit parlin dans Numpy.
Dessinez une structure arborescente en Python 3 à l'aide de graphviz
J'ai écrit Project Euler 1 en une seule ligne.
J'ai essayé d'utiliser pipenv, alors prenez note
Démarrage de Node.js dans un environnement virtuel
J'ai créé un outil de mot de passe en Python.
J'ai écrit l'aile coulissante dans la création.
J'ai écrit un graphe comme R glmnet en Python pour une modélisation clairsemée avec Lasso
[Examen d'ingénieur d'information de base] J'ai écrit un algorithme de recherche linéaire en Python.
J'ai écrit un module PyPI qui étend le style de paramètre dans le module sqlite3 de Python
Créer un fichier GIF en utilisant Pillow en Python
Quand j'obtiens une erreur de pilote chrome dans Selenium
Dessinez un graphique avec des étiquettes japonaises dans Jupyter
Je veux créer une fenêtre avec Python
J'ai essayé de jouer à un jeu de frappe avec Python
Créer un analyseur de données binaires à l'aide de Kaitai Struct
Afficher les avis sur les médicaments à l'aide de listes en Python
J'ai essayé d'utiliser Pythonect, un langage de programmation de flux de données.
J'ai essayé de lire un fichier CSV en utilisant Python
J'ai essayé d'ajouter un module Python 3 en C
[PyTorch] J'étais un peu perdu dans torch.max ()
Conseils pour utiliser Elastic Search de manière efficace
Créez un fichier MIDI en Python en utilisant pretty_midi
Enregistrer des vues YouTube sur une feuille de calcul à l'aide de Lambda
J'ai essayé d'utiliser la base de données (sqlite3) avec kivy
J'ai créé un programme cryptographique César en Python.
J'ai créé un jeu ○ ✕ avec TensorFlow