Jaaaa, ich habe es geschafft! Nach nur einem halben Jahr ist mir endlich eine Sprache eingefallen, die man in einem Parsercontest verwenden kann! Ich bin so toll etc.
Also gut, kommen wir zum Contest. Es geht in diesem Contest darum, eine Datei einzulesen, zu parsen und zu interpretieren.
Besprechen wir erst mal die Grundlagen:
Ein Parser entscheidet, ob der Input zur Sprache einer bestimmten Grammatik angehört. Das klingt jetzt kompliziert, ist aber relativ einfach: Eine Grammatik ist eine Reihe von Regeln, die bestimmen, wie eine Sprache auszusehen hat. Eine Sprache ist die Menge aller Zeichenketten, die zu der Grammatik passen.
Beispielsweise könnte ich folgende Grammatik aufstellen: Alle Wörter bestehen aus dem Buchstaben A, der N-mal aneinandergereiht wird, wobei N zwischen 0 und 5 liegen kann. Das Wort "AAAA" entspricht dieser Grammatik, das Wort "" auch. "AAAB" tut es nicht, weil die Sprache kein B erlaubt; "AAAAAA" paßt auch nicht, weil das A nur fünf mal vorkommen darf.
Der Parser hat die Aufgabe, herauszufinden ob der Input zur Spache paßt oder nicht. Er wird in Compilern und Interpretern normalerweise als erste Routine verwendet - immerhin macht es wenig Sinn, Code verarbeiten zu wollen, der gar nicht korrekt ist. (Dieser Teil ist für den Contest wichtig.)
Ein Interpreter ist ein Programm, das Programme (die nicht in Maschinencode vorliegen) einliest und ausführt. Das war's schon.
Also gut, wir haben die Grundlagen durch, es wird Zeit für den eigentlichen Inhalt des Contests. Die Aufgabe ist, einen Interpreter nach bestimmten Regeln zu schreiben.
Diese Regeln müssen befolgt werden.
- Der Input muß aus einer Datei einlesbar sein; andere Eingabemethoden sind optional
- Die erste Zeile beinhaltet einen Text, der ausgegeben werden soll. Im Text können sich Variablen im Format %Variablenname% befinden
- Alle darauffolgenden Zeilen beinhalten Variablendefinitionen im Format %Variablenname%:Wert|Wert|Wert...
- Alle Variablen sind Arrays von Strings. Wenn eine Variable irgendwo verwendet wird, wird ein zufälliger Wert aus der Variablendefinition verwendet
- Variablennamen sind alphanumerische Zeichenketten mit einer Länge von 1 bis 255.
- Nicht abgeschlossene Variablen sind Fehler. Beispiel: Ich bin ein %ding
- % wird vor | ausgewertet
- Jede Variable darf nur einmal definiert werden
- Variablen dürfen Verweise auf weitere Variablen beinhalten. Eine Variable darf auf sich selbst verweisen, aber nicht in jedem Wert einen Verweis auf sich selbst beinhalten (es muß also mindestens einen Wert geben, in dem die Variable nicht auf sich selbst verweist)
- Es darf Verweise auf Variablen geben, die nicht definiert sind. In diesem Fall ist der Variablenname mit Prozentzeichen unverändert zu übernehmen
- Input, der nicht den Regeln entspricht ist als solcher kenntlich zu machen
Das hier war mal in der Spezifikation, wurde aber aus Gründen der Verarbeitbarkeit optional gemacht:
- Variablennamen achten auf Groß- und Kleinschreibung. %bla% und %BLA% sind unterschiedliche Variablen
- Um ein Prozentzeichen auszugeben muß man einen Backslash davorsetzen (\%). Wenn man also ausgeben will %bla% ist <Inhalt von %bla%>, dann steht im Input \%bla\% ist %bla%. Wenn man einen Querstrich schreiben will, dann verwendet man auch einen Backslash (\|). Um eine Raute zu schreiben verwendet man - Überraschung - einen Backslach (\#). Um einen Backslash zu schreiben verwendet man einen doppelten Backslash (\\). Es ist dem Entwickler überlassen, die gängigen Backslash-Kombinationen wie \n, \t, \b und \r zu implementieren. Jede Backslashkombination, die keinen Sinn macht ist als Fehler zu melden
- Leerzeilen sowie Zeilen, die mit # anfangen, sind zu ignorieren. Whitespace (Leerzeichen, Tabs) wird am Anfang von Zeilen ignoriert, überall sonst nicht
Dazu kommen dann noch folgende Verhaltensweisen, die wünschenswert aber nicht notwendig sind:
- Das Programm kann Zeilenenden in allen drei Formaten (Unix/DOS/Mac) erkennen
- Es ist nicht möglich, das Programm durch beschädigten Input zum Absturz zu bringen oder es in eine Endlosschleife zu schicken (was mit korrektem Input durchaus möglich sein kann)
Allgemeine Konditionen
Der Contest läuft ab sofort und endet Ende April.
Erlaubt sind sämtliche Sprachen, die Programme oder Skripte müssen entweder auf Windows oder *nix lauffähig sein; natürlich muß der Quellcode offengelegt werden - ob unter einer Open Source-Lizenz oder kommentarlos als "wer's will soll's nehmen" bleibt euch überlassen. Da Public Domain in Deutschland urheberrechtlich nicht erlaubt ist ist die zlib-Lizenz vielleicht eine Überlegung wert, wenn man den Source ganz offiziell freigeben will.
Bewertet wird von den Usern, per Abstimmung. Es sollte dabei aber darauf geachtet werden, ob der Interpreter sich auch an die Spezifikation hält.
Die Sieger erhalten das tolle Gefühl, gewonnen zu haben. Vielleicht kann ich Chocwise noch einen Sonderrang aus den Rippen leiern - ich verspreche aber nichts.
Parsergeneratoren wie flex oder bison dürfen nicht verwendet werden. Ein bißchen Arbeit muß man schon selbst machen. ;)
Beispiele
Zum Schluß gebe ich noch ein paar Beispiele für Dateien, die der oben genannten Sprache entsprechen:
Diese einfache Datei kann als Output entweder Ich habe einen Hund. oder Ich habe eine Katze. erzeugen.
Hier haben wir ein Beispiel für einen Selbstverweis. Am Ende von %weiter% ist ein leerer Wert, der die Verarbeitung irgendwann aufhören läßt. Ein Beispiel für Output wäre: OMG LOL!!!!11!1!!11111!!1
Das hier sollte der Interpreter mit einer Fehlermeldung quittieren, weil die Variable in jedem Wert einen Selbstverweis enthält.
Auch wenn die Variable %tot% nirgends verwendet wird muß der Interpreter den Input zurückweisen, wenn eine derartige Definition drinsteht.
Diese Version funktioniert: Zeilen mit # am Anfang gelten als Kommentare; der Output wäre also %tot%.
Dieser Input ist mit dem letzten identisch, was die Verarbeitung angeht: Whitespace am Anfang von Zeilen wird ignoriert.
In der zweiten Zeile fehlt ein %. Auch davon sollte dem Interpreter schlecht werden.