diff --git a/lang/ast/expr.c b/lang/ast/expr.c index de81571..f8ea62f 100644 --- a/lang/ast/expr.c +++ b/lang/ast/expr.c @@ -492,6 +492,50 @@ static struct token_parse_result parse_left_paren( static struct token_parse_result parse_right_paren( struct ivy_parser *ctx, struct ivy_token *tok) { + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + b_queue_entry *entry = NULL; + + while (true) { + entry = b_queue_last(&state->s_operator_stack); + if (!entry) { + break; + } + + struct ivy_ast_node *node + = b_unbox(struct ivy_ast_node, entry, n_entry); + if (!node) { + /* this should never happen */ + return PARSE_RESULT(IVY_ERR_INTERNAL_FAILURE, 0); + } + + if (node->n_type != IVY_AST_OP) { + b_queue_delete(&state->s_operator_stack, entry); + b_queue_push_back(&state->s_output_queue, entry); + continue; + } + + struct ivy_ast_op_node *op_node = (struct ivy_ast_op_node *)node; + + if (op_node->n_op->op_id == IVY_OP_LEFT_PAREN) { + break; + } + + b_queue_delete(&state->s_operator_stack, entry); + b_queue_push_back(&state->s_output_queue, entry); + entry = NULL; + } + + if (!entry) { + /* mismatched parentheses */ + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + struct ivy_ast_node *paren = b_unbox(struct ivy_ast_node, entry, n_entry); + b_queue_delete(&state->s_operator_stack, entry); + ivy_ast_node_destroy(paren); + return PARSE_RESULT(IVY_OK, 0); }