Attribute grammar for the sleaf, dleaf, and tail attributes of a quirk20 program. [Revision 1] The attribute grammar is defined over abstract syntax trees that contain no errors. Attributes. D.fundec synthesized D.sleaf synthesized D.dleaf synthesized S.sleaf synthesized S.dleaf synthesized S.tail inherited E.dleaf synthesized E.tail inherited D.fundec is a synthesized boolean attribute that is true iff D is a function declaration. D.sleaf is a synthesized boolean attribute that is true iff D is a function declaration that contains no local function declarations. S.sleaf is a synthesized boolean attribute that is true iff S is a statement that contains no function declarations. D.dleaf is a synthesized boolean attribute that is true iff D is a constant, global variable, or field declaration, a variable declaration whose initializing expression contains no non-tail calls, or a function declaration that contains no non-tail calls. S.dleaf is a synthesized boolean attribute that is true iff S is a statement that contains no non-tail calls. E.dleaf is a synthesized boolean attribute that is true iff E is an expression that contains no non-tail calls. S.tail is an inherited boolean attribute that is true iff S is in a tail position. E.tail is an inherited boolean attribute that is true iff E is in a tail position. D --> constant T I = L; D.fundec = false; D.sleaf = false; D.dleaf = true. D --> static T I = L; D.fundec = false; D.sleaf = false; D.dleaf = true. D --> T I; D.fundec = false; D.sleaf = false; D.dleaf = true. D --> T I = E; E.tail = false; D.fundec = false; D.sleaf = false; D.dleaf = E.dleaf. D --> proc T0 I0 (T1 I1, ..., Tn In) S S.tail = true; D.fundec = true; D.sleaf = S.sleaf; D.dleaf = S.dleaf. S --> skip; S.sleaf = S.dleaf = true. S --> E; E.tail = S.tail; S.sleaf = true; S.dleaf = E.dleaf. S --> if (E1) S1 else S2 E1.tail = false; S1.tail = S2.tail = S.tail; S.sleaf = S1.sleaf and S2.sleaf; S.dleaf = E1.dleaf and S1.dleaf and S2.dleaf. S --> while (E1) S1 E1.tail = false; S1.tail = false; S.sleaf = S1.sleaf; S.dleaf = E1.dleaf and S1.dleaf. S --> return E; E.tail = true; S.sleaf = true; S.dleaf = E.dleaf. S --> { D1 ... Dm S1 ... Sn } S1.tail = false; ... Sn.tail = S.tail; S.sleaf = ! D1.fundec and ... ! Dm.fundec and S1.sleaf and ... Sn.sleaf; S.dleaf = (D1.fundec or D1.dleaf) and ... (Dm.fundec or Dm.dleaf) and S1.dleaf and ... Sn.dleaf. E --> E1 = E2 E1.tail = E2.tail = false; E.dleaf = E1.dleaf and E2.dleaf. E --> E1 || E2 E1.tail = false; E2.tail = E.tail; E.dleaf = E1.dleaf and E2.dleaf. E --> E1 && E2 E1.tail = false; E2.tail = E.tail; E.dleaf = E1.dleaf and E2.dleaf. E --> E1 B E2 E1.tail = E2.tail = false; E.dleaf = E1.dleaf and E2.dleaf. E --> U E1 E1.tail = false; E.dleaf = E1.dleaf. E --> L E.dleaf = true. E --> new R () E.dleaf = true. E --> new T [ E1 ] E1.tail = false; E.dleaf = E1.dleaf. E --> R.I E.dleaf = true. E --> E0 (E1, ..., En) E0.tail = E1.tail = ... = En.tail = false; E.dleaf = E.tail and ! E0.dleaf and E1.dleaf and ... En.dleaf. E --> I E.dleaf = true. E --> E1.I E1.tail = false; E.dleaf = E1.dleaf. E --> E1 [ E2 ] E1.tail = E2.tail = false; E.dleaf = E1.dleaf and E2.dleaf.