diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Makefile | 27 | ||||
-rwxr-xr-x | e | 4 | ||||
-rw-r--r-- | e.l | 57 | ||||
-rw-r--r-- | e.y | 117 | ||||
-rwxr-xr-x | examples/factorial | bin | 0 -> 15688 bytes | |||
-rw-r--r-- | examples/factorial.e | 16 | ||||
-rw-r--r-- | lib.c | 7 | ||||
-rw-r--r-- | qbe.c | 122 | ||||
-rw-r--r-- | qbe.h | 6 | ||||
-rw-r--r-- | types.h | 18 |
11 files changed, 378 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d48ea8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +eqbe +y.* +lex.* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ea84791 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +e: lex.yy.c y.tab.c qbe.o + cc lex.yy.c y.tab.c qbe.o -o eqbe + +lib.o: lib.c + cc lib.c -c -o lib.o + +qbe.o: qbe.c + cc qbe.c -c -o qbe.o + +lex.yy.c: y.tab.c e.l + lex e.l + +y.tab.c: e.y + yacc -d e.y + +clean: + rm -rf lex.yy.c y.tab.c y.tab.h eqbe *.o + +install: e lib.o + chmod +x ./e + cp e eqbe /usr/local/bin + cp lib.o /usr/local/share/ + +uninstall: + rm -rf /usr/local/bin/{e,eqbe} + rm -rf /usr/local/share/lib.o + @@ -0,0 +1,4 @@ +#!/bin/sh + +eqbe < $1 | qbe > /tmp/tmp.s +cc /usr/local/share/lib.o /tmp/tmp.s -o $2 @@ -0,0 +1,57 @@ +%{ +#include "types.h" +#include "y.tab.h" +#include <stdlib.h> +%} + +%option noyywrap +%option yylineno + +%% +[0-9]+ { + yylval.intlit = atoi(yytext); + return INTLIT; +} + +[A-Z] { + yylval.funcname = yytext[0]; + return FUNCTIONNAME; +} + + +[a-z] { + yylval.varname = yytext[0]; + return VARNAME; +} + +[-=+*/{}:] { + return yytext[0]; +} + +dec { + return FUNCTIONDEC; +} + +print { + return PRINT; +} + +input { + return INPUT; +} + +ret { + return RET; +} + +jmp { + return JMP; +} + +jnz { + return JNZ; +} + + +[:\n\t\v ] {;} +%% @@ -0,0 +1,117 @@ +%{ +#include <stdio.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include "types.h" +#include "qbe.h" + +extern int yylex(); +extern int yylineno; +extern char *yytext; +void yyerror(const char* s); + +exp *exprs[1024]; +int exprcount = 0; + + +function *funcs[1024]; +int funccount = 0; + +exp *newexpr(char name, char op, int val, bool isvar) { + exp *e = malloc(sizeof(exp)); + + e->name = name; + e->op = op; + e->var = isvar; + e->v = val; +} + +void appendexpr(exp *e) { + exprs[exprcount] = e; + exprcount++; +} + +void appendfunction(function *f) { + funcs[funccount] = f; + funccount++; +} + +function *copyexprsandclear(char name) { + function *f = malloc(sizeof(function)); + f->name = name; + memcpy(f->exprs, exprs, sizeof(exp) * 1024); + f->exprcount = exprcount; + + exprcount = 0; +} + +%} + + +%union { + char funcname; + char varname; + int intlit; + exp *expr; +} + +%token <intlit> INTLIT +%token <funcname> FUNCTIONNAME +%token <varname> VARNAME +%token FUNCTIONDEC +%token PRINT +%token INPUT +%token RET +%token JMP +%token JNZ + +%type <expr> EXPR + +%% +PROG : PROG F + | F + ; + +F : FUNCTIONDEC FUNCTIONNAME '{' EXPRS '}' {appendfunction(copyexprsandclear($2));} + ; + +EXPRS : EXPRS EXPR {appendexpr($2);} + | EXPR {appendexpr($1);} + ; + +EXPR : VARNAME {$$ = newexpr($1, 0, 0, false);} + | VARNAME '=' INTLIT {$$ = newexpr($1, '=', $3, false);} + | VARNAME '+' INTLIT {$$ = newexpr($1, '+', $3, false);} + | VARNAME '-' INTLIT {$$ = newexpr($1, '-', $3, false);} + | VARNAME '*' INTLIT {$$ = newexpr($1, '*', $3, false);} + | VARNAME '/' INTLIT {$$ = newexpr($1, '/', $3, false);} + + | VARNAME '=' VARNAME {$$ = newexpr($1, '=', $3, true);} + | VARNAME '+' VARNAME {$$ = newexpr($1, '+', $3, true);} + | VARNAME '-' VARNAME {$$ = newexpr($1, '-', $3, true);} + | VARNAME '*' VARNAME {$$ = newexpr($1, '*', $3, true);} + | VARNAME '/' VARNAME {$$ = newexpr($1, '/', $3, true);} + + + | PRINT VARNAME {$$ = newexpr($2, 'p', 0, false);} + | VARNAME '=' INPUT {$$ = newexpr($1, 'i', 0, false);} + | VARNAME '=' FUNCTIONNAME {$$ = newexpr($1, 'c', $3, false);} + | RET VARNAME {$$ = newexpr($2, 'r', 0, false);} + + | VARNAME ':' {$$ = newexpr($1, 'l', 0, false);} + | JMP VARNAME ':' {$$ = newexpr($2, 'j', 0, false);} + | JNZ VARNAME VARNAME ':' {$$ = newexpr($3, 'z', $2, false);} + ; +%% +void yyerror(const char *msg) { + fprintf(stderr, "%d:%s\n%s\n", yylineno, msg, yytext); +} + +int main() { + yyparse(); + + compile(stdout, funcs, funccount); + + return 0; +} diff --git a/examples/factorial b/examples/factorial Binary files differnew file mode 100755 index 0000000..c51b931 --- /dev/null +++ b/examples/factorial diff --git a/examples/factorial.e b/examples/factorial.e new file mode 100644 index 0000000..7cdd3ed --- /dev/null +++ b/examples/factorial.e @@ -0,0 +1,16 @@ +dec F { + a = input + t = 1 +l: + t * a + a - 1 + jnz a l: + ret t +} + +dec M { +l: + a = F + print a + jmp l: +} @@ -0,0 +1,7 @@ +#include <stdio.h> + +int readint() { + int i = 0; + scanf("%d", &i); + return i; +} @@ -0,0 +1,122 @@ +#include <stdio.h> +#include "types.h" + +int endcount = 0; + +void compileexpr(FILE *f, exp *e) { + switch (e->op) { + case '+': + if (e->var) + fprintf(f, + "%%%c =w add %%%c, %%%c\n", + e->name, e->name, e->vv); + else + fprintf(f, + "%%%c =w add %%%c, %d\n", + e->name, e->name, e->v); + break; + case '-': + if (e->var) + fprintf(f, + "%%%c =w sub %%%c, %%%c\n", + e->name, e->name, e->vv); + else + fprintf(f, + "%%%c =w sub %%%c, %d\n", + e->name, e->name, e->v); + break; + case '*': + if (e->var) + fprintf(f, + "%%%c =w mul %%%c, %%%c\n", + e->name, e->name, e->vv); + else + fprintf(f, + "%%%c =w mul %%%c, %d\n", + e->name, e->name, e->v); + break; + case '/': + if (e->var) + fprintf(f, + "%%%c =w div %%%c, %%%c\n", + e->name, e->name, e->vv); + else + fprintf(f, + "%%%c =w div %%%c, %d\n", + e->name, e->name, e->v); + break; + + case 0: + fprintf(f, + "%%%c =w copy 0\n", + e->name); + break; + + case '=': + fprintf(f, + "%%%c =w copy %d\n", + e->name, e->v); + break; + + case 'p': + fprintf(f, + "call $printf(l $fmt, ..., w %%%c)\n", + e->name); + break; + + case 'i': + fprintf(f, + "%%%c =w call $readint()\n", + e->name); + break; + + case 'r': + fprintf(f, + "ret %%%c\n", + e->name); + break; + case 'l': + fprintf(f, + "@label%c\n", + e->name); + break; + case 'j': + fprintf(f, + "jmp @label%c\n", + e->name); + break; + case 'z': + fprintf(f, + "jnz %%%c, @label%c, @end%d\n@end%d\n", + e->vv, e->name, endcount, endcount); + endcount++; + break; + default: + fprintf(f, + "%%%c =w call $%c()\n", + e->name, e->vv); + break; + + } +} + +void compilefunc(FILE *file, function *f) { + if (f->name == 'M') + fprintf(file, "export function w $main() {\n@start\n"); + else + fprintf(file, "export function w $%c() {\n@start\n", f->name); + + for (int i = 0; i < f->exprcount; i++) { + compileexpr(file, f->exprs[i]); + } + + fprintf(file, "}\n"); +} + +void compile(FILE *file, function *f[], int count) { + for (int i = 0; i < count; i++) { + compilefunc(file, f[i]); + } + printf("data $fmt = { b \"%%d\\n\", b 0 }\n"); + printf("data $fmtin = { b \"%%d\", b 0 }\n"); +} @@ -0,0 +1,6 @@ +#include <stdio.h> + +void compileexpr(FILE *f, exp *e); +void compilefunc(FILE *file, function *f); +void compile(FILE *file, function *f[], int count); + @@ -0,0 +1,18 @@ +#include <stdbool.h> + +typedef struct exp { + char name; + char op; + + bool var; + union { + int v; + char vv; + }; +} exp; + +typedef struct function { + exp *exprs[1024]; + int exprcount; + char name; +} function; |