OOC:en:3.7 A Postfix Writer
来自 ChinaUnix Wiki
So far we have not really decided what process() is going to do. If we want to emit a postfix version of the expression, we would add a character string to the struct Type to show the actual operator and process() would arrange for a single output line indented by a tab:
void process (const void * tree)
{
putchar(’\t’);
exec(tree);
putchar(’\n’);
}
exec() handles the dynamic linkage:
static void exec (const void * tree)
{
assert(tree && * (struct Type **) tree
&& (* (struct Type **) tree) —> exec);
(* (struct Type **) tree) —> exec(tree);
}
and every binary operator is emitted with the following function:
static void doBin (const void * tree)
{
exec(((struct Bin *) tree) —> left);
exec(((struct Bin *) tree) —> right);
printf(" %s", (* (struct Type **) tree) —> name);
}
The type descriptions tie everything together:
static struct Type _Add = { "+", mkBin, doBin, freeBin };
static struct Type _Sub = { "—", mkBin, doBin, freeBin };
const void * Add = & _Add;
const void * Sub = & _Sub;
It should be easy to guess how a numerical value is implemented. It is represented as a structure with a double information field:
struct Val {
const void * type;
double value;
};
static void * mkVal (va_list ap)
{ struct Val * node = malloc(sizeof(struct Val));
assert(node);
node —> value = va_arg(ap, double);
return node;
}
Processing consists of printing the value:
static void doVal (const void * tree)
{
printf(" %g", ((struct Val *) tree) —> value);
}
We are done — there is no subtree to delete, so we can use the library function free() directly to delete the value node:
static struct Type _Value = { "", mkVal, doVal, free };
const void * Value = & _Value;
A unary operator such as Minus is left as an exercise.
