ox

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

ast.c (3475B)



#include "../parser.h"
#include "../utils.h"

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>

Node*
make_postfix_node(UnaryOp op, Node* operand)
{
	Node* node = (Node*)calloc(1, sizeof(Node));
	if (node == NULL) panic("make_postfix_node: could not alloc");
	node->type = NODE_UNARY_EXPR;
	node->scope = NULL;
	node->next = NULL;
	node->data.unary_expr.op = op;
	node->data.unary_expr.operand = operand;
	node->data.unary_expr.is_postfix = true;
	return node;
}

Node*
make_subscript_node(Node* array, Node* index)
{
	Node* node = calloc(1, sizeof(Node));
	if (node == NULL) panic("make_subscript_node: could not alloc");
	node->type = NODE_SUBSCRIPT_EXPR;
	node->scope = NULL;
	node->next = NULL;
	node->data.subscript_expr.array = array;
	node->data.subscript_expr.index = index;
	return node;
}

Node*
make_number_node(Parser* par)
{
	Token tok = consume(par);
	assert(tok.type == TOKEN_INT_LITERAL || tok.type == TOKEN_FLOAT_LITERAL);
	size_t len = tok.end - tok.start;
	char buf[len + 1]; // strtod needs a \0 terminated string
	for (size_t i = 0; i < len; i++)
		buf[i] = par->src[tok.start + i];
	buf[len] = '\0';
	double value = strtod(buf, NULL);
	Node* node = (Node*)calloc(1, sizeof(Node));
	if (node == NULL) panic("make_number_node: could not alloc");
	node->type = tok.type == TOKEN_INT_LITERAL ? NODE_INT_LITERAL : NODE_FLOAT_LITERAL;
	node->scope = NULL;
	node->data.number.value = value;
	return node;
}

Node*
make_unary_node(UnaryOp op, Node* operand)
{
	Node* node = (Node*)calloc(1, sizeof(Node));
	if (node == NULL) panic("make_unary_node: could not alloc");
	node->type = NODE_UNARY_EXPR;
	node->scope = NULL;
	node->next = NULL;
	node->data.unary_expr.op = op;
	node->data.unary_expr.operand = operand;
	node->data.unary_expr.is_postfix = false;
	return node;
}

Node*
make_boolean_node(Parser* par, bool truthy)
{
	consume(par);
	Node* node = (Node*)calloc(1, sizeof(Node));
	if (node == NULL) panic("make_boolean_node: could not alloc");
	node->type = NODE_BOOL_LITERAL;
	node->scope = NULL;
	node->data.boolean.value = truthy;
	return node;
}

Node*
make_string_node(Parser* par)
{
	Token tok = consume(par);
	Node* node = (Node*)calloc(1, sizeof(Node));
	if (node == NULL) panic("make_string_node: could not alloc");
	node->type = NODE_STRING_LITERAL;
	node->scope = NULL;
	node->data.string.value.start = (tok.start + 1); // "...
	node->data.string.value.end = (tok.end - 1);     // ..."
	return node;
}

Node*
make_binary_node(OpType op, Node* lhs, Node* rhs)
{
	Node* node = (Node*)calloc(1, sizeof(Node));
	if (node == NULL) panic("make_binary_node: could not alloc");
	node->type = NODE_BINARY_EXPR;
	node->scope = NULL;
	node->next = NULL;
	node->data.binary_expr.op = op;
	node->data.binary_expr.lhs = lhs;
	node->data.binary_expr.rhs = rhs;
	return node;
}

Node*
make_empty_statement(void)
{
	Node* node = (Node*)calloc(1, sizeof(Node));
	if (node == NULL) panic("make_empty_statement: could not alloc");
	assert(node != NULL);
	node->type = NODE_EMPTY_STATEMENT;
	node->scope = NULL;
	return node;
}

Node*
make_call_node(Node* callee, NodeVec args)
{
	Node* call = (Node*)calloc(1, sizeof(Node));
	if (call == NULL) panic("make_call_node: could not alloc");
	assert(call != NULL);
	call->type = NODE_CALL_EXPR;
	call->scope = NULL;
	call->data.call_expr.callee = callee;
	call->data.call_expr.args = args.items;
	call->data.call_expr.cap = args.cap;
	call->data.call_expr.len = args.len;
	return call;
}