Лексический анализ теперь несколько удлиняется в основном из-за необходимости распознавания дополнительных операций:
yylex() /* hoc5 */{ ... switch (с) { case '>': return follow('=', GE, GT); case '<': return follow('=', LE, LT); case '=': return follow('=', EQ, '='); case '!': return follow('=', NE, NOT); case '|': return follow('|', OR, '|'); case '&': return follow('&', AND, '&'); case '\n': lineno++; return '\n'; default: return c; }}Функция
followungetcfollow(expect, ifyes, ifno) /* look ahead for >=, etc. */{ int с = getchar(); if (c == expect) return ifyes; ungetc(c, stdin); return ifno;}В файле
hoc.hhoc4$ cat hoc.h...typedef int (*Inst)(); /* machine instruction */#define STOP (Inst)0extern Inst prog[], *progp, *code();extern eval(), add(), sub(), mul(), div(), negate(), power();extern assign(), bltin(), varpush(), constpush(), print();extern prexpr();extern gt(), lt(), eq(), ge(), le(), ne(), and(), or(), not();extern ifcode(), whilecode();$Большая часть файла
code.clele() { Datum d1, d2; d2 = pop(); d1 = pop(); d1.val = (double)(d1.val <= d2.val); push(d1);}He совсем тривиальными являются функции
whilecodeifcodeexecuteSTOPexecuteSTOPexecutewhileifthenelseexecuteexecutewhilecodeifcodewhilecode() { Datum d; Inst *savepc = pc; /* loop body */ execute(savepc+2); /* condition */ d = pop(); while (d.val) { execute(*((Inst **)(savepc))); /* body */ execute(savepc+2); d = pop(); } pc = *((Inst **)(savepc+1)); /* next statement */}Как уже отмечалось ранее, после операции
whilecodewhilecodepcpc+1pc+2Функция
ifcodepcthenpc+1elsepc+2pc+3ifcode(){ Datum d; Inst *savepc = pc; /* then part */ execute(savepc+3); /* condition */ d = pop(); if (d.val) execute(*((Inst **)(savepc))); else if (*((Inst **)(savepc+1))) /* else part? */ execute(*((Inst **)(savepc+1))); pc = *((Inst**)(savepc+2)); /* next stmt */}Программа в файле
init.c