static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret);
static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret);
static AstTyped* parse_factor(OnyxParser* parser);
-static AstTyped* parse_expression(OnyxParser* parser);
+static AstTyped* parse_compound_assignment(OnyxParser* parser, AstTyped* lhs);
+static AstTyped* parse_compound_expression(OnyxParser* parser, b32 assignment_allowed);
+static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed);
static AstIfWhile* parse_if_stmt(OnyxParser* parser);
static AstIfWhile* parse_while_stmt(OnyxParser* parser);
static AstFor* parse_for_stmt(OnyxParser* parser);
name = NULL;
}
- AstTyped *expr = parse_expression(parser);
+ AstTyped *expr = parse_expression(parser, 0);
if (is_named) {
AstStructMember* sm = make_node(AstStructMember, Ast_Kind_Struct_Member);
expect_token(parser, '.');
expect_token(parser, '[');
while (parser->curr->type != ']') {
- AstTyped* value = parse_expression(parser);
+ AstTyped* value = parse_expression(parser, 0);
bh_arr_push(al->values, value);
if (parser->curr->type != ']')
switch ((u16) parser->curr->type) {
case '(': {
consume_token(parser);
- AstTyped* expr = parse_expression(parser);
+ AstTyped* expr = parse_compound_expression(parser, 0);
expect_token(parser, ')');
retval = expr;
break;
switch ((u16) parser->curr->type) {
case '[': {
OnyxToken *open_bracket = expect_token(parser, '[');
- AstTyped *expr = parse_expression(parser);
+ AstTyped *expr = parse_compound_expression(parser, 0);
AstKind kind = Ast_Kind_Array_Access;
AstArgument* arg = make_node(AstArgument, Ast_Kind_Argument);
arg->token = parser->curr;
- arg->value = parse_expression(parser);
+ arg->value = parse_expression(parser, 0);
if (arg != NULL && arg->kind != Ast_Kind_Error) {
bh_arr_push(call_node->arg_arr, arg);
}
}
+static AstTyped* parse_compound_assignment(OnyxParser* parser, AstTyped* lhs) {
+ if (parser->curr->type != '=') return lhs;
+
+ AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
+ assignment->token = expect_token(parser, '=');
+ assignment->operation = Binary_Op_Assign;
+ assignment->left = lhs;
+ assignment->right = parse_compound_expression(parser, 0);
+
+ return (AstTyped *) assignment;
+}
+
+static AstTyped* parse_compound_expression(OnyxParser* parser, b32 assignment_allowed) {
+ AstTyped* first = parse_expression(parser, assignment_allowed);
+
+ if (parser->curr->type == ',') {
+ AstCompound* compound = make_node(AstCompound, Ast_Kind_Compound);
+ compound->token = parser->curr;
+
+ bh_arr_new(global_heap_allocator, compound->exprs, 2);
+ bh_arr_push(compound->exprs, first);
+
+ while (parser->curr->type == ',') {
+ if (parser->hit_unexpected_token) return (AstTyped *) compound;
+ consume_token(parser);
+
+ AstTyped* expr = parse_expression(parser, 0);
+ bh_arr_push(compound->exprs, expr);
+
+ if (assignment_allowed && parser->curr->type == '=') {
+ return parse_compound_assignment(parser, (AstTyped *) compound);
+ }
+ }
+
+ return (AstTyped *) compound;
+
+ } else {
+ return first;
+ }
+}
+
// <expr> + <expr>
// <expr> - <expr>
// <expr> * <expr>
// <expr> %= <expr>
// <factor>
// With expected precedence rules
-static AstTyped* parse_expression(OnyxParser* parser) {
+static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed) {
bh_arr(AstBinaryOp*) tree_stack = NULL;
bh_arr_new(global_heap_allocator, tree_stack, 4);
bh_arr_set_length(tree_stack, 0);
bin_op_kind = binary_op_from_token_type(parser->curr->type);
if (bin_op_kind == Binary_Op_Count) goto expression_done;
+ if (binop_is_assignment(bin_op_kind) && !assignment_allowed) goto expression_done;
bin_op_tok = parser->curr;
consume_token(parser);
assignment->operation = Binary_Op_Assign;
assignment->token = expect_token(parser, '=');
assignment->left = (AstTyped *) if_node->local;
- assignment->right = parse_expression(parser);
+ assignment->right = parse_expression(parser, 0);
if_node->assignment = assignment;
expect_token(parser, ';');
}
- AstTyped* cond = parse_expression(parser);
+ AstTyped* cond = parse_expression(parser, 1);
AstBlock* true_stmt = parse_block(parser);
if_node->cond = cond;
consume_token(parser);
AstIfWhile* elseif_node = make_node(AstIfWhile, Ast_Kind_If);
- cond = parse_expression(parser);
+ cond = parse_expression(parser, 1);
true_stmt = parse_block(parser);
elseif_node->cond = cond;
assignment->operation = Binary_Op_Assign;
assignment->token = expect_token(parser, '=');
assignment->left = (AstTyped *) while_node->local;
- assignment->right = parse_expression(parser);
+ assignment->right = parse_expression(parser, 0);
while_node->assignment = assignment;
expect_token(parser, ';');
}
- while_node->cond = parse_expression(parser);
+ while_node->cond = parse_expression(parser, 1);
while_node->true_stmt = parse_block(parser);
if (parser->curr->type == Token_Type_Keyword_Else) {
for_node->var = var_node;
expect_token(parser, ':');
- for_node->iter = parse_expression(parser);
+ for_node->iter = parse_expression(parser, 1);
for_node->stmt = parse_block(parser);
return for_node;
assignment->operation = Binary_Op_Assign;
assignment->token = expect_token(parser, '=');
assignment->left = (AstTyped *) switch_node->local;
- assignment->right = parse_expression(parser);
+ assignment->right = parse_expression(parser, 0);
switch_node->assignment = assignment;
expect_token(parser, ';');
}
- switch_node->expr = parse_expression(parser);
+ switch_node->expr = parse_expression(parser, 1);
expect_token(parser, '{');
while (parser->curr->type == Token_Type_Keyword_Case) {
break;
}
- AstTyped* value = parse_expression(parser);
+ AstTyped* value = parse_expression(parser, 1);
bh_arr_push(case_values, value);
while (parser->curr->type == ',') {
if (parser->hit_unexpected_token) return switch_node;
consume_token(parser);
- value = parse_expression(parser);
+ value = parse_expression(parser, 1);
bh_arr_push(case_values, value);
}
assignment->token = parser->curr;
consume_token(parser);
- AstTyped* expr = parse_expression(parser);
+ AstTyped* expr = parse_expression(parser, 1);
if (expr == NULL) return 1;
assignment->right = expr;
AstTyped* expr = NULL;
if (parser->curr->type != ';') {
- expr = parse_expression(parser);
+ expr = parse_compound_expression(parser, 0);
if (expr == NULL || expr == (AstTyped *) &error_node) {
return (AstReturn *) &error_node;
} else {
AstUse* use_node = make_node(AstUse, Ast_Kind_Use);
use_node->token = use_token;
- use_node->expr = parse_expression(parser);
+ use_node->expr = parse_expression(parser, 1);
return (AstNode *) use_node;
}
}
case Token_Type_Literal_Integer:
case Token_Type_Literal_Float:
case Token_Type_Literal_String:
- retval = (AstNode *) parse_expression(parser);
+ retval = (AstNode *) parse_compound_expression(parser, 1);
break;
case Token_Type_Keyword_If:
AstType** insertion = (AstType **) &((AstArrayType *) new)->count_expr;
parse_polymorphic_variable(parser, &insertion);
} else {
- ((AstArrayType *) new)->count_expr = parse_expression(parser);
+ ((AstArrayType *) new)->count_expr = parse_expression(parser, 0);
}
}
case Token_Type_Literal_Float:
case Token_Type_Literal_True:
case Token_Type_Literal_False:
- *next_insertion = (AstType *) parse_expression(parser);
+ *next_insertion = (AstType *) parse_expression(parser, 0);
next_insertion = NULL;
break;
}
if (parser->curr->type == '=') {
consume_token(parser);
- mem->initial_value = parse_expression(parser);
+ mem->initial_value = parse_expression(parser, 0);
}
expect_token(parser, ';');
if (parser->curr->type == '=' && curr_param.vararg_kind == VA_Kind_Not_VA) {
consume_token(parser);
- curr_param.default_value = parse_expression(parser);
+ curr_param.default_value = parse_expression(parser, 0);
}
bh_arr_push(func->params, curr_param);
while (parser->curr->type != '}') {
if (parser->hit_unexpected_token) return (AstFunction *) ofunc;
- AstTyped* o_node = parse_expression(parser);
+ AstTyped* o_node = parse_expression(parser, 0);
bh_arr_push(ofunc->overloads, o_node);
onyx_report_error(parser->curr->pos, "#add_overload cannot be placed on procedures inside of other scopes");
}
- func_def->overloaded_function = (AstNode *) parse_expression(parser);
+ func_def->overloaded_function = (AstNode *) parse_expression(parser, 0);
}
}
return (AstTyped *) parse_enum_declaration(parser);
}
else {
- return parse_expression(parser);
+ return parse_expression(parser, 1);
}
}
if (parser->curr->type == '=') {
consume_token(parser);
- memres->initial_value = parse_expression(parser);
+ memres->initial_value = parse_expression(parser, 1);
} else {
memres->type_node = parse_type(parser);
if (parser->curr->type == '=') {
consume_token(parser);
- memres->initial_value = parse_expression(parser);
+ memres->initial_value = parse_expression(parser, 1);
}
}