We consider the language generated by the following grammar.
P D; E |
D D; D |
D : T |
T |
T |
T []T |
T T |
T T T |
E |
E |
E |
E E E |
E E[E] |
E E |
E E(E) |
Grammar symbol | Synthesized attribute | Inherited attribute |
E | E.type (type expression) | |
T | T.type (type expression) | |
.entry | ||
.val | ||
.val character |
D : T | { addtype(id.entry, T.type) } |
T | { T.type := } |
T | { T.type := } |
T []T1 | { T.type := array (0 ... .val - 1, T1.type) } |
T T1 | { T.type := pointer(T1) } |
T T1 T2 | { T.type := (T1.type T2.type) |
D : T {addtype(.entry, T.type)} | (1) |
E | { E.type := | } |
E | { E.type := | } |
E | { E.type := | lookup(id.entry) } |
E E1 E2 | { E.type := | if E1.type = |
and E2.type = | ||
then | ||
else } | ||
E E1[E2] | { E.type := | if E1.type = |
and E2.type = array(n, T) | ||
then T | ||
else } | ||
E E1 | { E.type := | if E1.type = pointer(T) |
then T | ||
else } | ||
E E1(E2) | { E.type := | if E2.type = S |
and E1.type = S T | ||
then T | ||
else } |
P D; S |
D D; D |
D : T |
T |
T |
T |
T []T |
T T |
E |
E |
E |
E E E |
E E E |
E E[E] |
E E |
S S1; S2 |
S := E |
S E S |
S E S |
S S1; S2 | { S.type := | if S1.type = void |
and S2.type = void | ||
then void | ||
else } | ||
S := E | { S.type := | if E.type = .type |
then void | ||
else } | ||
S E S1 | { S.type := | if E.type = boolean |
then S1.type | ||
else } | ||
S E S1 | { S.type := | if E.type = boolean |
then S1.type | ||
else } |