KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Брайан Керниган - UNIX — универсальная среда программирования

Брайан Керниган - UNIX — универсальная среда программирования

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Брайан Керниган, "UNIX — универсальная среда программирования" бесплатно, без регистрации.
Перейти на страницу:

list: /* nothing */

 | list 'n'

 | list asgn 'n'

 | list expr 'n' { printf("t%.8gn", $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 %dn", 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;

 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].eval);

 for (i = 0; builtins[i].name; i++) {

  s = install(builtins[i].name, BLTIN, 0.0);

  s->u.ptr = builtins[i].func;

 }

}

3.4.4. lex.l

%{

#include "hoc.h"

#include "y.tab.h"


extern int lineno;

%}

%%

[ t] { ; } /* skip blanks and tabs */

[0-9]+.?|[0-9][0-9]+ {

 sscanf(yytext, "%lf", &yylval.val);

 return NUMBER;

}

[a-zA-Z][a-zA-Z0-9]* {

 Symbol *s;

 if ((s=lookup(yytext)) == 0)

  s = install(yytext, UNDEF, 0.0);

 yylval.sym = s;

 return s->type == UNDEF ? VAR : s->type;

}

n {

 lineno++;

 return 'n';

} /* everything else */

. { return yytext[0]; }

3.4.5 makefile

YFLAGS = -d

OBJS = hoc.o lex.o init.o math.o symbol.o


hoc3: $(OBJS)

      cc $(OBJS) -lm -ll -o hoc3


hoc.o: hoc.h


lex.o init.o symbol.o: hoc.h y.tab.h

3.4.6 math.c

#include <math.h>

#include <errno.h>


extern int errno;

double errcheck();


double Log(x)

 double x;

{

 return errcheck(log(x), "log");

}


double Log10(x)

 double x;

{

 return errcheck(log10(x), "log10");

}


double Sqrt(x)

 double x;

{

 return errcheck(sqrt(x), "sqrt");

}


double Exp(x)

 double x;

{

 return errcheck(exp(x), "exp");

}


double Pow(x, y)

 double x, y;

{

 return errcheck(pow(x,y), "exponentiation");

}


double integer(x)

 double x;

{

 return (double)(long)x;

}


double errcheck(d, s) /* check result of library call */

 double d;

 char *s;

{

 if (errno == EDOM) {

  errno = 0;

  execerror(s, "argument out of domain");

 } else if (errno == ERANGE) {

  errno = 0;

  execerror(s, "result out of range");

 }

 return d;

}

3.4.7 symbol.c

#include "hoc.h"

#include "y.tab.h"


static Symbol *symlist =0; /* symbol table: linked list */


Symbol *lookup(s) /* find s in symbol table */

 char *s;

{

 Symbol *sp;


 for (sp = symlist; sp != (Symbol*)0; sp = sp->next)

  if (strcmp(sp->name, s) == 0)

   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 '' */

 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;

}

3.5 hoc4

3.5.1 code.c

#include "hoc.h"

#include "y.tab.h"


#define NSTACK 256

static Datum stack[NSTACK]; /* the stack */

static Datum *stackp; /* next free spot on stack */


#define NPROG 2000

Inst prog[NPROG]; /* the machine */

Inst *progp; /* next free spot for code generation */

Inst *pc; /* program counter during execution */


initcode() /* initialize for code generation */

{

 stackp = stack;

 progp = prog;

}


push(d) /* push d onto stack */

 Datum d;

{

 if (stackp >= &stack[NSTACK])

  execerror("stack overflow", (char*)0);

 *stackp++ = d;

}


Datum pop() /* pop and return top elem from stack */

{

 if (stackp <= stack)

  execerror("stack underflow", (char*)0);

 return *--stackp;

}


constpush() /* push constant onto stack */

{

 Datum d;

 d.val = ((Symbol*)*pc++)->u.val;

 push(d);

}


varpush() /* push variable onto stack */

{

 Datum d;

 d.sym = (Symbol*)(*pc++);

 push(d);

}


bltin() /* evaluate built-in on top of stack */

{

 Datum d;

 d = pop();

 d.val = (*(double(*)())(*pc++))(d.val);

 push(d);

}


eval() /* evaluate variable on stack */

{

 Datum d;

 d = pop() ;

 if (d.sym->type == UNDEF)

  execerror("undefined variable", d.sym->name);

 d.val = d.sym->u.val;

 push(d);

}


add() /* add top two elems on stack */

{

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val += d2.val;

 push(d1);

}


sub() /* subtract top of stack from next */

{

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 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();

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*