diff options
author | jdlugosz963 <jdlugosz963@gmail.com> | 2023-03-01 23:30:31 +0100 |
---|---|---|
committer | jdlugosz963 <jdlugosz963@gmail.com> | 2023-03-01 23:30:31 +0100 |
commit | f44f1f8c7ef7b6266667dce76db686af3258adfc (patch) | |
tree | e0775e2a07713f1ac23d37b5271340fe8cbebd16 | |
download | jadl-f44f1f8c7ef7b6266667dce76db686af3258adfc.tar.gz jadl-f44f1f8c7ef7b6266667dce76db686af3258adfc.zip |
Build simple abstract syntax tree
-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 | ||