parser: almost working
This commit is contained in:
113
src/parser.c
113
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);
|
||||
}
|
||||
|
||||
return parent;
|
||||
state->node->children[n] = nstate->node;
|
||||
state->tokens = nstate->tokens;
|
||||
free(nstate);
|
||||
} else {
|
||||
state->node->children[n] = read_token(token);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
11
src/parser.h
11
src/parser.h
@@ -1,7 +1,18 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum tag {
|
||||
PSEUDO,
|
||||
ATOM,
|
||||
LIST,
|
||||
INT,
|
||||
FLOAT,
|
||||
STRING,
|
||||
};
|
||||
|
||||
|
||||
typedef struct sc_ast {
|
||||
short tag;
|
||||
char* value;
|
||||
|
Reference in New Issue
Block a user