[Ebene höher] [Zurück] [Weiter] [Inhalt] [Seitenende]
Die unten angegebene Notation der
kontextfreien Grammatik ist im Handbuch in einer lesbareren Darstellung zu finden. Der
erste optionale Teil der Grammatikdatei, der Modul-Header, ist
ein in { } eingeschlossener Haskell-Codeteil. Hier
sind u.a. Importierungen und Fixity-Anweisungen für Operatoren
möglich.
| Header | Code | |
| Code | { Haskell } |
Anschließend folgt ein Direktiven-Teil. Hier wird der Name der erzeugten Parserfunktion, der Typ der Tokens und die einzelnen Tokenmatches festgelegt.
| Directives | { Directive } |
Lucky kennt die folgenden Direktiven:
| %name varid | bestimmt den Namen der erzeugten Parserfunktion. Der Typ dieser Funktion ist gegeben durch String -> [ %tokentype ] -> result, wobei result durch den Codeteil des Startsymbols der Grammatik (s.u.) gegeben ist. Das erste Argument (z.B. ein Dateiname) wird in jeder Alternative über den Platzhalter $0 weitergereicht. Fehlt die Direktive %name, ist der Name der Funktion luckyParser. | ||||||
| %tokentype Code | Bestimmt den Typ der Eingabetokens und damit der Parserfunktion (s.o.). Dieser muß mit den Tokenmatches (s.u.) typisierbar sein. Fehlt die Direktive %tokentype wird {[Char]} verwendet. | ||||||
| %token Matches | Hier werden
die Terminalsymbole der Grammatik definiert. Ein Terminal
ist ein Pattern, das gegen Tokens des Eingabetokenstroms
gematcht wird.
Ist das Patternmatching erfolgreich, dann konnte das Terminalsymbol erfolgreich geparst werden. Rückgabe ist in der Regel das gematchte Token. Dieses kann aber auch den Platzhalter $$ enthalten. Rückgabe ist dann die entsprechende projizierte Komponente des Patterns. Zum Beispiel: {
data Token = TVarid String
TComma
}
%tokentype { Token }
%token varid { TVarid $$ }
',' { TComma }
Rückgabe für ein erfolgreich gematchtes Token varid ist der String in der Konstruktoranwendung TVarid, während die Rückgabe für das Token ',' der Konstruktor selbst ist. |
Der Regelteil der Grammatikdatei wird durch %% eingeleitet:
| %% |
| Rules |
Die Regeln haben folgende Syntax:
| Rules | { Rule } | |
| Rule | LhsSymbol :: { Haskell-Type } | |
| [ LhsSymbol ] : Alts | ||
| [ LhsSymbol :: { Haskell-Type }] | ||
| LhsSymbol : Alts | ||
| LhsSymbol | Symbol |
Falls in einer Regel beide LhsSymbole angegeben sind, müssen beide die gleichen Symbole sein. Fehlt die Typangabe in einer Regel, wird der Typ beim Compilieren des Parsers inferiert.
| Alts | Alt { ContAlt } | |
| ContAlt | | Alt | |
| ! Alt | ||
| Alt | Symbole Code | |
| Symbole | { Symbol } | |
| Symbol | { alphanum } | |
| '{ any }' |
Innerhalb der Alternativen können die Rückgabewerte der Symbole von links nach rechts über $1, $2, ... im Haskell-Code referenziert werden. Über $0 kann das erste Argument der Parserfunktion (s.o.) referenziert werden.
Der letzte Teil der Grammatikdatei besteht, wie der Modul-Header, aus einem optionalen Haskell-Codeteil, dem Modul-Trailer. Hier können z.B. Routinen zur Konstruktion des Syntaxbaumes plaziert werden.
| Trailer | Code |
Modul-Header und Modul-Trailer werden unverändert in die Ausgabedatei übernommen. Im Modul-Header wird dabei in der ersten Zeile, die ein nicht whitespace-Zeichen enthält, der linke Rand ermittelt und von allen folgenden Zeilen abgeschnitten. Dies ist wegen der Layoutregeln zu berücksichtigen.
©1996,97,98 Norbert Klose (nklose@mail.com)