d1.val -= d2.val; push(d1);}mul() { Datum d1, d2; d2 = pop(); d1 = pop(); d1.val *= d2.val; push(d1);}div() { Datum d1, d2; d2 = pop(); if (d2.val == 0.0) execerror("division by zero", (char*)0); d1 = pop(); d1.val /= d2.val; push(d1);}negate() { Datum d; d = pop(); d.val = -d.val; push(d);}power() { Datum d1, d2; extern double Pow(); d2 = pop(); d1 = pop(); d1.val = Pow(d1.val, d2.val); push(d1);}assign() /* assign top value to next value */{ Datum d1, d2; d1= pop(); d2 = pop(); if (d1.sym->type != VAR && d1.sym->type != UNDEF) execerror("assignment to non-variable", d1.sym->name); d1.sym->u.val = d2.val; d1.sym->type = VAR; push(d2);}print() /* pop top value from stack, print it */{ Datum d; d = pop(); printf("\t%8g\n", d.val);}Inst *code(f) /* install one instruction or operand */ Inst f;{ Inst *oprogp = progp; if (progp >= &eprog[NPROG]) execerror("program too big", (char*)0); *progp++ = f; return oprogp;}execute(p) /* run the machine */ Inst *p;{ for (pc = p; *pc != STOP; ) (*(*pc++))();}3.5.2
hoc.htypedef struct Symbol { /* symbol table entry */ char *name; short type; /* VAR, BLTIN, UNDEF */ union { double val; /* if VAR */ double (*ptr)(); /* if BLTIN */ } u; struct Symbol *next; /* to link to another */} Symbol;Symbol *install(), *lookup();typedef union Datum { /* interpreter stack type */ double val; Symbol *sym;} Datum;extern Datum pop();typedef int (*Inst)(); /* machine instruction */#define STOP (Inst)0extern Inst prog[];extern eval(), add(), sub(), mul(), div(), negate(), power();extern assign(), bltin(), varpush(), constpush(), print();3.5.3
hoc.y%{#include "hoc.h"#define code2(c1,c2) code(c1); code(c2)#define code3(c1,c2,c3) code(c1); code(c2); code(c3)%}%union { Symbol *sym; /* symbol table pointer */ Inst *inst; /* machine instruction */}%token <sym> NUMBER VAR BLTIN UNDEF%right '='%left '+' '-'%left '*' '/'%left UNARYMINUS%right '^' /* exponentiation */%%list: /* nothing */ | list '\n' | list asgn '\n' { code2(pop, STOP); return 1; } | list expr '\n' { code2(print, STOP); return 1; } | list error '\n' { yyerrok; } ;asgn: VAR '=' expr { code3(varpush,(Inst)$1.assign); }