aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-30 08:36:14 +0200
committerBad Diode <bd@badd10de.dev>2021-10-30 08:36:14 +0200
commitf17b11003fe384b49a7bf844824f23167b6095e0 (patch)
tree7129ee8267bf8327d608c1d3a927295929b24631
parent4ebcd99d1fadac72ea58ea46012a86c5319ef7e7 (diff)
downloadbdl-f17b11003fe384b49a7bf844824f23167b6095e0.tar.gz
bdl-f17b11003fe384b49a7bf844824f23167b6095e0.zip
Add parsing of if expressions
-rwxr-xr-xREADME.md2
-rwxr-xr-xsrc/lexer.c2
-rwxr-xr-xsrc/lexer.h1
-rw-r--r--src/parser.c91
-rwxr-xr-xsrc/parser.h8
5 files changed, 95 insertions, 9 deletions
diff --git a/README.md b/README.md
index 321c43d..8ffd273 100755
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ program : <statement>* EOF
46<statement> : <definition> | <expression> 46<statement> : <definition> | <expression>
47 47
48<definition> : ( def <symbol> <expression> ) 48<definition> : ( def <symbol> <expression> )
49 | ( fun ( <symbol>* ) <body> ) 49 | ( fun <symbol> ( <symbol>* ) <body> )
50 ; 50 ;
51 51
52<expression> : <constant> 52<expression> : <constant>
diff --git a/src/lexer.c b/src/lexer.c
index f272901..cbcc175 100755
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -12,6 +12,7 @@ static const char* token_str[] = {
12 [TOKEN_TRUE] = "TOKEN_TRUE", 12 [TOKEN_TRUE] = "TOKEN_TRUE",
13 [TOKEN_FALSE] = "TOKEN_FALSE", 13 [TOKEN_FALSE] = "TOKEN_FALSE",
14 [TOKEN_LAMBDA] = "TOKEN_LAMBDA", 14 [TOKEN_LAMBDA] = "TOKEN_LAMBDA",
15 [TOKEN_IF] = "TOKEN_IF",
15 [TOKEN_EOF] = "TOKEN_EOF", 16 [TOKEN_EOF] = "TOKEN_EOF",
16}; 17};
17 18
@@ -126,6 +127,7 @@ find_primitive_type(const StringView value) {
126 if (TOKEN_IS_KEYWORD(value, "true")) { return TOKEN_TRUE; } 127 if (TOKEN_IS_KEYWORD(value, "true")) { return TOKEN_TRUE; }
127 if (TOKEN_IS_KEYWORD(value, "false")) { return TOKEN_FALSE; } 128 if (TOKEN_IS_KEYWORD(value, "false")) { return TOKEN_FALSE; }
128 if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } 129 if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; }
130 if (TOKEN_IS_KEYWORD(value, "if")) { return TOKEN_IF; }
129 131
130 return TOKEN_SYMBOL; 132 return TOKEN_SYMBOL;
131} 133}
diff --git a/src/lexer.h b/src/lexer.h
index 4fa4db5..4798a2b 100755
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -20,6 +20,7 @@ typedef enum TokenType {
20 20
21 // Keywords. 21 // Keywords.
22 TOKEN_LAMBDA, 22 TOKEN_LAMBDA,
23 TOKEN_IF,
23 24
24 // End of file. 25 // End of file.
25 TOKEN_EOF, 26 TOKEN_EOF,
diff --git a/src/parser.c b/src/parser.c
index 8a6c4ce..5551dd2 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -103,6 +103,7 @@ parse_lambda(Parser *parser, Errors *errors) {
103 .line = tok.line, 103 .line = tok.line,
104 .col = tok.col, 104 .col = tok.col,
105 }); 105 });
106 return NULL;
106 } 107 }
107 108
108 // Parse body. 109 // Parse body.
@@ -119,23 +120,81 @@ parse_lambda(Parser *parser, Errors *errors) {
119} 120}
120 121
121Object * 122Object *
122parse_list(Parser *parser, Errors *errors) { 123parse_if(Parser *parser, Errors *errors) {
123 if (errors->n != 0) { 124 Token start = next_token(parser);
125 Object *obj_if = object_alloc(start, OBJ_TYPE_IF);
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_NOT_ENOUGH_ARGS,
132 .line = tok.line,
133 .col = tok.col,
134 });
124 return NULL; 135 return NULL;
125 } 136 }
137 obj_if->condition = parse_tree(parser, errors);
126 138
127 Token tok = peek_token(parser); 139 tok = peek_token(parser);
128 if (tok.type == TOKEN_RPAREN) { 140 if (tok.type == TOKEN_RPAREN) {
129 error_push(errors, (Error){ 141 error_push(errors, (Error){
130 .type = ERR_TYPE_PARSER, 142 .type = ERR_TYPE_PARSER,
131 .value = ERR_UNBALANCED_PAREN, 143 .value = ERR_NOT_ENOUGH_ARGS,
132 .line = tok.line, 144 .line = tok.line,
133 .col = tok.col, 145 .col = tok.col,
134 }); 146 });
135 return NULL; 147 return NULL;
136 } 148 }
137 if (tok.type == TOKEN_LAMBDA) { 149 obj_if->expr_true = parse_tree(parser, errors);
138 return parse_lambda(parser, errors); 150
151 // Optional else expression.
152 tok = peek_token(parser);
153 if (tok.type == TOKEN_RPAREN) {
154 next_token(parser);
155 obj_if->expr_false = NULL;
156 return obj_if;
157 }
158 obj_if->expr_false = parse_tree(parser, errors);
159
160 tok = peek_token(parser);
161 if (tok.type != TOKEN_RPAREN) {
162 error_push(errors, (Error){
163 .type = ERR_TYPE_PARSER,
164 .value = ERR_TOO_MANY_ARGS,
165 .line = tok.line,
166 .col = tok.col,
167 });
168 return NULL;
169 }
170 next_token(parser);
171 return obj_if;
172}
173
174Object *
175parse_list(Parser *parser, Errors *errors) {
176 if (errors->n != 0) {
177 return NULL;
178 }
179
180 Token tok = peek_token(parser);
181 switch (tok.type) {
182 case TOKEN_RPAREN: {
183 error_push(errors, (Error){
184 .type = ERR_TYPE_PARSER,
185 .value = ERR_UNBALANCED_PAREN,
186 .line = tok.line,
187 .col = tok.col,
188 });
189 return NULL;
190 } break;
191 case TOKEN_LAMBDA: {
192 return parse_lambda(parser, errors);
193 } break;
194 case TOKEN_IF: {
195 return parse_if(parser, errors);
196 } break;
197 default: break;
139 } 198 }
140 199
141 Token start = previous_token(parser); 200 Token start = previous_token(parser);
@@ -327,13 +386,29 @@ object_display(Object *obj) {
327 printf(")"); 386 printf(")");
328 } break; 387 } break;
329 case OBJ_TYPE_LAMBDA: { 388 case OBJ_TYPE_LAMBDA: {
330 printf("#{lambda( "); 389 printf("#{ lambda( ");
331 for (size_t i = 0; i < array_size(obj->params); i++) { 390 for (size_t i = 0; i < array_size(obj->params); i++) {
332 object_display(obj->params[i]); 391 object_display(obj->params[i]);
333 printf(" "); 392 printf(" ");
334 } 393 }
335 printf(")}"); 394 printf(") ");
395 for (size_t i = 0; i < array_size(obj->body); i++) {
396 object_display(obj->body[i]);
397 printf(" ");
398 }
399 printf("}");
336 } break; 400 } break;
401 case OBJ_TYPE_IF: {
402 printf("#{ if ");
403 object_display(obj->condition);
404 printf(" ");
405 object_display(obj->expr_true);
406 if (obj->expr_false != NULL) {
407 printf(" ");
408 object_display(obj->expr_false);
409 }
410 printf(" }");
411 };
337 } 412 }
338 return; 413 return;
339} 414}
diff --git a/src/parser.h b/src/parser.h
index 17bd6d6..b2b07c8 100755
--- a/src/parser.h
+++ b/src/parser.h
@@ -12,6 +12,7 @@ typedef enum ObjectType {
12 OBJ_TYPE_STRING, 12 OBJ_TYPE_STRING,
13 OBJ_TYPE_PAIR, 13 OBJ_TYPE_PAIR,
14 OBJ_TYPE_LAMBDA, 14 OBJ_TYPE_LAMBDA,
15 OBJ_TYPE_IF,
15} ObjectType; 16} ObjectType;
16 17
17typedef struct Object { 18typedef struct Object {
@@ -35,6 +36,13 @@ typedef struct Object {
35 struct Object **params; 36 struct Object **params;
36 struct Object **body; 37 struct Object **body;
37 }; 38 };
39
40 // OBJ_TYPE_IF
41 struct {
42 struct Object *condition;
43 struct Object *expr_true;
44 struct Object *expr_false;
45 };
38 }; 46 };
39 47
40 size_t line; 48 size_t line;