diff options
author | Preston Pan <preston@nullring.xyz> | 2023-01-03 00:27:06 -0800 |
---|---|---|
committer | Preston Pan <preston@nullring.xyz> | 2023-01-03 00:27:06 -0800 |
commit | 9f342255a2260480701cc2ac2d0c623d4aba1348 (patch) | |
tree | 6ecd1332032eb09fd28aacab7418da9a5882cb94 /src | |
parent | 64feef1b9ea72adf7ba32998e9dca7d507607498 (diff) |
add some comments; fix some bugs in advance
Diffstat (limited to 'src')
-rw-r--r-- | src/ast.c | 59 | ||||
-rw-r--r-- | src/hash_table.c | 11 | ||||
-rw-r--r-- | src/include/.ast.h.swp | bin | 0 -> 12288 bytes | |||
-rw-r--r-- | src/include/ast.h | 6 | ||||
-rw-r--r-- | src/include/hash_table.h | 4 | ||||
-rw-r--r-- | src/include/parser.h | 7 | ||||
-rw-r--r-- | src/parser.c | 79 |
7 files changed, 151 insertions, 15 deletions
diff --git a/src/ast.c b/src/ast.c new file mode 100644 index 0000000..a2a7bb5 --- /dev/null +++ b/src/ast.c @@ -0,0 +1,59 @@ +#include "./include/ast.h" +#include <stdlib.h> + +/* A very... lightweight version of "inheritance" */ +ast_t *init_ast(int type) { + ast_t *a = (ast_t *)malloc(sizeof(ast_t)); + a->type = type; + a->car = NULL; + a->cdr = NULL; + a->string_value = NULL; + a->int_value = 0; + a->float_value = 0; + a->bool_value = false; + return a; +} + +ast_t *init_ast_string(char *value) { + ast_t *a = init_ast(AST_STRING); + a->string_value = value; + return a; +} + +ast_t *init_ast_int(int value) { + ast_t *a = init_ast(AST_INT); + a->int_value = value; + return a; +} + +ast_t *init_ast_float(double value) { + ast_t *a = init_ast(AST_FLOAT); + a->float_value = value; + return a; +} + +ast_t *init_ast_pair(ast_t *car, ast_t *cdr) { + ast_t *a = init_ast(AST_PAIR); + a->car = car; + a->cdr = cdr; + return a; +} + +ast_t *init_ast_bool(bool value) { + ast_t *a = init_ast(AST_BOOL); + a->bool_value = value; + return a; +} + +ast_t *init_ast_symbol(char *value) { + ast_t *a = init_ast(AST_SYMBOL); + a->string_value = value; + return a; +} + +ast_t *init_ast_function(ast_t *car, ast_t *cdr) { + ast_t *a = init_ast(AST_FUNCTION); + a->car = car; + a->cdr = cdr; + return a; +} diff --git a/src/hash_table.c b/src/hash_table.c index 9384945..3ca6dd0 100644 --- a/src/hash_table.c +++ b/src/hash_table.c @@ -70,6 +70,12 @@ ast_t *sl_list_get(sl_list_t *l, char *key) { return NULL; } +bool sl_list_exists(sl_list_l, char *key) { + if (sl_list_get(l, key) != NULL) + return true; + return false; +} + void sl_list_free(sl_list_t *l) { sl_node_t *cur = l->head; sl_node_t *tmp; @@ -111,6 +117,11 @@ void hash_table_free(hash_table_t *h) { free(h); } +bool hash_table_exists(hash_table_t *h, char *key) { + sl_list_t *l = h->buckets[hash(key, h->size)]; + return sl_list_exists(l, key); +} + /* DJB2 HASH FUNCTION */ unsigned long hash(char *key, int size) { unsigned long hash = 5381; diff --git a/src/include/.ast.h.swp b/src/include/.ast.h.swp Binary files differnew file mode 100644 index 0000000..31e16ab --- /dev/null +++ b/src/include/.ast.h.swp diff --git a/src/include/ast.h b/src/include/ast.h index f7be3d5..ca07c9d 100644 --- a/src/include/ast.h +++ b/src/include/ast.h @@ -17,15 +17,19 @@ typedef struct AST_STRUCT { /* For functions, the car will be a list of variables, and the cdr will be the * expression */ + int argument_number; /* number of arguments that function accepts. Used for + speeding up stuff. */ struct AST_STRUCT *car; struct AST_STRUCT *cdr; - char *string_value; + char *string_value; /* Also is symbol value */ int int_value; double float_value; bool bool_value; } ast_t; +ast_t *init_ast(int type); + ast_t *init_ast_string(char *value); ast_t *init_ast_int(int value); diff --git a/src/include/hash_table.h b/src/include/hash_table.h index df2d368..833daee 100644 --- a/src/include/hash_table.h +++ b/src/include/hash_table.h @@ -32,6 +32,8 @@ void sl_list_add(sl_list_t *l, char *key, ast_t *value); ast_t *sl_list_get(sl_list_t *l, char *key); +bool sl_list_exists(sl_list_t *l, char *key); + void sl_list_free(sl_list_t *l); hash_table_t *init_hash_table(int size); @@ -40,6 +42,8 @@ void hash_table_add(hash_table_t *h, char *key, ast_t *value); ast_t *hash_table_get(hash_table_t *h, char *key); +bool hash_table_exists(hash_table_t *h, char *key); + unsigned long hash(char *key, int size); void hash_table_free(hash_table_t *h); diff --git a/src/include/parser.h b/src/include/parser.h index 97a7fd9..64ae792 100644 --- a/src/include/parser.h +++ b/src/include/parser.h @@ -13,6 +13,7 @@ typedef struct { int i; int size; bool finished; + bool is_global; } parser_t; parser_t *init_parser(lexer_t *lexer); @@ -21,7 +22,7 @@ void parser_error(parser_t *parser); void parser_move(parser_t *parser); -void parser_eat(parser_t *parser, token_t *token); +void parser_eat(parser_t *parser, int type); ast_t *parse_string(parser_t *parser); @@ -39,9 +40,7 @@ ast_t *parse_symbol(parser_t *parser); ast_t *parse_function(parser_t *parser); -ast_t *parse_list(parser_t *parser); - -ast_t *parse_bind(parser_t *parser); +void parse_bind(parser_t *parser); ast_t *parse_expr(parser_t *parser); diff --git a/src/parser.c b/src/parser.c index f28fcc2..da2cf1d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -14,9 +14,8 @@ parser_t *init_parser(lexer_t *lexer) { p->i = 0; p->tokens = malloc(sizeof(token_t *)); - p->symbol_table = init_hash_table(); + p->symbol_table = init_hash_table(10000); p->finished = false; - if (p->tokens == NULL) die("malloc on p->tokens"); @@ -44,7 +43,11 @@ void parser_move(parser_t *parser) { parser->finished = true; } -void parser_eat(parser_t *parser, token_t *token) { parser_move(parser); } +void parser_eat(parser_t *parser, int type) { + parser_move(parser); + if (parser->tokens[parser->i]->type != type) + parser_error(parser); +} ast_t *parse_bool(parser_t *parser) { token_t *t = parser->tokens[parser->i]; @@ -75,31 +78,85 @@ ast_t *parse_float(parser_t *parser) { return init_ast_float(ret); } +ast_t *parse_symbol(parser_t *parser) { + char *str = parser->tokens[parser->i]->value; + parser_move(parser); + return init_ast_symbol(str); +} + +ast_t *parse_function_args(parser_t *parser) { + token_t *t = parser->tokens[parser->i]; + + ast_t *head; + ast_t *car; + ast_t *cdr; + while (t->type != TOKEN_LPAREN) { + } +} ast_t *parse_function(parser_t *parser) { parser_move(parser); - parser_eat(parser, init_token(TOKEN_LPAREN, "(", 0, 0)); - ast_t *car = parse_list(parser); /* gets list of symbols; does not check that - they are symbols :skull: */ + parser_eat(parser, TOKEN_LPAREN); + /* TODO: actually write a helper function that also keeps track + of the amount of arguments and checks that they are all identifiers.*/ + ast_t *car = parse_list(parser); ast_t *cdr = parse_expr(parser); /* a function can contain a single expression */ + parser_eat(parser, TOKEN_RPAREN); return init_ast_function(car, cdr); } +void parse_bind(parser_t *parser) { + parser_move(parser); + parser_eat(parser, TOKEN_ID); + + token_t *t = parser->tokens[parser->i]; + char *name = t->value; + parser_move(parser); + ast_t *expr = parse_expr(parser); /* unevaluated expr will be evaluated when + hash table transfers to visitor JIT */ + + hash_table_add(parser->symbol_table, name, expr); +} + ast_t *parse_list(parser_t *parser) { parser_move(parser); token_t *cur = parser->tokens[parser->i]; bool first_entry = true; + ast_t *head; + ast_t *car; + ast_t *cdr = + init_ast_pair(init_ast_pair(NULL, NULL), init_ast_pair(NULL, NULL)); while (cur->type != TOKEN_RPAREN) { if (cur->type == TOKEN_ID) { if (strcmp(cur->value, "lambda") == 0 && first_entry) return parse_function(parser); - else if (strcmp(cur->value, "bind") == 0 && first_entry) - return parse_bind(parser); - } else if (cur->type == TOKEN_LPAREN) - parse_list(parser); + else if (strcmp(cur->value, "bind") == 0 && first_entry) { + parse_bind(parser); + return NULL; + } + } else + car = parse_expr(parser); + + if (car == NULL) + parser_error(parser); first_entry = false; + + head = init_ast_pair(car, cdr); + parser_move(parser); + cur = parser->tokens[parser->i]; } } + +ast_t *parse_quote(parser_t *parser) { + parser_move(parser); + ast_t *car = init_ast_string("quote"); + ast_t *expr = parse_expr(parser); + ast_t *ret = init_ast_pair( + car, init_ast_pair( + expr, init_ast_pair(NULL, NULL))); /* Converts ' to `quote` */ + return ret; +} + ast_t *parse_expr(parser_t *parser) { token_t *t = parser->tokens[parser->i]; if (t->type == TOKEN_STRING) @@ -123,3 +180,5 @@ ast_t *parse_expr(parser_t *parser) { } return NULL; } + +void parser_error(parser_t *parser) { exit(1); } |