expressiosn can compile
This commit is contained in:
21
src/ast.h
Normal file
21
src/ast.h
Normal 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
126
src/compiler.c
Normal 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
7
src/compiler.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
char* compile(sc_ast*);
|
10
src/parser.c
10
src/parser.c
@@ -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) {
|
||||
|
19
src/parser.h
19
src/parser.h
@@ -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*);
|
||||
|
Reference in New Issue
Block a user