#include "head.html"

Bessere Parser

Annotierter Eingabestrom

Wir hatten den Parsertyp
String -> [ (a, String) ]
benutzt. Daß wir Zeichen gelesen hatten, war nicht wesentlich; es hätte irgendein Listentyp sein können. Also verallgemeinern wir zu
[s] -> [ (a, [s]) ]
Wir nutzen das wie folgt: wir wollen an jedes Eingabezeichen noch weiter Informationen anheften: seine Position im Quelltext (Zeile und Spalte). Wir definieren einen passenden Typ
#include "../src/Position.hs"
und denken dann an eine Benutzung
[(Char, Pos)] -> [ (a, [(Char, Pos)]) ]

Beliebige Ausgabe-Monade

Wir beherrschen den Nichtdeterminismus, indem wir mit Listen von Ergebnissen rechnen.
[s] -> [ (a, [s]) ]
Statt Listen könnten wir auch eine andere Instanz von MonadPlus nehmen. Das führt zum verallgemeinerter Parser-Typ
#include "../src/General_Parser_Type.hs"
Dabei denken wir vorwiegend an Maybe. Das entspricht einer Liste mit null oder einem Element, beschränkt also die Suchbäume auf die Breite 1, und beschleunigt damit die Parser.

Es ist jedoch Vorsicht geboten:

Just x `plus` Just y = Just x
d. h. wir vergessen das zweite Resultat. Das `plus` auf Maybe ist also nicht symmetrisch; wir müssen uns gut überlegen, in welcher Reihefolge wir die Argumente hinschreiben. Typischer Fall:
many1 :: Parser a -> Parser [a]
many1 p = do x  <- p
	     xs <- many p
	     return $ x : xs

many ::  Parser a -> Parser [a]
many p =      many1 p
       `plus` return []
Das ist in unserem Sinne richtigrum, denn das many1 p wird bevorzugt, bis es nicht mehr geht, und erst dann kommt return [] dran.

Fehlermeldungen

Bei Maybe stört uns, daß Nothing sehr wenig darüber aussagt, warum das Parsen fehlschlug. Wir möchten das Nothing mit der Fehlerposition annotieren.
#include "../src/Fehler.hs"
Beachte die Instanz von MonadPlus: von zwei fehlgeschlagenen Parses nehmen wir den längeren, d. h. wir informieren den User über den längsten korrekten Präfix der Eingabe. Damit wird unser Parser-Typ zu
#include "../src/Position_Parser_Basic.hs"
Dieses Modul hat das gleiche Inteface wie das ursprüngliche Parser_Basic.hs. Damit können wir die Parser-Kombinatoren ohne weiteres nachnutzen (Quelltext) und auch die Anwendungen (Quelltext) merken davon nichts - aber die Fehlermeldungen sind nun viel informativer. #include "foot.html"