stmt.c (4823B)
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 Token for_token = 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->line = for_token.line; 84 node->col = for_token.col; 85 node->filename = par->filename; 86 node->data.for_statement.init = init; 87 node->data.for_statement.cond = cond; 88 node->data.for_statement.increment = inc; 89 if (node == NULL) panic("parse_for: could not alloc"); 90 91 node->data.for_statement.body = body; 92 return node; 93 } 94 95 Node* 96 parse_assignment(Parser* par) 97 { 98 Token ident = expect(par, TOKEN_IDENT); 99 Span name = { .start = ident.start, .end = ident.end }; 100 101 expect(par, TOKEN_EQUAL); 102 Node* expr = parse_expression(par); 103 104 Node* assign = (Node*)calloc(1, sizeof(Node)); 105 if (assign == NULL) panic("parse_assignment: could not alloc"); 106 assign->type = NODE_VAR_ASSIGN; 107 assign->scope = NULL; 108 assign->data.var_assign.lhs = (Node*)calloc(1, sizeof(Node)); 109 if (assign->data.var_assign.lhs == NULL) panic("parse_for: lhs: could not alloc"); 110 /* 111 identifier 112 x = 5; 113 114 member field access 115 obj.field = 5; 116 obj->field = 5; 117 118 array or pointer indexing 119 arr[0] = 5; 120 *(p + 1) = 5; 121 122 dereference 123 *p = 5; 124 */ 125 assign->filename = par->filename; 126 assign->line = ident.line; 127 assign->col = ident.col; 128 assign->data.var_assign.lhs->type = NODE_IDENT; // TODO handle other cases, e.g. subscript assignment 129 assign->data.var_assign.lhs->scope = NULL; 130 assign->data.var_assign.lhs->data.ident.name = name; 131 assign->data.var_assign.rhs = expr; 132 expect(par, TOKEN_SEMICOLON); 133 return assign; 134 } 135 136 Node* 137 parse_break(Parser* par) 138 { 139 expect(par, TOKEN_BREAK); 140 expect(par, TOKEN_SEMICOLON); 141 142 Node* node = (Node*)calloc(1, sizeof(Node)); 143 if (node == NULL) panic("parse_break: could not alloc"); 144 node->type = NODE_BREAK; 145 node->scope = NULL; 146 return node; 147 } 148 149 Node* 150 parse_continue_statement(Parser* par) 151 { 152 expect(par, TOKEN_CONTINUE); // consume 'continue' 153 154 Node* node = (Node*)calloc(1, sizeof(Node)); 155 if (node == NULL) panic("parse_continue_statemenet: could not alloc"); 156 node->type = NODE_CONTINUE; 157 node->scope = NULL; 158 159 TokenType next_type = peek(par).type; 160 161 if (next_type != TOKEN_SEMICOLON) 162 node->data.cont.expr = parse_expression(par); 163 else 164 node->data.cont.expr = NULL; 165 166 expect(par, TOKEN_SEMICOLON); 167 return node; 168 } 169 170 Node* 171 parse_return_statement(Parser* par) 172 { 173 Token tok = expect(par, TOKEN_RETURN); // consume 'return' 174 Node* ret = (Node*)calloc(1, sizeof(Node)); 175 if (ret == NULL) panic("parse_return_statemenet: could not alloc"); 176 ret->type = NODE_RETURN; 177 ret->filename = par->filename; 178 ret->line = tok.line; 179 ret->col = tok.col; 180 ret->scope = NULL; 181 182 TokenType next_type = peek(par).type; 183 184 if (next_type != TOKEN_SEMICOLON) 185 ret->data.ret.expr = parse_expression(par); 186 else 187 ret->data.ret.expr = NULL; 188 189 expect(par, TOKEN_SEMICOLON); 190 return ret; 191 }