Subato

Resource Files

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


\documentclass[a4paper]{article} \usepackage[ngerman]{babel} \usepackage[utf8x]{inputenc} \usepackage[german=guillemets]{csquotes} %include polycode.fmt \setlength\parindent{0pt} \setlength{\parskip}{5pt plus 2pt minus 1pt} \usepackage{enumitem} \begin{document} \author{} \title{Übungsblatt 4 b)} \maketitle \section*{Aufgabe 4 b: Ein kleiner Parser für XML} In dieser Aufgabe soll ein kleiner Parser für XML Strukturen geschrieben werden. Dabei verwenden wir die in der Vorlesung entwickelte Parser-Kombinator Bibliothek. Das Ergebnis soll ein XML-Dokument des in Aufgabe 4 a) Datentyps für XML sein. > module ParseXML where > import XML > import OurParserLib > import Data.Char > import Data.List \begin{enumerate}[label=\alph*)] \item Implementieren Sie den Parser, der Tag- und Attributnamen parst. Ein Name ist ein nichtleerer String, der mit einem Buchstaben (isAlpha) oder einen der Zeichen \verb+'_'+ und \verb+':'+ begint und gefolgt wird von einer Zeichenkette aus beliebigen Zeichen die kein Whitespace sind und nicht eines der Zeichen \verb+'<', '/', '>', '\'', '='+ \verb+und '\"'+. > name :: Parser Char Name \item Implementieren Sie einen Parser, der einen schließenden XML-Tag parst. Das Ergebnisse sei der Tagname. Beachten Sie dass nach \verb+"</"+ kein Whitespace stehen darf, aber nach dem Tagnamen beliebiger Whitespace stehen darf. > closeTag :: Parser Char Name \item Implementieren Sie einen Parser, der Attributwerte erkennt. Ein Attributwert sei dabei eine entweder in doppelten Anführungszeichen \verb+"+ oder in einfachen Anführungszeichen eingeschlossene Zeichenkette, in der die verwendeten Anführungszeichen nicht verwendet werden dürfen. Wir vernachlässigen Character-Entities. > value :: Parser Char Value \item Implementieren Sie einen Parser der Attribute erkennt. Ein Attribute hatt einen Namen gefolgt vom Gleichheitszeichen, gefolgt von einem Attributwert. Vor und nach dem Gleichheitszeichen dürfen beliebig viele Weißzeichen stehen. > attribute :: Parser Char Attribute \item Implementieren Sie einen Parser, der eine Folge von Attributen erkennt. Vor den Attributen dürfen beliebig viele Weißzeichen stehen. Schließen Sie Attributlisten, in denen ein Schlüssel mehrfach vor kommt, aus. > attributes ::Parser Char [Attribute] \item Implementieren Sie einen Parser, der ein öffnendes Element-Tag erkennt. Ein Element-Tag beginnt mit dem Symbol \verb+<+ gefolgt von einen Namen. Anschließend kommt eine Attributeliste. Zum Ende kommt das Symbol \verb+>+. Vor dem letzten Symbol darf belliebig viel Weißraum stehen. Wir vernachlässigen direkt wieder schließende Elemente der Art \verb+<tag/>+. > openTag :: Parser Char (String, [Attribute]) \item Schreiben Sie einen Parser der beliebigen Text eines Textknotens erkennt. Text sei eine Folge vin beliebigen Zeichen außer \verb+<+. Wir vernachlässigen also Character-Entities, CData-Sections und vieles mehr. > text ::Parser Char XML \item Schreiben Sie einen Parser, der ein XML-Element erkennt. Ein XML-Element hat ein öffnendes und ein schließendes Tag. Beide haben denselben Tagnamen, was Sie mit der Funktion \verb+filtere+ ausdrücken können. Zwischen öffnenden und schließenden Tag steht eine Folge von beliebigen XMl-Knoten. Das können weitere Elemente oder Textknoten sein. > element :: Parser Char XML \end{enumerate} \end{document}
lhs
You are not logged in and therefore you cannot submit a solution.