stmt.c (4626B)
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_if(Parser* par) 11 { 12 expect(par, TOKEN_IF); 13 expect(par, TOKEN_LPAREN); // @later remove necessity for parens 14 Node* cond = parse_expression(par); 15 expect(par, TOKEN_RPAREN); 16 17 Node* then_body = parse_statement(par); 18 19 Node* else_body = NULL; 20 if (match(par, TOKEN_ELSE)) else_body = parse_statement(par); 21 22 Node* node = (Node*)calloc(1, sizeof(Node)); 23 if (node == NULL) panic("parse_if: could not alloc"); 24 node->type = NODE_IF; 25 node->scope = NULL; 26 node->data.if_statement.cond = cond; 27 node->data.if_statement.then_body = then_body; 28 node->data.if_statement.else_body = else_body; 29 return node; 30 } 31 32 Node* 33 parse_while(Parser* par) 34 { 35 expect(par, TOKEN_WHILE); 36 expect(par, TOKEN_LPAREN); 37 Node* cond = parse_expression(par); 38 expect(par, TOKEN_RPAREN); 39 40 Node* body = parse_statement(par); 41 42 Node* node = (Node*)calloc(1, sizeof(Node)); 43 if (node == NULL) panic("parse_while: could not alloc"); 44 node->type = NODE_WHILE; 45 node->scope = NULL; 46 node->data.while_statement.cond = cond; 47 node->data.while_statement.body = body; 48 return node; 49 } 50 51 Node* 52 parse_for(Parser* par) 53 { 54 expect(par, TOKEN_FOR); 55 expect(par, TOKEN_LPAREN); 56 57 // init can be empty, a decl, or a expr statement 58 Node* init = NULL; // int i = 0 ... conditional expression stment 59 if (!check(par, TOKEN_SEMICOLON)) { 60 Token tok2 = peek2(par); 61 if (tok2.type == TOKEN_IDENT) { 62 init = parse_declaration_statement(par); 63 } else { 64 // TODO check: init = parse_assignment_expr(par); 65 init = parse_expression_statement(par); 66 } 67 } else 68 expect(par, TOKEN_SEMICOLON); 69 70 Node* cond = NULL; // i < len ... optional expression 71 if (!check(par, TOKEN_SEMICOLON)) cond = parse_expression(par); 72 expect(par, TOKEN_SEMICOLON); 73 74 Node* inc = NULL; // i++ ... optional expression 75 if (!check(par, TOKEN_RPAREN)) { inc = parse_expression(par); } 76 expect(par, TOKEN_RPAREN); 77 78 Node* body = parse_statement(par); 79 80 Node* node = (Node*)calloc(1, sizeof(Node)); 81 node->type = NODE_FOR; 82 node->scope = NULL; 83 node->data.for_statement.init = init; 84 node->data.for_statement.cond = cond; 85 node->data.for_statement.increment = inc; 86 if (node == NULL) panic("parse_for: could not alloc"); 87 88 node->data.for_statement.body = body; 89 return node; 90 } 91 92 Node* 93 parse_assignment(Parser* par) 94 { 95 Token ident = expect(par, TOKEN_IDENT); 96 Span name = { .start = ident.start, .end = ident.end }; 97 98 expect(par, TOKEN_EQUAL); 99 Node* expr = parse_expression(par); 100 101 Node* assign = (Node*)calloc(1, sizeof(Node)); 102 if (assign == NULL) panic("parse_assignment: could not alloc"); 103 assign->type = NODE_VAR_ASSIGN; 104 assign->scope = NULL; 105 assign->data.var_assign.lhs = (Node*)calloc(1, sizeof(Node)); 106 if (assign->data.var_assign.lhs == NULL) panic("parse_for: lhs: could not alloc"); 107 /* 108 identifier 109 x = 5; 110 111 member field access 112 obj.field = 5; 113 obj->field = 5; 114 115 array or pointer indexing 116 arr[0] = 5; 117 *(p + 1) = 5; 118 119 dereference 120 *p = 5; 121 */ 122 assign->filename = par->filename; 123 assign->line = ident.line; 124 assign->col = ident.col; 125 assign->data.var_assign.lhs->type = NODE_IDENT; // TODO handle other cases, e.g. subscript assignment 126 assign->data.var_assign.lhs->scope = NULL; 127 assign->data.var_assign.lhs->data.ident.name = name; 128 assign->data.var_assign.rhs = expr; 129 expect(par, TOKEN_SEMICOLON); 130 return assign; 131 } 132 133 Node* 134 parse_break(Parser* par) 135 { 136 expect(par, TOKEN_BREAK); 137 expect(par, TOKEN_SEMICOLON); 138 139 Node* node = (Node*)calloc(1, sizeof(Node)); 140 if (node == NULL) panic("parse_break: could not alloc"); 141 node->type = NODE_BREAK; 142 node->scope = NULL; 143 return node; 144 } 145 146 Node* 147 parse_continue_statement(Parser* par) 148 { 149 expect(par, TOKEN_CONTINUE); // consume 'continue' 150 151 Node* node = (Node*)calloc(1, sizeof(Node)); 152 if (node == NULL) panic("parse_continue_statemenet: could not alloc"); 153 node->type = NODE_CONTINUE; 154 node->scope = NULL; 155 156 TokenType next_type = peek(par).type; 157 158 if (next_type != TOKEN_SEMICOLON) 159 node->data.cont.expr = parse_expression(par); 160 else 161 node->data.cont.expr = NULL; 162 163 expect(par, TOKEN_SEMICOLON); 164 return node; 165 } 166 167 Node* 168 parse_return_statement(Parser* par) 169 { 170 expect(par, TOKEN_RETURN); // consume 'return' 171 Node* ret = (Node*)calloc(1, sizeof(Node)); 172 if (ret == NULL) panic("parse_return_statemenet: could not alloc"); 173 ret->type = NODE_RETURN; 174 ret->scope = NULL; 175 176 TokenType next_type = peek(par).type; 177 178 if (next_type != TOKEN_SEMICOLON) 179 ret->data.ret.expr = parse_expression(par); 180 else 181 ret->data.ret.expr = NULL; 182 183 expect(par, TOKEN_SEMICOLON); 184 return ret; 185 }