U N S A R I V E R S A V I E I T A S N I S S Programmierung WS 2002 / 03: Musterlösung zum 12. Übungsblatt Prof. Dr. Gert Smolka, Dipl.-Inform. Thorsten Brunklaus Aufgabe 12.1: Syntaxbäume (10 = 2 + 2 + 3 2) (a) at at at at at "(" "bool" "->" "int" "->" "bool" ")" "->" Es gibt genau einen Syntaxbaum, denn die Grammatik ist eindeutig. (b) "int" "3" "*" "(" "2" "*" "y" "+" "x" ")" "*" Es gibt genau drei Syntaxbäume, entweder beginnend mit dem obersten, oder. "z" 1
(c) "2" "+" "3" "-" "4" "+" "7" "2" "+" "3" "-" "4" "+" "7" "2" "+" "3" "-" "4" "+" "7" 2
Aufgabe 12.2: Mehrdeutige Grammatik (6 = 2 + 4) (a) (i) (b) (ii) "x" "x" "x" "x" "x" "x" = "x" "x" Aufgabe 12.3: Zeichendarstellung von Typen (8) fun (Arrow(t,t )) = at t ^ "->" ^ t t = at t and at Bool = "bool" at Int = "int" at t = "(" ^ t ^ ")" Aufgabe 12.4: Zeichendarstellung von Ausdrücken (10) fun (Op(e,Leq,e )) = e ^ "<=" ^ e e = e and (Op(e,Add,e )) = e ^ "+" ^ e (Op(e,Sub,e )) = e ^ "-" ^ e e = e and (Op(e,Mul,e )) = e ^ "*" ^ e e = e and (Con n) = Int.toString n e = "(" ^ e ^ ")" 3
Aufgabe 12.5: Lexer und Parser für Typen mit Pfeil und Stern (20 = 6 + 6 + 8) (a) fun lex s = lex nil (String.lode s) (b) and lex ts nil = rev ts lex ts (#"i" :: #"n" :: #"t" ::rs) = lex (INT::ts) rs lex ts (#"-" :: #">" ::rs) = lex (ARROW::ts) rs lex ts (#"*"::rs) = lex (STAR::ts) rs lex ts (#"("::rs) = lex (LPAR::ts) rs lex ts (#")"::rs) = lex (RPAR::ts) rs lex ts cs = raise Error = s [ "->" ] s = a [ "*" s ] a = "int" "(" ")" "->" s "*" a "int" "(" ")" (c) (* *) = s [ "->" ] s = a [ "*" s ] s = a [ "*" s ] a = "int" "(" ")" fun match (a,ts) t = if null ts orelse hd ts <> t then raise Error else (a, tl ts) fun combine a ts p f = let val (a,tr) = p ts in (f(a,a ), tr) end 4
fun ts = (case s ts of (t, ARROW::tr) => combine t tr (fn (t, t ) => Arrow(t, t )) sts => sts) and s ts = (case a ts of (t, STAR::tr) => combine t tr s (fn (t, ts) => Star (t :: ts)) sts => sts) and s ts = (case a ts of (t, STAR::tr) => combine t tr s (fn (t, ts) => (t :: ts)) (t, tr) => ([t], tr)) and a (INT::tr) = (Int, tr) a (LPAR::tr) = match ( tr) RPAR a _ = raise Error fun parse ts = (case ts of (t, nil) => t _ => raise Error) Aufgabe 12.6: Kontextfreie Syntax von applikativen Ausdrücken (16 = 4 4) (a) = [ ] = "(" ")" (b) fun (App(e,e )) = e ^ " " ^ e e = e and (Id s) = s e = "(" ^ e ^ ")" (c) = ap ap = [ ap ] = "(" ")" ap "(" ")" 5
(d) fun ts = ap ( ts) and (ID _::ts) = ts (LPAR::ts) = (case ts of RPAR::tr => tr _ => raise Error) _ = raise Error and ap (ID _::tr) = ap tr ap (LPAR::tr) = ap ( (LPAR::tr)) ap tr = tr and test ts = ( ts = nil) handle Error => false Aufgabe 12.7: Lexer und Parser für Ausdrücke mit Cons und Append (30 = 10 + 6 + 4 + 10) (a) fun lex ts nil = rev ts lex ts (#" " ::cs) = lex ts cs lex ts (#"\n"::cs) = lex ts cs lex ts (#"\t"::cs) = lex ts cs lex ts (#":" :: #":" ::cs) = lex (CONS::ts) cs lex ts (#"@" ::cs) = lex (APPEND::ts) cs lex ts (#"(" ::cs) = lex (LPAR::ts) cs lex ts (#")" ::cs) = lex (RPAR::ts) cs lex ts (c ::cs) = if Char.isAlpha c then lexa ts [c] cs else raise Error (b) and lexa ts xs cs = if not(null cs) andalso Char.isAlphaNum(hd cs) then lexa ts (hd cs::xs) (tl cs) else lex (ID(implode(rev xs)) :: ts) cs fun lex s =lex nil (lode s) = ap [ ("::" "@") ] ap = [ ap ] = "(" ")" "::" "@" ap "(" ")" 6
(c) = ap [ ("::" "@") ] ap = ap ap = [ ap ] = "(" ")" "::" "@" ap ap "(" ")" (d) (* = ap [ ("::" "@") ] ap = ap ap = [ ap ] = "(" ")" *) datape opr = Cons Append datape = Id of string Op of * opr * App of * fun match (a,ts) t = if null ts orelse hd ts <> t then raise Error else (a, tl ts) fun combine a ts p f = let val (a,tr) = p ts in (f(a,a ), tr) end fun opa opr (a,a ) = Op(a,opr,a ) 7
fun firstat (ID _ ::_) = true firstat (LPAR ::_) = true firstat _ = false fun ts = case ap ts of (a, CONS ::tr) => combine a tr (opa Cons) (a, APPEND::tr) => combine a tr (opa Append) ats => ats and ap ts = ap ( ts) and ap (a,ts) = if firstat ts then ap (combine a ts App) else (a,ts) and (ID s ::ts) = (Id s, ts) (LPAR ::ts) = match ( ts) RPAR _ = raise Error fun parse ts = case ts of (a, nil) => a _ => raise Error 8