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