ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

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 }