Skip to content

Instantly share code, notes, and snippets.

@forestbelton
Created April 6, 2013 04:01
Show Gist options
  • Save forestbelton/5324716 to your computer and use it in GitHub Desktop.
Save forestbelton/5324716 to your computer and use it in GitHub Desktop.
Brainfuck compiler
%option noyywrap
%{
/*
* Copyright (c) 2010 Forest Belton (apples)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <string.h>
FILE *tmp;
void bf_decval(FILE *out, size_t count) {
if(count == 1)
fprintf(out, " decb (%%edi)\n");
else
fprintf(out, " sub $0x%x, (%%edi)\n", count & 0xff);
}
void bf_incval(FILE *out, size_t count) {
if(count == 1)
fprintf(out, " incb (%%edi)\n");
else
fprintf(out, " addb $0x%x, (%%edi)\n", count & 0xff);
}
void bf_decptr(FILE *out, size_t count) {
if(count == 1)
fprintf(out, " decl %%edi\n");
else
fprintf(out, " subl $0x%x, %%edi\n", count);
}
void bf_incptr(FILE *out, size_t count) {
if(count == 1)
fprintf(out, " incl %%edi\n");
else
fprintf(out, " addl $0x%x, %%edi\n", count);
}
const char bf_stbr[] =
"1:\n"
" movzbl (%edi), %ecx\n"
" jecxz 1f\n";
const char bf_endbr[] =
" jmp 1b\n"
"1:\n";
const char bf_getc[] =
" call getchar\n"
" movb %al, (%edi)\n";
const char bf_putc[] =
" movzbl (%edi), %eax\n"
" pushl %eax\n"
" call putchar\n";
const char bf_prologue[] =
".section .text\n\n"
".globl main\n"
"main:\n"
" pushl $1\n"
" pushl $30000\n"
" call calloc\n"
" movl %eax, %edi\n";
const char bf_epilogue[] =
" pushl $0\n"
" call exit\n";
%}
%%
"-"+ { bf_decval(yyout, strlen(yytext)); }
"+"+ { bf_incval(yyout, strlen(yytext)); }
"<"+ { bf_decptr(yyout, strlen(yytext)); }
">"+ { bf_incptr(yyout, strlen(yytext)); }
"[" { fprintf (yyout, "%s", bf_stbr); }
"]" { fprintf (yyout, "%s", bf_endbr); }
"," { fprintf (yyout, "%s", bf_getc); }
"." { fprintf (yyout, "%s", bf_putc); }
. { }
%%
int main(int argc, char *argv[]) {
int c;
tmp = tmpfile();
if(tmp == NULL) {
fprintf(stderr, "error: could not make temporary file\n");
exit(EXIT_FAILURE);
}
yyout = tmp;
fprintf(tmp, "%s", bf_prologue);
while(yylex() != 0);
fprintf(tmp, "%s", bf_epilogue);
fseek(tmp, 0, SEEK_SET);
while((c = fgetc(tmp)) != EOF)
putchar(c);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment