From ca0cf3baed0ca965f0c48abb85c9383a14194c5c Mon Sep 17 00:00:00 2001 From: hellerve Date: Mon, 4 Sep 2017 12:58:59 +0200 Subject: [PATCH] parser: almost working --- src/parser.c | 113 ++++++++++++++++++++++++++++++++++++++++++--------- src/parser.h | 11 +++++ 2 files changed, 105 insertions(+), 19 deletions(-) diff --git a/src/parser.c b/src/parser.c index d7925f4..d1fc7cf 100644 --- a/src/parser.c +++ b/src/parser.c @@ -37,34 +37,109 @@ char** tokenize(char* str) { return tokens; } -sc_ast* sc_parse(char* input) { - char** tokens = tokenize(input); - sc_ast* parent = malloc(sizeof(sc_ast)); - parent->tag = 0; - parent->value = NULL; - parent->children = NULL; - parent->n_children = 0; +sc_ast* make_node(int tag, char* value) { + sc_ast* node = malloc(sizeof(sc_ast)); + node->tag = tag; + node->value = value; + node->n_children = 0; + node->children = NULL; - while (*tokens) { - parent->n_children++; + return node; +} - sc_ast* child = malloc(sizeof(sc_ast)); - parent->children = realloc(parent->children, parent->n_children*sizeof(sc_ast*)); - child->tag = 1; - child->value = *tokens; - child->children = NULL; - child->n_children = 0; - parent->children[parent->n_children-1] = child; - tokens++; +sc_ast* make_pseudo() { + return make_node(PSEUDO, NULL); +} + +sc_ast* make_list() { + return make_node(LIST, NULL); +} + +sc_ast* make_int(char* value) { + return make_node(INT, value); +} + +sc_ast* make_float(char* value) { + return make_node(FLOAT, value); +} + +sc_ast* make_atom(char* value) { + return make_node(ATOM, value); +} + +typedef struct parse_state { + char** tokens; + sc_ast* node; +} parse_state; + +short is_numerical(char* inp) { + int i; + int len = strlen(inp); + + for (i = 0; i < len; i++) if (!isdigit(inp[i])) return 0; + + return 1; +} + +sc_ast* read_token(char* inp) { + if (is_numerical(inp)) return make_int(inp); + return make_atom(inp); +} + +parse_state* read_tokens(parse_state* state) { + char* token = state->tokens[0]; + state->tokens++; + int n = state->node->n_children++; + + state->node->children = realloc(state->node->children, n+1); + + if (!strncmp(token, "(", 2)) { + sc_ast* list = make_list(); + parse_state* nstate = malloc(sizeof(parse_state)); + nstate->node = list; + nstate->tokens = state->tokens; + + while (strncmp(nstate->tokens[0], ")", 2)) { + nstate = read_tokens(nstate); + } + + state->node->children[n] = nstate->node; + state->tokens = nstate->tokens; + free(nstate); + } else { + state->node->children[n] = read_token(token); } - return parent; + return state; +} + +sc_ast* sc_parse(char* input) { + char** tokens = tokenize(input); + parse_state* state = malloc(sizeof(parse_state)); + state->tokens = tokens; + state->node = make_pseudo(); + + state = read_tokens(state); + + return state->node->children[0]; +} + +const char* tag_to_string(int x) { + switch(x) { + case PSEUDO: return "pseudo"; + case ATOM: return "atom"; + case STRING: return "string"; + case INT: return "int"; + case FLOAT: return "float"; + case LIST: return "list"; + default: {char* t=malloc(3); snprintf(t, 3, "%d", x); return t;} + } } void sc_ast_print(sc_ast* ast) { int i; - printf("(%d) %s (%lu)\n", ast->tag, ast->value, ast->value ? strlen(ast->value) : 0); + printf("%s: %s\n", tag_to_string(ast->tag), ast->value); for (i = 0; i < ast->n_children; ++i) sc_ast_print(ast->children[i]); } diff --git a/src/parser.h b/src/parser.h index 36878f4..d592c7f 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,7 +1,18 @@ +#include #include #include #include +enum tag { + PSEUDO, + ATOM, + LIST, + INT, + FLOAT, + STRING, +}; + + typedef struct sc_ast { short tag; char* value;