diff --git a/ibuild.c b/ibuild.c index 9c699ec..4cfd606 100644 --- a/ibuild.c +++ b/ibuild.c @@ -35,7 +35,8 @@ void launch_compile(CompileOptions* co) else if (p==0) { char* args[] = {"compile", "test.c", "-o", "test", NULL}; - if((execvp(co->compiler_path, args)) == -1) + printf("SET COMPILER: %s\n", co->compiler_path); + if((execvp(co->compiler_path, args)) == -1) die("launch_compile() execvp error"); } } @@ -164,10 +165,12 @@ Token tokenizer_next(Tokenizer* t) typedef enum { + K_NA = -1, K_UNKNOWN = 0, K_COMPILER_PATH = 1, K_SRC_DIR = 2, K_BUILD_DIR = 3, + K_TARGET_EXEC = 4, } Key; typedef enum @@ -185,7 +188,7 @@ typedef struct typedef struct { - Tokenizer* tokenizer; + Arena* tokens_alloc; size_t loc; size_t cap; Arena alloc; @@ -201,6 +204,7 @@ static KeyMap keyword_mappings[] = { {K_COMPILER_PATH, "COMPILER_PATH"}, {K_SRC_DIR, "SRC_DIR"}, {K_BUILD_DIR, "BUILD_DIR"}, + {K_TARGET_EXEC, "TARGET_EXEC"}, {K_UNKNOWN, NULL}, }; @@ -222,9 +226,9 @@ Token parser_peek(Parser* p, size_t o) { if (p->loc + o >= p->cap) { - return ((Token*)p->tokenizer->alloc.start)[p->loc - 1]; + return ((Token*)p->tokens_alloc->start)[p->loc - 1]; } - return ((Token*)p->tokenizer->alloc.start)[p->loc + o]; + return ((Token*)p->tokens_alloc->start)[p->loc + o]; } Token parser_previous(Parser* p) @@ -234,30 +238,40 @@ Token parser_previous(Parser* p) die("parser logic error."); } - return ((Token*)p->tokenizer->alloc.start)[p->loc - 1]; + return ((Token*)p->tokens_alloc->start)[p->loc - 1]; } Token parser_advance(Parser* p) { if(p->loc + 1 >= p->cap) { - return ((Token*)p->tokenizer->alloc.start)[p->loc]; + return ((Token*)p->tokens_alloc->start)[p->loc]; } p->loc++; - return ((Token*)p->tokenizer->alloc.start)[p->loc]; + return ((Token*)p->tokens_alloc->start)[p->loc]; +} + +Token parser_expect(Parser* p, TokenType tt, char* s) +{ + if(p == NULL) die("parser_expect() p must not be NULL"); + if(p == NULL) die("parser_expect() s must not be NULL"); + + if(parser_peek(p, 1).type != tt) + die(s); + + return parser_advance(p); } Node* parser_expression(Parser* p) { - Token t = parser_peek(p,0); + Token t = parser_advance(p); if(t.type == T_STRING) { - Key k = key_lookup(t.value); - if(k == K_UNKNOWN) die("Syntax error: Unexpected expression encountered"); Node* node = (Node*)arena_alloc(&p->alloc, sizeof(Node)); - node->key = k; + node->key = K_NA; node->value = (void*)t.value; node->type = N_STRING; + parser_advance(p); return node; } @@ -266,11 +280,12 @@ Node* parser_expression(Parser* p) Node* parser_statement(Parser* p) { - Token t = parser_advance(p); + Token t = parser_peek(p, 0); if(t.type == T_IDENTIFIER) { Key k = key_lookup(t.value); if(k == K_UNKNOWN) die("Syntax error: Unexpected identifer encountered"); + parser_expect(p, T_IS, "Syntax error: Expected '=' after identifier"); Node* expression = parser_expression(p); Node* node = (Node*)arena_alloc(&p->alloc, sizeof(Node)); node->key = k; @@ -279,16 +294,50 @@ Node* parser_statement(Parser* p) } else { - printf("%d", t.type); die("Syntax error: expected an identifier"); } } -Node* parser_parse(Parser* p) +size_t parser_parse(Parser* p, Node*** out) { - return parser_statement(p); + Arena statements_alloc = ARENA_CONST; + + size_t size = 0; + + while(p->loc < p->cap - 1) + { + Node** temp = (Node**)arena_alloc(&statements_alloc, sizeof(Node*)); + *temp = parser_statement(p); + size++; + } + + *out = (Node**)statements_alloc.start; + + return size; } +void debug_parser(Node* n, int indent) +{ + for(int i = 0; i < indent; i++) + { + printf(" "); + } + + switch(n->type) + { + case N_PAIR: + printf("PAIR STATEMENT"); + printf(" Key: %10d\n", n->key); + if(n->value != NULL) + debug_parser((Node*)n->value, 2); + break; + case N_STRING: + printf("STRING EXPRESSION"); + printf(" Value: %s\n", (char*)n->value); + break; + } +} + /*** configuration file management ***/ long get_file_size(FILE* fd) @@ -300,13 +349,20 @@ long get_file_size(FILE* fd) return size; } -int process_config(Arena* tokens) +typedef struct +{ + Arena tokens; +} ConfigMemory; + +int process_config(Node*** ast) { if(!detect_config_file()) return 1; printf("IBUILD Configuration file detected.\n"); + ConfigMemory cm = {ARENA_CONST}; + FILE* fd = fopen("IBUILD", "r"); if(fd == NULL) die("process_config() file exists however fd is NULL"); @@ -315,6 +371,8 @@ int process_config(Arena* tokens) printf("IBUILD file of size: %d\n", fs); + if(fs < 2) return 0; + char* config_mem = malloc(fs + 1); fread(config_mem, sizeof(char), fs, fd); @@ -330,44 +388,64 @@ int process_config(Arena* tokens) Token token = tokenizer_next(&t); if(token.type == T_INVALID) die("illegal token!"); - Token* tm = arena_alloc(tokens, sizeof(Token)); + Token* tm = arena_alloc(&cm.tokens, sizeof(Token)); *tm = token; t_count++; if(token.type == T_EOF) break; } - Parser parser = {.tokenizer = &t, .loc = 0, .cap = t_count, .alloc = ARENA_CONST}; - parser_parse(&parser); + Parser parser = {.tokens_alloc = &cm.tokens, .loc = 0, .cap = t_count, .alloc = ARENA_CONST}; + Node** statements = NULL; + size_t statements_len = parser_parse(&parser, &statements); + + if(statements == NULL) die("parser return invalid results"); + + for (size_t i = 0; i < statements_len; i++) + debug_parser(statements[i], 0); + free(config_mem); - return 0; + arena_free(&cm.tokens); + *ast = statements; + return statements_len; } /*** build configuration process ***/ -/* -void populate_compile_options(CompileOptions* co, Token* t) -{ - switch(t->type) - { - case T_KEY_COMPILER_PATH: co->compiler_path = t->value; break; - case T_KEY_BUILD_DIR: co->build_dir = t->value; break; - case T_KEY_TARGET_EXEC: co->target_exec = t->value; break; - case T_KEY_SRC_DIR: co->compiler_path = t->value; break; - case T_KEY_VERSION: co->version = t->value; break; - } - }*/ -void build(Token* options) +void set_compiler_option(CompileOptions* co, Key k, char* val) +{ + switch(k) + { + case K_COMPILER_PATH: co->compiler_path = val; break; + case K_BUILD_DIR: co->build_dir = val; break; + case K_TARGET_EXEC: co->target_exec = val; break; + default: + die("Invalid compiler option was supplied!"); + } +} + +void populate_compile_options(CompileOptions* co, Node* n) +{ + switch(n->type) + { + case N_PAIR: + Key k = n->key; + set_compiler_option(co, k, (char*)((Node*)n->value)->value); + break; + } +} + +void build(int len, Node** st) { CompileOptions co; co.compiler_path = "/usr/bin/gcc"; + co.build_dir = "."; + co.src_dir = "."; + co.target_exec = "iexec"; - Token* temp = options; - for(; temp->type != T_EOF; temp++) - { - // populate_compile_options(&co, temp); - } + for (size_t i = 0; i < len; i++) + populate_compile_options(&co, st[i]); launch_compile(&co); printf("Compilation finished.\n"); @@ -375,15 +453,10 @@ void build(Token* options) int main(int argc, char** argv) { - Arena a = ARENA_CONST; + Node** ast = NULL; + int len_ast = process_config(&ast); - process_config(&a); - - Token* ptr = (Token*)a.start; - for(; ptr->type != T_EOF; ptr++) - { - printf("TokenType: %d, Value: %s\n", ptr->type, ptr->value); - } - + build(len_ast, ast); + return 0; }