expressiosn can compile

This commit is contained in:
2017-09-06 14:30:07 +02:00
parent ca0cf3baed
commit c5c228f959
9 changed files with 285 additions and 24 deletions

21
src/ast.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
enum tag {
PSEUDO,
ATOM,
LIST,
INT,
FLOAT,
STRING,
QUOTED,
};
typedef struct sc_ast {
short tag;
char* value;
int n_children;
struct sc_ast** children;
} sc_ast;

126
src/compiler.c Normal file
View File

@@ -0,0 +1,126 @@
#include "compiler.h"
char* get_prelude() {
char* str;
size_t size;
FILE* p = fopen("./assets/prelude.h", "r");
if (!p) {
puts("Error while opening the prelude file.");
exit(1);
}
fseek(p, 0, SEEK_END);
size = ftell(p);
fseek(p, 0, SEEK_SET);
str = malloc(size+1);
fread(str, size, 1, p);
fclose(p);
str[size] = '\0';
return str;
}
char* compile_expr(sc_ast* ast);
char* compile_define(sc_ast* ast) {
char* rhs = compile_expr(ast->children[2]);
char* name = ast->children[1]->value;
char* res = malloc(strlen(rhs)+strlen(name)+10);
sprintf(res, "Value %s = %s", name, rhs);
return res;
}
char* compile_list(sc_ast* ast) {
if (!strcmp(ast->children[0]->value, "define")) return compile_define(ast);
int i;
char* tmp;
char* res = malloc(strlen(ast->children[0]->value)+4);
sprintf(res, "%s(", ast->children[0]->value);
int reslen = strlen(res)+1;
tmp = compile_expr(ast->children[1]);
reslen += strlen(tmp)+2;
res = realloc(res, reslen);
snprintf(res, reslen, "%s%s", res, tmp);
for (i = 2; i < ast->n_children; i++) {
tmp = compile_expr(ast->children[i]);
reslen += strlen(tmp)+2;
res = realloc(res, reslen);
snprintf(res, reslen, "%s, %s", res, tmp);
}
res = realloc(res, reslen+1);
snprintf(res, reslen+1, "%s)", res);
return res;
}
char* compile(sc_ast* ast) {
int i;
char* tmp;
char* main = malloc(35);
strcpy(main, "int main(int argc, char** argv) {");
int mainlen = strlen(main)+1;
char* res = get_prelude();
int reslen = strlen(res)+1;
for (i = 0; i < ast->n_children; i++) {
tmp = compile_expr(ast->children[i]);
if (!tmp) continue;
mainlen += strlen(tmp)+1;
main = realloc(main, mainlen);
snprintf(main, mainlen, "%s;%s", main, tmp);
}
res = realloc(res, reslen+mainlen+2);
snprintf(res, reslen+mainlen+2, "%s;%s;}", res, main);
return res;
}
char* compile_expr(sc_ast* ast) {
char* ret = NULL;
char* tmp;
int i;
int retlen = 1;
switch (ast->tag) {
case INT:
tmp = malloc(strlen(ast->value)+10);
sprintf(tmp, "MakeInt(%s)", ast->value);
return tmp;
case FLOAT:
tmp = malloc(strlen(ast->value)+10);
sprintf(tmp, "MakeInt(%s)", ast->value);
return tmp;
case ATOM:
return ast->value;
case STRING:
ret = malloc(strlen(ast->value)+3);
sprintf(ret, "\"%s\"", ast->value);
return ret;
case LIST:
return compile_list(ast);
case PSEUDO:
for (i = 0; i < ast->n_children; i++) {
tmp = compile(ast->children[i]);
if (!tmp) continue;
retlen += strlen(tmp);
if (ret) {
ret = realloc(ret, retlen);
snprintf(ret, retlen, "%s%s", ret, tmp);
} else {
ret = tmp;
}
}
return ret;
default:
printf("Unknown AST tag: %d\n", ast->tag);
exit(1);
}
}

7
src/compiler.h Normal file
View File

@@ -0,0 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ast.h"
char* compile(sc_ast*);

View File

@@ -23,7 +23,7 @@ char** tokenize(char* str) {
str++;
}else {
t = str;
while (*t && *t != ' ' && *t != '(' && *t != ')') ++t;
while (*t && *t != ' ' && *t != '\n' && *t != '\t' && *t != '(' && *t != ')') ++t;
tokens[len-1] = malloc(t-str+1);
strncpy(tokens[len-1], str, t-str);
tokens[len-1][t-str] = '\0';
@@ -91,7 +91,7 @@ parse_state* read_tokens(parse_state* state) {
state->tokens++;
int n = state->node->n_children++;
state->node->children = realloc(state->node->children, n+1);
state->node->children = realloc(state->node->children, (n+1)*sizeof(sc_ast));
if (!strncmp(token, "(", 2)) {
sc_ast* list = make_list();
@@ -104,7 +104,7 @@ parse_state* read_tokens(parse_state* state) {
}
state->node->children[n] = nstate->node;
state->tokens = nstate->tokens;
state->tokens = ++nstate->tokens;
free(nstate);
} else {
state->node->children[n] = read_token(token);
@@ -119,9 +119,9 @@ sc_ast* sc_parse(char* input) {
state->tokens = tokens;
state->node = make_pseudo();
state = read_tokens(state);
while (state->tokens[0]) state = read_tokens(state);
return state->node->children[0];
return state->node;
}
const char* tag_to_string(int x) {

View File

@@ -3,24 +3,7 @@
#include <stdlib.h>
#include <string.h>
enum tag {
PSEUDO,
ATOM,
LIST,
INT,
FLOAT,
STRING,
};
typedef struct sc_ast {
short tag;
char* value;
int n_children;
struct sc_ast** children;
} sc_ast;
#include "ast.h"
sc_ast* sc_parse(char*);
void sc_ast_print(sc_ast*);