Arthur J. O'Dwyer said:
ObOnTopic:
struct expr {
enum {ANDexp, ORexp, ATOM} type;
/* If it is a secondary expression... */
struct expr *lhs, *rhs;
/* If it is an atom... */
char varname[10];
};
I think it is worth pointing out that this is one of those rare
places where a union makes sense even in strictly conforming C
code.
An "and" or "or" expression needs *just* the lhs and
rhs, while an "atom" expression needs *just* the varname -- so
why store all three in every kind of "expr" node? This gives
something like:
struct expr {
enum expr_type e_type;
union {
struct {
struct expr *sub_lhs, *sub_rhs;
} un_subexprs;
char un_varname[10];
} e_un;
};
Note that, in this case, the union and sub-struct types have no
tags (because none is really needed). The sub-struct is required
so that the lhs and rhs are in fact separate variables -- but if
you wanted to get rid of it, you could use an array instead:
struct expr {
enum expr_type e_type;
union {
struct expr *un_subexprs[2];
char un_varname[10];
} e_un;
};
and use un_subexprs[0] as the LHS and un_subexprs[1] as the RHS.
Unfortunately, there is no way to get rid of the separate union
member. I sometimes wish that C99 had adopted "anonymous" sub-
struct/union from one of the many dialects that have them (such
as Plan 9 C). As it is, you might choose to write:
#define e_varname e_un.un_varname
and/or:
#define e_lhs e_un.un_subexprs[0] /* assuming array */
#define e_rhs e_un.un_subexprs.sub_rhs /* assuming struct */
so that you can pretend C has anonymous sub-elements, even though
it does not. Note that this #define trick works only if the
struct-member "pseudo-names" (here e_varname, e_lhs, and e_rhs)
are not used as ordinary variable names, and tend not to work in
(for instance) debuggers.