#include #include #include #include char var_eof[2] = {-1, 0}; char var_eol[2] = {10, 0}; char var_quote[2] = {34, 0}; char var_false[1] = {0}; char var_true[2] = {'1', 0}; char * eq(char * a, char * b) { return (strcmp(a, b) == 0) ? var_true : var_false; } char * lt(char * a, char * b) { return (strcmp(a, b) < 0) ? var_true : var_false; } char * not(char * a) { return (strcmp(a, var_true) != 0) ? var_true : var_false; } char * addstringchar(char * str, char * chr) { int str_len = strlen(str); assert(strlen(chr) == 1); char * res = malloc((str_len + 2) * sizeof(char)); strcpy(res, str); res[str_len + 0] = chr[0]; res[str_len + 1] = 0; return res; } char * emit(char * str) { fputs(str, stdout); return 0; } char * trace(char * var_name, char * var_value) { const char * env_trace = getenv("TRACE"); if( !env_trace ) return 0; fputs(var_name, stderr); fputs("=", stderr); fputs(var_value, stderr); fputs(var_eol, stderr); return 0; } int LINE = 1; char * peek() { char * res = malloc(2*sizeof(char)); res[0] = getc(stdin); res[1] = 0; ungetc(res[0], stdin); return res; } void skip() { char c = getc(stdin); if( c == 10 ) LINE += 1; } void skipchar(char * chr) { assert(strlen(chr) == 1); char * act = peek(); assert(strlen(act) == 1); if( chr[0] == act[0] ) {skip(); return;}; fprintf(stderr, "Expected '%c' on line %d but saw '%c' instead%c", chr[0], LINE, act[0], 10); exit(1); } char * increaseindent(char * var_indent) { var_indent = addstringchar(var_indent, " "); var_indent = addstringchar(var_indent, " "); var_indent = addstringchar(var_indent, " "); var_indent = addstringchar(var_indent, " "); return var_indent; } char * lexident() { char * var_char; char * var_isbeforea; char * var_isafterz; char * var_word; var_word = ""; while (1) { var_char = peek(); var_isbeforea = lt(var_char, "a"); if ( 0 < strlen(var_isbeforea) ) { break; } var_isafterz = lt("z", var_char); if ( 0 < strlen(var_isafterz) ) { break; } var_word = addstringchar(var_word, var_char); skip(); } return var_word; } char * parseconststring() { char * var_char; char * var_iseof; char * var_isquote; skipchar(var_quote); while (1) { var_char = peek(); var_iseof = eq(var_char, var_eof); if ( 0 < strlen(var_iseof) ) { break; } var_isquote = eq(var_char, var_quote); if ( 0 < strlen(var_isquote) ) { break; } skip(); } skipchar(var_quote); emit("i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)"); return 0; } char * parseexprvarref() { char * var_varname; var_varname = lexident(); emit("i8* %"); emit(var_varname); return 0; } char * parseexprcall() { char * var_char; char * var_first; char * var_funcname; char * var_isspace; char * var_isnotspace; char * var_isfirst; char * var_isnotfirst; char * var_isquote; char * var_isnotquote; var_funcname = lexident(); emit(var_funcname); emit("("); var_first = "1"; while (1) { var_char = peek(); var_isspace = eq(var_char, " "); var_isnotspace = not(var_isspace); if ( 0 < strlen(var_isnotspace) ) { break; } skip(); var_isfirst = eq(var_first, "1"); var_isnotfirst = not(var_isfirst); if ( 0 < strlen(var_isnotfirst) ) { emit(", "); } var_char = peek(); var_isquote = eq(var_char, var_quote); var_isnotquote = not(var_isquote); if ( 0 < strlen(var_isquote) ) { parseconststring(); } if ( 0 < strlen(var_isnotquote) ) { parseexprvarref(); } var_first = "0"; } emit(")"); return 0; } char * parsestatdeclare(char * var_indent) { char * var_var; skipchar(" "); var_var = lexident(); emit(var_indent); emit("char * var_"); emit(var_var); emit(";"); emit(var_eol); skipchar(var_eol); return 0; } char * parsestatset(char * var_indent) { char * var_var; skipchar(" "); var_var = lexident(); skipchar(" "); emit(var_indent); emit("var_"); emit(var_var); emit(" = "); parseconststring(); emit(";"); emit(var_eol); skipchar(var_eol); return 0; } char * parsestatcalc(char * var_indent) { char * var_var; char * var_varidx; skipchar(" "); var_var = lexident(); skipchar(" "); emit(var_indent); emit("%"); emit(var_var); var_varidx = mapgetkey("funcvarused", var_var); var_varidx = intinc(var_varidx); mapsetkey("funcvarused"var_var, var_varidx, ); emit("."); emit(var_varidx); emit(" = call i8* @"); parseexprcall(); emit(";"); emit(var_eol); skipchar(var_eol); return 0; } char * parseblock(char * var_indent); char * parsestatif(char * var_indent) { char * var_indentt; skipchar(" "); emit(var_indent); emit("if ( 0 < strlen("); parseexprvarref(); emit(") )\n"); emit(var_indent); emit("{\n"); skipchar(var_eol); var_indentt = increaseindent(var_indent); parseblock(var_indentt); emit(var_indent); emit("}\n"); return 0; } char * parsestatforever(char * var_indent) { char * var_indentt; emit(var_indent); emit("while (1)\n"); emit(var_indent); emit("{\n"); skipchar(var_eol); var_indentt = increaseindent(var_indent); parseblock(var_indentt); emit(var_indent); emit("}\n"); return 0; } char * parsestatbreak(char * var_indent) { emit(var_indent); emit("break;\n"); skipchar(var_eol); return 0; } char * parsestatreturn(char * var_indent) { char * var_char; char * var_isspace; char * var_isnotspace; emit(var_indent); emit("ret "); var_char = peek(); var_isspace = eq(var_char, " "); var_isnotspace = not(var_isspace); if ( 0 < strlen(var_isspace) ) { skip(); parseexprvarref(); } if ( 0 < strlen(var_isnotspace) ) { emit("i18* 0"); } emit(";"); emit(var_eol); skipchar(var_eol); return 0; } char * parsestattrace(char * var_indent) { char * var_varname; emit(var_indent); emit("trace("); emit(var_quote); skipchar(" "); var_varname = lexident(); emit(var_varname); emit(var_quote); emit(", var_"); emit(var_varname); emit(");\n"); skipchar(var_eol); return 0; } char * parsestat(char * var_indent) { char * var_call; char * var_char; char * var_first; char * var_iscall; char * var_isfirst; char * var_isspace; char * var_isquote; char * var_isnotfirst; char * var_isnotspace; char * var_isnotquote; var_call = lexident(); trace("call", var_call); var_iscall = eq(var_call, "declare"); if ( 0 < strlen(var_iscall) ) { parsestatdeclare(var_indent); return 0; } var_iscall = eq(var_call, "set"); if ( 0 < strlen(var_iscall) ) { parsestatset(var_indent); return 0; } var_iscall = eq(var_call, "calc"); if ( 0 < strlen(var_iscall) ) { parsestatcalc(var_indent); return 0; } var_iscall = eq(var_call, "if"); if ( 0 < strlen(var_iscall) ) { parsestatif(var_indent); return 0; } var_iscall = eq(var_call, "forever"); if ( 0 < strlen(var_iscall) ) { parsestatforever(var_indent); return 0; } var_iscall = eq(var_call, "break"); if ( 0 < strlen(var_iscall) ) { parsestatbreak(var_indent); return 0; } var_iscall = eq(var_call, "return"); if ( 0 < strlen(var_iscall) ) { parsestatreturn(var_indent); return 0; } var_iscall = eq(var_call, "trace"); if ( 0 < strlen(var_iscall) ) { parsestattrace(var_indent); return 0; } emit(var_indent); emit(var_call); emit("("); var_first = "1"; while (1) { var_char = peek(); var_isspace = eq(var_char, " "); var_isnotspace = not(var_isspace); if ( 0 < strlen(var_isnotspace) ) { break; } skip(); var_char = peek(); var_isquote = eq(var_char, var_quote); var_isnotquote = not(var_isquote); if ( 0 < strlen(var_isquote) ) { parseconststring(); } if ( 0 < strlen(var_isnotquote) ) { parseexprvarref(); } var_isfirst = eq(var_first, "1"); var_isnotfirst = not(var_isfirst); if ( 0 < strlen(var_isnotfirst) ) { emit(", "); } var_first = "0"; } skipchar(var_eol); emit(");\n"); return 0; } char * parseblock(char * var_indent) { char * var_char; char * var_copy; char * var_iseol; char * var_isnoteol; char * var_isdone; char * var_iseoblock; while (1) { while (1) { var_char = peek(); var_iseol = eq(var_char, var_eol); var_isnoteol = not(var_iseol); if ( 0 < strlen(var_isnoteol) ) { break; } skip(); } var_copy = " "; while (1) { var_isdone = eq(var_copy, var_indent); if ( 0 < strlen(var_isdone) ) { break; } skipchar("\t"); var_copy = increaseindent(var_copy); } var_char = peek(); var_iseoblock = eq(var_char, "/"); if ( 0 < strlen(var_iseoblock) ) { skip(); skipchar(var_eol); break; } skipchar("\t"); parsestat(var_indent); } return 0; } char * parsefunc() { char * var_char; char * var_first; char * var_funcname; char * var_iseoblock; char * var_isfirst; char * var_isspace; char * var_isnotfirst; char * var_isnotspace; char * var_var; mapclear("funcvarused"); var_funcname = lexident(); trace("funcname", var_funcname); emit("define i8* @"); emit(var_funcname); emit("("); var_first = "1"; while (1) { var_char = peek(); var_isspace = eq(var_char, " "); var_isnotspace = not(var_isspace); if ( 0 < strlen(var_isnotspace) ) { break; } skip(); var_var = lexident(); var_isfirst = eq(var_first, "1"); var_isnotfirst = not(var_isfirst); if ( 0 < strlen(var_isnotfirst) ) { emit(", "); } emit("i8* %"); emit(var_var); mapsetkey("funcvarused""var", "0", ); emit("_0"); var_first = "0"; } var_char = peek(); var_iseoblock = eq(var_char, "/"); if ( 0 < strlen(var_iseoblock) ) { skipchar("/"); skipchar(var_eol); emit(");"); emit("\n"); return 0; } skipchar(":"); skipchar(var_eol); emit(")\n{\n"); parseblock(" "); emit("}\n\n"); return 0; } char * emitheader() { emit("target datalayout = "); emit(var_quote); emit("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"); emit(var_quote); emit(var_eol); emit("target triple = "); emit(var_quote); emit("x86_64-pc-linux-gnu"); emit(var_quote); emit(var_eol); emit(var_eol); emit("define i8* @addstringchar(i8* %0, i8* %1)"); emit(var_eol); emit("{"); emit(var_eol); emit(" ; todo"); emit(var_eol); emit(" ret i8* %0;"); emit(var_eol); emit("}"); emit(var_eol); emit(var_eol); return 0; } char * emitfooter() { emit(""); return 0; } char * main() { char * var_char; char * var_iseof; char * var_iseol; char * var_isnoteol; emitheader(); while (1) { var_char = peek(); var_iseof = eq(var_char, var_eof); if ( 0 < strlen(var_iseof) ) { break; } while (1) { var_char = peek(); var_iseol = eq(var_char, var_eol); var_isnoteol = not(var_iseol); if ( 0 < strlen(var_isnoteol) ) { break; } skip(); } parsefunc(); } emitfooter(); return 0; }