#import "@preview/codly:1.3.0": * #import "@preview/codly-languages:0.1.1": * #import "@preview/catppuccin:1.0.1": catppuccin, flavors #show: codly-init.with() #show: catppuccin.with(flavors.latte) #codly(languages: codly-languages) = Exercise 01 #let question(body) = block( fill: luma(255), inset: 8pt, radius: 4pt )[ #body ] == 01 Eigentschaften einer Gramatik #question[ Besitzen die folgenden Grammatiken die LL(1)-Eigenschaft? Begründen Sie Ihre Antwort in textueller Form (warum LL(1), warum nicht LL(1)). Sollte es mindestens eine LL(1)-Verletzungen geben, geben Sie bitte alle an. Geben Sie zudem für jede Grammatik, welche die LL(1)- Eigenschaft nicht besitzt, die theoretisch minimale Anzahl an Vorgriffssymbolen an, die für das Parsen der jeweiligen Grammatik notwendig wäre. ] === Task a #question[ ``` Temperature = ["-"] ( Celsius | Kelvin ) . Celsius = { number } "◦C" . Kelvin = { number } "K" . ``` ] Conflicts: - $"first"("Celsius") inter "first"("Kelvin") = { "number" } arrow.r.double "LL(1) conflict" $ - Both productions begin with the same token (number). This is a LL(1) conflict. - It is not even LL(k) because there can be infinite (number) token before the distiction between Celsius and Kelvin happens. === Task b #question[ ``` Locals = "class" ident "{" { VarDecl | FuncDecl } "}" . VarDecl = "int" ident { "," ident } ";" . FuncDecl = "fn" "int" ident "(" ")" ";" . ``` ] $ "first"("FunDecl") inter "first"("VarDecl") = {"\"int\""} inter {"\"fn\""} = emptyset $ $ ("follow"("VarDecl") union "follow"("FuncDecl")) inter ("first"("FunDecl") union "first"("VarDecl")) \ = {"\"int\"", "\"fn\""} inter { "\"}\"" } = emptyset $ - No LL(1) conflict - No left recursion - Grammer is LL(1) === Task c #question[ ``` Var = ident ":" Type . Type = ( Primitive | FuncType ) . Primitive = "i32" | "f64" . FuncType = Type "->" Primitive . ``` ] - There is left recurion. Which means that the grammar is not LL(1). Consider the following snippet. The first element of `FuncType` evaluates to `Type`, which then can evaluate to `FuncType` => left recursion ``` FuncType = Type "->" Primitive . Type = ( Primitive | FuncType ) . ``` - `First(Type)` can also not be computed because of the left recursion. So checking the intersection of `First(Type)` and `First(FuncType)` is not possible. - Allthogh it is not LL(1) it is LL(2). == 02 Beseitigung von LL(1)-Konflikten mittels Faktorisierung Beseitigen Sie in folgenden Grammatiken die enthaltenen LL(1)-Konflikte mittels Einsetzen und Faktorisie- rung. Geben Sie dazu eine umgeformte, ggf. vereinfachte EBNF Grammatik an. === Task a #question[ ``` StructDecl = ident "=" "{" { Value | NullableValue } "}" . Value = ident ":" Type . NullableValue = ident ":" "?" Type . Type = "i32" | "i64" | "string" . ``` ] ``` StructDecl = ident "=" "{" { NullableValue } "}" . NullableValue = ident ":" ["?"] Type . Type = "i32" | "i64" | "string" . ``` === Task b #question[ ``` Args = FixArgs ";" VarArgs . FixArgs = ident ":" Type { ";" ident ":" Type } . VarArgs = "..." ident . Type = "i32" | "string" . ``` ] ``` Args = FixArgs VarArgs . FixArgs = ident ":" Type ";" { ident ":" Type ";" } . VarArgs = "..." ident . Type = "i32" | "string" . ``` == 03 Beseitigung von Linksrekursion #question[ Beseitigen Sie in folgender Grammatik die enthaltenen LL(1)-Konflikte. Geben Sie dazu eine umgeformte EBNF Grammatik ohne Rekursion an. Beseitigen Sie mögliche Linksrekursionen durch Umformung in eine Iteration (nicht durch Umformung in Rechtsrekursion). ``` Fields = Type Assigns . Assigns = ident "=" Expr . Expr = ident | number | Expr ( "==" | "!=" ) ( ident | number ) . Type = ident | Type "->" ident . ``` ] First lets look at the Type Production: ``` Type = ident | Type "->" ident . ``` This can be rewritten as: ``` Type = ident { "->" ident } . ``` Seconnd we need to address the Expr Production: ``` Expr = ident | number | Expr ( "==" | "!=" ) ( ident | number ) . ``` This can be rewritten as: ``` Expr = ( ident | number ) { ( "==" | "!=" ) ( ident | number ) } . ``` The resulting grammer would be this: ``` Fields = Type Assigns . Assigns = ident "=" Expr . Expr = ( ident | number ) { ( "==" | "!=" ) ( ident | number ) } . Type = ident { "->" ident } . ``` == 04 LL(4) Grammatik #question[ Geben Sie eine einfache Grammatik mit mindestens 3 Produktionen an, welche die LL(4)-Eigenschaft, jedoch nicht die LL(3)-Eigenschaft besitzt. ] ``` A = B | C . B = "one" "two" "three" "B" . C = "one" "two" "three" "C" . ```