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