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();3.4.2
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; } ;asgn: VAR '=' expr { $$=$1->u.val=$3; $1->type = VAR; } ;expr: NUMBER | VAR { if ($1->type == UNDEF) execerror("undefined variable", $1->name); $$ = $1->u.val; } | asgn | BLTIN '(' expr ')' { $$ = (*($1->u.ptr))($3); } | expr '+' expr { $$ = $1 + $3; } | expr '+' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { if ($3 == 0.0) execerror("division by zero", ""); $$ = $1 / $3; } | expr '^' expr { $$ = Pow($1, $3); } | '(' expr ')' { $$ = $2; } | '-' expr %prec UNARYMINUS { $$ = -$2; } ;%%/* end of grammar */#include <stdio.h>#include <ctype.h>char *progname;int lineno = 1;#include <setjmp.h>jmp_buf begin;main(argc, argv) /* hoc3 */ char *argv[];{ progname = argv[0]; init(); setjmp(begin); yyparse();}yyerror(s) char *s;{ warning(s, (char *)0);}execerror(s, t) char *s, *t;{ warning(s, t); longjmp(begin, 0);}warning(s, t) char *s, *t;{ fprintf (stderr, "%s: %s", progname, s); if (t && *t) fprintf(stderr, " %s", t); fprintf(stderr, " near line %d\n", lineno);}3.4.3
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 eval;} 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;