aboutsummaryrefslogtreecommitdiff
path: root/works/life
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-11-22 20:53:01 +0800
committercrupest <crupest@outlook.com>2021-11-22 20:53:01 +0800
commit226bfe84c5f690462adbf386dc66316cc21fdb28 (patch)
treed2a3ed9ab5f176cd0f848b1febf741f201c19f03 /works/life
parent205f243379919b7830726f9dcc4ae7d33c84e857 (diff)
downloadcrupest-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.y65
-rw-r--r--works/life/compile-principle-experiment/1/makefile5
-rw-r--r--works/life/compile-principle-experiment/2/hoc.y106
-rw-r--r--works/life/compile-principle-experiment/2/makefile5
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