Eine pdf-Version der Aufgabe ist hier zu laden.
Gegeben Sie die kleine Parser Bibliothek, die in der Vorlesung live entwickelt wurde:
module OurParserLib where import Data.Char --Der Parsertyp: type Parser token result = [token] -> [(result,[token])] -- Zum Erkennen von Token mit bestimmter Eigentschaft. satisfy :: (t -> Bool) -> Parser t t satisfy p [] = [] satisfy p (x:xs) |p x = [(x,xs)] |otherwise = [] --Zum Erkennen eines Terminalsymbols. terminal :: Eq t => t -> Parser t t terminal t = satisfy ((==) t) -- Infix Parserkombinatoren infixl 9 +- infix 6 <<- infixl 3 !|+ -- Die Sequenz zweier Parser (+-) :: Parser t r1 -> Parser t r2 -> Parser t (r1,r2) (+-) p1 p2 xs = [ ((r1,r2),ts2)| (r1,ts1) <- p1 xs, (r2,ts2) <- p2 ts1] -- Die Alternativkombination. Diese Version macht einen Shortcut. -- Wenn der erste Parser erfolgreich ist, wird der zweite ignoriert. (!|+) :: Parser t r -> Parser t r -> Parser t r (!|+) p1 p2 xs |null p1res = p2 xs |otherwise = p1res where p1res = p1 xs -- Die Eigentliche fmap-Funktion, nur unsere Parser sind keine Instanz -- Functor. Die Ergebnisse des Parsers werden mit einer Funktion manipuliert. (<<-) :: Parser t r1 -> (r1 -> r2) -> Parser t r2 (<<-) p f = \xs -> [(f result,rest) |(result,rest) <- p xs] -- 0 bis n-fache Wiederholung (Sequenz) eines Parsers. zeroToN :: Parser t r -> Parser t [r] zeroToN = zeroToN2 [] where zeroToN2 acc p xs | null res1 = [(reverse acc,xs)] | otherwise = zeroToN2 (r1: acc) p rest where res1 = p xs (r1,rest) = head res1 -- 1 bis n-fache Wiederholung (Sequenz) eines Parsers. oneToN :: Parser t r -> Parser t [r] oneToN p = p +- zeroToN p <<- \(x,xs)-> (x:xs) -- Für einen Parser auf Strings, also mit Token Char, wird ein -- neuer Parser erzeugt, der Whitespace am Anfang der Tokenliste -- ignoriert ignoreSpace :: Parser Char r -> Parser Char r ignoreSpace p = \xs -> p (dropWhile isSpace xs) -- Folgende Funktion erlaubt es, aus der Ergebnisliste erfolgreiche -- Parsergebnisse zu löschen, wenn Sie eine bestimmte Eigentschaft nicht -- haben. Hilfreich, wenn etwas nicht durch kontextfreie Grammatik -- darstellbar, zum Beispiel verschiedene Tagnamen bei öffnenden und -- schließenden XML-Tags. filtere :: (r -> Bool) -> Parser t r -> Parser t r filtere pred p = \xs -> filter (\(r,_) -> pred r) (p xs)
Desweiteren die Datenstruktur für XML aus dem Teil a) der Aufgabe,
Implementieren Sie einen Parser für XML nach der im Template ParseXML.lhs angegebenen Spezifikation