[PHP/MySQL] Scriptcode auswerten

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

[PHP/MySQL] Scriptcode auswerten

Beitrag von BeRsErKeR »

Hallo ich habe eine SQL-Datenbank auf die ich per PHP/MySQL zugreife. In der Datenbank gibt es Einträge, die Scriptcode in Textform enthalten. Der Scriptcode ist keine gängige Sprache (es gibt keine Compiler/Interpreter etc dafür).

Solche Skripte haben die Form:

<scriptexpr> <scriptexpr> ...

Also eine beliebige Anzahl von Skriptanweisungen.

Eine Skriptanweisung hat die Form:

<command><N> <params>;

<command> ist ein Befehlsname.
<N> ist entweder nicht vorhanden (was für 1 steht) oder eine Zahl von 2-4. Dies ist die Anzahl der Parameter.
<params> ist eine Liste von Parametern, die mit Kommata getrennt sind (Integer oder String in einfachen Hochkommata).

Dazu kommt eine Hand voll von Spezialbefehlen der Form:

<command> { <scriptexpr> }

<command> ist ein Befehlsname.
<scriptexpr> ist eine Skriptanweisung der oben genannten Form.


Was ich nun tun möchte ist, den Skriptcode aus einer Datenbank lesen (ist kein Problem) und das Skript in PHP "ausführen". Das ich dafür eine Art Mini-Interpreter brauche ist mir bewusst. Die Daten auf denen die Skripte angewendet werden sind in meinen PHP Skripten integriert.

Meine Frage ist nun wie ich die Auswertung der Skripte bzw. Befehle am besten realisieren könnte. Zur Info: Es gibt an die 100 Befehle.

Eine riesiges switch-case mit allen Befehlen erscheint mir nicht geeignet. In C++ gesprochen: Eine Art std::map mit KEY = Befehlsname und VALUE = Funktionspointer wäre meiner Meinung nach schon etwas angenehmer, wobei ich nicht weiß ob und wie sowas in PHP funktioniert. Um 100 Funktionen für jeden Befehl werde ich wohl auch nicht so recht drum rum kommen.

Ich würde gern erstmal wissen, wie man das ganze vielleicht am besten umsetzen könnte. Die Befehle darf man sich nicht als einfache Operationen auf Variable vorstellen.


Ein Beispiel wäre z.B. der Befehl

Str,1;

Dieser erhöht die Stärke eines Charakters um 1. In den PHP-Skripten gibt es dann irgendwo die Variable $Str oder ein Array mit dem Index 'Str', die bei diesem Befehl um 1 erhöht werden muss. Es gibt aber noch viele weitere Befehle, die ganz verschiedene Werte ändern. Letztlich ändern aber alle Befehle nur Werte. Daher dachte ich schon an eine Art Substitution. Beispiel:

Str,x; wird zu $Str = $Str + x;

Das ganze könnte man dann z.B. mit eval() ausführen.


Was ich allerdings noch vergessen habe. Im oben genannten Scriptcode können auch noch if-Anweisungen vorkommen, allerdings ohne else oder elseif. Die Form ist dabei wie in C++, allerdings gibt es im Skript selbst keine Variablen, sondern nur vordefinierte Abfragefunktionen.

Beispiel:

if(getitemcount(356) > 1) { Str,1; }

Das bedeutet z.B., dass die Stärke um 1 erhöht wird, wenn ich vom Item mit der ID 356 mindestens 2 Items besitze.


Sprich ich muss ifs auch berücksichtigen und die Abfragefunktionen ebenfalls in PHP zur Verfügung stellen. Diese könnte ich in PHP aber ggf. genauso wie im Skript nennen um das eval() zu erleichtern. Das if sollte ja theoretisch auch so direkt evaluierbar sein (mit Ausnahme der logischen Operatoren, die im Skript & oder | sind und in PHP and bzw. or).


Also grundsätzlich tendiere ich zu leichter Anpassung bzw. Substitution mit anschließendem eval(). Wäre aber über Hinweise und Meinungen dankbar. Auch in Hinblick auf den Fummelkram mit den Eingabestings. Mir fällt in dem Zusammenhang z.B. strtok ein aber vielleicht gibt es da noch schönere Dinge. Glaub für regexes gabs da in PHP auch paar Sachen. Will nicht alles händisch zusammenbasteln müssen.
Ohne Input kein Output.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [PHP/MySQL] Scriptcode auswerten

Beitrag von Chromanoid »

Du könntest das ganze einfach direkt in PHP Code umwandeln (das Resultat evt. cachen [vielleicht sogar vorkompiliert]). ANTLR könnte dabei hilfreich sein (gibt es afaik allerdings nicht für php) - ansonsten sollte das aber auch relativ einfach mit reg. Exp. möglich sein. (edit: hab gerade gesehen, dass du selbst das ganze schon so überlegst :)) Ansonsten halt einfach alles in eine Art Baum packen und LISP ähnlich abarbeiten. Jeder Befehl (auch if & co.) wird dann von einer eigenen Klasse/Objekt repräsentiert und hat eine einzige Funktion nämlich execute() und die entsprechenden Parameter als Member.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [PHP/MySQL] Scriptcode auswerten

Beitrag von BeRsErKeR »

Danke erstmal für die Antwort.
Chromanoid hat geschrieben:Jeder Befehl (auch if & co.) wird dann von einer eigenen Klasse/Objekt repräsentiert und hat eine einzige Funktion nämlich execute() und die entsprechenden Parameter als Member.
Nun ja mich schreck dabei wie gesagt die große Anzahl an Befehlen ab, da ich ja dann an die 100 Klassen bräuchte und jeweils den Code für das Ausführen. Das ist schon ziemlich großer Schreibaufwand. Daher auch die Überlegung mit dem Umwandeln in PHP Code. Prinzipiell sollte das nicht so aufwendig sein. Es sind dann zwar auch an die 100 Umformregeln, allerdings kann man da vieles in Form von:

$Befehl." = ".$Parameter.";"

machen und spart sich so einen Großteil der Einzelumwandlungen und halt den ganzen Klassen- und Methodenkram. Würde sich dann auf Textsubstitution und eval() beschränken. Das String-Umformen mit Regex wär denk ich auch nicht so schwierig, weil die Parameteranzahl Teil des Befehls ist.

Ich warte mal noch auf weitere Ideen und Hinweise und werd dann eventuell in diese Richtung gehen.
Ohne Input kein Output.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [PHP/MySQL] Scriptcode auswerten

Beitrag von Chromanoid »

Naja jeder Befehl würde ja von einer Befehlsklasse erben. Da käme pro Befehl neben bspw. execute(Context c) also nur "class Xy extends BaseCommand {...};" dazu. Durch die Tatsache, dass man bei new einfach den Klassennamen als String-Variable übergeben kann, sollte man nicht viel Mehraufwand haben. Die geparsten Kommando-Objekt-Bäume sollten imo schneller ausführbar sein als eval (natürlich nur wenn du sie geparst cached).
Evt. könntest du aber auch einmalig alle Scripte in eine große PHP Datei als Funktionen übersetzen und dann mittels Variabel Funktionen ausführen, das sollte am schnellsten gehen.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [PHP/MySQL] Scriptcode auswerten

Beitrag von BeRsErKeR »

Geschwindigkeit spielt keine große Rolle. Es können maximal etwa 18 solcher Skirpte gleichzeitig ausgeführt werden (und das nur einmalig bei einer Änderung, also nicht zyklisch). Diese bestehen meist nur aus einem Befehl, maximal vielleicht aus 6 (ist aber selten). In der Regel werden nur ca. 5-6 Skripte ausgeführt. Daher befürchte ich da keine großen Zeitprobleme. Falls dem beim Testen doch so sein sollte geh ich vielleicht den Weg über Klassen. Ich versuchs momentan erstmal mit eval(), da es für mich momentan am einfachsten und schnellsten zu implementieren ist.

Per Regex filter ich die möglichen Skriptelemente heraus und verarbeite sie dann durch Substitution + eval(). Konnte es leider noch nicht testen, aber ich bin guter Dinge. ;)
Ohne Input kein Output.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [PHP/MySQL] Scriptcode auswerten

Beitrag von BeRsErKeR »

Hab ein paar Tests gemacht. Das Verarbeiten eines Skriptes mit einem Befehl dauert 0.1-0.3 MIllisekunden. Da es maximal wie gesagt weniger als 20 Skripte mit maximal 5-6 Befehlen, sprich 120 Befehle insgesamt werden können, wären das im worst case 36 Millisekunden. Damit kann ich leben. Hab auch mal geguckt ob das direkte Zuweisen zu einem Array schneller ist, als eval(). Das war zwar der Fall, aber es handelte sich um etwa 0.02 Millisekunden (2.4 Millisekunden insgesamt im sehr unwahrscheinlichen worst case).
Ohne Input kein Output.
Antworten