From 53d3939960fe177c1958bce8e93c435cba7cf5e3 Mon Sep 17 00:00:00 2001 From: rodri Date: Sat, 31 Aug 2024 16:07:04 +0000 Subject: stage 2. --- s2/mkfile | 10 +++++ s2/rhoc.y | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 s2/mkfile create mode 100644 s2/rhoc.y (limited to 's2') diff --git a/s2/mkfile b/s2/mkfile new file mode 100644 index 0000000..b60aa5d --- /dev/null +++ b/s2/mkfile @@ -0,0 +1,10 @@ + NUMBER +%token VAR +%type expr +%right '=' +%left '+' '-' +%left '*' '/' +%left UNMIN +%% +list: /* ε */ + | list '\n' + | list expr '\n' { print("\t%.8g\n", $2); } + | list expr ';' { print("\t%.8g\n", $2); } + | list error '\n' { yyerrok; } + ; +expr: NUMBER + | VAR { $$ = mem[$1]; } + | VAR '=' expr { $$ = mem[$1] = $3; } + | '-' expr %prec UNMIN { $$ = -$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 ')' { $$ = $1 * $3; } + | '(' expr ')' { $$ = $2; } + ; +%% +#include +#include +#include +#include + +Biobuf *bin; +jmp_buf begin; +int lineno; +int prompt; + +int yyparse(void); + +void +error(char *msg, int ln) +{ + fprint(2, "%s at line %d\n", msg, ln); +} + +void +yyerror(char *msg) +{ + error(msg, lineno); +} + +int +yylex(void) +{ + int c; + + if(prompt){ + print("%d: ", lineno); + prompt--; + } + while((c = Bgetc(bin)) == ' ' || c == '\t') + ; + if(c == '.' || isdigit(c)){ + Bungetc(bin); + Bgetd(bin, &yylval.val); + return NUMBER; + } + if(islower(c)){ + yylval.idx = c - 'a'; + return VAR; + } + if(c == '\n'){ + lineno++; + prompt++; + } + return c; +} + +void +rterror(char *msg) +{ + error(msg, lineno-1); + longjmp(begin, 0); +} + +int +catch(void *ureg, char *msg) +{ + if(strncmp(msg, "sys: fp", 7) == 0){ + error("floating point exception", lineno-1); + notejmp(ureg, begin, 0); + } + return 0; +} + +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(); + bin = Bfdopen(0, OREAD); + if(bin == nil) + sysfatal("Bfdopen: %r"); + lineno++; + prompt++; + setjmp(begin); + atnotify(catch, 1); + yyparse(); + Bterm(bin); + exits(0); +} -- cgit v1.2.3