J'ai essayé de créer un langage original "PPAP Script" qui imagé PPAP (Pen Pineapple Appo Pen) avec Python

Hier (6ème jour) était seiketkm's "[J'ai développé une application Robophone qui vient du futur](http://qiita.com/seiketkm/items/ C'était 46992f933294a7668dba) ". Cet article est l'article du 7ème jour du Tech-Circle Hands on Advent Calendar 2016.


Cette fois, je voudrais créer un langage original en utilisant PLY (lex + yacc), qui est une bibliothèque d'analyse de phrases / d'analyse syntaxique de Python.

En parlant du langage original, TrumpScript, un langage de programmation inspiré de Donald Trump, a déjà été publié. https://github.com/samshadwell/TrumpScript

TrumpScript a les fonctionnalités suivantes.

Tel…. De cette manière, c'est un langage plein de sens qui reproduit fidèlement M. Donald Trump.

Donc, cette fois, contrairement à TrumpScript, "[PPAPScript](https://github.com/sakaro01/PPAPScript." Je vais créer "git)". pikotaro.jpg

Spécifications de script PPAP

Les spécifications que j'ai proposées sont comme ça.

Qu'est-ce que le pli

Avant d'implémenter PPAPScript, j'expliquerai le ply utilisé cette fois. ply est une bibliothèque Python qui implémente lex et yacc en Python et les rassemble sous forme de module.

Méthode d'introduction

L'installation du pli peut être faite avec pip. Il prend également en charge python3.

$ pip install ply 

À partir de là, j'expliquerai l'utilisation minimale dans lex.py et yacc.py.

Explication de lex.py

Ceci est une explication de lex.py, qui est responsable de l'analyse des phrases.

1. Importez lex.

import ply.lex as lex 

2. Définissez la phrase que vous souhaitez analyser dans une variable appelée "tokens" au format tapple.

tokens = (
    'NUMBER',
    'PLUS',
    'MINUS',
    'TIMES',
    'DIVIDE',
    'LPAREN',
    'RPAREN',
)

3. Définissez une règle d'analyse des phrases à l'aide d'expressions régulières.

Il y a deux manières de le définir. Dans les deux méthodes, la convention de dénomination des noms de variables et des noms de fonctions est définie sous la forme t_ (nom de jeton).

Définition de règles d'analyse de phrases simples

t_PLUS   = r'\+'
t_MINUS  = r'-'
t_TIMES  = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'

Lors du traitement pendant l'analyse de phrase

Définissez l'expression régulière sur la première ligne de la fonction. Un objet LexToken est toujours passé en argument. Ce sera l'objet de la phrase correspondante. Dans l'exemple suivant, la valeur de jeton qui correspond à la règle d'expression régulière est convertie en type int.

def t_NUMBER(t):
    r'\d+'
    t.value = int(t.value)
    return t

4. Ignorez les chaînes inutiles.

Une variable spéciale appelée t_ignore vous permet de sauter certaines chaînes. Dans l'exemple ci-dessous, les espaces et les tabulations sont ignorés.

t_ignore = ' \t'

5. Définissez la syntaxe de destruction des jetons.

Vous pouvez définir des règles d'expression régulière de commentaire à l'aide d'une variable spéciale appelée t_ignore_COMMENT.

t_ignore_COMMENT = r'\#.*'

6. Définissez la gestion des erreurs.

La fonction t_error sera appelée si aucune phrase ne correspond.

def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(t)

7. Construisez.

Construisez avec lex (). Ceci termine la préparation de l'analyse des phrases.

lex.lex()

Explication de yacc.py

Ceci est une description de yacc.py, qui est responsable de l'analyse syntaxique.

1. Importez yacc.

import ply.yacc as yacc

2. Écrivez la règle d'analyse syntaxique.

L'exemple suivant définit une règle de syntaxe pour l'ajout.

def p_expression_minus(p):
    'expression : expression PLUS term'
    p[0] = p[1] - p[3]

Voici les règles de définition.

def p_expression_minus(p):
    'expression : expression MINUS term'
    #Symbole sans terminaison:Symbole sans terminaison終端記号 非終端記号
def p_expression_minus(p):
    'expression : expression MINUS term'
    #  p[0]         p[1]     p[2] p[3]
 
    p[0] = p[1] - p[3]
def p_statement_assign(p):
    """statement : NAME EQUALS expression"""
    names[p[1]] = p[3]


def p_expression_minus(p):
    'expression : expression MINUS term'
 
    p[0] = p[1] - p[3]

3. Synthétisez les règles de syntaxe.

Des règles de syntaxe similaires peuvent être regroupées, comme indiqué ci-dessous.

def p_expression_binop(p):
    """expression : expression PLUS expression
                  | expression MINUS expression
                  | expression TIMES expression
                  | expression DIVIDE expression"""
    if p[2] == '+':
        p[0] = p[1] + p[3]
    elif p[2] == '-':
        p[0] = p[1] - p[3]
    elif p[2] == '*':
        p[0] = p[1] * p[3]
    elif p[2] == '/':
        p[0] = p[1] / p[3]

4. Définissez la gestion des erreurs.

Similaire à lex, il est appelé lorsqu'aucune règle de syntaxe ne correspond.

def p_error(p):
    print "Syntax error in input"

5. Analyser.

Créez un objet paraser avec yacc () et effectuez une analyse de syntaxe avec parser.parse (). Passez la chaîne de caractères que vous souhaitez analyser comme argument.

parser = yacc.yacc()
parser.parse(data)

Implémenter le script PPAP

L'implémentation sera créée sur la base de l'exemple README dans le référentiel ply. https://github.com/dabeaz/ply/blob/master/README.md

Démarrez le programme avec "PPAP"

L'indicateur est contrôlé par la partie qui exécute yacc.parse ().

# Started flag is true by "PPAP" command
has_started = False

def parse(data, debug=0):
    if data == "PPAP":
        global has_started
        has_started = True
        print("Started PPAPScript!")
        return

    if has_started:
        return yacc.parse(data, debug=debug)
    else:
        print('PPAPScript run by "PPAP" command.')
        return

Créez un contournement qui ignore "PPAP" dans l'expression régulière car "PPAP" est intercepté par l'analyse de la phrase de la variable (t_NAME).

def t_NAME(t):
    r"""(?!PPAP)[a-zA-Z_][a-zA-Z0-9_]*"""
    return t

Seules les combinaisons de "stylo", "ananas" et "pomme" peuvent être utilisées (les cas sont ignorés)

Vous pouvez limiter le nom de la variable avec l'expression régulière lex, mais puisque vous souhaitez émettre un message d'erreur dédié, utilisez le module re pour gérer l'erreur.

def t_NAME(t):
    r"""(?!PPAP)[a-zA-Z_][a-zA-Z0-9_]*"""
    pattern = re.compile(r'^(apple|pineapple|pen)+', re.IGNORECASE)
    if pattern.match(t.value):
        return t
    else:
        print("This variable name can't be used '%s'.\n "
              "Variable can use 'apple', 'pineapple', 'pen'." % t.value)
        t.lexer.skip(t)

Assurez-vous d'ajouter "I_have_a" ou "I_have_an" à l'affectation de déclaration des variables.

La raison de définir avec def est de donner la priorité à l'analyse des phrases. (Lex a priorité dans l'ordre défini par def) Dans ce cas, la définition est requise avant t_NAME.

def t_DECLARE(t):
    r"""I_have_(an|a)"""
    return t

La fonction de sortie est "Ah!"

Lex et yacc ont tous deux des définitions ordinaires.

def t_PRINT(t):
    r"""Ah!"""
    return t
def p_statement_print_expr(p):
    """statement : PRINT expression"""
    print(p[2])

Exécution du script PPAP

Le produit fini est publié dans le référentiel suivant, je vais donc le cloner. PPAPScript

$ git clone https://github.com/sakaro01/PPAPScript.git

Installez le pli.

$ pip install -r requirements.txt

Exécutez PPAPScript.

$ python ppapscript.py

Jouons de manière interactive. (Actuellement uniquement interactif) PPAPScript_.gif

Résumé

la prochaine fois

Le prochain Tech-Circle Hands on Advent Calendar 2016 sera en charge de mon synchrone Koga Yuta est. Probablement un robot. Il peut être intéressant d'appliquer cet article pour créer un langage de commande de robot original.

référence

Recommended Posts

J'ai essayé de créer un langage original "PPAP Script" qui imagé PPAP (Pen Pineapple Appo Pen) avec Python
J'ai essayé de créer une fonction de similitude d'image avec Python + OpenCV
[Python] J'ai essayé de faire une application qui calcule le salaire en fonction des heures de travail avec tkinter
J'ai essayé d'implémenter le perceptron artificiel avec python
J'ai essayé de créer une application OCR avec PySimpleGUI
J'ai essayé de créer diverses "données factices" avec Python faker
J'ai essayé de créer une interface graphique à trois yeux côte à côte avec Python et Tkinter
[1 hour challenge] J'ai essayé de créer un site de bonne aventure qui soit trop adapté à Python
[5e] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de faire une activité qui définit collectivement les informations de position
[2nd] J'ai essayé de créer un certain outil de type Authenticator avec python
[Python] Un mémo que j'ai essayé de démarrer avec asyncio
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé de créer une application de notification de publication à 2 canaux avec Python
J'ai essayé de créer une application todo en utilisant une bouteille avec python
[4th] J'ai essayé de créer un certain outil de type Authenticator avec python
[Python] Japonais simple ⇒ J'ai essayé de créer un outil de traduction en anglais
[1er] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé un langage fonctionnel avec Python
J'ai créé un capteur d'ouverture / fermeture (lien Twitter) avec TWE-Lite-2525A
J'ai essayé de faire un signal avec Raspeye 4 (édition Python)
[Zaif] J'ai essayé de faciliter le commerce de devises virtuelles avec Python
Je veux faire un jeu avec Python
J'ai essayé d'obtenir des données CloudWatch avec Python
J'ai essayé de sortir LLVM IR avec Python
J'ai essayé de détecter un objet avec M2Det!
J'ai essayé d'automatiser la fabrication des sushis avec python
J'ai essayé d'envoyer un email avec SendGrid + Python
J'ai essayé de faire un processus périodique avec CentOS7, Selenium, Python et Chrome
[Python] J'ai essayé de créer une IA Shiritori qui améliore le vocabulaire grâce aux batailles
J'ai essayé de faire une simulation de séparation de source sonore en temps réel avec l'apprentissage automatique Python
J'ai essayé d'implémenter Mine Sweeper sur un terminal avec python
J'ai essayé de démarrer avec le script python de blender_Part 01
J'ai essayé de toucher un fichier CSV avec Python
J'ai essayé de résoudre Soma Cube avec python
[Mac] Je souhaite créer un serveur HTTP simple qui exécute CGI avec Python
Suite ・ J'ai essayé de créer Slackbot après avoir étudié Python3
J'ai essayé de démarrer avec le script python de blender_Partie 02
J'ai essayé de résoudre le problème avec Python Vol.1
J'ai essayé d'agréger et de comparer les données de prix unitaires par langue avec Real Gachi by Python
J'ai essayé de trouver la classe alternative avec tensorflow
J'ai essayé de créer un environnement d'apprentissage automatique avec Python (Mac OS X)
J'ai essayé de résoudre la théorie des nombres entiers d'AOJ avec Python
J'ai essayé de faire d'Othello AI que j'ai appris 7,2 millions de mains par apprentissage profond avec Chainer
J'ai essayé de trouver l'entropie de l'image avec python
J'ai essayé de simuler la propagation de l'infection avec Python
J'ai essayé différentes méthodes pour envoyer du courrier japonais avec Python
J'ai essayé d'envoyer un e-mail d'Amazon SES avec Python
[Python] J'ai essayé de visualiser des tweets sur Corona avec WordCloud
J'ai fait un chronomètre en utilisant tkinter avec python
J'ai essayé de changer le script python de 2.7.11 à 3.6.0 sur Windows10
J'ai essayé de créer un article dans Wiki.js avec SQL Alchemy
J'ai essayé fp-growth avec python
J'ai essayé de gratter avec Python
J'ai essayé gRPC avec Python
J'ai essayé de gratter avec du python