Ich habe versucht, eine Originalsprache "PPAP Script" zu erstellen, die PPAP (Pen Pineapple Appo Pen) mit Python abbildet

Gestern (6. Tag) war seiketkm "Ich habe eine Robophone-App entwickelt, die aus der Zukunft stammt Es war 46992f933294a7668dba) ". Dieser Artikel ist der 7. Tagesartikel von Tech-Circle Hands on Advent Calendar 2016.


Dieses Mal möchte ich eine Originalsprache mit PLY (lex + yacc) erstellen, einer Bibliothek für Phrasenanalyse / Syntaxanalyse von Python.

TrumpScript, eine von Donald Trump inspirierte Programmiersprache, wurde bereits veröffentlicht. https://github.com/samshadwell/TrumpScript

TrumpScript bietet die folgenden Funktionen.

Eine solche…. Auf diese Weise ist es eine Sprache voller Sinn, die Herrn Donald Trump getreu wiedergibt.

Diesmal also im Gegensatz zu TrumpScript "PPAPScript. Ich werde "git)" erstellen. pikotaro.jpg

PPAP-Skriptspezifikationen

Die Spezifikationen, die ich mir ausgedacht habe, sind wie folgt.

Was ist Lage?

Vor der Implementierung von PPAPScript werde ich die diesmal verwendete Lage erläutern. ply ist eine Python-Bibliothek, die Lex und Yacc in Python implementiert und als Modul zusammenfügt.

Einführungsmethode

Die Installation der Lage kann mit pip erfolgen. Es unterstützt auch Python3.

$ pip install ply 

Von hier aus werde ich die Mindestverwendung in lex.py und yacc.py erläutern.

Erklärung von lex.py.

Dies ist eine Erklärung von lex.py, das für die Phrasenanalyse verantwortlich ist.

1. Lex importieren.

import ply.lex as lex 

2. Definieren Sie die Phrase, die Sie analysieren möchten, in einer Variablen namens "Token" im Tapple-Format.

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

3. Definieren Sie eine Phrasenanalyseregel mit regulären Ausdrücken.

Es gibt zwei Möglichkeiten, es zu definieren. In beiden Methoden wird die Namenskonvention für Variablennamen und Funktionsnamen in der Form t_ (Token-Name) definiert.

Definition einfacher Regeln für die Phrasenanalyse

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

Bei der Verarbeitung während der Phrasenanalyse

Definieren Sie den regulären Ausdruck in der ersten Zeile der Funktion. Ein LexToken-Objekt wird immer als Argument übergeben. Dies ist das Objekt der übereinstimmenden Phrase. Im folgenden Beispiel wird der Tokenwert, der der Regel für reguläre Ausdrücke entspricht, in den Typ int konvertiert.

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

4. Überspringen Sie unnötige Zeichenfolgen.

Mit einer speziellen Variablen namens t_ignore können Sie bestimmte Zeichenfolgen überspringen. Im folgenden Beispiel werden Leerzeichen und Tabulatoren übersprungen.

t_ignore = ' \t'

5. Definieren Sie die Syntax zum Zerstören von Token.

Sie können Regeln für kommentierende reguläre Ausdrücke mithilfe einer speziellen Variablen namens t_ignore_COMMENT definieren.

t_ignore_COMMENT = r'\#.*'

6. Definieren Sie die Fehlerbehandlung.

Die Funktion t_error wird aufgerufen, wenn keine Phrase übereinstimmt.

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

7. Bauen.

Mit lex () erstellen. Damit ist die Vorbereitung für die Phrasenanalyse abgeschlossen.

lex.lex()

Erklärung von yacc.py.

Dies ist eine Beschreibung von yacc.py, das für die Syntaxanalyse verantwortlich ist.

1. Importieren Sie yacc.

import ply.yacc as yacc

2. Schreiben Sie die Syntax-Parsing-Regel.

Das folgende Beispiel definiert eine Syntaxregel zum Hinzufügen.

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

Das Folgende sind die Regeln zum Definieren.

def p_expression_minus(p):
    'expression : expression MINUS term'
    #Nicht abschließendes Symbol:Nicht abschließendes Symbol終端記号 非終端記号
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. Synthetisieren Sie die Syntaxregeln.

Ähnliche Syntaxregeln können wie unten gezeigt zusammengefasst werden.

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. Definieren Sie die Fehlerbehandlung.

Ähnlich wie bei lex wird es aufgerufen, wenn keine Syntaxregel übereinstimmt.

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

5. Analysieren.

Erstellen Sie mit yacc () ein Paraser-Objekt und führen Sie mit parser.parse () eine Syntaxanalyse durch. Übergeben Sie die Zeichenfolge, die Sie analysieren möchten, als Argument.

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

Implementieren Sie das PPAP-Skript

Die Implementierung wird basierend auf dem README-Beispiel im Repository von ply erstellt. https://github.com/dabeaz/ply/blob/master/README.md

Starten Sie das Programm mit "PPAP"

Das Flag wird von dem Teil gesteuert, der yacc.parse () ausführt.

# 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

Erstellen Sie eine Umgehung, die "PPAP" im regulären Ausdruck ignoriert, da "PPAP" von der Phrasenanalyse der Variablen (t_NAME) erfasst wird.

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

Es können nur Kombinationen von "Stift", "Ananas" und "Apfel" verwendet werden (Fälle werden ignoriert).

Sie können den Variablennamen mit dem regulären Ausdruck lex einschränken. Da Sie jedoch eine dedizierte Fehlermeldung ausgeben möchten, verwenden Sie das Modul re zur Fehlerbehandlung.

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)

Stellen Sie sicher, dass Sie "I_have_a" oder "I_have_an" zur Deklarationszuweisung von Variablen hinzufügen.

Der Grund für die Definition mit def ist die Priorisierung der Phrasenanalyse. (Lex hat Vorrang in der durch def definierten Reihenfolge) In diesem Fall ist die Definition vor t_NAME erforderlich.

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

Die Ausgabefunktion ist "Ah!"

Sowohl Lex als auch Yacc haben gewöhnliche Definitionen.

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

PPAP-Skript ausführen

Das fertige Produkt wird im folgenden Repository veröffentlicht, daher werde ich es klonen. PPAPScript

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

Lage installieren.

$ pip install -r requirements.txt

Führen Sie PPAPScript aus.

$ python ppapscript.py

Lass uns interaktiv spielen. (Derzeit nur interaktiv) PPAPScript_.gif

Zusammenfassung

nächstes Mal

Der nächste Tech-Circle Hands on Advent Calendar 2016 wird für mein synchrones Koga Yuta verantwortlich sein. ist. Wahrscheinlich ein Roboter. Es kann interessant sein, diesen Artikel anzuwenden, um eine ursprüngliche Roboterbefehlssprache zu erstellen.

Referenz

Recommended Posts

Ich habe versucht, eine Originalsprache "PPAP Script" zu erstellen, die PPAP (Pen Pineapple Appo Pen) mit Python abbildet
Ich habe versucht, mit Python + OpenCV eine Bildähnlichkeitsfunktion zu erstellen
[Python] Ich habe versucht, mit tkinter eine Anwendung zu erstellen, die das Gehalt anhand der Arbeitszeit berechnet
Ich habe versucht, künstliches Perzeptron mit Python zu implementieren
Ich habe versucht, eine OCR-App mit PySimpleGUI zu erstellen
Ich habe versucht, mit Python faker verschiedene "Dummy-Daten" zu erstellen
Ich habe versucht, die Benutzeroberfläche neben Python und Tkinter dreiäugig zu gestalten
[1 Stunde Herausforderung] Ich habe versucht, eine Wahrsagerseite zu erstellen, die für Python zu geeignet ist
[5.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe versucht, eine Aktivität zu erstellen, die gemeinsam die Positionsinformationen festlegt
[2nd] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
[Python] Ein Memo, das ich versucht habe, mit Asyncio zu beginnen
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ich habe versucht, mit Python eine 2-Kanal-Post-Benachrichtigungsanwendung zu erstellen
Ich habe versucht, eine ToDo-App mit einer Flasche mit Python zu erstellen
[4.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
[Python] Einfaches Japanisch ⇒ Ich habe versucht, ein englisches Übersetzungswerkzeug zu erstellen
[1.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe eine funktionale Sprache mit Python ausprobiert
Ich habe mit TWE-Lite-2525A einen Öffnungs- / Schließsensor (Twitter-Link) erstellt
Ich habe versucht, mit Raspeye 4 (Python Edition) ein signalähnliches Signal zu erzeugen.
[Zaif] Ich habe versucht, den Handel mit virtuellen Währungen mit Python zu vereinfachen
Ich möchte ein Spiel mit Python machen
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
Ich habe versucht, LLVM IR mit Python auszugeben
Ich habe versucht, ein Objekt mit M2Det zu erkennen!
Ich habe versucht, die Herstellung von Sushi mit Python zu automatisieren
Ich habe versucht, eine E-Mail mit SendGrid + Python zu senden
Ich habe versucht, einen periodischen Prozess mit CentOS7, Selenium, Python und Chrome durchzuführen
[Python] Ich habe versucht, eine Shiritori-KI zu erstellen, die den Wortschatz durch Schlachten verbessert
Ich habe versucht, mit Python Machine Learning ein Echtzeit-Modell zur Trennung von Tonquellen zu erstellen
Ich habe versucht, Mine Sweeper auf dem Terminal mit Python zu implementieren
Ich habe versucht, mit Blenders Python script_Part 01 zu beginnen
Ich habe versucht, eine CSV-Datei mit Python zu berühren
Ich habe versucht, Soma Cube mit Python zu lösen
[Mac] Ich möchte einen einfachen HTTP-Server erstellen, auf dem CGI mit Python ausgeführt wird
Fortsetzung ・ Ich habe versucht, Slackbot zu erstellen, nachdem ich Python3 studiert habe
Ich habe versucht, mit Blenders Python script_Part 02 zu beginnen
Ich habe versucht, das Problem mit Python Vol.1 zu lösen
Ich habe versucht, Stückpreisdaten nach Sprache mit Real Gachi von Python zu aggregieren und zu vergleichen
Ich habe versucht, die alternative Klasse mit Tensorflow zu finden
Ich habe versucht, mit Python (Mac OS X) eine Umgebung für maschinelles Lernen zu erstellen.
Ich habe versucht, AOJs Integer-Theorie mit Python zu lösen
Ich habe versucht, Othello AI zu machen, dass ich 7,2 Millionen Hände durch tiefes Lernen mit Chainer gelernt habe
Ich habe versucht, die Entropie des Bildes mit Python zu finden
Ich habe versucht zu simulieren, wie sich die Infektion mit Python ausbreitet
Ich habe verschiedene Methoden ausprobiert, um japanische Post mit Python zu senden
Ich habe versucht, mit Python eine E-Mail von Amazon SES zu senden
[Python] Ich habe versucht, Tweets über Corona mit WordCloud zu visualisieren
Ich habe eine Stoppuhr mit tkinter mit Python gemacht
Ich habe versucht, das Python-Skript unter Windows 10 von 2.7.11 auf 3.6.0 zu ändern
Ich habe versucht, einen Artikel mit SQL Alchemy auf Wiki.js zu erstellen
Ich habe fp-Wachstum mit Python versucht
Ich habe versucht, mit Python zu kratzen
Ich habe gRPC mit Python ausprobiert
Ich habe versucht, mit Python zu kratzen