ox

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

stmt.c (4426B)


      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 			init = parse_expression_statement(par);
     65 		}
     66 	} else
     67 		expect(par, TOKEN_SEMICOLON);
     68 
     69 	Node* cond = NULL; // i < len ... optional expression
     70 	if (!check(par, TOKEN_SEMICOLON)) cond = parse_expression(par);
     71 	expect(par, TOKEN_SEMICOLON);
     72 
     73 	Node* inc = NULL; // i++ ... optional expression
     74 	if (!check(par, TOKEN_RPAREN)) { inc = parse_expression(par); }
     75 	expect(par, TOKEN_RPAREN);
     76 
     77 	Node* body = parse_statement(par);
     78 
     79 	Node* node = (Node*)calloc(1, sizeof(Node));
     80 	node->type = NODE_FOR;
     81 	node->scope = NULL;
     82 	node->data.for_statement.init = init;
     83 	node->data.for_statement.cond = cond;
     84 	node->data.for_statement.increment = inc;
     85 	if (node == NULL) panic("parse_for: could not alloc");
     86 
     87 	node->data.for_statement.body = body;
     88 	return node;
     89 }
     90 
     91 Node*
     92 parse_assignment(Parser* par)
     93 {
     94 	Token ident = expect(par, TOKEN_IDENT);
     95 	Span name = { .start = ident.start, .end = ident.end };
     96 
     97 	expect(par, TOKEN_EQUAL);
     98 	Node* expr = parse_expression(par);
     99 
    100 	Node* assign = (Node*)calloc(1, sizeof(Node));
    101 	if (assign == NULL) panic("parse_assignment: could not alloc");
    102 	assign->type = NODE_VAR_ASSIGN;
    103 	assign->scope = NULL;
    104 	assign->data.var_assign.lhs = (Node*)calloc(1, sizeof(Node));
    105 	if (assign->data.var_assign.lhs == NULL) panic("parse_for: lhs: could not alloc");
    106 	/*
    107 	    identifier
    108 	    x = 5;
    109 
    110 	    member field access
    111 	    obj.field = 5;
    112 	    obj->field = 5;
    113 
    114 	    array or pointer indexing
    115 	    arr[0] = 5;
    116 	    *(p + 1) = 5;
    117 
    118 	    dereference
    119 	    *p = 5;
    120 	*/
    121 	assign->data.var_assign.lhs->type = NODE_IDENT; // TODO handle other cases
    122 	assign->data.var_assign.lhs->scope = NULL;
    123 	assign->data.var_assign.lhs->data.ident.name = name;
    124 	assign->data.var_assign.rhs = expr;
    125 	return assign;
    126 }
    127 
    128 Node*
    129 parse_break(Parser* par)
    130 {
    131 	expect(par, TOKEN_BREAK);
    132 	expect(par, TOKEN_SEMICOLON);
    133 
    134 	Node* node = (Node*)calloc(1, sizeof(Node));
    135 	if (node == NULL) panic("parse_break: could not alloc");
    136 	node->type = NODE_BREAK;
    137 	node->scope = NULL;
    138 	return node;
    139 }
    140 
    141 Node*
    142 parse_continue_statement(Parser* par)
    143 {
    144 	expect(par, TOKEN_CONTINUE); // consume 'continue'
    145 
    146 	Node* node = (Node*)calloc(1, sizeof(Node));
    147 	if (node == NULL) panic("parse_continue_statemenet: could not alloc");
    148 	node->type = NODE_CONTINUE;
    149 	node->scope = NULL;
    150 
    151 	TokenType next_type = peek(par).type;
    152 
    153 	if (next_type != TOKEN_SEMICOLON)
    154 		node->data.cont.expr = parse_expression(par);
    155 	else
    156 		node->data.cont.expr = NULL;
    157 
    158 	expect(par, TOKEN_SEMICOLON);
    159 	return node;
    160 }
    161 
    162 Node*
    163 parse_return_statement(Parser* par)
    164 {
    165 	expect(par, TOKEN_RETURN); // consume 'return'
    166 	Node* ret = (Node*)calloc(1, sizeof(Node));
    167 	if (ret == NULL) panic("parse_return_statemenet: could not alloc");
    168 	ret->type = NODE_RETURN;
    169 	ret->scope = NULL;
    170 
    171 	TokenType next_type = peek(par).type;
    172 
    173 	if (next_type != TOKEN_SEMICOLON)
    174 		ret->data.ret.expr = parse_expression(par);
    175 	else
    176 		ret->data.ret.expr = NULL;
    177 
    178 	expect(par, TOKEN_SEMICOLON);
    179 	return ret;
    180 }