diff options
author | crupest <crupest@outlook.com> | 2021-11-22 20:53:01 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-11-22 20:53:01 +0800 |
commit | 226bfe84c5f690462adbf386dc66316cc21fdb28 (patch) | |
tree | d2a3ed9ab5f176cd0f848b1febf741f201c19f03 /works/life | |
parent | 205f243379919b7830726f9dcc4ae7d33c84e857 (diff) | |
download | crupest-226bfe84c5f690462adbf386dc66316cc21fdb28.tar.gz crupest-226bfe84c5f690462adbf386dc66316cc21fdb28.tar.bz2 crupest-226bfe84c5f690462adbf386dc66316cc21fdb28.zip |
import(life): Add compile principle codes.
Diffstat (limited to 'works/life')
-rw-r--r-- | works/life/compile-principle-experiment/1/hoc.y | 65 | ||||
-rw-r--r-- | works/life/compile-principle-experiment/1/makefile | 5 | ||||
-rw-r--r-- | works/life/compile-principle-experiment/2/hoc.y | 106 | ||||
-rw-r--r-- | works/life/compile-principle-experiment/2/makefile | 5 |
4 files changed, 181 insertions, 0 deletions
diff --git a/works/life/compile-principle-experiment/1/hoc.y b/works/life/compile-principle-experiment/1/hoc.y new file mode 100644 index 0000000..c4452ad --- /dev/null +++ b/works/life/compile-principle-experiment/1/hoc.y @@ -0,0 +1,65 @@ +%{ +#define YYSTYPE double /* data type of yacc stack */ +#include <stdio.h> +#include <ctype.h> +#include <math.h> + +int yylex(); +int yyerror(const char * s); +%} +%token NUMBER +%left '+' '-' /* left associative, same precedence */ +%left '*' '/' '%' /* left assoc., higher precedence */ +%left UNARYMINUS +%% +list: /* nothing */ + | list '\n' + | list expr '\n' { printf("%lf\n", $2); } + ; +expr: NUMBER { $$ = $1; } + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr { $$ = $1 / $3; } + | expr '%' expr { $$ = fmod($1, $3); } + | '-' expr %prec UNARYMINUS { $$ = -$2; } + | '(' expr ')' { $$ = $2; } + ; +%% + +int lineno = 1; + +int main(int argc, char** argv) +{ + yyparse(); + return 0; +} + +int yylex() +{ + int c; + + do { + c = getchar(); + } while (c == ' ' || c == '\t'); + + if (c == EOF) + return 0; + + if (c == '.' || isdigit(c)) { + ungetc(c, stdin); + scanf("%lf", &yylval); + return NUMBER; + } + + if (c == '\n') + lineno++; + + return c; +} + +int yyerror(const char* s) +{ + fprintf(stderr, "Error occured near line %d\n", lineno); + return 0; +} diff --git a/works/life/compile-principle-experiment/1/makefile b/works/life/compile-principle-experiment/1/makefile new file mode 100644 index 0000000..65bcca2 --- /dev/null +++ b/works/life/compile-principle-experiment/1/makefile @@ -0,0 +1,5 @@ +hoc: hoc.c + cc hoc.c -o hoc + +hoc.c: hoc.y + bison hoc.y -o hoc.c diff --git a/works/life/compile-principle-experiment/2/hoc.y b/works/life/compile-principle-experiment/2/hoc.y new file mode 100644 index 0000000..14500bb --- /dev/null +++ b/works/life/compile-principle-experiment/2/hoc.y @@ -0,0 +1,106 @@ +%{ +#include <stdio.h> +#include <ctype.h> +#include <math.h> + +int yylex(); +int yyerror(const char * s); +void execerror(const char* s, const char* t); +void warning(const char* s, const char* t); + +double mem[26]; /* memory for variables 'a'..'z' */ +%} + +%union { /* stack type */ + double val; /* actual value */ + int index; /* index into mem[] */ +} +%token <val> NUMBER +%token <index> VAR +%type <val> expr +%right '=' +%left '+' '-' +%left '*' '/' +%left UNARYMINUS +%% +list: /* nothing */ + | list '\n' + | list expr '\n' { printf("\t%.8g\n", $2); } + | list error '\n' { yyerrok; } + ; +expr: NUMBER + | VAR { $$ = mem[$1]; } + | VAR '=' expr { $$ = mem[$1] = $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 ')' { $$ = $2; } + | '-' expr %prec UNARYMINUS { $$ = -$2; } + ; +%% + /* end of grammar */ + +int lineno = 1; +#include <signal.h> +#include <setjmp.h> +jmp_buf begin; + +void fpecatch(int s); + +int main(int argc, char** argv) +{ + (void)setjmp(begin); + signal(SIGFPE, fpecatch); + yyparse(); +} + +int yylex() +{ + int c; + + while ((c=getchar()) == ' ' || c == '\t') + ; + if (c == EOF) + return 0; + if (c == '.' || isdigit(c)) { /* number */ + ungetc(c, stdin); + scanf("%lf", &yylval.val); + return NUMBER; + } + if (islower(c)) { + yylval.index = c - 'a'; /* ASCII only */ + return VAR; + } + if (c == '\n') + lineno++; + return c; +} + +int yyerror(const char *s) +{ + warning(s, (char *)0); + return 0; +} + +void execerror(const char* s, const char* t) +{ + warning(s, t); + longjmp(begin, 0); +} + +void fpecatch(int s) +{ + execerror("floating point exception", (char *) 0); +} + +void warning(const char* s, const char* t) +{ + fprintf(stderr, "%s", s); + if (t && *t) + fprintf(stderr, " %s", t); + fprintf(stderr, " near line %d\n", lineno); +} diff --git a/works/life/compile-principle-experiment/2/makefile b/works/life/compile-principle-experiment/2/makefile new file mode 100644 index 0000000..65bcca2 --- /dev/null +++ b/works/life/compile-principle-experiment/2/makefile @@ -0,0 +1,5 @@ +hoc: hoc.c + cc hoc.c -o hoc + +hoc.c: hoc.y + bison hoc.y -o hoc.c |