Skip to content

Instantly share code, notes, and snippets.

@lukewilson2002
Created August 18, 2018 04:21
Show Gist options
  • Save lukewilson2002/34264e49d0d65487db7fd4f2fe75a441 to your computer and use it in GitHub Desktop.
Save lukewilson2002/34264e49d0d65487db7fd4f2fe75a441 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum Token
{
LEFT, RIGHT,
PLUS, MINUS,
READ, WRITE,
LLOOP, RLOOP,
};
struct TokenArray
{
enum Token *tokens;
size_t len;
size_t capacity;
};
int newtokenarray(struct TokenArray **out)
{
enum Token *mem = malloc(sizeof(enum Token)*8);
if (mem == NULL) return 1;
struct TokenArray *array = malloc(sizeof(struct TokenArray));
if (array == NULL) return 1;
array->tokens = mem;
array->len = 0;
array->capacity = 8;
*out = array;
return 0;
}
void pushtoken(struct TokenArray *array, enum Token token)
{
if (array->len + 1 > array->capacity)
{
void *new_ptr = realloc(array->tokens, array->capacity * 2); // Reallocate
if (new_ptr == NULL)
{
printf("Panic: reallocation for TokenArray failed.");
exit(1);
}
array->tokens = new_ptr;
}
array->tokens[array->len++] = token; // Add the token
}
void cleanuptokenarray(struct TokenArray *array)
{
free(array->tokens);
}
void tokenize(struct TokenArray **array, const char *input)
{
if (*array == NULL)
newtokenarray(array);
size_t len = strlen(input);
for (size_t i = 0; i < len; i++)
{
switch (input[i])
{
case '>':
pushtoken(*array, RIGHT);
break;
case '<':
pushtoken(*array, LEFT);
break;
case '+':
pushtoken(*array, PLUS);
break;
case '-':
pushtoken(*array, MINUS);
break;
case ',':
pushtoken(*array, READ);
break;
case '.':
pushtoken(*array, WRITE);
break;
case '[':
pushtoken(*array, LLOOP);
break;
case ']':
pushtoken(*array, RLOOP);
break;
default:
break;
}
}
}
void pushstr(char **dst, const char *src)
{
void *new_mem = realloc(*dst, strlen(*dst)+strlen(src)+2);
if (new_mem == NULL)
{
printf("Panic: reallocation for pushstr failed.");
exit(1);
}
*dst = new_mem;
strcat(*dst, src);
}
static char *preface = "#include <stdio.h>\n\nint main() {\n char tape[30000] = {0};\n char *ptr = tape;\n";
char *generatecode(const struct TokenArray *array)
{
char *output = malloc(sizeof(char)*(strlen(preface)+1));
memcpy(output, preface, strlen(preface)+1);
unsigned indents = 1;
for (size_t i = 0; i < array->len; i++)
{
switch (array->tokens[i])
{
case RIGHT:
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
pushstr(&output, "++ptr;\n");
break;
case LEFT:
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
pushstr(&output, "--ptr;\n");
break;
case PLUS:
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
pushstr(&output, "*++ptr;\n");
break;
case MINUS:
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
pushstr(&output, "*--ptr;\n");
break;
case READ:
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
pushstr(&output, "*ptr=getchar();\n");
break;
case WRITE:
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
pushstr(&output, "putchar(*ptr);\n");
break;
case LLOOP:
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
++indents;
pushstr(&output, "while (*ptr) {\n");
break;
case RLOOP:
--indents;
for (unsigned t = 0; t < indents; t++)
pushstr(&output, " ");
pushstr(&output, "}\n");
break;
}
}
pushstr(&output, "}\n");
return output;
}
int main(int argc, char const *argv[])
{
struct TokenArray *tokens;
newtokenarray(&tokens);
tokenize(&tokens, "<><>");
char *code = generatecode(tokens);
printf("%s", code);
cleanuptokenarray(tokens);
free(code);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment