Files
armorpaint/base/sources/libs/kong/parser.c
T
luboslenco 8b4284f8dd Update kong
2025-04-11 10:06:07 +02:00

1295 lines
37 KiB
C

#include "parser.h"
#include "errors.h"
#include "functions.h"
#include "sets.h"
#include "tokenizer.h"
#include "types.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
static statement *statement_allocate(void) {
statement *s = (statement *)malloc(sizeof(statement));
debug_context context = {0};
check(s != NULL, context, "Could not allocate statement");
return s;
}
// static void statement_free(statement *statement) {
// free(statement);
// }
static void statements_init(statements *statements) {
statements->size = 0;
}
static void statements_add(statements *statements, statement *statement) {
statements->s[statements->size] = statement;
statements->size += 1;
}
static expression *expression_allocate(void) {
expression *e = (expression *)malloc(sizeof(expression));
debug_context context = {0};
check(e != NULL, context, "Could not allocate expression");
init_type_ref(&e->type, NO_NAME);
return e;
}
// static void expression_free(expression *expression) {
// free(expression);
// }
typedef struct state {
tokens *tokens;
size_t index;
debug_context context;
} state_t;
static token current(state_t *state) {
token token = tokens_get(state->tokens, state->index);
return token;
}
static void update_debug_context(state_t *state) {
state->context.column = current(state).column;
state->context.line = current(state).line;
}
static void advance_state(state_t *state) {
state->index += 1;
update_debug_context(state);
}
static void match_token(state_t *state, int token, const char *error_message) {
int current_token = current(state).kind;
if (current_token != token) {
error(state->context, error_message);
}
}
static void match_token_identifier(state_t *state) {
if (current(state).kind != TOKEN_IDENTIFIER) {
error(state->context, "Expected an identifier");
}
}
static definition parse_definition(state_t *state);
static statement *parse_statement(state_t *state, block *parent_block);
static expression *parse_expression(state_t *state);
void parse(const char *filename, tokens *tokens) {
state_t state = {0};
state.context.filename = filename;
state.tokens = tokens;
state.index = 0;
for (;;) {
token token = current(&state);
if (token.kind == TOKEN_NONE) {
return;
}
else {
parse_definition(&state);
}
}
}
static statement *parse_block(state_t *state, block *parent_block) {
match_token(state, TOKEN_LEFT_CURLY, "Expected an opening curly bracket");
advance_state(state);
statements statements;
statements_init(&statements);
statement *new_block = statement_allocate();
new_block->kind = STATEMENT_BLOCK;
new_block->block.parent = parent_block;
new_block->block.vars.size = 0;
for (;;) {
switch (current(state).kind) {
case TOKEN_RIGHT_CURLY: {
advance_state(state);
new_block->block.statements = statements;
return new_block;
}
case TOKEN_NONE: {
update_debug_context(state);
error(state->context, "File ended before a block ended");
return NULL;
}
default:
statements_add(&statements, parse_statement(state, &new_block->block));
break;
}
}
}
typedef enum modifier {
MODIFIER_IN,
// Out,
} modifier_t;
typedef struct modifiers {
modifier_t m[16];
size_t size;
} modifiers_t;
// static void modifiers_init(modifiers_t *modifiers) {
// modifiers->size = 0;
// }
// static void modifiers_add(modifiers_t *modifiers, modifier_t modifier) {
// modifiers->m[modifiers->size] = modifier;
// modifiers->size += 1;
// }
static definition parse_struct(state_t *state);
static definition parse_function(state_t *state);
static definition parse_const(state_t *state, attribute_list attributes);
static double attribute_parameter_to_number(name_id attribute_name, name_id parameter_name) {
if (attribute_name == add_name("topology") && parameter_name == add_name("triangle")) {
return 0;
}
type_id type = find_type_by_name(parameter_name);
if (type != NO_TYPE) {
return (double)type;
}
debug_context context = {0};
error(context, "Unknown attribute parameter %s", get_name(parameter_name));
return 0;
}
static definition parse_definition(state_t *state) {
attribute_list attributes = {0};
descriptor_set *current_sets[64];
size_t current_sets_count = 0;
if (current(state).kind == TOKEN_HASH) {
advance_state(state);
match_token(state, TOKEN_LEFT_SQUARE, "Expected left square");
advance_state(state);
while (current(state).kind != TOKEN_RIGHT_SQUARE) {
attribute current_attribute = {0};
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
current_attribute.name = current(state).identifier;
if (current_attribute.name == add_name("root_constants")) {
current_sets[current_sets_count] = create_set(current_attribute.name);
current_attribute.parameters[current_attribute.paramters_count] = current_sets[current_sets_count]->index;
current_sets_count += 1;
}
advance_state(state);
if (current(state).kind == TOKEN_LEFT_PAREN) {
advance_state(state);
while (current(state).kind != TOKEN_RIGHT_PAREN) {
if (current(state).kind == TOKEN_IDENTIFIER) {
if (current_attribute.name == add_name("set")) {
if (current(state).identifier == add_name("root_constants")) {
debug_context context = {0};
error(context, "Descriptor set can not be called root_constants");
}
current_sets[current_sets_count] = create_set(current(state).identifier);
current_attribute.parameters[current_attribute.paramters_count] = current_sets[current_sets_count]->index;
current_sets_count += 1;
}
else {
current_attribute.parameters[current_attribute.paramters_count] =
attribute_parameter_to_number(current_attribute.name, current(state).identifier);
}
current_attribute.paramters_count += 1;
advance_state(state);
}
else if (current(state).kind == TOKEN_FLOAT || current(state).kind == TOKEN_INT) {
current_attribute.parameters[current_attribute.paramters_count] = current(state).number;
current_attribute.paramters_count += 1;
advance_state(state);
}
else {
debug_context context = {0};
error(context, "Expected an identifier or a number");
}
if (current(state).kind != TOKEN_RIGHT_PAREN) {
match_token(state, TOKEN_COMMA, "Expected a comma");
advance_state(state);
}
}
advance_state(state);
}
attributes.attributes[attributes.attributes_count] = current_attribute;
attributes.attributes_count += 1;
if (current(state).kind != TOKEN_RIGHT_SQUARE) {
match_token(state, TOKEN_COMMA, "Expected a comma");
advance_state(state);
}
}
advance_state(state);
}
switch (current(state).kind) {
case TOKEN_STRUCT: {
if (current_sets_count != 0) {
debug_context context = {0};
error(context, "A struct can not be assigned to a set");
}
definition structy = parse_struct(state);
get_type(structy.type)->attributes = attributes;
return structy;
}
case TOKEN_FUNCTION: {
if (current_sets_count != 0) {
debug_context context = {0};
error(context, "A function can not be assigned to a set");
}
definition d = parse_function(state);
function *f = get_function(d.function);
f->attributes = attributes;
return d;
}
case TOKEN_CONST: {
definition d = parse_const(state, attributes);
for (size_t set_index = 0; set_index < current_sets_count; ++set_index) {
add_definition_to_set(current_sets[set_index], d);
}
return d;
}
default: {
update_debug_context(state);
error(state->context, "Expected a struct, a function or a const");
definition d = {0};
return d;
}
}
}
static type_ref parse_type_ref(state_t *state) {
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
token type_name = current(state);
advance_state(state);
uint32_t array_size = 0;
if (current(state).kind == TOKEN_LEFT_SQUARE) {
advance_state(state);
if (current(state).kind == TOKEN_INT) {
array_size = (uint32_t)current(state).number;
if (array_size == 0) {
error(state->context, "Array size of 0 is not allowed");
}
advance_state(state);
}
else {
array_size = UINT32_MAX;
}
match_token(state, TOKEN_RIGHT_SQUARE, "Expected a closing square bracket");
advance_state(state);
}
type_ref t;
init_type_ref(&t, type_name.identifier);
t.unresolved.array_size = array_size;
return t;
}
static statement *parse_statement(state_t *state, block *parent_block) {
switch (current(state).kind) {
case TOKEN_IF: {
advance_state(state);
match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket");
advance_state(state);
expression *test = parse_expression(state);
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
statement *if_block = parse_statement(state, parent_block);
statement *s = statement_allocate();
s->kind = STATEMENT_IF;
s->iffy.test = test;
s->iffy.if_block = if_block;
s->iffy.else_size = 0;
while (current(state).kind == TOKEN_ELSE) {
advance_state(state);
if (current(state).kind == TOKEN_IF) {
advance_state(state);
match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket");
advance_state(state);
expression *test = parse_expression(state);
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
statement *if_block = parse_statement(state, parent_block);
s->iffy.else_tests[s->iffy.else_size] = test;
s->iffy.else_blocks[s->iffy.else_size] = if_block;
}
else {
statement *else_block = parse_statement(state, parent_block);
s->iffy.else_tests[s->iffy.else_size] = NULL;
s->iffy.else_blocks[s->iffy.else_size] = else_block;
}
s->iffy.else_size += 1;
assert(s->iffy.else_size < 64);
}
return s;
}
case TOKEN_WHILE: {
advance_state(state);
match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket");
advance_state(state);
expression *test = parse_expression(state);
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
statement *while_block = parse_statement(state, parent_block);
statement *s = statement_allocate();
s->kind = STATEMENT_WHILE;
s->whiley.test = test;
s->whiley.while_block = while_block;
return s;
}
case TOKEN_DO: {
advance_state(state);
statement *do_block = parse_statement(state, parent_block);
statement *s = statement_allocate();
s->kind = STATEMENT_DO_WHILE;
s->whiley.while_block = do_block;
match_token(state, TOKEN_WHILE, "Expected \"while\"");
advance_state(state);
match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket");
advance_state(state);
expression *test = parse_expression(state);
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
s->whiley.test = test;
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
return s;
}
case TOKEN_FOR: {
statements outer_block_statements;
statements_init(&outer_block_statements);
statement *outer_block = statement_allocate();
outer_block->kind = STATEMENT_BLOCK;
outer_block->block.parent = parent_block;
outer_block->block.vars.size = 0;
outer_block->block.statements = outer_block_statements;
advance_state(state);
match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket");
advance_state(state);
statement *pre = parse_statement(state, &outer_block->block);
statements_add(&outer_block->block.statements, pre);
expression *test = parse_expression(state);
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
expression *post_expression = parse_expression(state);
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
statement *inner_block = parse_statement(state, &outer_block->block);
statement *post_statement = statement_allocate();
post_statement->kind = STATEMENT_EXPRESSION;
post_statement->expression = post_expression;
statements_add(&inner_block->block.statements, post_statement);
statement *s = statement_allocate();
s->kind = STATEMENT_WHILE;
s->whiley.test = test;
s->whiley.while_block = inner_block;
statements_add(&outer_block->block.statements, s);
return outer_block;
}
case TOKEN_LEFT_CURLY: {
return parse_block(state, parent_block);
}
case TOKEN_VAR: {
advance_state(state);
match_token_identifier(state);
token name = current(state);
advance_state(state);
match_token(state, TOKEN_COLON, "Expected a colon");
advance_state(state);
type_ref type = parse_type_ref(state);
expression *init = NULL;
if (current(state).kind == TOKEN_OPERATOR) {
check(current(state).op == OPERATOR_ASSIGN, state->context, "Expected an assign");
advance_state(state);
init = parse_expression(state);
}
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
statement *statement = statement_allocate();
statement->kind = STATEMENT_LOCAL_VARIABLE;
statement->local_variable.var.name = name.identifier;
statement->local_variable.var.type = type;
statement->local_variable.var.variable_id = 0;
statement->local_variable.init = init;
return statement;
}
case TOKEN_RETURN: {
advance_state(state);
expression *expr = parse_expression(state);
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
statement *statement = statement_allocate();
statement->kind = STATEMENT_RETURN_EXPRESSION;
statement->expression = expr;
return statement;
}
case TOKEN_DISCARD: {
advance_state(state);
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
statement *statement = statement_allocate();
statement->kind = STATEMENT_DISCARD;
return statement;
}
default: {
expression *expr = parse_expression(state);
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
statement *statement = statement_allocate();
statement->kind = STATEMENT_EXPRESSION;
statement->expression = expr;
return statement;
}
}
}
static expression *parse_assign(state_t *state);
static expression *parse_expression(state_t *state) {
return parse_assign(state);
}
static expression *parse_logical(state_t *state);
static expression *parse_assign(state_t *state) {
expression *expr = parse_logical(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_ASSIGN || op == OPERATOR_MINUS_ASSIGN || op == OPERATOR_PLUS_ASSIGN || op == OPERATOR_DIVIDE_ASSIGN ||
op == OPERATOR_MULTIPLY_ASSIGN) {
advance_state(state);
expression *right = parse_logical(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_bitwise(state_t *state);
static expression *parse_logical(state_t *state) {
expression *expr = parse_bitwise(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_OR || op == OPERATOR_AND) {
advance_state(state);
expression *right = parse_bitwise(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_equality(state_t *state);
static expression *parse_bitwise(state_t *state) {
expression *expr = parse_equality(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_BITWISE_XOR || op == OPERATOR_BITWISE_OR || op == OPERATOR_BITWISE_AND) {
advance_state(state);
expression *right = parse_equality(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_comparison(state_t *state);
static expression *parse_equality(state_t *state) {
expression *expr = parse_comparison(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_EQUALS || op == OPERATOR_NOT_EQUALS) {
advance_state(state);
expression *right = parse_comparison(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_shift(state_t *state);
static expression *parse_comparison(state_t *state) {
expression *expr = parse_shift(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_GREATER || op == OPERATOR_GREATER_EQUAL || op == OPERATOR_LESS || op == OPERATOR_LESS_EQUAL) {
advance_state(state);
expression *right = parse_shift(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_addition(state_t *state);
static expression *parse_shift(state_t *state) {
expression *expr = parse_addition(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_LEFT_SHIFT || op == OPERATOR_RIGHT_SHIFT) {
advance_state(state);
expression *right = parse_addition(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_multiplication(state_t *state);
static expression *parse_addition(state_t *state) {
expression *expr = parse_multiplication(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_MINUS || op == OPERATOR_PLUS) {
advance_state(state);
expression *right = parse_multiplication(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_unary(state_t *state);
static expression *parse_multiplication(state_t *state) {
expression *expr = parse_unary(state);
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_DIVIDE || op == OPERATOR_MULTIPLY || op == OPERATOR_MOD) {
advance_state(state);
expression *right = parse_unary(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_BINARY;
expression->binary.left = expr;
expression->binary.op = op;
expression->binary.right = right;
expr = expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return expr;
}
static expression *parse_primary(state_t *state);
static expression *parse_unary(state_t *state) {
bool done = false;
while (!done) {
if (current(state).kind == TOKEN_OPERATOR) {
operatorr op = current(state).op;
if (op == OPERATOR_NOT || op == OPERATOR_MINUS) {
advance_state(state);
expression *right = parse_unary(state);
expression *expression = expression_allocate();
expression->kind = EXPRESSION_UNARY;
expression->unary.op = op;
expression->unary.right = right;
return expression;
}
else {
done = true;
}
}
else {
done = true;
}
}
return parse_primary(state);
}
static expression *parse_member_or_element_access(state_t *state, expression *of) {
if (current(state).kind == TOKEN_DOT) {
advance_state(state);
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
token token = current(state);
advance_state(state);
expression *member = expression_allocate();
member->kind = EXPRESSION_MEMBER;
member->member.of = of;
member->member.member_name = token.identifier;
expression *sub = parse_member_or_element_access(state, member);
return sub;
}
else if (current(state).kind == TOKEN_LEFT_SQUARE) {
advance_state(state);
expression *index = parse_expression(state);
match_token(state, TOKEN_RIGHT_SQUARE, "Expected a closing square bracket");
advance_state(state);
expression *element = expression_allocate();
element->kind = EXPRESSION_ELEMENT;
element->element.of = of;
element->element.element_index = index;
expression *sub = parse_member_or_element_access(state, element);
return sub;
}
if (current(state).kind == TOKEN_LEFT_PAREN) {
error(state->context, "Function members not supported.");
}
return of;
}
static expression *parse_call(state_t *state, name_id func_name);
static expression *parse_primary(state_t *state) {
expression *left = NULL;
switch (current(state).kind) {
case TOKEN_BOOLEAN: {
bool value = current(state).boolean;
advance_state(state);
left = expression_allocate();
left->kind = EXPRESSION_BOOLEAN;
left->boolean = value;
break;
}
case TOKEN_FLOAT: {
double value = current(state).number;
advance_state(state);
left = expression_allocate();
left->kind = EXPRESSION_FLOAT;
left->number = value;
break;
}
case TOKEN_INT: {
double value = current(state).number;
advance_state(state);
left = expression_allocate();
left->kind = EXPRESSION_INT;
left->number = value;
break;
}
/*case TOKEN_STRING: {
token token = current(state);
advance_state(state);
left = expression_allocate();
left->kind = EXPRESSION_STRING;
left->string = add_name(token.string);
break;
}*/
case TOKEN_IDENTIFIER: {
token token = current(state);
advance_state(state);
if (current(state).kind == TOKEN_LEFT_PAREN) {
left = parse_call(state, token.identifier);
}
else {
expression *var = expression_allocate();
var->kind = EXPRESSION_VARIABLE;
var->variable = token.identifier;
left = var;
}
break;
}
case TOKEN_LEFT_PAREN: {
advance_state(state);
expression *expr = parse_expression(state);
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
left = expression_allocate();
left->kind = EXPRESSION_GROUPING;
left->grouping = expr;
break;
}
default:
error(state->context, "Unexpected token");
return NULL;
}
return parse_member_or_element_access(state, left);
}
static expressions parse_parameters(state_t *state) {
expressions e;
e.size = 0;
if (current(state).kind == TOKEN_RIGHT_PAREN) {
advance_state(state);
return e;
}
for (;;) {
e.e[e.size] = parse_expression(state);
e.size += 1;
if (current(state).kind == TOKEN_COMMA) {
advance_state(state);
}
else {
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
return e;
}
}
}
static expression *parse_call(state_t *state, name_id func_name) {
match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket");
advance_state(state);
expression *call = NULL;
call = expression_allocate();
call->kind = EXPRESSION_CALL;
call->call.func_name = func_name;
call->call.parameters = parse_parameters(state);
return parse_member_or_element_access(state, call);
}
static definition parse_struct_inner(state_t *state, name_id name) {
match_token(state, TOKEN_LEFT_CURLY, "Expected an opening curly bracket");
advance_state(state);
token member_names[MAX_MEMBERS];
type_ref type_refs[MAX_MEMBERS];
token member_values[MAX_MEMBERS];
size_t count = 0;
while (current(state).kind != TOKEN_RIGHT_CURLY) {
debug_context context = {0};
check(count < MAX_MEMBERS, context, "Out of members");
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
member_names[count] = current(state);
advance_state(state);
if (current(state).kind == TOKEN_COLON) {
advance_state(state);
type_refs[count] = parse_type_ref(state);
}
else {
type_ref t;
t.type = NO_TYPE;
t.unresolved.name = NO_NAME;
t.unresolved.array_size = 0;
type_refs[count] = t;
}
if (current(state).kind == TOKEN_OPERATOR && current(state).op == OPERATOR_ASSIGN) {
advance_state(state);
if (current(state).kind == TOKEN_BOOLEAN || current(state).kind == TOKEN_FLOAT || current(state).kind == TOKEN_INT ||
current(state).kind == TOKEN_IDENTIFIER) {
member_values[count] = current(state);
advance_state(state);
if (current(state).kind == TOKEN_LEFT_PAREN) {
advance_state(state);
match_token(state, TOKEN_RIGHT_PAREN, "Expected a right paren");
advance_state(state);
}
}
else {
debug_context context = {0};
error(context, "Unsupported assign in struct");
}
}
else {
member_values[count].kind = TOKEN_NONE;
member_values[count].identifier = NO_NAME;
}
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
++count;
}
advance_state(state);
definition definition;
definition.kind = DEFINITION_STRUCT;
definition.type = add_type(name);
type *s = get_type(definition.type);
for (size_t i = 0; i < count; ++i) {
member member;
member.name = member_names[i].identifier;
member.value = member_values[i];
if (member.value.kind != TOKEN_NONE) {
if (member.value.kind == TOKEN_BOOLEAN) {
init_type_ref(&member.type, add_name("bool"));
}
else if (member.value.kind == TOKEN_FLOAT) {
init_type_ref(&member.type, add_name("float"));
}
else if (member.value.kind == TOKEN_INT) {
init_type_ref(&member.type, add_name("int"));
}
else if (member.value.kind == TOKEN_IDENTIFIER) {
global *g = find_global(member.value.identifier);
if (g != NULL && g->name != NO_NAME) {
init_type_ref(&member.type, get_type(g->type)->name);
}
else {
init_type_ref(&member.type, add_name("fun"));
}
}
else {
debug_context context = {0};
error(context, "Unsupported value in struct");
}
}
else {
member.type = type_refs[i];
}
s->members.m[i] = member;
}
s->members.size = count;
return definition;
}
static definition parse_struct(state_t *state) {
advance_state(state);
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
token name = current(state);
advance_state(state);
return parse_struct_inner(state, name.identifier);
}
static definition parse_function(state_t *state) {
advance_state(state);
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
token name = current(state);
advance_state(state);
match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket");
advance_state(state);
uint8_t parameters_size = 0;
name_id param_names[256] = {0};
type_ref param_types[256] = {0};
name_id param_attributes[256] = {0};
while (current(state).kind != TOKEN_RIGHT_PAREN) {
if (current(state).kind == TOKEN_HASH) {
advance_state(state);
match_token(state, TOKEN_LEFT_SQUARE, "Expected an opening square bracket");
advance_state(state);
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
token attribute_name = current(state);
param_attributes[parameters_size] = attribute_name.identifier;
advance_state(state);
match_token(state, TOKEN_RIGHT_SQUARE, "Expected a closing square bracket");
advance_state(state);
}
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
param_names[parameters_size] = current(state).identifier;
advance_state(state);
match_token(state, TOKEN_COLON, "Expected a colon");
advance_state(state);
param_types[parameters_size] = parse_type_ref(state);
if (current(state).kind == TOKEN_COMMA) {
advance_state(state);
}
parameters_size += 1;
}
match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket");
advance_state(state);
match_token(state, TOKEN_COLON, "Expected a colon");
advance_state(state);
type_ref return_type = parse_type_ref(state);
statement *block = parse_block(state, NULL);
definition d;
d.kind = DEFINITION_FUNCTION;
d.function = add_function(name.identifier);
function *f = get_function(d.function);
f->return_type = return_type;
f->parameters_size = parameters_size;
for (uint8_t parameter_index = 0; parameter_index < parameters_size; ++parameter_index) {
f->parameter_names[parameter_index] = param_names[parameter_index];
f->parameter_types[parameter_index] = param_types[parameter_index];
f->parameter_attributes[parameter_index] = param_attributes[parameter_index];
}
f->block = block;
return d;
}
static definition parse_const(state_t *state, attribute_list attributes) {
advance_state(state);
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
token name = current(state);
advance_state(state);
match_token(state, TOKEN_COLON, "Expected a colon");
advance_state(state);
name_id type_name = NO_NAME;
type_id type = NO_TYPE;
if (current(state).kind == TOKEN_LEFT_CURLY) {
type = parse_struct_inner(state, NO_NAME).type;
}
else {
match_token(state, TOKEN_IDENTIFIER, "Expected an identifier");
type_name = current(state).identifier;
advance_state(state);
}
bool array = false;
uint32_t array_size = UINT32_MAX;
if (current(state).kind == TOKEN_LEFT_SQUARE) {
array = true;
advance_state(state);
if (current(state).kind == TOKEN_INT) {
array_size = (uint32_t)current(state).number;
advance_state(state);
}
match_token(state, TOKEN_RIGHT_SQUARE, "Expected a right square bracket");
advance_state(state);
}
expression *value = NULL;
if (current(state).kind == TOKEN_OPERATOR && current(state).op == OPERATOR_ASSIGN) {
advance_state(state);
value = parse_expression(state);
}
match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
advance_state(state);
definition d = {0};
if (type_name == NO_NAME) {
debug_context context = {0};
check(type != NO_TYPE, context, "Const has no type");
d.kind = DEFINITION_CONST_CUSTOM;
d.global = add_global(type, attributes, name.identifier);
}
else if (type_name == add_name("tex2d")) {
d.kind = DEFINITION_TEX2D;
type_id t_id = tex2d_type_id;
if (array) {
type_id array_type_id = add_type(get_type(t_id)->name);
get_type(array_type_id)->base = t_id;
get_type(array_type_id)->built_in = get_type(t_id)->built_in;
get_type(array_type_id)->array_size = array_size;
t_id = array_type_id;
}
d.global = add_global(t_id, attributes, name.identifier);
}
else if (type_name == add_name("tex2darray")) {
d.kind = DEFINITION_TEX2DARRAY;
d.global = add_global(tex2darray_type_id, attributes, name.identifier);
}
else if (type_name == add_name("texcube")) {
d.kind = DEFINITION_TEXCUBE;
d.global = add_global(texcube_type_id, attributes, name.identifier);
}
else if (type_name == add_name("sampler")) {
d.kind = DEFINITION_SAMPLER;
d.global = add_global(sampler_type_id, attributes, name.identifier);
}
else if (type_name == add_name("bvh")) {
d.kind = DEFINITION_BVH;
d.global = add_global(bvh_type_id, attributes, name.identifier);
}
else if (type_name == add_name("float")) {
debug_context context = {0};
check(value != NULL, context, "const float requires an initialization value");
check(value->kind == EXPRESSION_FLOAT || value->kind == EXPRESSION_INT, context, "const float requires a number");
global_value float_value;
float_value.kind = GLOBAL_VALUE_FLOAT;
float_value.value.floats[0] = (float)value->number;
d.kind = DEFINITION_CONST_BASIC;
d.global = add_global_with_value(float_id, attributes, name.identifier, float_value);
}
else if (type_name == add_name("float2")) {
debug_context context = {0};
check(value != NULL, context, "const float2 requires an initialization value");
check(value->kind == EXPRESSION_CALL, context, "const float2 requires a constructor call");
check(value->call.func_name == add_name("float2"), context, "const float2 requires a float2 call");
check(value->call.parameters.size == 3, context, "const float2 construtor call requires two parameters");
global_value float2_value;
float2_value.kind = GLOBAL_VALUE_FLOAT2;
for (int i = 0; i < 2; ++i) {
check(value->call.parameters.e[i]->kind == EXPRESSION_FLOAT || value->call.parameters.e[i]->kind == EXPRESSION_INT, context,
"const float2 construtor parameters have to be numbers");
float2_value.value.floats[i] = (float)value->call.parameters.e[i]->number;
}
d.kind = DEFINITION_CONST_BASIC;
d.global = add_global_with_value(float2_id, attributes, name.identifier, float2_value);
}
else if (type_name == add_name("float3")) {
debug_context context = {0};
check(value != NULL, context, "const float3 requires an initialization value");
check(value->kind == EXPRESSION_CALL, context, "const float3 requires a constructor call");
check(value->call.func_name == add_name("float3"), context, "const float3 requires a float3 call");
check(value->call.parameters.size == 3, context, "const float3 construtor call requires three parameters");
global_value float3_value;
float3_value.kind = GLOBAL_VALUE_FLOAT3;
for (int i = 0; i < 3; ++i) {
check(value->call.parameters.e[i]->kind == EXPRESSION_FLOAT || value->call.parameters.e[i]->kind == EXPRESSION_INT, context,
"const float3 construtor parameters have to be numbers");
float3_value.value.floats[i] = (float)value->call.parameters.e[i]->number;
}
d.kind = DEFINITION_CONST_BASIC;
d.global = add_global_with_value(float3_id, attributes, name.identifier, float3_value);
}
else if (type_name == add_name("float4")) {
debug_context context = {0};
if (!array) {
check(value != NULL, context, "const float4 requires an initialization value");
check(value->kind == EXPRESSION_CALL, context, "const float4 requires a constructor call");
check(value->call.func_name == add_name("float4"), context, "const float4 requires a float4 call");
check(value->call.parameters.size == 4, context, "const float4 construtor call requires four parameters");
}
else {
check(value == NULL, context, "const float4[] does not allow an initialization value");
}
global_value float4_value;
float4_value.kind = GLOBAL_VALUE_FLOAT4;
if (!array) {
for (int i = 0; i < 4; ++i) {
check(value->call.parameters.e[i]->kind == EXPRESSION_FLOAT || value->call.parameters.e[i]->kind == EXPRESSION_INT, context,
"const float4 construtor parameters have to be numbers");
float4_value.value.floats[i] = (float)value->call.parameters.e[i]->number;
}
}
d.kind = DEFINITION_CONST_BASIC;
if (array) {
type_id array_type_id = add_type(get_type(float4_id)->name);
get_type(array_type_id)->base = float4_id;
get_type(array_type_id)->built_in = true;
get_type(array_type_id)->array_size = array_size;
d.global = add_global(array_type_id, attributes, name.identifier);
}
else {
d.global = add_global_with_value(float4_id, attributes, name.identifier, float4_value);
}
}
else {
debug_context context = {0};
error(context, "Unsupported global");
}
return d;
}