XML Parser

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