Technik, Gothic und Anderes

Technik ist Spiel, Gothic ist ernst und Zeit hat man zuviel

Archiv für 'Theorie und Schnipsel' Kategorie


Automatisches und mehrfaches submitten von Formularen

Geschrieben von skaldrom am 30. July 2008

Wirre Gedanken

FormularDieser Beitrag ist dem Titz gewidmet. Dem Titz, der sich aufgeregt hat :pirate-grumble: , obwohl es gar nicht nötig gewesen wäre und der sich nun mit einer gewissen Teilnehmerredundanz anfreunden muss. Hauptsache ist doch, das PHP fliesst und die Variablen bleiben sauber… Und ein Bierchen würde ich auch noch springen lassen :bier:

Eine wichtige Frage zu Beginn: Wieso sollten wir denn automatisch und mehrfach Formulare submitten wollen? Hmm, um den Titz zu ärgern? Weil wir es können? Weil man manchmal tun muss, was man tun muss? Weil man seine 84 Kinder an einem elektronischen Fussballturnier anmelden will :laola: (hat eigentlich schon jemand bemerkt, dass ich neue Smilies und unglaublich Freude daran habe?)? Oder weil man über einen Wettbewerb gestolpert ist, der ebendies nicht verbietet (also das Mehrfachsubmitten, nicht das Kinderanmelden oder die neuen Smilies) und der kein Captcha hat (vielleicht, weil es der Titz vergessen hat)?

Nachtrag 31.07.2008: Schenken mir doch so unglaublich nette Mitarbeiter einer Versicherung heute morgen am Bahnhof einen Müsliriegel. Und auf diesem eher gesunden Teil hat es, ja rate, oh wissbegieriges Volk, einen Wettbewerb. Ob der Titz wohl am Abend für eine andere Firma weitercoded? Ich werde mich auf jeden Fall während der Zugfahrt mal damit befassen :computer: .

Vorgehen

Erster Schritt: Selenium IDE

Man könnte nun wie wild losprogrammieren, oder aber einen einfacheren Weg wählen. Ein guter Startpunkt für automatisiertes Browsen generell ist die Selenium IDE. Dieses geniale Teil für den Firefox zeichnet wie ein Macrorecorder alles auf, was im Browser gemacht wird. Hat man die Teilnahme beim Wettbewerb einmal so aufgezeichnet, so müssen nur noch die click’s, die das Form absenden, durch clickAndWait’s ersetzt werden, damit vor dem Weiterausfüllen (bei mehrseitigen Formularen) auf die neue Seite gewartet wird. Es empfiehlt sich, eine Abschlussüberprüfung als letzten Schritt hinzuzufügen, um um kontrollieren zu können, ob die Kinder erfolgreich angemeldet wurden (markieren des “Dankeblabla”, dann rechte Maustaste und assertTextPresent).

Ein Wettbewerb über 2 Seiten. Aufgezeichnet und bearbeitet mit der Selenium IDE.

Ein Wettbewerb über 2 Seiten. Aufgezeichnet und bearbeitet mit der Selenium IDE.

Diesen Testcase kann man nun abspeichern und eigentlich immer wieder ausführen. Ein Klick reicht und Firefox rasselt alles schön durch. Den Namen leicht verändern kann man durch Editieren des Skripts…

Für den zweiten Schritt sollte man das Testscript als PHP exportieren.

Zweiter Schritt: Selenium RC

Die Selenium RC Komponente kann den Browser fernsteuern und so ferngesteuert am Wettbewerb teilnehmen. Um sie unter Linux Debian zum Laufen zu kriegen, war ein Bisschen Gemurkse notwendig.

Lesen Sie den Rest dieses Beitrages »

Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel | 2 Komentare »

Mit PHP einen Monat mit verlinkbaren Daten anzeigen

Geschrieben von skaldrom am 28. June 2008

CalendarFür eine Applikation, in der man Ressourcen reservieren kann, wollte ich ein Kalender mit verlinkbaren Tagen anzeigen (grad wie im Meeting Room Booking System). Da ich aus dem Alter raus bin, in dem man alles selber machen muss und ausserdem eine PHP-Datumsfunktionsphobie (PHPYpiresiaChronophobia) entwickelt habe, wollte ich eigentlich etwas Fertiges verwenden. Es gibt vorallem Kalender in JavaScript, ein Tutorial das den Kommentaren nach nicht funktioniert (und das mittlerweile vom Web verschwunden ist), Scripts ohne Ausgabebeispiele, Riesenmonster (deren Anwendungsbeispiele mehr Code haben als eine Eigenimplementation) oder Kalender, die zwar gut sind, aber irgendwie nicht gepasst haben (I18n, …). Ich möchte auch nix mit Ajax, Sigolin und Meister Propper, denn es soll eine Enterprise-Applikation geben, und da ist JavaScript halt nicht so opportun (und erspart mir wieder ein paar graue Haare mehr). Aber vor allem (aber das verschweige ich hier) hat das wie eine spannende Aufgabe ausgesehen, und als Kontrollfreak will ich es eben doch selber gemacht haben :-D .

Ziel

Das Ziel ist es einen Kalender zu erhalten, der die Wochen anzeigt, bei dem ein Tag (Event) markiert werden kann und das heutige Datum speziell ausgezeichnet ist. Er sollte also in etwa so aussehen (die Monatsnamen und Namen der Wochentage sollten sich auch noch der Sprache anpassen):

PHP-Kalender

Man sollte entweder ein Monat und ein Jahr übergeben können oder einfach nichts, wobei dann der aktuelle Monat und das aktuelle Jahr verwendet werden.

Vorgehen und Implementation

Ich habe mich entschlossen, dem Enterprisefassadefrontsidedecontrollerkurtmitgurtgimmeabreak-Pattern zu folgen… Quatsch, meine Gewohnheit und die Stimmen in meinem Kopf haben mich dazu gezwungen, den Kalender in zwei verschiedenen Funktionen zu implementieren. PHP hat ein absolut geniales Array-Handling, und wenn ich an solchen datenmanipulierenden Aufgaben arbeite habe ich mir angewöhnt, zuerst die reinen Daten in einem (mehrdimensionalen, ev. assoziativen) Array abzubilden. Dies hat den grossen Vorteil, dass ich die aufbereiteten Daten nicht nur für die HTML-Ausgabe, sondern auch von anderen Funktionen aus benutzen kann. Das Ziel wäre ein Array, dass auf der einen Dimension die Wochen und auf der Anderen die Wochentage hat. Man nehme den ASCIIstift hervor und zeichne ein Beispiel für Juni 2008:

[22] => {   '',   '',   '',   '',   '',   '',  '1'}
[23] => {  '2',  '3',  '4',  '5',  '6',  '7',  '8'}
[24] => {  '8',  '9', '10', '11', '12', '13', '14'}
...
[27] => { '31',   '',   '',   '',   '',   '',   ''}

Die Benamsung ist wie folgt:
PHP-Kalender benamst
Lesen Sie den Rest dieses Beitrages »

Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel | Keine Kommentare »

AIML: Intelligenz im XML

Geschrieben von skaldrom am 10. June 2008

BrainWenn man schon keine eigene Intelligenz besitzt, ist man froh, dass es sie auch in künstlicher Form gibt. Bis vor einiger Zeit wurde ziemlich proprietär rumgewurstelt, aber nun gibt es AIML, die Artificial Intelligence Markup Language die mit XML und Standardisierung das Verwenden unter verschiedenen Plattformen möglich macht. XML und Intelligenz ist also doch nicht per se ein Widerspruch.

Interessant ist das Ziel dieser Bemühungen (wie auf Pandorabots beschrieben):

Inhalte zu erstellen, die den Besucher dazu veranlassen so lange wie möglich mit dem Bot zu reden.

Auf der Basis von AIML wurden verschiedene Interpreter für verschiedene Programmiersprache geschaffen, Inhaltsdateien erstellt, die alle von der offiziellen Homepage oder der Tools Page heruntergeladen werden können.

AIML als XML (Gimme Code!)

AIML ist ziemlich komplex. Es gibt die Möglichkeit einer Unterteilung in Themen, der Extraktion von Mustern, der spezifischen Auswahl der Antworten etc, etc… Die englischen Übersichten und Tutorials gehen tiefer in die Materie.

AIML Tags

Die wichtigsten Tags von AIML:
Lesen Sie den Rest dieses Beitrages »

Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel | 3 Komentare »

PHP_SELF ist böse! Potentielles Cross Site Scripting (XSS)!

Geschrieben von skaldrom am 7. May 2008

Was haben wir gelernt?

EvilJa, uns wurde gelehrt, dass man wenn immer möglich nicht Dateinamen direkt, sondern eine Variable angeben soll, die für den Dateinamen steht. Warum konnte mir zwar noch niemand so genau sagen, aber ich nehme an, dass es darum geht, dass der Dateinamen oder der Pfad ändern könnte. So habe ich ziemlich oft ganz brav geschrieben:

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method ="post">
...
</form>

Und (zum Glück) bin ich nicht der Einzige. Eine kleine Suche auf Googles Codesearch hat gezeigt, dass mindestens Mambo, PHPMyFAQ, Einige Wordpressthemes und viele mehr dasselbe Problem haben. Ich bin bei Weitem auch nicht der Erste, der über Probleme mit dieser Technik erfahren und darüber geschrieben hat.

Problem? mit $_SERVER['PHP_SELF']?

Lasst mich ausholen: Der Apache Webserver hat eine Option AcceptPathInfo, welche standardmässig auf On ist. Mit dieser Option mappt der Apache beliebig lange Pfade auf Dateien, sofern diese irgendwie Bestandteil des Pfades sind. Der Rest wird in Umgebungsvariablen mitgegeben.

Gimme Code

Nehmen wir an, es gäbe eine Datei /subdir/mypath.php welche so aussieht:

<?php
echo "<pre>";
echo "REQUEST_URI: ".$_SERVER['REQUEST_URI']."\n";
echo "PHP_SELF:    ".$_SERVER['PHP_SELF']."\n";
echo "SCRIPT_NAME: ".$_SERVER['SCRIPT_NAME']."\n";
echo "</pre>";
?>

Bei einem Aufruf von: http://localhost/subdir/mypath.php/additional/stuff/nonsense.php?para=4 mappt Apache netterweise alles auf unsere Datei http://localhost/subdir/mypath.php und verstaut den Rest im $_SERVER Array. Die Ausgabe ist:

REQUEST_URI: /subdir/mypath.php/additional/stuff/nonsense.php?para=4
PHP_SELF:    /subdir/mypath.php/additional/stuff/nonsense.php
SCRIPT_NAME: /subdir/mypath.php

PHP_SELF übernimmt also den ganzen Krempel und würde ihn bei unserem Form auch so darstellen. Angenommen, wir haben ein PHP-Script mit der URL http://localhost/contact/myform.php mit folgendem Inhalt:
<form action=”<?php echo $_SERVER['PHP_SELF']; ?>” method =”post”>

Ruft man dieses nun mit folgender URL auf (die aufwändiger als notwendig konstruiert und des besseren Verständnisses wegen nicht URL-encodiert ist):
http://localhost/contact/myform.php/”></form>Hier ein Javascript: <script>alert(’gotcha’);</script><form action=”/contact/myform.php
erhält man:
<form action=”/”></form>Hier ein Javascript: <script>alert(’gotcha’);</script><form action=”/contact/myform.php” method =”post”>

Also vollkommen gültiges HTML (sogar das Form funktioniert) mit fremdbestimmbaren Seiteninhalt. Das ist ja wohl hässlich…

Theorie! Gib mir Praxis!

Ich weiss nicht, wie lange folgende Links funktionieren, beziehungsweise diese Sites anfällig für diese Art von XSS sind:

Digital Postcard (Kein XSS, aber mein Text :-) ):
Postcard XSS

Multimediatreff:
Multimediatreff

Jobs. ch (nicht im Form, dafür mit hohem PageRank):
Jobs.ch

Was nutzt das dem bösen Hacker?

Text in Fremdpages einbauen, Phishing, Indentitätenklau und noch einiges Weiteres. Ein Folgeartikel wird mindestens eine Anwendung zeigen.

Was tun?

Ganz einfach: Das oft verschmähte $_SERVER['SCRIPT_NAME'] verwenden!!!

BTW: Viele Variablen in $_SERVER sind anfällig, aber alles muss ich ja auch nicht verplappern, oder?

Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel | Keine Kommentare »

Kleine SEO-Tools mit Quelltext in PHP

Geschrieben von skaldrom am 20. March 2008

ToolsEs gibt viele Sites, die online Tools für die Suchmaschinenoptimierung (SEO) anbieten. Es gibt Handverlesene Verzeichnisse von Linkvendor, Eigenentwicklungen von Ravenseo und riesige Zusammenstellungen von den Fachinformatikern, dem Website Spy, dem SEO-Chat und der SEO-Company. Wieso braucht es denn noch mehr? Ganz einfach: Google Schweiz wird - extrem überraschenderweise - nirgends so richtig berücksichtigt. Ausserdem will ich auf der Kommandozeile arbeiten und den Quellcode möchte ich auch, um die Bewertungen nachzuvollziehen und um darin herumzuwurschteln.

Naja, dann hab ich halt mal angefangen. Das Resultat gibts auch zum Download: PHP SEO-Tools.
Lesen Sie den Rest dieses Beitrages »

Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel | Keine Kommentare »

Active Record Pattern in PHP

Geschrieben von skaldrom am 12. March 2008

StorageIn PHP gibt es verschiedene Implementierungen des Active Record Patterns. Auch wenn es uns nimmer so auffällt, die objektorientierte Welt des Codes und die relationale Welt der Daten sind zwei verschiedene Paradigmen, und es braucht unheimlich viel Leim um sie zusammenzukleben. Objektorientierte Datenbanken entwickeln sich, sind jedoch noch nicht Standard (um es mal vorsichtig auszudrücken). Das Active Record Pattern hilft uns mit ein Bisschen Standard-Klebe.

Mit diesem Pattern können Daten aus der Datenbank gesucht und direkt in Objekte übergeführt werden. Änderungen an den Objekten und das Speichern bewirken, dass diese Änderungen auch in die Datenbank übernommen werden.

Ich habe mich für MyActiveRecord von Jake Grimley entschieden, weil es sauber implementiert, nicht zu gross und trotzdem nicht featurearm ist. Die Dokumentation ist ziemlich gut und reicht aus um zu starten.

Benutzung von MyActiveRecord

Suchen und finden

Der Dreh- und Angelpunkt dürfte die Funktion FindAll($class, $where=0, $orderby=’id ASC’, $limit=10000, $offset=0) sein. Sie liefert eine Kollektion von Objekten der entsprechenden Klasse zurück:

foreach (MyActiveRecord :: FindAll('thing') as $thing) {
  echo "I am a {$thing->name}!<br/>\n";
}

Lesen Sie den Rest dieses Beitrages »

Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel | Keine Kommentare »

Drupal mit neuen Google AdSense Werbeblöcken (Serverbasiert)

Geschrieben von admin am 16. November 2007

Neues AdSense


(Affilliate Link :-) ) sind neuerdings Serverbasiert. Das heisst: Aussehen, Inhalt, etc kann grösstenteils von der AdSense-Seite aus gemanaged und muss nicht mehr mühsam von Hand auf jeder Seite eingepflegt, geftpt und gecheckt werden. Das geniale Drupal AdSense Modul beherrscht diese neue Variante leider (noch) nicht von Haus aus. Mit einem kleinen Patch geht das aber.

Vorgehen

  1. Die Datei adsense.module mit diesem Patch so patchen, wie in diesem Beitrag beschrieben.
  2. Auf der Google AdSense Seite AdSense-Setup → Anzeigen Verwalten aufrufen und eine neue Anzeige designen.
  3. Den Code anzeigen lassen und die Slot-Nummer notieren. Es sollte etwas sein wie 2666876213.
  4. In Dupal als Administrator Administer → Site configuration → Google AdSense aufrufen und Custom Channels aufklappen.
  5. Die Slotnummer in einen Channel schreiben.
  6. Diesen Channel beim Block für die Anzeige einsetzen.
  7. Warten… Und sich freuen…
Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel, Web | Keine Kommentare »

Einfache Animationen auf der Konsole mit PHP (1-Dimensional)

Geschrieben von skaldrom am 7. November 2007

AnimationWenn man mit PHP Konsolenapplikationen schreibt, wäre es manchmal schön, eine pfundige Ausgabe mit etwas Bewegung erzeugen zu können. Solche Kleinstanimationen eignen sich auch für Aufgaben beim Erlernen von PHP, denn sie sind sehr unaufwändig und es tut sich trotzdem was.

Diese Ausgaben sind Eindimensional (auf einer Linie) und funktionieren unter Linux und Windows. Ich warte sehnsüchtig auf die PHP-Languagebindings für die aalib oder libcaca :-)…

Der Trick ist der Carriage Return (CR), der den Cursor an den Anfang der Zeile setzt, aber nicht vertikal weiterscrollt. in PHP wird dieses Zeichen mit \r codiert. Grundsätzlich ist der Ablauf wie folgt:

Bilderfolge in ein Array rendern
Solange man Lust hat:
    Zeige nächstes Bild
    Warte
  }
}

Unter Linux können zur weiteren Effektsteigerungen auch noch ANSI-Escapesequenzen verwendet werden. Mit diesen kryptischen Dingern kann man den einzelnen Zeichen Vorder- und Hintergrundfarbe verpassen und verwirrendes einschalten wie etwa ein Blinken. ESCAPE ist in PHP beispielsweise 33 in oktal und wird mittels \033 dargestellt.

Nun, zeig mal Code!

<?php
// Render Movie
$frames=array();
// 10 images for this movie
for($i=0;$i<10;$i++) {
    // The background consits of blue underscores
    $frame=array_fill(0, 10, "\033[34m_\033[0m");
    // One actor is a red star
    $frame[$i]="\033[31m*\033[0m";
    // The other a green dot
    $frame[9-$i]="\033[32m.\033[0m";
    // Join Background and actors
    $frames[]=join("",$frame);
}

// Output
for($i=0;$i<20;$i++) {
  foreach($frames as $frame) {
        // Rewind cursor and show frame
        print "\r".$frame;
        // Sleep a bit, because nights are hard these times...
        usleep(100000)
  }
}
print "\n";
?>
Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel | Keine Kommentare »

Erstellen eines Timers in Xoops

Geschrieben von skaldrom am 1. November 2007

Xoops ist ein geniales CMS, auch wenn es in letzter Zeit durch administrative Querelen nicht sehr gute Schlagzeilen gemacht hat. Wir benutzen es in einer erweiterten Version als Intranet.

Nun braucht ein Modul plötzlich unendlich lange um sich darzustellen. Das hindert unseren rasanten Arbeitsfluss und darum muss darum korrigiert werden. Statt rumzufrickeln lohnt es sich, die Sache seriös anzugehen.

Xoops bietet eine sehr gute Debugfunktion an: Adminsitration → Systemeinstellungen → Voreinstellungen → Allgemeine Einstellungen → Debug-Modus kann auf PHP-Debug gesetzt werden. Danach werden unten an der Seite viele Infos dargestellt, unter Anderem SQL-Befehle und Timer.

Xoops Debug

Genau solche Timer kann man selber einfach erstellen. Zuerst muss der XoopsLogger eingebunden werden:

include_once(XOOPS_ROOT_PATH . '/class/logger.php');

Um einen Timer zu starten:

$xoopsLogger->startTime( 'absence_count_query' );

Um ihn wieder zu stoppen:

$xoopsLogger->stopTime( 'absence_count_query' );

Diese Timer wird nun - wie oben ersichtlich - wunderschön in die Debugfunktion eingereiht.

Teile und geniesse:
  • Technorati
  • del.icio.us
  • MisterWong
  • Digg
  • StumbleUpon
  • blogmarks
  • Furl
  • Simpy
  • Spurl
  • YahooMyWeb

Ähnliche Artikel

Eingeordnet in Theorie und Schnipsel, Web | 1 Kommentar »

Eine eigene Programmiersprache erschaffen? Lexer und Parser in PHP!

Geschrieben von skaldrom am 25. October 2007

Ich will Gott sein!

Paper SnippetsWer träumt nicht davon: Eine eigene Programmiersprache, denn der Syntax und das Wort sind Ausdruck! Einen Schritt weiter gehen und vom Programmiersprachenanwender zum Programmiersprachenerschaffer aufsteigen! Auch dies ist nun möglich in PHP, doch leider nur mit minimaler Dokumentation.

Ich gehe davon aus, dass die Leserin/Der Leser Grundlagen im Compilerbau besitzt. Ansonsten müsste man sich diese noch aneignen. Compilerbau ist rekursiv und somit göttlich! *schwärm*.

Das Beispiel

Ich möchte einen Interpreter bauen für normale, arithmetische Ausdrücke wie 9*(8+6)-2/(-4). Klar könnte man diesen einfach durch eval hauen, aber erstens macht das nicht so viel Spass und zweitens ist dieses Beispiel sowas wie das Hello World des Compilerbaus.

Als BNF habe ich folgendes vor:

<Expression> ::= '+' <Expression> // Unäres + (Vorzeichen)
<Expression> ::= '-' <Expression> // Unäres - (Vorzeichen)
<Expression> ::= <Term>
<Expression> ::= <Expression> '+' <Term>
<Expression> ::= <Expression> '-' <Term>
<Term> ::=  <Factor>
<Term> ::= <Term> '*' <Factor>
<Term> ::= <Term> '/' <Factor>
<Factor> ::=  NUMBER // Ok, hier hab ich abgekürzt ;) Soll der Lexer erledigen...
<Factor> ::= '(' <Expression> ')'

Ein Problem stellen die unären Plus- und Minusoperatoren dar. Sie besitzen das gleiche Symbol, nicht aber die gleiche Priorität wie ihre binären Kollegen. Lemon erlaubt keine änderung der Priorität nach Regeln und so funzen jetzt halt auch Konstrukte wie —+++—+1…

Die Werkzeuge

Ich verwende PHP_LexerGenerator, der kompatibel zum re2c Format ist und den PHP_ParserGenerator der in grossen Teilen dem LEMON Parser Generator entspricht. Heruntergeladen werden können sie mittels folgenden Zeilen, die allerdings unter Umständen noch eine Anpassungen der Versionsnummer brauchen:

pear install channel://pear.php.net/PHP_ParserGenerator-0.1.5
pear install channel://pear.php.net/PHP_LexerGenerator-0.3.4

Als einziges, weiteres Beispiel für diese Libs ausserhalb der Doku habe ich nur dieses Drupalmodul gefunden.

Die Realisierung

Der Lexer

Für den Lexer muss eine plex Datei erstellt werden. Sie beinhaltet den Rumpf des Lexerobjekts und die lexikalischen Regeln:

TermLexer.plex

<?php
class TermLexer
{
    private $data;
    public $counter;
    public $token;
    public $value;
    public $node;
    public $line;
    private $state = 1;

    function __construct($data)
    {
        $this->data = $data;
        $this->counter = 0;
        $this->line = 1;
    }

/*!lex2php
%input $this->data
%counter $this->counter
%token $this->token
%value $this->value
%line $this->line
number = /[0-9]+(\.[0-9]+)?/
multiplication = /\*/

division = @/@
plus = /\+/
minus = /\-/
openP = /\(/
closeP = /\)/
other = /./
*/
/*!lex2php
%statename START
multiplication {
  $this->token = TermParser::TP_MULTIPLICATION;
  //echo "multiplication: ".$this->value."\n";
}
division {
  $this->token = TermParser::TP_DIVISION;
  //echo "division: ".$this->value."\n";
}
plus{
  $this->token = TermParser::TP_PLUS;
  //echo "plus: ".$this->value."\n";
}
minus{
  $this->token = TermParser::TP_MINUS;
  //echo "plus: ".$this->value."\n";
}
openP {
  $this->token = TermParser::TP_OPENP;
  //echo "openP: ".$this->value."\n";
}
closeP {
  $this->token = TermParser::TP_CLOSEP;
  //echo "closeP: ".$this->value."\n";
}
number {
  $this->token = TermParser::TP_NUMBER;
  //echo "number: ".$this->value."\n";
}
other {
  return false;
}
*/

}

So richtig laufen tuts aber noch nicht, da er Konstanten des Parsers benötigt. Die stehen erst zur Verfügung wenn wir den Parser auch gebaut haben.

Der Parser

Der Parser wird vom Lexer mit Tokens gefüttert. Die Notation im Lemon-Style unterscheidet sich von Lex und Yacc, ist aber durchaus logisch. Hier der ganze Code, mal hingeknallt:

TermParser.y

/* This is an example for a Parser in PHP */
%name TP_
%declare_class {class TermParser}
%include_class
{
    // states whether the parse was successful or not
    public $successful = true;
    public $retvalue = 0;
    private $lex;
    private $internalError = false;

    function __construct($lex) {
        $this->lex = $lex;
    }
}

%token_prefix TP_

%parse_accept
{
    $this->successful = !$this->internalError;
    $this->internalError = false;
    $this->retvalue = $this->_retvalue;
    echo "WORKED!!\n\n";
}

%syntax_error
{
    $this->internalError = true;
    echo "Syntax Error on line " . $this->lex->line . ": token '" .
        $this->lex->value . "' count ".$this->lex->counter." while parsing rule: ";
    foreach ($this->yystack as $entry) {
        echo $this->tokenName($entry->major) . '->';
    }
    foreach ($this->yy_get_expected_tokens($yymajor) as $token) {
        $expect[] = self::$yyTokenName[$token];
    }
    echo "\n"
    throw new Exception('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN. '), expected one of: ' . implode(',', $expect));
}

%left PLUS MINUS.
%left MULTIPLICATION DIVISION.

start(res)       ::= expression(expr). { res = expr; }

/* Unary minus or plus */
expression(res)  ::= PLUS expression(e). { res = +e; }
expression(res)  ::= MINUS expression(e). { res = -e; }

/* The common stuff */
expression(res)  ::= term(t). { res = t; }
expression(res)  ::= expression(e1) PLUS term(t2). { res = e1+t2; }
expression(res)  ::= expression(e1) MINUS term(t2). { res = e1-t2; }

term(res)        ::= factor(f). { res = f; }
term(res)        ::= term(t1) MULTIPLICATION factor(f2). { res = t1*f2; }
term(res)        ::= term(t1) DIVISION factor(f2). { res = t1/f2; }

factor(res)      ::= NUMBER(n). { res = n; }
factor