1. a) I have tried to show which declaration of an identifier matches each use by using a different indentation for each set of declarations & corresponding uses (this does not match the nesting - e.g. function p's variables are not inside the struct!).
<global <struct <1st level inside function p <2nd level inside function p static int i, j, k, a ; static float b, c ; static struct {int i, j, k;} x; static void p(){int i, n, d; float e; for ( n= 1; n<= 2; n++){ i= j; k++; d= a+b*c+ e; if (e) e= d; if (n== 1){ int i, m, a; float f; i= j; m= n; f=a* b+c* d; p= x+ f; if (k< 2) p();}}}int main(void){ k= 0; j= 0; x. k= 0; x. j= 0; p(); return 0;}
b) I have tried to hint at the structure of the parse trees for the statements by the way they are indented below. Each expression would also have a tree structure (which I have added at the end for one of the more complex expressions). I have added the type information (I=int, F=float, with more complex types in [ ]) and type conversions (int_to_float, float_to_int), and indicated semantic errors by [!].
for nI = 1I nI <= 2I nI++ { iI= jI kI++ dI=float_to_int (((int_float(aI)+(bF*cF))+eF) if eF eF= dI {} if (nI == 1I) { iI= jI mI= nI fF= (int_to_float(aI)*bF)+(cF*int_to_float(dI)) p[func!]= x[struct!]+fF if kI < 2I p[void(void)]() {} } {} } . . . kI= 0I jI= 0I x[struct].kI= 0I x[struct].jI= 0I p[void(void)]() return 0I e.g. d=float_to_int (((int_float(a)+(b*c))+e) would look something like: = d () float_to_int + + e () * int_float a b c
2. I can't draw all the links (e.g. the names in the middle column (int, double, void, long int, r, UU, x, z, s, rr) should be links to the right-hand column entries for those names) but the dictionary should look something like this:
double -> 0: type -> builtin char -> 0: type -> builtin int -> 0: type -> builtin void -> 0: type -> builtin long int-> 0: type -> builtin i -> 2: param -> long int* -> 1: var int j -> 2: param -> long int* -> 1: var int a -> 1: var -> int [10] p -> 1: func void, long int*, long int* red -> 2: const int 0 blue -> 2: const int 1 x -> 2: type -> enum (2?) y -> 2: type -> char z -> 2: type -> x [5] f1 -> 2: field long int r f2 -> 2: field long int r f3 -> 2: field double r f4 -> 2: field double r f5 -> 2: field char r UU -> 2: field r -> union . . . b -> 2: field char UU f6 -> 2: field y UU s -> 2: type r -> 2: type -> struct . . . -> 2: struct tag-> (also points to struct above) xx -> 2: var x zz -> 2: var z ss -> 2: var s rr -> 2: var rr
There are still lots of details here to be resolved (e.g. how exactly is "long int*" held?) but you should be able to see the general ideas.