parser: almost working

This commit is contained in:
2017-09-04 12:58:59 +02:00
parent cf1fa2fd5b
commit ca0cf3baed
2 changed files with 105 additions and 19 deletions

View File

@@ -37,34 +37,109 @@ char** tokenize(char* str) {
return tokens; return tokens;
} }
sc_ast* sc_parse(char* input) { sc_ast* make_node(int tag, char* value) {
char** tokens = tokenize(input); sc_ast* node = malloc(sizeof(sc_ast));
sc_ast* parent = malloc(sizeof(sc_ast)); node->tag = tag;
parent->tag = 0; node->value = value;
parent->value = NULL; node->n_children = 0;
parent->children = NULL; node->children = NULL;
parent->n_children = 0;
while (*tokens) { return node;
parent->n_children++; }
sc_ast* child = malloc(sizeof(sc_ast)); sc_ast* make_pseudo() {
parent->children = realloc(parent->children, parent->n_children*sizeof(sc_ast*)); return make_node(PSEUDO, NULL);
child->tag = 1; }
child->value = *tokens;
child->children = NULL; sc_ast* make_list() {
child->n_children = 0; return make_node(LIST, NULL);
parent->children[parent->n_children-1] = child; }
tokens++;
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) { void sc_ast_print(sc_ast* ast) {
int i; 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]); for (i = 0; i < ast->n_children; ++i) sc_ast_print(ast->children[i]);
} }

View File

@@ -1,7 +1,18 @@
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
enum tag {
PSEUDO,
ATOM,
LIST,
INT,
FLOAT,
STRING,
};
typedef struct sc_ast { typedef struct sc_ast {
short tag; short tag;
char* value; char* value;