1. a. Explain the structure of: i. portable compilers; 4 marks ii. high level optimising compilers. 4 marks Why are their priorities different? 2 marks b. Using the fragment of three address code below, show how a flow graph can be obtained and how a loop can be identified. All statements use the same notation as that used throughout the lectures. (1) B1: I := 1 (2) J := 1 (3) K := 1 (4) B2: if I$>$N goto B5 (5) B3: if J$>$N goto B6 (6) B4: T1 := 0[SP] (7) T2 := T1 - 4 (8) T3 := 4 * I (9) T4 := T2[T3] (10) T5 := 4[SP] (11) T6 := T5 -4 (12) T7 := 4 * J (13) T8 := T6[T7] (14) if T4 $<=$ T8 goto B6 8 marks c. What is the alternative to three address code, which is sometimes used? 2 marks 2. a. Explain, with appropriate examples, four types of high level, machine independent optimisation. 8 marks b. Consider the following attribute grammar, which defines a syntax directed translation scheme. decls -> decl decls ¦ empty decl -> type list list.inheritance:= type.type type -> int type.type:= integer type -> real type.type:= real list -> list1 , id list1.inheritance:= list.inheritance addtype(id.entry, list.inheritance) list -> id addtype(id.entry, list.inheritance) id -> letter* and the following string int a, b real c, d i. Construct the parse tree, with the attributes of all nodes shown. 8 marks ii. Explain what is meant by a dependency graph for such a parse tree. 4 marks