static statement *parse_func_call(linked_list *tokens) { linked_list *accumulator = ll_new(); linked_iter iterator = ll_iter_head(tokens); statement *call = new(call); call->type = FUNC_CALL; call->data = ((parse_token*)ll_iter_next(&iterator))->data; call->children = ll_new(); int paren_level = 0; ll_iter_next(&iterator); //Discard opening parenthesis for(parse_token *current = ll_iter_next(&iterator); ll_iter_has_next(&iterator); current = ll_iter_next(&iterator)) { if(paren_level == 0 && (equals_string(current->data, ",") || equals_string(current->data, ")"))) { statement *parameter = parse_simple_expression(accumulator); if(parameter != NULL) ll_add_last(call->children, parameter); ll_clear(accumulator); } else { ll_add_last(accumulator, current); } if(equals_string(current->data, "(")) paren_level += 1; else if(equals_string(current->data, ")")) paren_level -= 1; } statement *parameter = parse_simple_expression(accumulator); if(parameter != NULL) ll_add_last(call->children, parameter); ll_destroy(accumulator); return call; }
/** * Removes the next item in the iterator from the linked list. * Use in conjunction with ll_iter_peek or ll_iter_has_next to find * and remove values. * i: the linked list iterator. */ DSValue ll_iter_remove(LLIter * i) { DSValue payload; if(ll_iter_has_next(i)) { LLNode * node = i->current; payload = i->current->payload; i->list->size--; /* Don't remember what this does.... * TODO: figure out what this line is */ if(i->list->size != 0) { i->list->tail = NULL; } if(i->current == i->list->head) { /* handle if node is head */ i->list->head = (LLNode*)i->current->nextNode; } else { /* handle if node if not head */ i->previous->nextNode = i->current->nextNode; } i->current = (LLNode*)i->current->nextNode; free(node); } return payload; }
/** * Frees a linked list. */ void ll_free(LL * list) { LLIter i; /* free all nodes */ ll_iter_get(&i, list); while(ll_iter_has_next(&i)) { ll_iter_remove(&i); } /* free list container */ free(list); }
/* Print a list of tokens to stdout, mostly for debugging purposes */ void print_tlist(linked_list *list) { if(ll_empty(list)) { return; } linked_iter iterator = ll_iter_head(list); parse_token *current = ll_iter_next(&iterator); while(ll_iter_has_next(&iterator)) { print_token(current); current = ll_iter_next(&iterator); } print_token(current); }
/* Print an AST node to stdout (recursive) */ void dump_node(linked_list *list, int indentation) { linked_iter iterator = ll_iter_head(list); while(ll_iter_has_next(&iterator)) { for(int i = 0; i < indentation; i++) { printf("\t"); } statement *state = ll_iter_next(&iterator); printf("%s", statement_to_string(state->type)); printf(": %s\n", evaluate(state->data)); if(state->children != NULL) { dump_node(state->children, indentation + 1); } } }
static void continue_build(build *current, char *filename, file_contents newest) { slice name_slice = new_slice(filename); slice *boxed_slice = new(boxed_slice); *boxed_slice = name_slice; hm_put(current->declarations, slice_hash(name_slice), boxed_slice, filename); linked_iter iterator = ll_iter_head(newest.imports); while(ll_iter_has_next(&iterator)) { import_declaration *dec = ll_iter_next(&iterator); char *filename = resolve_name(dec->name); slice filename_slice = new_slice(filename); slice *boxed_filename = new(boxed_filename); *boxed_filename = filename_slice; if(!hm_has(current->declarations, slice_hash(filename_slice), &(filename_slice))) { file_contents contents = get_contents(filename); ll_concat(current->composite.structs, contents.structs); ll_concat(current->composite.functions, contents.functions); hm_put(current->declarations, slice_hash(filename_slice), boxed_filename, filename); continue_build(current, filename, contents); } } }
/* Print the created AST to stdout, mostly for debugging purposes */ void dump(file_contents contents) { { linked_iter iterator = ll_iter_head(contents.imports); while(ll_iter_has_next(&iterator)) { import_declaration *import = ll_iter_next(&iterator); printf("IMPORT: %s\n", evaluate(import->name)); } } { linked_iter iterator = ll_iter_head(contents.enums); while(ll_iter_has_next(&iterator)) { enum_declaration *dec = ll_iter_next(&iterator); printf("ENUM: %s\n", evaluate(dec->name)); linked_iter items = ll_iter_head(dec->options); while(ll_iter_has_next(&items)) { statement *option = ll_iter_next(&items); printf("\tOPTION: %s\n", evaluate(option->data)); } } } { linked_iter iterator = ll_iter_head(contents.structs); while(ll_iter_has_next(&iterator)) { struct_declaration *current = ll_iter_next(&iterator); printf("STRUCT: %s\n", evaluate(current->name)); linked_iter iterator = ll_iter_head(current->members); while(ll_iter_has_next(&iterator)) { struct_member *member = ll_iter_next(&iterator); printf("\tMEMBER: NAME: %s | TYPE: %s\n", evaluate(member->name), evaluate(member->type)); } } } { linked_iter iterator = ll_iter_head(contents.functions); while(ll_iter_has_next(&iterator)) { func_declaration *current = ll_iter_next(&iterator); printf("FUNC: %s | TYPE : %s\n", evaluate(current->name), evaluate(current->type)); printf("\tPARAMETERS:\n"); dump_node(current->parameters, 2); printf("\tBODY:\n"); dump_node(current->root->children, 2); } } }
static statement *parse_simple_expression(linked_list *tokens) { while(equals_string(((parse_token*)ll_get_first(tokens))->data, "(") && equals_string(((parse_token*)ll_get_last(tokens))->data, ")")) { ll_remove_first(tokens); ll_remove_last(tokens); } int size = ll_size(tokens); switch(size) { case 0: return NULL; case 1: return parse_single_token(tokens); default: { if(size == 2) { parse_token *token = ll_get_first(tokens); bool isStack; if((isStack = equals_string(token->data, "new")) || equals_string(token->data, "newref")) { statement *expression = new(expression); expression->children = ll_new(); expression->type = isStack ? STACK_INIT : HEAP_INIT; linked_list *name = ll_duplicate(tokens); ll_remove_first(name); ll_add_first(expression->children, parse_simple_expression(name)); return expression; } } int paren_level = 1; linked_iter iterator = ll_iter_head(tokens); bool is_index = true, is_call = true; ll_iter_next(&iterator); parse_token *second = ll_iter_next(&iterator); if(equals_string(second->data, "(")) { is_index = false; } else if(equals_string(second->data, "[")) { is_call = false; } else { is_index = is_call = false; } while((is_index || is_call) && ll_iter_has_next(&iterator)) { parse_token *token = ll_iter_next(&iterator); if(equals_string(token->data, "(") || equals_string(token->data, "[")) { paren_level += 1; } else if(paren_level == 0) { is_index = false; is_call = false; } else if(equals_string(token->data, ")") || equals_string(token->data, "]")) { paren_level -= 1; } } if(is_index) { return parse_array_index(tokens); } else if(is_call) { return parse_func_call(tokens); } linked_list *operator = get_node(); linked_iter level = ll_iter_head(operator); while(ll_iter_has_next(&level)) { int paren_level = 0; linked_list *currentLevel = ll_iter_next(&level); linked_iter iterator = ll_iter_head(tokens); for(parse_token *current = ll_iter_next(&iterator); ll_iter_has_next(&iterator); current = ll_iter_next(&iterator)) { char currentChar = current->data.data[0]; if(currentChar == '(') { paren_level += 1; } else if(currentChar == ')') { paren_level -= 1; } if(paren_level != 0) continue; linked_iter innerMost = ll_iter_head(currentLevel); while(ll_iter_has_next(&innerMost)) { operator_node *currentOperator = ll_iter_next(&innerMost); if(equals_string(current->data, currentOperator->data)) { if(!is_unary_operator(new_slice(currentOperator->data))) { linked_list *op1 = ll_duplicate(tokens); while(ll_get_last(op1) != current) ll_remove_last(op1); ll_remove_last(op1); linked_list *op2 = tokens; while(ll_get_first(op2) != current) ll_remove_first(op2); ll_remove_first(op2); statement *expression = new(expression); expression->data = new_slice(""); expression->children = ll_new(); expression->type = currentOperator->operatorType; statement *op1_exp = parse_simple_expression(op1); statement *op2_exp = parse_simple_expression(op2); ll_add_last(expression->children, op1_exp); ll_add_last(expression->children, op2_exp); return expression; } else { statement *expression = new(expression); expression->data = new_slice(currentOperator->data); expression->type = currentOperator->operatorType; linked_list *rest = ll_duplicate(tokens); ll_remove_first(rest); expression->children = ll_new(); ll_add_first(expression->children, parse_simple_expression(rest)); return expression; } } } } } return NULL; } } }