summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c59
-rw-r--r--src/hash_table.c11
-rw-r--r--src/include/.ast.h.swpbin0 -> 12288 bytes
-rw-r--r--src/include/ast.h6
-rw-r--r--src/include/hash_table.h4
-rw-r--r--src/include/parser.h7
-rw-r--r--src/parser.c79
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
new file mode 100644
index 0000000..31e16ab
--- /dev/null
+++ b/src/include/.ast.h.swp
Binary files differ
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); }