return sp; return 0; /* 0 ==> not found */}Symbol *install(s, t, d) /* install s in symbol table */ char *s; int t; double d;{ Symbol *sp; char *emalloc(); sp = (Symbol*)emalloc(sizeof(Symbol)); sp->name = emalloc(strlen(s)+1); /* +1 for '\0' */ strcpy(sp->name, s); sp->type = t; sp->u.val = d; sp->next = symlist; /* put at front of list */ symlist = sp; return sp;}char *emalloc(n) /* check return from malloc */ unsigned n;{ char *p, *malloc(); p = malloc(n); if (p == 0) execerror("out of memory", (char*)0); return p;}$Файл
init.cPIinitmain$ cat init.c#include "hoc.h"#include "y.tab.h"#include <math.h>extern double Log(), Log10(), Exp(), Sqrt(), integer();static struct { /* Constants */ char *name; double cval;} consts[] = { "PI", 3.14159265358979323846, "E", 2.71828182845904523536, "GAMMA", 0.57721566490153286060, /* Euler */ "DEG", 57.29577951308232087680, /* deg/radian */ "PHI", 1.61803398874989484820, /* golden ratio */ 0, 0};static struct { /* Built-ins */ char *name; double (*func)();} builtins[] = { "sin", sin, "cos", cos, "atan", atan, "log", Log, /* checks argument */ "log10", Log10, /* checks argument */ "exp", Exp, /* checks argument */ "sqrt", Sqrt, /* checks argument */ "int", integer, "abs", fabs, 0, 0};init() /* install constants and built-ins in table */{ int i; Symbol *s; for (i = 0; consts[i].name; i++) install(consts[i].name, VAR, consts[i].cval); for (i = 0; builtins[i].name; i++) { s = install(builtins[i].name, BLTIN, 0.0); s->u.ptr = builtins[i].func; }}Данные хранятся в таблицах, а не вводятся в текст программы, чтобы легче было их читать и изменять. Таблицы определены как статические, что обеспечивает их доступность только в данном файле. Мы вскоре вернемся к обсуждению стандартных математических функций типа
LogSqrtПостроив такой базис, можно перейти к изменениям в грамматике, которые осуществляются на его основе.
$ cat hoc.y%{#include "hoc.h"extern double Pow();%}%union { double val; /* actual value */ Symbol *sym; /* symbol table pointer */}%token <val> NUMBER%token <sym> VAR BLTIN UNDEF%type <val> expr asgn%right '='%left '+'%left '*' '/'%left UNARYMINUS%right '^' /* exponentiation */%%list: /* nothing */ | list '\n' | list asgn '\n' | list expr '\n' { printf("\t%.8g\n", $2); } | list error '\n' { yyerrok; } ;