expr.c (6249B)
1 #include "../parser.h" 2 #include "../utils.h" 3 4 #include <stdio.h> 5 #include <string.h> 6 #include <stdbool.h> 7 #include <assert.h> 8 9 Node* 10 parse_func_call(Parser* par) 11 { 12 Token tok = expect(par, TOKEN_IDENT); 13 Span callee = { .start = tok.start, .end = tok.end }; 14 Node* ident = make_ident_node(callee); 15 16 const char* name = span_str(par->src, ident->data.ident.name, (char[IDENTSZ]) { 0 }); 17 printf("parse_func_call: %s\n", name); 18 19 expect(par, TOKEN_LPAREN); 20 21 Node* call = (Node*)calloc(1, sizeof(Node)); 22 if (call == NULL) panic("parse_func_call: alloc failed"); 23 24 // start parse arguments 25 if (peek(par).type != TOKEN_RPAREN) { 26 call->data.call_expr.args = (Node**)calloc(4, sizeof(Node*)); 27 if (call->data.call_expr.args == NULL) 28 panic("parse_func_call: args: could not alloc"); 29 call->data.call_expr.cap = 4; 30 call->data.call_expr.len = 0; 31 32 for (;;) { 33 Node* arg = parse_expression(par); 34 35 if (call->data.call_expr.len == call->data.call_expr.cap) { 36 call->data.call_expr.cap *= 2; 37 call->data.call_expr.args 38 = (Node**)realloc(call->data.call_expr.args, 39 call->data.call_expr.cap * sizeof(Node*)); 40 } 41 call->data.call_expr.args[call->data.call_expr.len++] = arg; 42 43 if (!match(par, TOKEN_COMMA)) break; // found `)` instead of `,` 44 } 45 } 46 // ends parse arguments 47 48 expect(par, TOKEN_RPAREN); 49 50 call->type = NODE_CALL_EXPR; 51 call->scope = NULL; 52 call->data.call_expr.callee = ident; 53 return call; 54 } 55 56 Node* 57 parse_number(Parser* par) 58 { 59 Token tok = consume(par); 60 assert(tok.type == TOKEN_NUMBER_LITERAL); 61 62 size_t len = tok.end - tok.start; 63 char buf[len + 1]; // strtod needs a \0 terminated string 64 for (size_t i = 0; i < len; i++) 65 buf[i] = par->src[tok.start + i]; 66 buf[len] = '\0'; 67 double value = strtod(buf, NULL); 68 69 Node* num_node = (Node*)calloc(1, sizeof(Node)); 70 if (num_node == NULL) panic("parse_number: alloc failed"); 71 num_node->type = NODE_NUMBER_LITERAL; 72 num_node->scope = NULL; 73 num_node->data.number.value = value; 74 return num_node; 75 } 76 77 Node* 78 parse_ident(Parser* par) 79 { 80 Token tok = consume(par); 81 assert(tok.type == TOKEN_IDENT); 82 Node* ident_node = (Node*)calloc(1, sizeof(Node)); 83 if (ident_node == NULL) panic("parse_ident: alloc failed"); 84 ident_node->type = NODE_IDENT; 85 ident_node->scope = NULL; 86 ident_node->data.ident.name = (Span) { .start = tok.start, .end = tok.end }; 87 88 // const char* name = span_str( 89 // par->src, (Span) { .start = tok.start, .end = tok.end }, (char[IDENTSZ]) { 0 }); 90 // printf("parse_ident: %s\n", name); 91 92 return ident_node; 93 } 94 95 NodeVec 96 parse_func_arguments(Parser* par) 97 { 98 NodeVec v = { 0 }; 99 if (peek(par).type == TOKEN_RPAREN) return v; // found `)` no arguments 100 101 v.cap = 4; 102 v.items = (Node**)calloc(v.cap, sizeof(Node*)); 103 if (v.items == NULL) panic("parse_func_arguments: could not alloc"); 104 105 for (;;) { 106 Node* arg = parse_expression(par); 107 108 if (v.len == v.cap) { 109 v.cap *= 2; 110 v.items = (Node**)realloc(v.items, v.cap * sizeof(Node*)); 111 } 112 113 v.items[v.len++] = arg; 114 115 if (!match(par, TOKEN_COMMA)) break; // found `)` instead of `,` 116 } 117 return v; 118 } 119 120 Node* 121 parse_postfix(Parser* par) 122 { 123 Node* node = parse_primary(par); 124 125 for (;;) { 126 if (match(par, TOKEN_PLUSPLUS)) { 127 node = make_postfix_node(OPER_POSTINC, node); 128 } else if (match(par, TOKEN_MINUSMINUS)) { 129 node = make_postfix_node(OPER_POSTDEC, node); 130 } else if (match(par, TOKEN_LBRACKET)) { 131 Node* index = parse_expression(par); // parse inside brackets 132 expect(par, TOKEN_RBRACKET); 133 node = make_subscript_node(node, index); 134 // } else if (match(par, TOKEN_DOT)) { // TODO dot members and arrows 135 // Token id = expect(par, TOKEN_IDENTIFIER); 136 // expr = make_member_node(expr, id); 137 // } else if (match(par, TOKEN_ARROW)) { 138 // Token id = expect(par, TOKEN_IDENTIFIER); 139 // expr = make_ptrmember_node(expr, id); 140 } else if (match(par, TOKEN_LPAREN)) { 141 NodeVec args = parse_func_arguments(par); // parse func call args 142 expect(par, TOKEN_RPAREN); 143 node = make_call_node(node, args); 144 } else { 145 break; 146 } 147 } 148 return node; 149 } 150 151 #define STARTING_ROOT_NODES 32 152 153 Node* 154 make_program_node(void) 155 { 156 Node* node = (Node*)calloc(1, sizeof(Node)); 157 if (node == NULL) panic("make_program_node: alloc failed"); 158 node->type = NODE_PROGRAM; 159 node->scope = NULL; 160 node->next = NULL; 161 node->data.program.cap = STARTING_ROOT_NODES; 162 node->data.program.len = 0; 163 node->data.program.decl = (Node**)calloc(STARTING_ROOT_NODES, sizeof(Node)); 164 if (node->data.program.decl == NULL) panic("make_program_node: decls: alloc failed"); 165 return node; 166 } 167 168 Node* 169 make_ident_node(Span name) 170 { 171 Node* node = (Node*)calloc(1, sizeof(Node)); 172 if (node == NULL) panic("make_ident_node: alloc failed"); 173 node->type = NODE_IDENT; 174 node->scope = NULL; 175 node->next = NULL; 176 node->data.ident.name = name; 177 return node; 178 } 179 180 Node* 181 parse_primary(Parser* par) 182 { 183 Token tok = peek(par); 184 if (tok.type == TOKEN_STRING_LITERAL) { return make_string_node(par); } 185 if (tok.type == TOKEN_NUMBER_LITERAL) { return make_number_node(par); } 186 if (tok.type == TOKEN_IDENT) { return parse_ident(par); } 187 if (tok.type == TOKEN_LPAREN) { 188 consume(par); // consume '(' 189 Node* node = parse_expression(par); 190 expect(par, TOKEN_RPAREN); 191 return node; 192 } 193 194 const char* name = span_str( 195 par->src, (Span) { .start = tok.start, .end = tok.end }, (char[IDENTSZ]) { 0 }); 196 panic("Expected Primary Expr, but found '%s' (%s at %s:%zu:%zu", 197 name, 198 token_type_str(tok.type), 199 par->filename, 200 tok.line, 201 tok.col); 202 203 return NULL; 204 } 205 206 Node* 207 parse_unary(Parser* par) 208 { 209 Node* inner = NULL; 210 switch (peek(par).type) { 211 case TOKEN_MINUS: 212 consume(par); 213 inner = parse_unary(par); 214 return make_unary_node(OPER_MINUS, inner); 215 case TOKEN_MINUSMINUS: 216 consume(par); 217 inner = parse_unary(par); 218 return make_unary_node(OPER_PREDEC, inner); 219 case TOKEN_BANG: 220 consume(par); 221 inner = parse_unary(par); 222 return make_unary_node(OPER_BANG, inner); 223 // TODO add others '~a' '$a' '*a' '^a' '@a' '&a' 224 case TOKEN_PLUSPLUS: 225 consume(par); 226 inner = parse_unary(par); 227 return make_unary_node(OPER_PREINC, inner); 228 case TOKEN_PLUS: 229 consume(par); 230 return parse_unary(par); 231 default: 232 return parse_postfix(par); 233 } 234 } 235 236 // called by parse_multiplicative 237 Node* 238 parse_term(Parser* par) 239 { 240 return parse_unary(par); 241 }