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.

个主工具