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; }
reaver::despayre::expression reaver::despayre::_v1::parse_expression(reaver::despayre::context & ctx) { auto expr = parse_simple_expression(ctx); auto peeked = peek(ctx); auto start = get<0>(fmap(expr, [](auto && expr){ return expr.range.start(); })); if (peeked && (peeked->type == token_type::plus || peeked->type == token_type::minus)) { auto operations = parse_operations(ctx); return expression{ range_type{ start, operations.back().range.end() }, std::move(expr), std::move(operations) }; } auto end = get<0>(fmap(expr, [](auto && expr){ return expr.range.end(); })); return expression{ range_type{ start, end }, std::move(expr), {} }; }
std::vector<reaver::despayre::operation> reaver::despayre::_v1::parse_operations(reaver::despayre::context & ctx) { auto peeked = peek(ctx); std::vector<operation> operations; while (peeked && (peeked->type == token_type::plus || peeked->type == token_type::minus)) { operation_type operation = expect(ctx, peeked->type).type == token_type::plus ? operation_type::addition : operation_type::removal; auto operand = parse_simple_expression(ctx); auto end = get<0>(fmap(operand, [](auto && op){ return op.range.end(); })); operations.push_back({ range_type{ peeked->range.start(), end }, operation, std::move(operand) }); peeked = peek(ctx); } return operations; }
static statement *parse_array_index(linked_list *tokens) { statement *index = new(index); index->type = OP_INDEX; index->data = new_slice(""); index->children = ll_new(); statement *name = new(name); name->type = NAME; name->data = ((parse_token*)ll_get_first(tokens))->data; name->children = NULL; ll_add_first(index->children, name); linked_list *inside_list = ll_duplicate(tokens); ll_remove_first(inside_list); //Remove name ll_remove_first(inside_list); //Remove [ ll_remove_last(inside_list); //Remove ] statement *inside = parse_simple_expression(inside_list); ll_destroy(inside_list); ll_add_last(index->children, inside); return index; }
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; } } }
static statement *get_expression(parse_source *source, int *indent) { parse_token token = get_mandatory_token(source); if(equals_string(token.data, "{")) { statement *expression = new(expression); expression->type = BLOCK; expression->children = ll_new(); expression->data = new_slice(""); int finished = *indent; *indent += 1; while(*indent != finished) { statement *state = get_expression(source, indent); if(state != NULL) ll_add_last(expression->children, state); } return expression; } else if(equals_string(token.data, "}")) { *indent -= 1; return NULL; } else if(equals_string(token.data, "if") || equals_string(token.data, "while") || equals_string(token.data, "for")) { statement *expression = new(expression); if(equals_string(token.data, "if")) expression->type = IF; else if(equals_string(token.data, "while")) expression->type = WHILE; else if(equals_string(token.data, "for")) expression->type = FOR; expression->children = ll_new(); expression->data = new_slice(""); ll_add_last(expression->children, get_expression(source, indent)); //Add the header if(expression->type == FOR) { ll_add_last(expression->children, get_expression(source, indent)); //Add the header ll_add_last(expression->children, get_expression(source, indent)); //Add the header } ll_add_last(expression->children, get_expression(source, indent)); //Add the body if(expression->type == IF) { parse_token next = peek_mandatory_token(source); if(equals_string(next.data, "else")) { get_mandatory_token(source); statement *elseState = new(elseState); elseState->type = ELSE; elseState->children = ll_new(); elseState->data = new_slice(""); ll_add_last(expression->children, elseState); ll_add_first(elseState->children, get_expression(source, indent)); } } return expression; } else if(equals_string(token.data, "break") || equals_string(token.data, "continue")) { statement *expression = new(expression); expression->type = equals_string(token.data, "break") ? BREAK : CONTINUE; expression->data = new_slice(""); expression->children = NULL; parse_token next = get_mandatory_token(source); if(!equals_string(next.data, ";")) semantic_error("Expected a semicolon after a break or continue", next.origin); return expression; } else if(equals_string(token.data, "return")) { statement *expression = new(expression); expression->type = RETURN; expression->data = new_slice(""); expression->children = ll_new(); ll_add_last(expression->children, get_expression(source, indent)); return expression; } else { linked_list *accumulator = ll_new(); parse_token next = token; while(true) { parse_token *allocated = new(allocated); *allocated = token; ll_add_last(accumulator, allocated); next = peek_mandatory_token(source); if(equals_string(next.data, "{") || equals_string(next.data, "}")) break; if(equals_string(next.data, ";")) { get_mandatory_token(source); break; } token = get_mandatory_token(source); } statement *expression = parse_simple_expression(accumulator); ll_delete_all(accumulator); return expression; } }