aboutsummaryrefslogtreecommitdiffstats
path: root/src/parser.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-30 08:16:08 +0200
committerBad Diode <bd@badd10de.dev>2021-10-30 08:16:08 +0200
commit4ebcd99d1fadac72ea58ea46012a86c5319ef7e7 (patch)
tree548d749c8fd93a3520f56de7b594d85d83fae062 /src/parser.c
parentfbddf5e0c46778c1e403389ba557ef036b7b0fb5 (diff)
downloadbdl-4ebcd99d1fadac72ea58ea46012a86c5319ef7e7.tar.gz
bdl-4ebcd99d1fadac72ea58ea46012a86c5319ef7e7.zip
Add parsing of lambda expression
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c130
1 files changed, 106 insertions, 24 deletions
diff --git a/src/parser.c b/src/parser.c
index 2d70c9d..8a6c4ce 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,6 +1,9 @@
1#include "parser.h" 1#include "parser.h"
2#include "darray.h" 2#include "darray.h"
3 3
4static Object **objects = NULL;
5static Root *roots = NULL;
6
4Token 7Token
5peek_token(const Parser *parser) { 8peek_token(const Parser *parser) {
6 return parser->tokens[parser->current]; 9 return parser->tokens[parser->current];
@@ -68,19 +71,81 @@ parse_symbol(Token tok) {
68} 71}
69 72
70Object * 73Object *
74parse_lambda(Parser *parser, Errors *errors) {
75 Token start = next_token(parser);
76 Object *lambda = object_alloc(start, OBJ_TYPE_LAMBDA);
77 array_init(lambda->params, 0);
78 array_init(lambda->body, 0);
79
80 // Parse parameters.
81 Token tok = next_token(parser);
82 if (tok.type == TOKEN_LPAREN) {
83 while (has_next_token(parser)) {
84 Token tok = next_token(parser);
85 if (tok.type == TOKEN_RPAREN) {
86 break;
87 }
88 if (tok.type != TOKEN_SYMBOL) {
89 error_push(errors, (Error){
90 .type = ERR_TYPE_PARSER,
91 .value = ERR_WRONG_ARG_TYPE,
92 .line = tok.line,
93 .col = tok.col,
94 });
95 }
96 Object *symbol = parse_symbol(tok);
97 array_push(lambda->params, symbol);
98 }
99 } else if (tok.type != TOKEN_NIL) {
100 error_push(errors, (Error){
101 .type = ERR_TYPE_PARSER,
102 .value = ERR_WRONG_ARG_TYPE,
103 .line = tok.line,
104 .col = tok.col,
105 });
106 }
107
108 // Parse body.
109 while (has_next_token(parser)) {
110 Token tok = peek_token(parser);
111 if (tok.type == TOKEN_RPAREN) {
112 next_token(parser);
113 break;
114 }
115 Object *expr = parse_tree(parser, errors);
116 array_push(lambda->body, expr);
117 }
118 return lambda;
119}
120
121Object *
71parse_list(Parser *parser, Errors *errors) { 122parse_list(Parser *parser, Errors *errors) {
72 if (errors->n != 0) { 123 if (errors->n != 0) {
73 return NULL; 124 return NULL;
74 } 125 }
126
127 Token tok = peek_token(parser);
128 if (tok.type == TOKEN_RPAREN) {
129 error_push(errors, (Error){
130 .type = ERR_TYPE_PARSER,
131 .value = ERR_UNBALANCED_PAREN,
132 .line = tok.line,
133 .col = tok.col,
134 });
135 return NULL;
136 }
137 if (tok.type == TOKEN_LAMBDA) {
138 return parse_lambda(parser, errors);
139 }
140
75 Token start = previous_token(parser); 141 Token start = previous_token(parser);
76 Object *root = object_alloc(start, OBJ_TYPE_PAIR); 142 Object *root = object_alloc(start, OBJ_TYPE_PAIR);
77 root->car = NULL; 143 root->head = NULL;
78 root->cdr = NULL; 144 root->tail = NULL;
79 Object *current = root; 145 Object *current = root;
80 while (has_next_token(parser)) { 146 while (has_next_token(parser)) {
81 current->car = parse_tree(parser, errors); 147 current->head = parse_tree(parser, errors);
82 if (errors->n != 0 || current->car == NULL) { 148 if (errors->n != 0 || current->head == NULL) {
83 object_free(root);
84 return NULL; 149 return NULL;
85 } 150 }
86 151
@@ -91,12 +156,11 @@ parse_list(Parser *parser, Errors *errors) {
91 } 156 }
92 157
93 Object *next = object_alloc(start, OBJ_TYPE_PAIR); 158 Object *next = object_alloc(start, OBJ_TYPE_PAIR);
94 next->car = NULL; 159 next->head = NULL;
95 next->cdr = NULL; 160 next->tail = NULL;
96 current->cdr = next; 161 current->tail = next;
97 current = current->cdr; 162 current = current->tail;
98 } 163 }
99 object_free(root);
100 error_push(errors, (Error){ 164 error_push(errors, (Error){
101 .type = ERR_TYPE_PARSER, 165 .type = ERR_TYPE_PARSER,
102 .value = ERR_UNBALANCED_PAREN, 166 .value = ERR_UNBALANCED_PAREN,
@@ -156,7 +220,7 @@ parse_tree(Parser *parser, Errors *errors) {
156 220
157Root * 221Root *
158parse(Token *tokens, Errors *errors) { 222parse(Token *tokens, Errors *errors) {
159 Root *roots = NULL; 223 // Build initial AST.
160 array_init(roots, 0); 224 array_init(roots, 0);
161 Parser parser = { 225 Parser parser = {
162 .tokens = tokens, 226 .tokens = tokens,
@@ -170,15 +234,24 @@ parse(Token *tokens, Errors *errors) {
170 } 234 }
171 array_push(roots, root); 235 array_push(roots, root);
172 } 236 }
237
238 // Perform semantic analysis.
239 // 1. Ensure core grammar is correct.
240 // 2. Check that symbols are defined before usage.
241 // 3. Remove unnecessary statements.
173 return roots; 242 return roots;
174} 243}
175 244
176Object * 245Object *
177object_alloc(Token tok, ObjectType type) { 246object_alloc(Token tok, ObjectType type) {
247 if (objects == NULL) {
248 array_init(objects, 0);
249 }
178 Object *node = malloc(sizeof(Object)); 250 Object *node = malloc(sizeof(Object));
179 node->line = tok.line; 251 node->line = tok.line;
180 node->col = tok.col; 252 node->col = tok.col;
181 node->type = type; 253 node->type = type;
254 array_push(objects, node);
182 return node; 255 return node;
183} 256}
184 257
@@ -190,35 +263,36 @@ object_free(Object *node) {
190 if (IS_STRING(node) || IS_SYMBOL(node)) { 263 if (IS_STRING(node) || IS_SYMBOL(node)) {
191 array_free(node->text); 264 array_free(node->text);
192 } 265 }
193 if (IS_PAIR(node)) { 266 if (IS_LAMBDA(node)) {
194 object_free(node->car); 267 array_free(node->params);
195 object_free(node->cdr); 268 array_free(node->body);
196 } 269 }
197 free(node); 270 free(node);
198} 271}
199 272
200void 273void
201free_roots(Root *roots) { 274free_objects(void) {
202 if (roots != NULL) { 275 if (objects != NULL) {
203 for (size_t i = 0; i < array_size(roots); i++) { 276 for (size_t i = 0; i < array_size(objects); i++) {
204 object_free(roots[i]); 277 object_free(objects[i]);
205 } 278 }
206 array_free(roots); 279 array_free(objects);
207 } 280 }
281 array_free(roots);
208} 282}
209 283
210void 284void
211display_pair(Object *obj) { 285display_pair(Object *obj) {
212 object_display(obj->car); 286 object_display(obj->head);
213 if (obj->cdr == NULL) { 287 if (obj->tail == NULL) {
214 return; 288 return;
215 } 289 }
216 if (IS_PAIR(obj->cdr)) { 290 if (IS_PAIR(obj->tail)) {
217 printf(" "); 291 printf(" ");
218 display_pair(obj->cdr); 292 display_pair(obj->tail);
219 } else { 293 } else {
220 printf(" . "); 294 printf(" . ");
221 object_display(obj->cdr); 295 object_display(obj->tail);
222 } 296 }
223} 297}
224 298
@@ -252,6 +326,14 @@ object_display(Object *obj) {
252 display_pair(obj); 326 display_pair(obj);
253 printf(")"); 327 printf(")");
254 } break; 328 } break;
329 case OBJ_TYPE_LAMBDA: {
330 printf("#{lambda( ");
331 for (size_t i = 0; i < array_size(obj->params); i++) {
332 object_display(obj->params[i]);
333 printf(" ");
334 }
335 printf(")}");
336 } break;
255 } 337 }
256 return; 338 return;
257} 339}