diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hash_table.c | 121 | ||||
-rw-r--r-- | src/include/ast.h | 42 | ||||
-rw-r--r-- | src/include/hash_table.h | 47 | ||||
-rw-r--r-- | src/include/lexer.h | 39 | ||||
-rw-r--r-- | src/include/macros.h | 85 | ||||
-rw-r--r-- | src/include/parser.h | 49 | ||||
-rw-r--r-- | src/include/print.h | 16 | ||||
-rw-r--r-- | src/include/sl_list.h | 23 | ||||
-rw-r--r-- | src/include/stack.h | 16 | ||||
-rw-r--r-- | src/include/token.h | 22 | ||||
-rw-r--r-- | src/include/visitor.h | 26 | ||||
-rw-r--r-- | src/lexer.c | 150 | ||||
-rw-r--r-- | src/macros.c | 10 | ||||
-rw-r--r-- | src/main.c | 39 | ||||
-rw-r--r-- | src/parser.c | 125 | ||||
-rw-r--r-- | src/stack.c | 34 | ||||
-rw-r--r-- | src/token.c | 15 | ||||
-rw-r--r-- | src/visitor.c | 25 |
18 files changed, 884 insertions, 0 deletions
diff --git a/src/hash_table.c b/src/hash_table.c new file mode 100644 index 0000000..9384945 --- /dev/null +++ b/src/hash_table.c @@ -0,0 +1,121 @@ +#include "./include/hash_table.h" +#include "./include/ast.h" +#include "./include/macros.h" +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +pair_t *init_pair(char *key, ast_t *value) { + pair_t *p = (pair_t *)malloc(sizeof(pair_t)); + if (p == NULL) + die("malloc on pair"); + p->key = key; + p->value = value; + return p; +} + +sl_node_t *init_sl_node(char *key, ast_t *value) { + sl_node_t *n = (sl_node_t *)malloc(sizeof(sl_node_t)); + if (n == NULL) + die("malloc on node"); + n->value = init_pair(key, value); + n->next = NULL; + return n; +} + +/*** SINGLY LINKED LIST FUNCTIONS ***/ +sl_list_t *init_sl_list() { + sl_list_t *l = (sl_list_t *)malloc(sizeof(sl_list_t)); + if (l == NULL) + die("malloc on list"); + l->size = 0; + l->head = NULL; + return l; +} + +void sl_list_add(sl_list_t *l, char *key, ast_t *value) { + sl_node_t *cur = l->head; + bool modified = false; + if (l->head == NULL) { + l->head = init_sl_node(key, value); + l->size++; + } + + for (int i = 0; i < l->size - 1; i++) { + if (strcmp(cur->value->key, key) == 0) { + cur->value->value = value; + modified = true; + break; + } + cur = cur->next; + } + if (strcmp(cur->value->key, key) == 0) { + cur->value->value = value; + modified = true; + } + + if (!modified) { + cur->next = init_sl_node(key, value); + l->size++; + } +} + +ast_t *sl_list_get(sl_list_t *l, char *key) { + sl_node_t *cur = l->head; + for (int i = 0; i < l->size; i++) { + if (strcmp(cur->value->key, key) == 0) + return cur->value->value; + cur = cur->next; + } + return NULL; +} + +void sl_list_free(sl_list_t *l) { + sl_node_t *cur = l->head; + sl_node_t *tmp; + for (int i = 0; i < l->size; i++) { + tmp = cur; + cur = cur->next; + free(tmp); + } + free(l); +} + +/*** HASH TABLE FUNCTIONS ***/ +hash_table_t *init_hash_table(int size) { + hash_table_t *h = (hash_table_t *)malloc(sizeof(hash_table_t)); + if (h == NULL) + die("malloc on hash table"); + h->size = size; + h->buckets = malloc(sizeof(sl_list_t *)); + if (h->buckets == NULL) + die("malloc on buckets"); + for (int i = 0; i < h->size; i++) + h->buckets[i] = init_sl_list(); + return h; +} + +void hash_table_add(hash_table_t *h, char *key, ast_t *value) { + sl_list_t *l = h->buckets[hash(key, h->size)]; + sl_list_add(l, key, value); +} + +ast_t *hash_table_get(hash_table_t *h, char *key) { + sl_list_t *l = h->buckets[hash(key, h->size)]; + return sl_list_get(l, key); +} + +void hash_table_free(hash_table_t *h) { + for (int i = 0; i < h->size; i++) + sl_list_free(h->buckets[i]); + free(h); +} + +/* DJB2 HASH FUNCTION */ +unsigned long hash(char *key, int size) { + unsigned long hash = 5381; + int c; + while ((c = *key++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + return hash % size; +} diff --git a/src/include/ast.h b/src/include/ast.h new file mode 100644 index 0000000..f7be3d5 --- /dev/null +++ b/src/include/ast.h @@ -0,0 +1,42 @@ +#ifndef AST_H +#define AST_H +#include <stdbool.h> + +typedef struct AST_STRUCT { + enum { + /* complex types */ + AST_PAIR, + AST_SYMBOL, + /* self evaluating types */ + AST_STRING, + AST_BOOL, + AST_INT, + AST_FLOAT, + AST_FUNCTION, + } type; + + /* For functions, the car will be a list of variables, and the cdr will be the + * expression */ + struct AST_STRUCT *car; + struct AST_STRUCT *cdr; + + char *string_value; + int int_value; + double float_value; + bool bool_value; +} ast_t; + +ast_t *init_ast_string(char *value); + +ast_t *init_ast_int(int value); + +ast_t *init_ast_float(double value); + +ast_t *init_ast_pair(ast_t *car, ast_t *cdr); + +ast_t *init_ast_bool(bool value); + +ast_t *init_ast_symbol(char *value); + +ast_t *init_ast_function(ast_t *car, ast_t *cdr); +#endif diff --git a/src/include/hash_table.h b/src/include/hash_table.h new file mode 100644 index 0000000..df2d368 --- /dev/null +++ b/src/include/hash_table.h @@ -0,0 +1,47 @@ +#ifndef HASH_TABLE_H +#define HASH_TABLE_H +#include "./ast.h" + +typedef struct { + char *key; + ast_t *value; +} pair_t; + +typedef struct SL_NODE_STRUCT { + pair_t *value; + struct SL_NODE_STRUCT *next; +} sl_node_t; + +typedef struct { + sl_node_t *head; + int size; +} sl_list_t; + +typedef struct { + int size; + sl_list_t **buckets; +} hash_table_t; + +pair_t *init_pair(char *key, ast_t *value); + +sl_node_t *init_sl_node(char *key, ast_t *value); + +sl_list_t *init_sl_list(); + +void sl_list_add(sl_list_t *l, char *key, ast_t *value); + +ast_t *sl_list_get(sl_list_t *l, char *key); + +void sl_list_free(sl_list_t *l); + +hash_table_t *init_hash_table(int size); + +void hash_table_add(hash_table_t *h, char *key, ast_t *value); + +ast_t *hash_table_get(hash_table_t *h, char *key); + +unsigned long hash(char *key, int size); + +void hash_table_free(hash_table_t *h); + +#endif diff --git a/src/include/lexer.h b/src/include/lexer.h new file mode 100644 index 0000000..36c5db8 --- /dev/null +++ b/src/include/lexer.h @@ -0,0 +1,39 @@ +#ifndef LEXER_H +#define LEXER_H + +#include "./token.h" + +#include <stdbool.h> + +typedef struct { + char *source; + int i; + char c; + + int row; + int col; + bool finished; +} lexer_t; + +void lexer_reset(lexer_t *lexer, char *source); + +lexer_t *init_lexer(char *source); + +void lexer_move(lexer_t *lexer); + +void lexer_skip_whitespace(lexer_t *lexer); + +void lexer_skip_comment(lexer_t *lexer); + +token_t *lexer_collect_bool(lexer_t *lexer); + +token_t *lexer_collect_id(lexer_t *lexer); + +token_t *lexer_collect_num(lexer_t *lexer); + +token_t *lexer_collect_string(lexer_t *lexer); + +token_t *lexer_collect_next(lexer_t *lexer); + +void lexer_error(lexer_t *lexer); +#endif diff --git a/src/include/macros.h b/src/include/macros.h new file mode 100644 index 0000000..ee89597 --- /dev/null +++ b/src/include/macros.h @@ -0,0 +1,85 @@ +#ifndef MACROS_H +#define MACROS_H +/* + * This is free and unencumbered software released into the public domain. + * For more information, please refer to <https://unlicense.org>. Code snippet + * taken from + * https://gist.github.com/RabaDabaDoba/145049536f815903c79944599c6f952a. + */ + +/* Regular text */ +#define BLK "\e[0;30m" +#define RED "\e[0;31m" +#define GRN "\e[0;32m" +#define YEL "\e[0;33m" +#define BLU "\e[0;34m" +#define MAG "\e[0;35m" +#define CYN "\e[0;36m" +#define WHT "\e[0;37m" + +/* Regular bold text */ +#define BBLK "\e[1;30m" +#define BRED "\e[1;31m" +#define BGRN "\e[1;32m" +#define BYEL "\e[1;33m" +#define BBLU "\e[1;34m" +#define BMAG "\e[1;35m" +#define BCYN "\e[1;36m" +#define BWHT "\e[1;37m" + +/* Regular underline text */ +#define UBLK "\e[4;30m" +#define URED "\e[4;31m" +#define UGRN "\e[4;32m" +#define UYEL "\e[4;33m" +#define UBLU "\e[4;34m" +#define UMAG "\e[4;35m" +#define UCYN "\e[4;36m" +#define UWHT "\e[4;37m" + +/* Regular background */ +#define BLKB "\e[40m" +#define REDB "\e[41m" +#define GRNB "\e[42m" +#define YELB "\e[43m" +#define BLUB "\e[44m" +#define MAGB "\e[45m" +#define CYNB "\e[46m" +#define WHTB "\e[47m" + +/* High intensty background */ +#define BLKHB "\e[0;100m" +#define REDHB "\e[0;101m" +#define GRNHB "\e[0;102m" +#define YELHB "\e[0;103m" +#define BLUHB "\e[0;104m" +#define MAGHB "\e[0;105m" +#define CYNHB "\e[0;106m" +#define WHTHB "\e[0;107m" + +/* High intensty text */ +#define HBLK "\e[0;90m" +#define HRED "\e[0;91m" +#define HGRN "\e[0;92m" +#define HYEL "\e[0;93m" +#define HBLU "\e[0;94m" +#define HMAG "\e[0;95m" +#define HCYN "\e[0;96m" +#define HWHT "\e[0;97m" + +/* Bold high intensity text */ +#define BHBLK "\e[1;90m" +#define BHRED "\e[1;91m" +#define BHGRN "\e[1;92m" +#define BHYEL "\e[1;93m" +#define BHBLU "\e[1;94m" +#define BHMAG "\e[1;95m" +#define BHCYN "\e[1;96m" +#define BHWHT "\e[1;97m" + +#define reset "\e[0m" +#define CRESET "\e[0m" +#define COLOR_RESET "\e[0m" + +void die(char *message); +#endif diff --git a/src/include/parser.h b/src/include/parser.h new file mode 100644 index 0000000..97a7fd9 --- /dev/null +++ b/src/include/parser.h @@ -0,0 +1,49 @@ +#ifndef PARSER_H +#define PARSER_H +#include "./ast.h" +#include "./hash_table.h" +#include "./lexer.h" +#include "./token.h" +#include <stdbool.h> +#include <stdio.h> + +typedef struct { + token_t **tokens; + hash_table_t *symbol_table; + int i; + int size; + bool finished; +} parser_t; + +parser_t *init_parser(lexer_t *lexer); + +void parser_error(parser_t *parser); + +void parser_move(parser_t *parser); + +void parser_eat(parser_t *parser, token_t *token); + +ast_t *parse_string(parser_t *parser); + +ast_t *parse_int(parser_t *parser); + +ast_t *parse_float(parser_t *parser); + +ast_t *parse_bool(parser_t *parser); + +ast_t *parse_list(parser_t *parser); + +ast_t *parse_quote(parser_t *parser); + +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); + +ast_t *parse_expr(parser_t *parser); + +ast_t *read_in(char *s); +#endif diff --git a/src/include/print.h b/src/include/print.h new file mode 100644 index 0000000..9dbecbd --- /dev/null +++ b/src/include/print.h @@ -0,0 +1,16 @@ +#ifndef PRINT_H +#define PRINT_H +#include "./ast.h" + +void print_string(ast_t *str); + +void print_int(ast_t *i); + +void print_bool(ast_t *b); + +void print_float(ast_t *f); + +void print_func(ast_t *f); + +void print(ast_t *res); +#endif diff --git a/src/include/sl_list.h b/src/include/sl_list.h new file mode 100644 index 0000000..5a7c130 --- /dev/null +++ b/src/include/sl_list.h @@ -0,0 +1,23 @@ +#ifndef SL_LIST_H +#define SL_LIST_H + +typedef struct SL_NODE_STRUCT { + void *p1; + void *p2; +} sl_node_t; + +typedef struct { + sl_node_t *head; + int size; +} sl_list_t; + +sl_node_t *init_sl_node(void *value); + +sl_list_t *init_sl_list(); + +void sl_list_add(sl_list_t *l, void *value, int i); + +void sl_list_del(sl_list_t *l, int i); + +void *sl_list_get(sl_list_t *l, int i); +#endif diff --git a/src/include/stack.h b/src/include/stack.h new file mode 100644 index 0000000..e8047c8 --- /dev/null +++ b/src/include/stack.h @@ -0,0 +1,16 @@ +#ifndef STACK_H +#define STACK_H +#include "./hash_table.h" +typedef struct { + hash_table_t **stack; + int cur; +} stack_t; + +stack_t *init_stack(int ht_size); + +void stack_push(stack_t *s, hash_table_t *h); + +hash_table_t *stack_peek(stack_t *s); + +hash_table_t *stack_pop(stack_t *s); +#endif diff --git a/src/include/token.h b/src/include/token.h new file mode 100644 index 0000000..83c595b --- /dev/null +++ b/src/include/token.h @@ -0,0 +1,22 @@ +#ifndef TOKEN_H +#define TOKEN_H + +typedef struct { + enum { + TOKEN_ID, + TOKEN_LPAREN, + TOKEN_RPAREN, + TOKEN_BOOL, + TOKEN_INT, + TOKEN_FLOAT, + TOKEN_STRING, + TOKEN_QUOTE, + TOKEN_PERIOD, + } type; + char *value; + int row; + int col; +} token_t; + +token_t *init_token(int type, char *value, int row, int col); +#endif diff --git a/src/include/visitor.h b/src/include/visitor.h new file mode 100644 index 0000000..87f2853 --- /dev/null +++ b/src/include/visitor.h @@ -0,0 +1,26 @@ +#ifndef VISITOR_H +#define VISITOR_H +#include "./ast.h" +#include "./hash_table.h" +#include "./stack.h" + +typedef struct { + hash_table_t *symbol_table; + stack_t *stack_frame; + ast_t *root; +} visitor_t; + +void eval_error(visitor_t *v); + +visitor_t *init_visitor(ast_t *root); + +bool is_self_evaluating(ast_t *e); + +ast_t *eval_symbol(visitor_t *v, ast_t *e); + +ast_t *eval_list(visitor_t *v, ast_t *e); + +ast_t *eval_expr(visitor_t *v, ast_t *e); + +ast_t *eval(visitor_t *v); +#endif diff --git a/src/lexer.c b/src/lexer.c new file mode 100644 index 0000000..02417a1 --- /dev/null +++ b/src/lexer.c @@ -0,0 +1,150 @@ +#include "./include/lexer.h" +#include "./include/macros.h" +#include "./include/token.h" + +#include <ctype.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void lexer_reset(lexer_t *lexer, char *source) { + lexer->source = source; + lexer->c = source[0]; + lexer->i = 0; + lexer->row = 1; + lexer->col = 1; + lexer->finished = false; +} + +lexer_t *init_lexer(char *source) { + lexer_t *l = (lexer_t *)malloc(sizeof(lexer_t)); + if (l == NULL) + die("malloc on lexer"); + lexer_reset(l, source); + return l; +} + +void lexer_move(lexer_t *lexer) { + if (lexer->c != '\0') { + lexer->i++; + lexer->c = lexer->source[lexer->i]; + if (lexer->c == '\n') { + lexer->row++; + lexer->col = 0; + } + } else + lexer->finished = true; +} + +void lexer_ignore_whitespace(lexer_t *lexer) { + while (isspace(lexer->c)) + lexer_move(lexer); +} + +void lexer_skip_comment(lexer_t *lexer) { + while (lexer->c != '\n' && lexer->c != '\0') + lexer_move(lexer); +} + +static bool is_valid_id_char(char c) { + if (c == '(' || c == ')' || isdigit(c) || c == '"' || c == '\'' || c == '#' || + c == '.') + return false; + return true; +} + +static char *char_to_string(char c) { + char *s = (char *)malloc(2 * sizeof(char)); + s[0] = c; + s[1] = '\0'; + return s; +} + +token_t *lexer_collect_bool(lexer_t *lexer) { + lexer_move(lexer); + if (lexer->c == 't') + return init_token(TOKEN_BOOL, "T", lexer->row, lexer->col); + else if (lexer->c == 'f') + return init_token(TOKEN_BOOL, "F", lexer->row, lexer->col); + else + return NULL; +} + +token_t *lexer_collect_id(lexer_t *lexer) { + char *ret = (char *)malloc(1); + ret[0] = '\0'; + + while (is_valid_id_char(lexer->c)) { + ret = realloc(ret, (strlen(ret) + 2)); + strcat(ret, char_to_string(lexer->c)); + lexer_move(lexer); + } + return init_token(TOKEN_ID, ret, lexer->row, lexer->col); +} + +token_t *lexer_collect_num(lexer_t *lexer) { + char *ret = (char *)malloc(1); + ret[0] = '\0'; + bool is_float = false; + while (isdigit(lexer->c) || (lexer->c == '.' && !is_float)) { + if (lexer->c == '.') + is_float = true; + ret = realloc(ret, (strlen(ret) + 2)); + strcat(ret, char_to_string(lexer->c)); + lexer_move(lexer); + } + if (is_float) + return init_token(TOKEN_FLOAT, ret, lexer->row, lexer->col); + return init_token(TOKEN_INT, ret, lexer->row, lexer->col); +} + +token_t *lexer_collect_string(lexer_t *lexer) { + char *ret = (char *)malloc(1); + ret[0] = '\0'; + lexer_move(lexer); + while (lexer->c != '"') { + ret = realloc(ret, (strlen(ret) + 2)); + strcat(ret, char_to_string(lexer->c)); + lexer_move(lexer); + } + lexer_move(lexer); + return init_token(TOKEN_STRING, ret, lexer->row, lexer->col); +} + +static token_t *lexer_move_with(lexer_t *lexer, token_t *token) { + lexer_move(lexer); + return token; +} + +token_t *lexer_collect_next(lexer_t *lexer) { + if (lexer->c == '\0') { + lexer->finished = true; + return NULL; + } + if (isspace(lexer->c)) + lexer_ignore_whitespace(lexer); + + if (isdigit(lexer->c)) + return lexer_collect_num(lexer); + else if (is_valid_id_char(lexer->c)) + return lexer_collect_id(lexer); + else if (lexer->c == '"') + return lexer_collect_string(lexer); + else if (lexer->c == '#') + return lexer_collect_bool(lexer); + else if (lexer->c == '(') + return lexer_move_with( + lexer, init_token(TOKEN_LPAREN, "(", lexer->row, lexer->col)); + else if (lexer->c == ')') + return lexer_move_with( + lexer, init_token(TOKEN_RPAREN, ")", lexer->row, lexer->col)); + else if (lexer->c == '\'') + return lexer_move_with( + lexer, init_token(TOKEN_QUOTE, "'", lexer->row, lexer->col)); + else if (lexer->c == '.') + return lexer_move_with( + lexer, init_token(TOKEN_PERIOD, ".", lexer->row, lexer->col)); + else + return NULL; +} diff --git a/src/macros.c b/src/macros.c new file mode 100644 index 0000000..1effefe --- /dev/null +++ b/src/macros.c @@ -0,0 +1,10 @@ +#include "./include/macros.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +void die(char *message) { + fprintf(stderr, "%sFATAL ERROR: %s%s\n", RED, message, reset); + exit(EXIT_FAILURE); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..08cadbc --- /dev/null +++ b/src/main.c @@ -0,0 +1,39 @@ +#define _GNU_SOURCE +#include "./include/lexer.h" +#include "./include/token.h" +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int main(int argc, char **argv) { + /* Test Lexer */ + lexer_t *lexer = init_lexer("'(fasd \"aaaaaaaa\" 4)"); + token_t *t = lexer_collect_next(lexer); + while (t != NULL) { + printf("%d: %s\n", t->type, t->value); + t = lexer_collect_next(lexer); + } + /* printf("Welcome to the NXS REPL.\n"); */ + + /* char *buf = malloc(2); */ + /* size_t size = 2; */ + /* lexer_t *lexer; */ + /* lexer = init_lexer("a"); */ + /* token_t *t; */ + /* while (true) { */ + /* printf("> "); */ + /* fflush(stdout); */ + /* getline(&buf, &size, stdin); */ + /* strcat(buf, "\0"); */ + /* lexer_reset(lexer, buf); */ + /* t = lexer_collect_next(lexer); */ + /* while (!lexer->finished) { */ + /* printf("%d\t%s\n", t->type, t->value); */ + /* t = lexer_collect_next(lexer); */ + /* printf("lmao\n"); */ + /* } */ + /* } */ + + return 0; +} diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..f28fcc2 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,125 @@ +#include "./include/parser.h" +#include "./include/hash_table.h" +#include "./include/lexer.h" +#include "./include/macros.h" +#include "./include/token.h" +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +parser_t *init_parser(lexer_t *lexer) { + parser_t *p = (parser_t *)malloc(sizeof(parser_t)); + if (p == NULL) + die("malloc on parser"); + + p->i = 0; + p->tokens = malloc(sizeof(token_t *)); + p->symbol_table = init_hash_table(); + p->finished = false; + + if (p->tokens == NULL) + die("malloc on p->tokens"); + + int size = 1; + token_t *t = lexer_collect_next(lexer); + p->tokens[size - 1] = t; + + while (true) { + t = lexer_collect_next(lexer); + if (t == NULL) + break; + size++; + p->tokens = realloc(p->tokens, size * sizeof(token_t *)); + p->tokens[size - 1] = t; + } + + p->size = size; + return p; +} + +void parser_move(parser_t *parser) { + if (parser->i != parser->size - 1) + parser->i++; + else + parser->finished = true; +} + +void parser_eat(parser_t *parser, token_t *token) { parser_move(parser); } + +ast_t *parse_bool(parser_t *parser) { + token_t *t = parser->tokens[parser->i]; + parser_move(parser); + if (strcmp("T", t->value) == 0) { + return init_ast_bool(true); + } else + return init_ast_bool(false); +} + +static char *escape_string(char *str) { return str; } + +ast_t *parse_string(parser_t *parser) { + char *str = parser->tokens[parser->i]->value; + parser_move(parser); + return init_ast_string(escape_string(str)); +} + +ast_t *parse_int(parser_t *parser) { + int ret = atoi(parser->tokens[parser->i]->value); + parser_move(parser); + return init_ast_int(ret); +} + +ast_t *parse_float(parser_t *parser) { + double ret = atof(parser->tokens[parser->i]->value); + parser_move(parser); + return init_ast_float(ret); +} + +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: */ + ast_t *cdr = + parse_expr(parser); /* a function can contain a single expression */ + return init_ast_function(car, cdr); +} + +ast_t *parse_list(parser_t *parser) { + parser_move(parser); + token_t *cur = parser->tokens[parser->i]; + bool first_entry = true; + 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); + first_entry = false; + } +} +ast_t *parse_expr(parser_t *parser) { + token_t *t = parser->tokens[parser->i]; + if (t->type == TOKEN_STRING) + return parse_string(parser); + else if (t->type == TOKEN_INT) + return parse_int(parser); + else if (t->type == TOKEN_FLOAT) + return parse_float(parser); + else if (t->type == TOKEN_BOOL) + return parse_bool(parser); + else if (t->type == TOKEN_LPAREN) + return parse_list(parser); + else if (t->type == TOKEN_QUOTE) + return parse_quote(parser); + else if (t->type == TOKEN_ID) + return parse_symbol(parser); + else if (t->type == TOKEN_LPAREN) + return parse_list(parser); + else { + parser_error(parser); + } + return NULL; +} diff --git a/src/stack.c b/src/stack.c new file mode 100644 index 0000000..4898d83 --- /dev/null +++ b/src/stack.c @@ -0,0 +1,34 @@ +#include "./include/stack.h" +#include "./include/hash_table.h" +#include "./include/macros.h" +#include <stdlib.h> + +stack_t *init_stack(int ht_size) { + stack_t *s = (stack_t *)malloc(sizeof(stack_t)); + if (s == NULL) + die("malloc on stack"); + s->stack = NULL; + s->cur = -1; + return s; +} + +void stack_push(stack_t *s, hash_table_t *h) { + if (s->stack == NULL) { + s->stack = malloc(sizeof(hash_table_t *)); + if (s->stack == NULL) + die("malloc on stack within stack"); + } else { + s->stack = realloc(s->stack, 2 + s->cur); + } + s->cur++; + s->stack[s->cur] = h; +} + +hash_table_t *stack_peek(stack_t *s) { return s->stack[s->cur]; } + +hash_table_t *stack_pop(stack_t *s) { + hash_table_t *h = s->stack[s->cur]; + s->stack[s->cur] = NULL; + s->cur--; + return h; +} diff --git a/src/token.c b/src/token.c new file mode 100644 index 0000000..1cd0d91 --- /dev/null +++ b/src/token.c @@ -0,0 +1,15 @@ +#include "./include/token.h" +#include "./include/macros.h" + +#include <stdlib.h> + +token_t *init_token(int type, char *value, int row, int col) { + token_t *t = (token_t *)malloc(sizeof(token_t)); + if (t == NULL) + die("malloc on token struct"); + t->type = type; + t->value = value; + t->row = row; + t->col = col; + return t; +} diff --git a/src/visitor.c b/src/visitor.c new file mode 100644 index 0000000..25296c1 --- /dev/null +++ b/src/visitor.c @@ -0,0 +1,25 @@ +#include "./include/visitor.h" +#include "./include/hash_table.h" +#include "./include/macros.h" +#include "./include/stack.h" +#include <stdlib.h> + +visitor_t *init_visitor(ast_t *root) { + visitor_t *v = (visitor_t *)malloc(sizeof(visitor_t)); + if (v == NULL) + die("malloc on visitor"); + v->stack_frame = init_stack(512); + v->symbol_table = init_hash_table(10000); + v->root = root; + return v; +} + +bool is_self_evaluating(ast_t *e) { + if (e->type == AST_STRING || e->type == AST_INT || e->type == AST_FLOAT || + e->type == AST_BOOL || e->type == AST_FUNCTION) + return true; + + if (e->type == AST_PAIR && e->car == NULL && e->cdr == NULL) + return true; + return false; +} |