ox

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

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 }