3.7 Постфиксная запись |
Предыдущая Содержание Следующая |
До сих пор мы не решили, что на самом деле собирается делать process(). Если бы мы пожелали эмиттировать постфиксную версию выражения, то добавили бы строку символов в struct Type, чтобы показать фактический оператор, а process() организовала бы вывод в одну строку с отступами с помощью символа табуляции:
void process (const void * tree) { putchar(’\t’); exec(tree); putchar(’\n’); }
динамическую компоновку обрабатывает exec():
static void exec (const void * tree) { assert(tree && * (struct Type **) tree && (* (struct Type **) tree) —> exec);
(* (struct Type **) tree) —> exec(tree); }
и каждый бинарный оператор эмиттируется с помощью следующей функции:
static void doBin (const void * tree) { exec(((struct Bin *) tree) -> left); exec(((struct Bin *) tree) -> right); printf(" %s", (* (struct Type **) tree) -> name); }
Всё вместе связывают описания типов:
static struct Type _Add = { "+", mkBin, doBin, freeBin }; static struct Type _Sub = { "-", mkBin, doBin, freeBin };
const void * Add = & _Add; const void * Sub = & _Sub;
Должно быть просто догадаться, как реализовать числовое значение. Оно представляется в виде структуры с информационным полем типа double:
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; }
Обработка состоит из распечатывания этого значения:
static void doVal (const void * tree) { printf(" %g", ((struct Val *) tree) -> value); }
Всё сделано — не надо удалять поддеревья, поэтому для удаления узла значения можно использовать непосредственно библиотечную функцию free():
static struct Type _Value = { "", mkVal, doVal, free };
const void * Value = & _Value;
Такой унарный оператор, как Minus (вычитание), оставим в качестве упражнения.
|
Предыдущая Содержание Следующая |