options { name = wert; } PARSER_BEGIN(name) package pfad; import pfad; public class name { ... } PARSER_END(name) Tokendefinition Regeln
Jede Definitionsdatei kann mit einer "options" - Anweisung beginnen, welche optional ist. In ihr wird das globale Verhalten des Parsers festgelegt. In der Regel leisten die Standardeinstellungen gute Dienste, sodass auf den Teil verzichtet werden kann
Zwingend notwendig hingegen ist der darauf folgende Block, der mit "PARSER_BEGIN" eingeleitet und mit "PARSER_END" abgeschlossen wird. In ihm können zusätzliche, javaspezifische Anweisungen gemacht werden, die in den Parser übernommen werden. Obligatorisch ist dabei eine entsprechende Methode, die den Zugriff auf den Parser ermöglicht. In der Regel bedient man sich einer "static void main" - Methode, falls der Parser über die Kommandozeile aufrufbar sein soll.
Im Anschluss folgen noch die Tokendefinition, sowie die Ableitungsregeln, ohne die der Parser nicht sinnvoll einsetzbar wäre
Der grundsätzliche Aufbau einer Grammatikregel in JavaCC ist nachfolgend definiert.
void metasymbol() { ... // Code der am Anfang der Methode steht } { <Terminal> { ... } | <Terminal1> <Terminal2> { ... } | ( <Terminal1> | <Terminal2> ) { ... } | [ <Terminal> ] { ... } | ( <Terminal> )? { ... } | ( <Terminal> )+ { ... } | ( <Terminal> )* { ... } }
Jedes Nichtterminalsymbol wird durch eine Javamethode repräsentiert. In ihr werden die Ableitungsregel beschrieben. Terminalsymbole, zuvor mit Hilfe von Token definiert, können hier ebenso zum Einsatz kommen, wie auch Nichtterminalsymbole. Letztere müssen als Javamethode realisiert werden und können entsprechend aufgerufen werden. Das eben gezeigte Beispiel entählt nur Terminalsymbole. Im Kapitel JavaCC in der Praxis, werden wir uns komplexeren Grammatikdefinitionen widmen
Der erste Block beinhaltet Javacode, der vor dem eigentlichen Ableitungsschritt ausgeführt werden soll. Hierzu zählen z.B. Variablendefinitionen, die dann im weiteren Verlauf genutzt werden können
Eine Besonderheit von JavaCC ist die Möglichkeit, Javacode in die Ableitungsregeln zu integrieren. Erreicht wird dies durch "{ ... }" Blöcke. Der darin enthaltene Code wird unmittelbar nach der jeweiligen Ableitungsregel ausgeführt.