From 8cca4d1fe83f792d0f3c5dd897611ea2ff441de0 Mon Sep 17 00:00:00 2001 From: rodri Date: Sat, 31 Aug 2024 16:07:15 +0000 Subject: stage 3. --- s3/builtin.c | 46 ++++++++++++++++ s3/dat.h | 23 ++++++++ s3/fns.h | 7 +++ s3/mkfile | 16 ++++++ s3/rhoc.y | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ s3/sym.c | 31 +++++++++++ 6 files changed, 295 insertions(+) create mode 100644 s3/builtin.c create mode 100644 s3/dat.h create mode 100644 s3/fns.h create mode 100644 s3/mkfile create mode 100644 s3/rhoc.y create mode 100644 s3/sym.c (limited to 's3') diff --git a/s3/builtin.c b/s3/builtin.c new file mode 100644 index 0000000..e9208cf --- /dev/null +++ b/s3/builtin.c @@ -0,0 +1,46 @@ +#include +#include +#include "dat.h" +#include "fns.h" +#include "y.tab.h" + +static Const consts[] = { + "π", 3.14159265358979323846, + "e", 2.71828182845904523536, + "γ", 0.57721566490153286060, + "DEG", 57.29577951308232087680, + "Φ", 1.61803398874989484820, +}; + +static Builtin builtins[] = { + "sin", sin, + "cos", cos, + "atan", atan, + "atan2", atan2, + "log", log, + "log10", log10, + "exp", exp, + "sqrt", sqrt, + "int", round, + "abs", fabs, +}; + +double +round(double n) +{ + return floor(n + 0.5); +} + +void +init(void) +{ + Symbol *s; + int i; + + for(i = 0; i < nelem(consts); i++) + install(consts[i].name, CONST, consts[i].val); + for(i = 0; i < nelem(builtins); i++){ + s = install(builtins[i].name, BLTIN, 0); + s->u.fn = builtins[i].fn; + } +} diff --git a/s3/dat.h b/s3/dat.h new file mode 100644 index 0000000..9cdb6c7 --- /dev/null +++ b/s3/dat.h @@ -0,0 +1,23 @@ +typedef struct Symbol Symbol; +typedef struct Const Const; +typedef struct Builtin Builtin; + +struct Symbol { + char *name; + int type; + union { + double val; + double (*fn)(double); + } u; + Symbol *next; +}; + +struct Const { + char *name; + double val; +}; + +struct Builtin { + char *name; + double (*fn)(); +}; diff --git a/s3/fns.h b/s3/fns.h new file mode 100644 index 0000000..3591979 --- /dev/null +++ b/s3/fns.h @@ -0,0 +1,7 @@ +int yyparse(void); + +Symbol *install(char *, int, double); +Symbol *lookup(char *); +double round(double); +void init(void); +void *emalloc(ulong); diff --git a/s3/mkfile b/s3/mkfile new file mode 100644 index 0000000..70aeac7 --- /dev/null +++ b/s3/mkfile @@ -0,0 +1,16 @@ + NUMBER +%token VAR CONST BLTIN UNDEF +%type expr asgn +%right '=' +%left '+' '-' +%left '*' '/' +%left '%' +%right '^' +%left UMINUS +%% +list: /* ε */ + | list '\n' + | list asgn '\n' + | list expr '\n' { print("\t%.8g\n", $2); } + | list error '\n' { yyerrok; } + ; +asgn: VAR '=' expr + { + if($1->type == CONST) + rterror("assignment to constant"); + $$ = $1->u.val = $3; + $1->type = VAR; + } + ; +expr: NUMBER + | VAR + { + if($1->type == UNDEF) + rterror("undefined variable"); + $$ = $1->u.val; + } + | asgn + | BLTIN '(' expr ')' { $$ = $1->u.fn($3); } + | '-' expr %prec UMINUS { $$ = -$2; } + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr + { + if($3 == 0) + rterror("division by zero"); + $$ = $1 / $3; + } + | expr '%' expr { $$ = fmod($1, $3); } + | expr '^' expr { $$ = pow($1, $3); } + | expr '(' expr ')' { $$ = $1 * $3; } + | '(' expr ')' { $$ = $2; } + ; +%% +#include +#include +#include +#include +#include "fns.h" + +Biobuf *bin; +jmp_buf begin; +int lineno; +int prompt; + +void * +emalloc(ulong n) +{ + void *p; + + p = malloc(n); + if(p == nil) + sysfatal("malloc: %r"); + memset(p, 0, n); + setmalloctag(p, getcallerpc(&n)); + return p; +} + +void +yyerror(char *msg) +{ + fprint(2, "%s at line %d\n", msg, lineno); +} + +void +rterror(char *msg) +{ + fprint(2, "%s at line %d\n", msg, lineno-1); + longjmp(begin, 0); +} + +int +catch(void *ureg, char *msg) +{ + if(strncmp(msg, "sys: fp", 7) == 0){ + yyerror("floating point exception"); + notejmp(ureg, begin, 0); + } + return 0; +} + +int +yylex(void) +{ + Symbol *s; + char sname[256], *p; + Rune r; + + if(prompt){ + print("%d: ", lineno); + prompt--; + } + while((r = Bgetrune(bin)) == ' ' || r == '\t') + ; + if(r == Beof) + return 0; + if(r == '.' || isdigitrune(r)){ + Bungetrune(bin); + Bgetd(bin, &yylval.val); + return NUMBER; + } + if(isalpharune(r)){ + p = sname; + do{ + if(p+runelen(r) - sname >= sizeof(sname)) + return r; /* force syntax error. */ + p += runetochar(p, &r); + }while((r = Bgetrune(bin)) != Beof && + (isalpharune(r) || isdigitrune(r))); + Bungetrune(bin); + *p = 0; + if((s = lookup(sname)) == nil) + s = install(sname, UNDEF, 0); + yylval.sym = s; + return s->type == UNDEF || s->type == CONST ? VAR : s->type; + } + if(r == '\n'){ + lineno++; + prompt++; + } + return r; +} + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + ARGBEGIN{ + default: usage(); + }ARGEND; + if(argc > 0) + usage(); + atnotify(catch, 1); + bin = Bfdopen(0, OREAD); + if(bin == nil) + sysfatal("Bfdopen: %r"); + lineno++; + prompt++; + init(); + setjmp(begin); + yyparse(); + Bterm(bin); + exits(0); +} diff --git a/s3/sym.c b/s3/sym.c new file mode 100644 index 0000000..8749791 --- /dev/null +++ b/s3/sym.c @@ -0,0 +1,31 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +static Symbol *symtab; + +Symbol * +install(char *s, int t, double v) +{ + Symbol *sym; + + sym = emalloc(sizeof(Symbol)); + sym->name = strdup(s); + sym->type = t; + sym->u.val = v; + sym->next = symtab; + symtab = sym; + return sym; +} + +Symbol * +lookup(char *s) +{ + Symbol *sym; + + for(sym = symtab; sym != nil; sym = sym->next) + if(strcmp(sym->name, s) == 0) + return sym; + return nil; +} -- cgit v1.2.3