@@ -12945,6 +12945,32 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
1294512945 }
1294612946}
1294712947
12948+ /**
12949+ * Certain expressions are not writable, but in order to provide a better
12950+ * experience we give a specific error message. In order to maintain as much
12951+ * information in the tree as possible, we replace them with local variable
12952+ * writes.
12953+ */
12954+ static pm_node_t *
12955+ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t *equals, pm_node_t *value) {
12956+ switch (PM_NODE_TYPE(target)) {
12957+ case PM_SOURCE_ENCODING_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_ENCODING); break;
12958+ case PM_FALSE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_FALSE); break;
12959+ case PM_SOURCE_FILE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_FILE); break;
12960+ case PM_SOURCE_LINE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_LINE); break;
12961+ case PM_NIL_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_NIL); break;
12962+ case PM_SELF_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_SELF); break;
12963+ case PM_TRUE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_TRUE); break;
12964+ default: break;
12965+ }
12966+
12967+ pm_constant_id_t name = pm_parser_constant_id_location(parser, target->location.start, target->location.end);
12968+ pm_local_variable_write_node_t *result = pm_local_variable_write_node_create(parser, name, 0, value, &target->location, equals);
12969+
12970+ pm_node_destroy(parser, target);
12971+ return (pm_node_t *) result;
12972+ }
12973+
1294812974/**
1294912975 * Parse a list of targets for assignment. This is used in the case of a for
1295012976 * loop or a multi-assignment. For example, in the following code:
@@ -19357,13 +19383,25 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
1935719383 pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
1935819384 return parse_write(parser, (pm_node_t *) multi_target, &token, value);
1935919385 }
19386+ case PM_SOURCE_ENCODING_NODE:
19387+ case PM_FALSE_NODE:
19388+ case PM_SOURCE_FILE_NODE:
19389+ case PM_SOURCE_LINE_NODE:
19390+ case PM_NIL_NODE:
19391+ case PM_SELF_NODE:
19392+ case PM_TRUE_NODE: {
19393+ // In these special cases, we have specific error messages
19394+ // and we will replace them with local variable writes.
19395+ parser_lex(parser);
19396+ pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
19397+ return parse_unwriteable_write(parser, node, &token, value);
19398+ }
1936019399 default:
19400+ // In this case we have an = sign, but we don't know what
19401+ // it's for. We need to treat it as an error. We'll mark it
19402+ // as an error and skip past it.
1936119403 parser_lex(parser);
19362-
19363- // In this case we have an = sign, but we don't know what it's for. We
19364- // need to treat it as an error. For now, we'll mark it as an error
19365- // and just skip right past it.
19366- pm_parser_err_token(parser, &token, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
19404+ pm_parser_err_token(parser, &token, PM_ERR_EXPRESSION_NOT_WRITABLE);
1936719405 return node;
1936819406 }
1936919407 }
0 commit comments