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 | |
parent | 64feef1b9ea72adf7ba32998e9dca7d507607498 (diff) |
add some comments; fix some bugs in advance
-rw-r--r-- | LICENSE | 7 | ||||
-rw-r--r-- | Makefile | 0 | ||||
-rw-r--r-- | README.md | 2 | ||||
-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 |
10 files changed, 160 insertions, 15 deletions
@@ -0,0 +1,7 @@ +Copyright © 2022 Preston Pan <preston@nullring.xyz> + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Makefile @@ -1,3 +1,5 @@ # NoExcess This is basically a scheme-like language that is aimed to be scheme with no additional fluff. Currently does not work. +The makefile also currently does not work as it contains nothing. +Amazing. 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); } |