diff options
| -rw-r--r-- | lexer.c | 243 | ||||
| -rw-r--r-- | lexer.h | 65 | ||||
| -rw-r--r-- | memory.c | 27 | ||||
| -rw-r--r-- | memory.h | 15 | ||||
| -rw-r--r-- | parser.c | 174 | ||||
| -rw-r--r-- | parser.h | 18 | ||||
| -rw-r--r-- | types.c | 232 | ||||
| -rw-r--r-- | types.h | 65 |
8 files changed, 839 insertions, 0 deletions
| @@ -0,0 +1,243 @@ | |||
| 1 | #include "lexer.h" | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <stdlib.h> | ||
| 4 | #include <string.h> | ||
| 5 | |||
| 6 | Lexer *lexer_make() | ||
| 7 | { | ||
| 8 | Lexer *lexer = (Lexer *)malloc(sizeof(Lexer)); | ||
| 9 | return lexer; | ||
| 10 | } | ||
| 11 | |||
| 12 | void lexer_free(Lexer *lexer) | ||
| 13 | { | ||
| 14 | Token *token = lexer->tokens; | ||
| 15 | Token *token_next = NULL; | ||
| 16 | |||
| 17 | while (token) | ||
| 18 | { | ||
| 19 | token_next = token->next; | ||
| 20 | jadl_free(token->value); | ||
| 21 | jadl_free(token); | ||
| 22 | token = token_next; | ||
| 23 | } | ||
| 24 | jadl_free(lexer); | ||
| 25 | } | ||
| 26 | |||
| 27 | Token *lexer_token_make(char *value, int value_len, TokenType type) | ||
| 28 | { | ||
| 29 | Token *token = jadl_malloc(sizeof(token)); | ||
| 30 | token->value = jadl_malloc(sizeof(char) * value_len + 1); | ||
| 31 | token->value[value_len] = '\0'; | ||
| 32 | token->type = type; | ||
| 33 | strncpy(token->value, value, value_len); | ||
| 34 | token->is_decimal_point = 0; | ||
| 35 | return token; | ||
| 36 | } | ||
| 37 | |||
| 38 | Lexer *lexer_token_push(Lexer *lexer, Token *token) | ||
| 39 | { | ||
| 40 | token->next = lexer->tokens; | ||
| 41 | lexer->tokens = token; | ||
| 42 | return lexer; | ||
| 43 | } | ||
| 44 | |||
| 45 | Lexer *lexer_tokens_reverse(Lexer *lexer) | ||
| 46 | { | ||
| 47 | Token *token = lexer->tokens; | ||
| 48 | Token *token_next = NULL; | ||
| 49 | lexer->tokens=NULL; | ||
| 50 | |||
| 51 | while (token) | ||
| 52 | { | ||
| 53 | token_next = token->next; | ||
| 54 | |||
| 55 | lexer_token_push(lexer, token); | ||
| 56 | |||
| 57 | token = token_next; | ||
| 58 | } | ||
| 59 | return lexer; | ||
| 60 | } | ||
| 61 | |||
| 62 | char *lexer_token_make_string(char *str, Token **token) | ||
| 63 | { | ||
| 64 | char *end = str; | ||
| 65 | int is_string_read = 1; | ||
| 66 | str += 1; | ||
| 67 | |||
| 68 | do | ||
| 69 | { | ||
| 70 | end = strchr(end+1, '"'); | ||
| 71 | if (!end) | ||
| 72 | { | ||
| 73 | lexer_token_make_error("Cannot find end of string!", token); | ||
| 74 | is_string_read = 0; | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | is_string_read = 1; | ||
| 78 | } while(*(end-1) == '\\'); | ||
| 79 | |||
| 80 | if(is_string_read) | ||
| 81 | { | ||
| 82 | int str_len = (end - str); | ||
| 83 | *token = lexer_token_make(str, str_len, TOKEN_TYPE_STRING); | ||
| 84 | } | ||
| 85 | |||
| 86 | return (!is_string_read) ? NULL : end + 1; | ||
| 87 | } | ||
| 88 | |||
| 89 | char *lexer_token_make_number(char *str, Token **token) | ||
| 90 | { | ||
| 91 | char *end = lexer_token_terminated_symbol(str); | ||
| 92 | |||
| 93 | char *next = str; | ||
| 94 | int is_decimal_point=0; | ||
| 95 | int is_number_read=1; | ||
| 96 | |||
| 97 | while(next<end) | ||
| 98 | { | ||
| 99 | if (!is_decimal_point && *next == '.') | ||
| 100 | is_decimal_point=1; | ||
| 101 | else if(*next == '.') { | ||
| 102 | lexer_token_make_error( | ||
| 103 | "Cannot read number, becouse it has too many decimal points!", token); | ||
| 104 | is_number_read = 0; | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | else if(!isdigit(*next)) { | ||
| 108 | lexer_token_make_error("Cannot read number, becouse it isnt digit!", token); | ||
| 109 | is_number_read = 0; | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | |||
| 113 | is_number_read = 1; | ||
| 114 | next+=1; | ||
| 115 | } | ||
| 116 | |||
| 117 | if(is_number_read) | ||
| 118 | { | ||
| 119 | int str_len = (end - str + 1); *token = lexer_token_make(str, str_len, TOKEN_TYPE_NUMBER); | ||
| 120 | (*token)->is_decimal_point = is_decimal_point; | ||
| 121 | } | ||
| 122 | |||
| 123 | return (is_number_read) ? end + 1 : NULL; | ||
| 124 | } | ||
| 125 | |||
| 126 | char *lexer_token_terminated_symbol(char *str) | ||
| 127 | { | ||
| 128 | static char *chars_to_terminate = " ()[],;\"`"; | ||
| 129 | char *terminated = strpbrk(str, chars_to_terminate); | ||
| 130 | terminated = (terminated == NULL) ? &str[strlen(str) - 1] : terminated - 1; | ||
| 131 | return terminated; | ||
| 132 | } | ||
| 133 | |||
| 134 | char *lexer_token_make_symbol(char *str, Token **token) | ||
| 135 | { | ||
| 136 | char *end = lexer_token_terminated_symbol(str); | ||
| 137 | |||
| 138 | int str_len = (end - str + 1); | ||
| 139 | |||
| 140 | *token = lexer_token_make(str, str_len, TOKEN_TYPE_SYMBOL); | ||
| 141 | |||
| 142 | if(strncmp(str, SYMBOL_NIL, str_len) == 0) | ||
| 143 | (*token)->type = TOKEN_TYPE_NIL; | ||
| 144 | else if(strncmp(str, SYMBOL_FALSE, str_len) == 0 || | ||
| 145 | strncmp(str, SYMBOL_FALSE_SHORT, str_len) == 0) | ||
| 146 | (*token)->type = TOKEN_TYPE_FALSE; | ||
| 147 | else if(strncmp(str, SYMBOL_TRUE, str_len) == 0 || | ||
| 148 | strncmp(str, SYMBOL_TRUE_SHORT, str_len == 0)) | ||
| 149 | (*token)->type = TOKEN_TYPE_TRUE; | ||
| 150 | |||
| 151 | return end + 1; | ||
| 152 | } | ||
| 153 | |||
| 154 | char *lexer_token_make_special(char *str, Token **token) | ||
| 155 | { | ||
| 156 | *token = lexer_token_make(str, 1, TOKEN_TYPE_SPECIAL); | ||
| 157 | return str + 1; | ||
| 158 | } | ||
| 159 | |||
| 160 | |||
| 161 | void lexer_token_make_error(char *message, Token **token) | ||
| 162 | { | ||
| 163 | unsigned long message_len = strlen(message); | ||
| 164 | *token = lexer_token_make(message, message_len, TOKEN_TYPE_ERROR); | ||
| 165 | } | ||
| 166 | |||
| 167 | |||
| 168 | Lexer *lexer_tokenize(char *str) { | ||
| 169 | Lexer *lexer = lexer_make(); | ||
| 170 | Token *token = NULL; | ||
| 171 | |||
| 172 | while (str && *str) { | ||
| 173 | /* if(!*str) return lexer; */ | ||
| 174 | |||
| 175 | switch (*str) { | ||
| 176 | case ' ': | ||
| 177 | case ';': | ||
| 178 | token = NULL; | ||
| 179 | str += 1; | ||
| 180 | break; | ||
| 181 | case '(': | ||
| 182 | case ')': | ||
| 183 | case '[': | ||
| 184 | case ']': | ||
| 185 | str = lexer_token_make_special(str, &token); | ||
| 186 | break; | ||
| 187 | case '0': | ||
| 188 | case '1': | ||
| 189 | case '2': | ||
| 190 | case '3': | ||
| 191 | case '4': | ||
| 192 | case '5': | ||
| 193 | case '6': | ||
| 194 | case '7': | ||
| 195 | case '8': | ||
| 196 | case '9': | ||
| 197 | str = lexer_token_make_number(str, &token); | ||
| 198 | break; | ||
| 199 | case '"': | ||
| 200 | str = lexer_token_make_string(str, &token); | ||
| 201 | break; | ||
| 202 | default: | ||
| 203 | str = lexer_token_make_symbol(str, &token); | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | if (token) | ||
| 207 | lexer_token_push(lexer, token); | ||
| 208 | } | ||
| 209 | |||
| 210 | return lexer; | ||
| 211 | } | ||
| 212 | |||
| 213 | void lexer_tokens_print(Lexer *lexer) | ||
| 214 | { | ||
| 215 | Token *token = lexer->tokens; | ||
| 216 | while (token) { | ||
| 217 | switch(token->type) { | ||
| 218 | case TOKEN_TYPE_STRING: | ||
| 219 | printf("String: "); | ||
| 220 | break; | ||
| 221 | case TOKEN_TYPE_SYMBOL: | ||
| 222 | printf("Symbol: "); | ||
| 223 | break; | ||
| 224 | case TOKEN_TYPE_SPECIAL: | ||
| 225 | printf("Special: "); | ||
| 226 | break; | ||
| 227 | case TOKEN_TYPE_NUMBER: | ||
| 228 | printf("Number: "); | ||
| 229 | break; | ||
| 230 | case TOKEN_TYPE_TRUE: | ||
| 231 | printf("True: "); | ||
| 232 | break; | ||
| 233 | case TOKEN_TYPE_FALSE: | ||
| 234 | printf("False: "); | ||
| 235 | break; | ||
| 236 | case TOKEN_TYPE_NIL: | ||
| 237 | printf("Nil: "); | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | printf("%s\n", token->value); | ||
| 241 | token = token->next; | ||
| 242 | } | ||
| 243 | } | ||
| @@ -0,0 +1,65 @@ | |||
| 1 | #ifndef _LEXER | ||
| 2 | #define _LEXER | ||
| 3 | |||
| 4 | #include <stddef.h> | ||
| 5 | #include <stdio.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | #include <string.h> | ||
| 8 | #include <ctype.h> | ||
| 9 | |||
| 10 | #include "types.h" | ||
| 11 | #include "memory.h" | ||
| 12 | |||
| 13 | #define SYMBOL_NIL "nil" | ||
| 14 | #define SYMBOL_TRUE_SHORT "#t" | ||
| 15 | #define SYMBOL_TRUE "#true" | ||
| 16 | #define SYMBOL_FALSE_SHORT "#f" | ||
| 17 | #define SYMBOL_FALSE "#false" | ||
| 18 | |||
| 19 | |||
| 20 | typedef enum _TokenType { | ||
| 21 | TOKEN_TYPE_SYMBOL, | ||
| 22 | TOKEN_TYPE_NUMBER, | ||
| 23 | TOKEN_TYPE_STRING, | ||
| 24 | TOKEN_TYPE_TRUE, | ||
| 25 | TOKEN_TYPE_FALSE, | ||
| 26 | TOKEN_TYPE_NIL, | ||
| 27 | TOKEN_TYPE_SPECIAL, | ||
| 28 | TOKEN_TYPE_ERROR | ||
| 29 | } TokenType; | ||
| 30 | |||
| 31 | |||
| 32 | typedef struct _Token { | ||
| 33 | TokenType type; | ||
| 34 | int is_decimal_point; | ||
| 35 | char *value; | ||
| 36 | struct _Token *next; | ||
| 37 | } Token; | ||
| 38 | |||
| 39 | typedef struct _Lexer { | ||
| 40 | int error; | ||
| 41 | Token *tokens; | ||
| 42 | } Lexer; | ||
| 43 | |||
| 44 | int lexer_tokens_count(char *str); | ||
| 45 | |||
| 46 | Lexer *lexer_make(); | ||
| 47 | void lexer_free(Lexer *lexer); | ||
| 48 | Token *lexer_token_make(char *value, int value_len, TokenType type); | ||
| 49 | Lexer *lexer_token_push(Lexer *lexer, Token *token); | ||
| 50 | |||
| 51 | char *lexer_token_terminated_symbol(char *str); | ||
| 52 | char *lexer_token_make_string(char *str, Token **token); | ||
| 53 | char *lexer_token_make_symbol(char *str, Token **token); | ||
| 54 | char *lexer_token_make_special(char *str, Token **token); | ||
| 55 | char *lexer_token_make_number(char *str, Token **token); | ||
| 56 | |||
| 57 | void lexer_token_make_error(char *message, Token **token); | ||
| 58 | |||
| 59 | Lexer *lexer_tokenize(char *str); | ||
| 60 | |||
| 61 | |||
| 62 | void lexer_tokens_print(Lexer *lexer); | ||
| 63 | Lexer *lexer_tokens_reverse(Lexer *lexer); | ||
| 64 | |||
| 65 | #endif | ||
diff --git a/memory.c b/memory.c new file mode 100644 index 0000000..387268b --- /dev/null +++ b/memory.c | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #include "memory.h" | ||
| 2 | |||
| 3 | #include <stdio.h> | ||
| 4 | |||
| 5 | void *jadl_malloc(size_t size) { | ||
| 6 | void *ptr = malloc(size); | ||
| 7 | if(ptr == NULL) | ||
| 8 | { | ||
| 9 | printf("malloc: ERROR"); | ||
| 10 | exit(1); | ||
| 11 | } | ||
| 12 | return ptr; | ||
| 13 | } | ||
| 14 | |||
| 15 | void jadl_free(void *ptr) { | ||
| 16 | return free(ptr); | ||
| 17 | } | ||
| 18 | |||
| 19 | long usage() { | ||
| 20 | struct rusage r_usage; | ||
| 21 | getrusage(RUSAGE_SELF, &r_usage); | ||
| 22 | return r_usage.ru_maxrss; | ||
| 23 | } | ||
| 24 | |||
| 25 | void usage_print() { | ||
| 26 | printf("Mem usage: %ld kilobytes\n", usage()); | ||
| 27 | } | ||
diff --git a/memory.h b/memory.h new file mode 100644 index 0000000..ba78b22 --- /dev/null +++ b/memory.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #ifndef _MEMORY | ||
| 2 | #define _MEMORY | ||
| 3 | |||
| 4 | #include <stddef.h> | ||
| 5 | #include <stdio.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | #include <sys/resource.h> | ||
| 8 | |||
| 9 | void *jadl_malloc(size_t size); | ||
| 10 | void jadl_free(void *ptr); | ||
| 11 | |||
| 12 | long usage(); | ||
| 13 | void usage_print(); | ||
| 14 | |||
| 15 | #endif | ||
diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..574d2ac --- /dev/null +++ b/parser.c | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | #include "parser.h" | ||
| 2 | #include "lexer.h" | ||
| 3 | #include "types.h" | ||
| 4 | #include <stdio.h> | ||
| 5 | |||
| 6 | |||
| 7 | LISP_OBJECT *parser_parse_str(char *str) | ||
| 8 | { | ||
| 9 | Lexer *lexer = lexer_tokenize(str); | ||
| 10 | lexer_tokens_reverse(lexer); | ||
| 11 | |||
| 12 | Token *token = lexer->tokens; | ||
| 13 | LISP_OBJECT *lisp_obj = NULL; | ||
| 14 | lisp_obj = parser_parse_tokens(&token); | ||
| 15 | |||
| 16 | lexer_free(lexer); | ||
| 17 | |||
| 18 | return lisp_obj; | ||
| 19 | } | ||
| 20 | |||
| 21 | LISP_OBJECT *parser_parse_tokens(Token **token) | ||
| 22 | { | ||
| 23 | LISP_OBJECT *lisp_obj = NULL; | ||
| 24 | switch((*token)->type) | ||
| 25 | { | ||
| 26 | case TOKEN_TYPE_SPECIAL: | ||
| 27 | lisp_obj = parser_make_list(token); | ||
| 28 | break; | ||
| 29 | case TOKEN_TYPE_NUMBER: | ||
| 30 | lisp_obj = parser_make_number(token); | ||
| 31 | break; | ||
| 32 | case TOKEN_TYPE_STRING: | ||
| 33 | lisp_obj = parser_make_string(token); | ||
| 34 | break; | ||
| 35 | case TOKEN_TYPE_SYMBOL: | ||
| 36 | lisp_obj = parser_make_symbol(token); | ||
| 37 | break; | ||
| 38 | case TOKEN_TYPE_TRUE: | ||
| 39 | lisp_obj = parser_make_true(token); | ||
| 40 | break; | ||
| 41 | case TOKEN_TYPE_FALSE: | ||
| 42 | lisp_obj = parser_make_false(token); | ||
| 43 | break; | ||
| 44 | case TOKEN_TYPE_NIL: | ||
| 45 | lisp_obj = parser_make_nil(token); | ||
| 46 | break; | ||
| 47 | case TOKEN_TYPE_ERROR: | ||
| 48 | lisp_obj = lisp_object_make_error((*token)->value); | ||
| 49 | *token = (*token)->next; | ||
| 50 | break; | ||
| 51 | default: | ||
| 52 | *token = (*token)->next; | ||
| 53 | lisp_obj = lisp_object_make_error("Something bad happenend!"); | ||
| 54 | } | ||
| 55 | return lisp_obj; | ||
| 56 | } | ||
| 57 | |||
| 58 | LISP_OBJECT *parser_make_list(Token **token) | ||
| 59 | { | ||
| 60 | LISP_OBJECT *lisp_list_obj = lisp_object_make_list(); | ||
| 61 | char close_delimiter = ( *(*token)->value == '(' ) ? ')' : ']'; | ||
| 62 | *token = (*token)->next; | ||
| 63 | int is_close_delimiter = 1; | ||
| 64 | |||
| 65 | while(*token) | ||
| 66 | { | ||
| 67 | if((*token)->type==TOKEN_TYPE_SPECIAL && | ||
| 68 | *(*token)->value==close_delimiter) | ||
| 69 | { | ||
| 70 | is_close_delimiter=0; | ||
| 71 | *token=(*token)->next; | ||
| 72 | break; | ||
| 73 | } | ||
| 74 | |||
| 75 | lisp_object_list_push(lisp_list_obj, | ||
| 76 | (void *)parser_parse_tokens(token)); | ||
| 77 | |||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | List *list = list_reverse(lisp_list_obj->value.list); | ||
| 82 | lisp_list_obj->value.list = list; | ||
| 83 | |||
| 84 | if(is_close_delimiter != 0) | ||
| 85 | { | ||
| 86 | LISP_OBJECT *err_msg = lisp_object_make_error("Unbalanced parenthesis!"); | ||
| 87 | lisp_object_list_push(lisp_list_obj, err_msg); | ||
| 88 | } | ||
| 89 | |||
| 90 | return lisp_list_obj; | ||
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | LISP_OBJECT *parser_make_number(Token **token) | ||
| 95 | { | ||
| 96 | LISP_OBJECT *lisp_obj = NULL; | ||
| 97 | char *number_str = (*token)->value; | ||
| 98 | union | ||
| 99 | { | ||
| 100 | long long natural; | ||
| 101 | double floating; | ||
| 102 | |||
| 103 | } number; | ||
| 104 | |||
| 105 | if((*token)->is_decimal_point) | ||
| 106 | { | ||
| 107 | sscanf(number_str, "%lf", &number.floating); | ||
| 108 | lisp_obj = lisp_object_make_number_float(number.floating); | ||
| 109 | } | ||
| 110 | else | ||
| 111 | { | ||
| 112 | sscanf(number_str, "%lld", &number.natural); | ||
| 113 | lisp_obj = lisp_object_make_number_natural(number.natural); | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | *token=(*token)->next; | ||
| 118 | return lisp_obj; | ||
| 119 | } | ||
| 120 | |||
| 121 | LISP_OBJECT *parser_make_string(Token **token) | ||
| 122 | { | ||
| 123 | char *str = (*token)->value; | ||
| 124 | LISP_OBJECT *lisp_obj = lisp_object_make_string(str); | ||
| 125 | |||
| 126 | *token=(*token)->next; | ||
| 127 | return lisp_obj; | ||
| 128 | } | ||
| 129 | |||
| 130 | LISP_OBJECT *parser_make_symbol(Token **token) | ||
| 131 | { | ||
| 132 | char *str = (*token)->value; | ||
| 133 | LISP_OBJECT *lisp_obj = lisp_object_make_symbol(str); | ||
| 134 | |||
| 135 | *token=(*token)->next; | ||
| 136 | return lisp_obj; | ||
| 137 | } | ||
| 138 | |||
| 139 | LISP_OBJECT *parser_make_true(Token **token) | ||
| 140 | { | ||
| 141 | LISP_OBJECT *lisp_obj = lisp_object_make_true(); | ||
| 142 | |||
| 143 | *token=(*token)->next; | ||
| 144 | return lisp_obj; | ||
| 145 | } | ||
| 146 | |||
| 147 | LISP_OBJECT *parser_make_false(Token **token) | ||
| 148 | { | ||
| 149 | LISP_OBJECT *lisp_obj = lisp_object_make_false(); | ||
| 150 | |||
| 151 | *token=(*token)->next; | ||
| 152 | return lisp_obj; | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | LISP_OBJECT *parser_make_nil(Token **token) | ||
| 157 | { | ||
| 158 | LISP_OBJECT *lisp_obj = lisp_object_make_nil(); | ||
| 159 | |||
| 160 | *token=(*token)->next; | ||
| 161 | return lisp_obj; | ||
| 162 | } | ||
| 163 | |||
| 164 | int main() | ||
| 165 | { | ||
| 166 | char *test = "(display (string-append \"4*3+2=\" (number->string (+ (* 4 3) 1))))"; | ||
| 167 | |||
| 168 | |||
| 169 | LISP_OBJECT *obj = NULL; | ||
| 170 | |||
| 171 | obj = parser_parse_str(test); | ||
| 172 | lisp_object_print(obj, 0); | ||
| 173 | lisp_object_free(obj); | ||
| 174 | } | ||
diff --git a/parser.h b/parser.h new file mode 100644 index 0000000..2a4c523 --- /dev/null +++ b/parser.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | #ifndef _PARSER | ||
| 2 | #define _PARSER | ||
| 3 | |||
| 4 | #include "types.h" | ||
| 5 | #include "lexer.h" | ||
| 6 | |||
| 7 | LISP_OBJECT *parser_parse_str(char *str); | ||
| 8 | LISP_OBJECT *parser_parse_tokens(Token **token); | ||
| 9 | |||
| 10 | LISP_OBJECT *parser_make_list(Token **token); | ||
| 11 | LISP_OBJECT *parser_make_number(Token **token); | ||
| 12 | LISP_OBJECT *parser_make_string(Token **token); | ||
| 13 | LISP_OBJECT *parser_make_symbol(Token **token); | ||
| 14 | LISP_OBJECT *parser_make_true(Token **token); | ||
| 15 | LISP_OBJECT *parser_make_false(Token **token); | ||
| 16 | LISP_OBJECT *parser_make_nil(Token **token); | ||
| 17 | |||
| 18 | #endif | ||
| @@ -0,0 +1,232 @@ | |||
| 1 | #include "types.h" | ||
| 2 | #include "memory.h" | ||
| 3 | #include <stdio.h> | ||
| 4 | |||
| 5 | |||
| 6 | List *list_make(void *ptr) | ||
| 7 | { | ||
| 8 | return list_push(NULL, ptr); | ||
| 9 | } | ||
| 10 | |||
| 11 | List *list_push(List *list, void *ptr) | ||
| 12 | { | ||
| 13 | List *new_head = (List*)malloc(sizeof(List)); | ||
| 14 | new_head->next=list; | ||
| 15 | new_head->ptr=ptr; | ||
| 16 | return new_head; | ||
| 17 | } | ||
| 18 | |||
| 19 | |||
| 20 | List *list_reverse(List *list) | ||
| 21 | { | ||
| 22 | List *current = list; | ||
| 23 | List *next = NULL; | ||
| 24 | List *new_list = NULL; | ||
| 25 | while (current) { | ||
| 26 | next = current->next; | ||
| 27 | |||
| 28 | current->next = new_list; | ||
| 29 | new_list = current; | ||
| 30 | |||
| 31 | current = next; | ||
| 32 | } | ||
| 33 | return new_list; | ||
| 34 | } | ||
| 35 | |||
| 36 | void list_free(List *list) | ||
| 37 | { | ||
| 38 | List *next = NULL; | ||
| 39 | while (list) | ||
| 40 | { | ||
| 41 | next = list->next; | ||
| 42 | |||
| 43 | jadl_free(list->ptr); | ||
| 44 | jadl_free(list); | ||
| 45 | |||
| 46 | list = next; | ||
| 47 | } | ||
| 48 | |||
| 49 | } | ||
| 50 | |||
| 51 | void lisp_object_list_push(LISP_OBJECT *lisp_list_obj, void *ptr) | ||
| 52 | { | ||
| 53 | List *new_head = list_push(lisp_list_obj->value.list, ptr); | ||
| 54 | lisp_list_obj->value.list = new_head; | ||
| 55 | } | ||
| 56 | |||
| 57 | LISP_OBJECT *lisp_object_make() | ||
| 58 | { | ||
| 59 | LISP_OBJECT *lisp_obj = jadl_malloc(sizeof(LISP_OBJECT)); | ||
| 60 | lisp_obj->is_decimal_point = 0; | ||
| 61 | return lisp_obj; | ||
| 62 | } | ||
| 63 | |||
| 64 | void lisp_object_list_free(LISP_OBJECT *lisp_obj_list) | ||
| 65 | { | ||
| 66 | if(lisp_obj_list->type != LISP_TYPE_LIST) | ||
| 67 | return; | ||
| 68 | |||
| 69 | List *list = lisp_obj_list->value.list; | ||
| 70 | List *next = NULL; | ||
| 71 | |||
| 72 | while (list) | ||
| 73 | { | ||
| 74 | next = list->next; | ||
| 75 | |||
| 76 | LISP_OBJECT *lisp_obj = list->ptr; | ||
| 77 | |||
| 78 | lisp_object_free(lisp_obj); | ||
| 79 | |||
| 80 | jadl_free(list); | ||
| 81 | list = next; | ||
| 82 | } | ||
| 83 | jadl_free(lisp_obj_list); | ||
| 84 | } | ||
| 85 | |||
| 86 | void lisp_object_free(LISP_OBJECT *lisp_obj) | ||
| 87 | { | ||
| 88 | if (lisp_obj->type == LISP_TYPE_LIST) | ||
| 89 | lisp_object_list_free(lisp_obj); | ||
| 90 | else | ||
| 91 | { | ||
| 92 | if (lisp_obj->type != LISP_TYPE_FALSE && | ||
| 93 | lisp_obj->type != LISP_TYPE_TRUE && | ||
| 94 | lisp_obj->type != LISP_TYPE_NIL) | ||
| 95 | { | ||
| 96 | jadl_free(lisp_obj->value.ptr); | ||
| 97 | } | ||
| 98 | jadl_free(lisp_obj); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | LISP_OBJECT *lisp_object_make_list() | ||
| 103 | { | ||
| 104 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 105 | lisp_obj->type = LISP_TYPE_LIST; | ||
| 106 | lisp_obj->value.ptr = NULL; | ||
| 107 | return lisp_obj; | ||
| 108 | } | ||
| 109 | |||
| 110 | LISP_OBJECT *lisp_object_make_number_natural(long long number) | ||
| 111 | { | ||
| 112 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 113 | lisp_obj->type = LISP_TYPE_NUMBER; | ||
| 114 | lisp_obj->value.number_natural = jadl_malloc(sizeof(long long)); | ||
| 115 | *lisp_obj->value.number_natural = number; | ||
| 116 | return lisp_obj; | ||
| 117 | } | ||
| 118 | |||
| 119 | LISP_OBJECT *lisp_object_make_number_float(double number) | ||
| 120 | { | ||
| 121 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 122 | lisp_obj->type = LISP_TYPE_NUMBER; | ||
| 123 | lisp_obj->value.number_float = jadl_malloc(sizeof(double)); | ||
| 124 | *lisp_obj->value.number_float = number; | ||
| 125 | lisp_obj->is_decimal_point = 1; | ||
| 126 | return lisp_obj; | ||
| 127 | } | ||
| 128 | |||
| 129 | LISP_OBJECT *lisp_object_make_string(char *str) | ||
| 130 | { | ||
| 131 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 132 | lisp_obj->type = LISP_TYPE_STRING; | ||
| 133 | lisp_obj->value.string = jadl_malloc(sizeof(char)*strlen(str)); | ||
| 134 | strcpy(lisp_obj->value.string, str); | ||
| 135 | return lisp_obj; | ||
| 136 | } | ||
| 137 | |||
| 138 | LISP_OBJECT *lisp_object_make_symbol(char *str) | ||
| 139 | { | ||
| 140 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 141 | lisp_obj->type = LISP_TYPE_SYMBOL; | ||
| 142 | lisp_obj->value.symbol = jadl_malloc(sizeof(char)*strlen(str)); | ||
| 143 | strcpy(lisp_obj->value.symbol, str); | ||
| 144 | return lisp_obj; | ||
| 145 | } | ||
| 146 | |||
| 147 | LISP_OBJECT *lisp_object_make_error(char *str) | ||
| 148 | { | ||
| 149 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 150 | lisp_obj->type = LISP_TYPE_ERROR; | ||
| 151 | lisp_obj->value.error = jadl_malloc(sizeof(char)*strlen(str)); | ||
| 152 | strcpy(lisp_obj->value.error, str); | ||
| 153 | return lisp_obj; | ||
| 154 | } | ||
| 155 | |||
| 156 | LISP_OBJECT *lisp_object_make_nil() | ||
| 157 | { | ||
| 158 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 159 | lisp_obj->type = LISP_TYPE_NIL; | ||
| 160 | return lisp_obj; | ||
| 161 | } | ||
| 162 | |||
| 163 | LISP_OBJECT *lisp_object_make_true() | ||
| 164 | { | ||
| 165 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 166 | lisp_obj->type = LISP_TYPE_TRUE; | ||
| 167 | return lisp_obj; | ||
| 168 | } | ||
| 169 | |||
| 170 | LISP_OBJECT *lisp_object_make_false() | ||
| 171 | { | ||
| 172 | LISP_OBJECT *lisp_obj = lisp_object_make(); | ||
| 173 | lisp_obj->type = LISP_TYPE_FALSE; | ||
| 174 | return lisp_obj; | ||
| 175 | } | ||
| 176 | |||
| 177 | int lisp_object_print(LISP_OBJECT *obj, int indent) | ||
| 178 | { | ||
| 179 | int count = 0; | ||
| 180 | for(int i=0; i<indent; i++) { printf(" "); } | ||
| 181 | |||
| 182 | switch(obj->type) | ||
| 183 | { | ||
| 184 | case LISP_TYPE_LIST: | ||
| 185 | printf(" │\n"); | ||
| 186 | break; | ||
| 187 | default: | ||
| 188 | printf("└─ "); | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | |||
| 192 | switch(obj->type) | ||
| 193 | { | ||
| 194 | case LISP_TYPE_LIST: | ||
| 195 | List *lst = obj->value.list; | ||
| 196 | int temp = 0; | ||
| 197 | while (lst) | ||
| 198 | { | ||
| 199 | count ++; | ||
| 200 | temp = lisp_object_print((LISP_OBJECT *)lst->ptr, | ||
| 201 | indent+1); | ||
| 202 | count += temp; | ||
| 203 | lst = lst->next; | ||
| 204 | } | ||
| 205 | break; | ||
| 206 | case LISP_TYPE_STRING: | ||
| 207 | printf("STRING: %s\n", obj->value.string); | ||
| 208 | break; | ||
| 209 | case LISP_TYPE_ERROR: | ||
| 210 | printf("ERROR: %s\n", obj->value.error); | ||
| 211 | break; | ||
| 212 | case LISP_TYPE_SYMBOL: | ||
| 213 | printf("SYMBOL: %s\n", obj->value.symbol); | ||
| 214 | break; | ||
| 215 | case LISP_TYPE_NUMBER: | ||
| 216 | if(obj->is_decimal_point) | ||
| 217 | printf("NUMBER: %lf\n", *obj->value.number_float); | ||
| 218 | else | ||
| 219 | printf("NUMBER: %lld\n", *obj->value.number_natural); | ||
| 220 | break; | ||
| 221 | case LISP_TYPE_TRUE: | ||
| 222 | printf("TRUE\n"); | ||
| 223 | break; | ||
| 224 | case LISP_TYPE_FALSE: | ||
| 225 | printf("FALSE\n"); | ||
| 226 | break; | ||
| 227 | case LISP_TYPE_NIL: | ||
| 228 | printf("NIL\n"); | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | return count; | ||
| 232 | } | ||
| @@ -0,0 +1,65 @@ | |||
| 1 | #ifndef _TYPES | ||
| 2 | #define _TYPES | ||
| 3 | |||
| 4 | #include <stddef.h> | ||
| 5 | #include <stdlib.h> | ||
| 6 | #include <string.h> | ||
| 7 | |||
| 8 | #include "memory.h" | ||
| 9 | |||
| 10 | |||
| 11 | typedef enum _LispType { | ||
| 12 | LISP_TYPE_SYMBOL, | ||
| 13 | LISP_TYPE_LIST, | ||
| 14 | LISP_TYPE_STRING, | ||
| 15 | LISP_TYPE_NUMBER, | ||
| 16 | LISP_TYPE_NIL, | ||
| 17 | LISP_TYPE_TRUE, | ||
| 18 | LISP_TYPE_FALSE, | ||
| 19 | LISP_TYPE_ERROR | ||
| 20 | } LispType; | ||
| 21 | |||
| 22 | |||
| 23 | typedef struct _List { | ||
| 24 | void *ptr; | ||
| 25 | struct _List *next; | ||
| 26 | } List; | ||
| 27 | |||
| 28 | List *list_make(void *ptr); | ||
| 29 | List *list_push(List *list, void *ptr); | ||
| 30 | List *list_reverse(List *list); | ||
| 31 | |||
| 32 | typedef struct _LispObject { | ||
| 33 | LispType type; | ||
| 34 | int is_decimal_point; | ||
| 35 | |||
| 36 | union { | ||
| 37 | char *string; | ||
| 38 | char *symbol; | ||
| 39 | char *error; | ||
| 40 | long long *number_natural; | ||
| 41 | double *number_float; | ||
| 42 | struct _LispObject (*function)(struct _LispObject*); | ||
| 43 | List *list; | ||
| 44 | void *ptr; | ||
| 45 | } value; | ||
| 46 | } LISP_OBJECT; | ||
| 47 | |||
| 48 | void lisp_object_free(LISP_OBJECT *lisp_obj); | ||
| 49 | |||
| 50 | void lisp_object_list_push(LISP_OBJECT *lisp_list_obj, void *ptr); | ||
| 51 | |||
| 52 | LISP_OBJECT *lisp_object_make(); | ||
| 53 | LISP_OBJECT *lisp_object_make_list(); | ||
| 54 | LISP_OBJECT *lisp_object_make_number_natural(long long number); | ||
| 55 | LISP_OBJECT *lisp_object_make_number_float(double number); | ||
| 56 | LISP_OBJECT *lisp_object_make_string(char *str); | ||
| 57 | LISP_OBJECT *lisp_object_make_symbol(char *str); | ||
| 58 | LISP_OBJECT *lisp_object_make_error(char *str); | ||
| 59 | LISP_OBJECT *lisp_object_make_nil(); | ||
| 60 | LISP_OBJECT *lisp_object_make_true(); | ||
| 61 | LISP_OBJECT *lisp_object_make_false(); | ||
| 62 | |||
| 63 | int lisp_object_print(LISP_OBJECT *obj, int indent); | ||
| 64 | |||
| 65 | #endif | ||
