diff --git a/lang/ast/expr/arith.c b/lang/ast/expr/arith.c index 179529d..0934921 100644 --- a/lang/ast/expr/arith.c +++ b/lang/ast/expr/arith.c @@ -7,6 +7,7 @@ #include #include #include +#include static void print_operand(struct ivy_ast_node *node) { @@ -448,6 +449,33 @@ struct token_parse_result arith_parse_operand( return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } + if (state->s_sub_type == EXPR_SUBTYPE_COMPLEX_MSG) { + /* this is an unlabeled complex message arg */ + if (state->s_prev_token != IVY_SYM_COMMA + && state->s_prev_token != IVY_SYM_LEFT_PAREN) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + struct ivy_token *empty_label = malloc(sizeof *empty_label); + if (!empty_label) { + return PARSE_RESULT(IVY_ERR_NO_MEMORY, 0); + } + memset(empty_label, 0x0, sizeof *empty_label); + empty_label->t_type = IVY_TOK_LABEL; + + b_queue_push_back(&state->s_labels, &empty_label->t_entry); + + struct expr_parser_state *arg_expr + = (struct expr_parser_state *)parser_push_state( + ctx, IVY_AST_EXPR, 0); + expr_copy_terminators(state, arg_expr); + expr_add_terminator(arg_expr, IVY_SYM_COMMA); + arg_expr->s_sub_type = EXPR_SUBTYPE_COMPLEX_ARG; + arg_expr->s_subexpr_depth = state->s_subexpr_depth + 1; + + return PARSE_RESULT(IVY_OK, PARSE_REPEAT_TOKEN); + } + if (state->s_prev_component == EXPR_CMP_OPERAND) { return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } @@ -623,11 +651,14 @@ struct token_parse_result arith_parse_left_paren( = (struct expr_parser_state *)parser_push_state( ctx, IVY_AST_EXPR, 0); + expr_add_terminator(msg_expr, IVY_SYM_COMMA); msg_expr->s_msg = (struct ivy_ast_msg_node *)msg; msg_expr->s_sub_type = EXPR_SUBTYPE_COMPLEX_MSG; msg_expr->s_type = EXPR_TYPE_ARITH; msg_expr->s_subexpr_depth = state->s_subexpr_depth + 1; + msg_expr->s_prev_token = state->s_prev_token = IVY_SYM_LEFT_PAREN; + return PARSE_RESULT(IVY_OK, 0); } @@ -648,6 +679,8 @@ not_complex_msg: msg_expr->s_type = EXPR_TYPE_ARITH; msg_expr->s_subexpr_depth = state->s_subexpr_depth + 1; + msg_expr->s_prev_token = state->s_prev_token = IVY_SYM_LEFT_PAREN; + return PARSE_RESULT(IVY_OK, 0); } @@ -974,6 +1007,7 @@ struct token_parse_result arith_parse_semicolon( break; case EXPR_SUBTYPE_KEYWORD_MSG: case EXPR_SUBTYPE_CASCADE: + case EXPR_SUBTYPE_COMPLEX_ARG: case EXPR_SUBTYPE_NONE: break; default: @@ -1217,6 +1251,12 @@ struct token_parse_result arith_parse_comma( struct expr_parser_state *state = parser_get_state(ctx, struct expr_parser_state); + if (state->s_sub_type == EXPR_SUBTYPE_COMPLEX_MSG) { + /* this is a comma separator between two complex message args */ + state->s_prev_token = IVY_SYM_COMMA; + return PARSE_RESULT(IVY_OK, 0); + } + if (expr_terminates_at_token(state, IVY_SYM_COMMA)) { struct token_parse_result result = expr_finalise_and_return(ctx, state); @@ -1348,8 +1388,23 @@ struct token_parse_result arith_parse_label( state = msg_expr; } - if (state->s_sub_type == EXPR_SUBTYPE_KEYWORD_MSG - || state->s_sub_type == EXPR_SUBTYPE_COMPLEX_MSG) { + if (state->s_sub_type == EXPR_SUBTYPE_COMPLEX_MSG) { + /* this label denotes the start of a complex message arg */ + if (state->s_prev_token != IVY_SYM_COMMA + && state->s_prev_token != IVY_SYM_LEFT_PAREN) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + b_queue_push_back(&state->s_labels, &tok->t_entry); + + struct expr_parser_state *arg_expr + = (struct expr_parser_state *)parser_push_state( + ctx, IVY_AST_EXPR, 0); + expr_copy_terminators(state, arg_expr); + expr_add_terminator(arg_expr, IVY_SYM_COMMA); + arg_expr->s_sub_type = EXPR_SUBTYPE_COMPLEX_ARG; + arg_expr->s_subexpr_depth = state->s_subexpr_depth + 1; + } else if (state->s_sub_type == EXPR_SUBTYPE_KEYWORD_MSG) { /* we may have just finished parsing a keyword-message argument, * and this label marks the start of a new one. store the label * and create a new argument parsing context. */ diff --git a/lang/ast/expr/expr.h b/lang/ast/expr/expr.h index c8c725e..b71861a 100644 --- a/lang/ast/expr/expr.h +++ b/lang/ast/expr/expr.h @@ -33,6 +33,8 @@ enum expr_subtype { EXPR_SUBTYPE_KEYWORD_ARG, /* complex messages */ EXPR_SUBTYPE_COMPLEX_MSG, + /* expression delimited by commas */ + EXPR_SUBTYPE_COMPLEX_ARG, /* message cascade operation */ EXPR_SUBTYPE_CASCADE, };