yarp 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -0
- data/CONTRIBUTING.md +4 -0
- data/{Makefile.in → Makefile} +5 -4
- data/README.md +6 -3
- data/config.yml +83 -274
- data/docs/build_system.md +4 -15
- data/docs/building.md +1 -5
- data/docs/encoding.md +1 -0
- data/docs/{extension.md → ruby_api.md} +6 -3
- data/docs/serialization.md +71 -24
- data/ext/yarp/api_node.c +173 -585
- data/ext/yarp/extconf.rb +15 -10
- data/ext/yarp/extension.c +4 -2
- data/ext/yarp/extension.h +1 -1
- data/include/yarp/ast.h +167 -306
- data/include/yarp/defines.h +5 -15
- data/include/yarp/enc/yp_encoding.h +1 -0
- data/include/yarp/unescape.h +1 -1
- data/include/yarp/util/yp_buffer.h +9 -0
- data/include/yarp/util/yp_constant_pool.h +3 -0
- data/include/yarp/util/yp_list.h +7 -7
- data/include/yarp/util/yp_newline_list.h +4 -0
- data/include/yarp/util/yp_state_stack.h +1 -1
- data/include/yarp/util/yp_string.h +5 -1
- data/include/yarp/version.h +2 -3
- data/include/yarp.h +4 -2
- data/lib/yarp/ffi.rb +226 -0
- data/lib/yarp/lex_compat.rb +16 -2
- data/lib/yarp/node.rb +594 -1437
- data/lib/yarp/ripper_compat.rb +3 -3
- data/lib/yarp/serialize.rb +312 -149
- data/lib/yarp.rb +167 -2
- data/src/enc/yp_unicode.c +9 -0
- data/src/node.c +92 -250
- data/src/prettyprint.c +81 -206
- data/src/serialize.c +124 -149
- data/src/unescape.c +29 -35
- data/src/util/yp_buffer.c +18 -0
- data/src/util/yp_list.c +7 -16
- data/src/util/yp_state_stack.c +0 -6
- data/src/util/yp_string.c +8 -17
- data/src/yarp.c +444 -717
- data/yarp.gemspec +5 -5
- metadata +6 -6
- data/config.h.in +0 -25
- data/configure +0 -4487
data/src/yarp.c
CHANGED
@@ -431,6 +431,53 @@ yp_parser_constant_id_token(yp_parser_t *parser, const yp_token_t *token) {
|
|
431
431
|
return yp_parser_constant_id_location(parser, token->start, token->end);
|
432
432
|
}
|
433
433
|
|
434
|
+
// Mark any range nodes in this subtree as flipflops.
|
435
|
+
static void
|
436
|
+
yp_flip_flop(yp_node_t *node) {
|
437
|
+
switch (YP_NODE_TYPE(node)) {
|
438
|
+
case YP_NODE_AND_NODE: {
|
439
|
+
yp_and_node_t *cast = (yp_and_node_t *) node;
|
440
|
+
yp_flip_flop(cast->left);
|
441
|
+
yp_flip_flop(cast->right);
|
442
|
+
break;
|
443
|
+
}
|
444
|
+
case YP_NODE_OR_NODE: {
|
445
|
+
yp_or_node_t *cast = (yp_or_node_t *) node;
|
446
|
+
yp_flip_flop(cast->left);
|
447
|
+
yp_flip_flop(cast->right);
|
448
|
+
break;
|
449
|
+
}
|
450
|
+
case YP_NODE_PARENTHESES_NODE: {
|
451
|
+
yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node;
|
452
|
+
|
453
|
+
if ((cast->body != NULL) && YP_NODE_TYPE_P(cast->body, YP_NODE_STATEMENTS_NODE)) {
|
454
|
+
yp_statements_node_t *statements = (yp_statements_node_t *) cast->body;
|
455
|
+
if (statements->body.size == 1) yp_flip_flop(statements->body.nodes[0]);
|
456
|
+
}
|
457
|
+
|
458
|
+
break;
|
459
|
+
}
|
460
|
+
case YP_NODE_RANGE_NODE: {
|
461
|
+
yp_range_node_t *cast = (yp_range_node_t *) node;
|
462
|
+
if (cast->left) {
|
463
|
+
yp_flip_flop(cast->left);
|
464
|
+
}
|
465
|
+
if (cast->right) {
|
466
|
+
yp_flip_flop(cast->right);
|
467
|
+
}
|
468
|
+
|
469
|
+
// Here we change the range node into a flip flop node. We can do
|
470
|
+
// this since the nodes are exactly the same except for the type.
|
471
|
+
assert(sizeof(yp_range_node_t) == sizeof(yp_flip_flop_node_t));
|
472
|
+
node->type = YP_NODE_FLIP_FLOP_NODE;
|
473
|
+
|
474
|
+
break;
|
475
|
+
}
|
476
|
+
default:
|
477
|
+
break;
|
478
|
+
}
|
479
|
+
}
|
480
|
+
|
434
481
|
// In a lot of places in the tree you can have tokens that are not provided but
|
435
482
|
// that do not cause an error. For example, in a method call without
|
436
483
|
// parentheses. In these cases we set the token to the "not provided" type. For
|
@@ -461,18 +508,42 @@ typedef struct {
|
|
461
508
|
yp_arguments_node_t *arguments;
|
462
509
|
yp_location_t closing_loc;
|
463
510
|
yp_block_node_t *block;
|
511
|
+
|
512
|
+
// This boolean is used to tell if there is an implicit block (i.e., an
|
513
|
+
// argument passed with an & operator).
|
514
|
+
bool implicit_block;
|
464
515
|
} yp_arguments_t;
|
465
516
|
|
466
|
-
#define YP_EMPTY_ARGUMENTS ((yp_arguments_t) {
|
517
|
+
#define YP_EMPTY_ARGUMENTS ((yp_arguments_t) { \
|
518
|
+
.opening_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, \
|
519
|
+
.arguments = NULL, \
|
520
|
+
.closing_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, \
|
521
|
+
.block = NULL, \
|
522
|
+
.implicit_block = false \
|
523
|
+
})
|
524
|
+
|
525
|
+
// Check that the set of arguments parsed for a given node is valid. This means
|
526
|
+
// checking that we don't have both an implicit and explicit block.
|
527
|
+
static void
|
528
|
+
yp_arguments_validate(yp_parser_t *parser, yp_arguments_t *arguments) {
|
529
|
+
if (arguments->block != NULL && arguments->implicit_block) {
|
530
|
+
yp_diagnostic_list_append(
|
531
|
+
&parser->error_list,
|
532
|
+
arguments->block->base.location.start,
|
533
|
+
arguments->block->base.location.end,
|
534
|
+
"both block arg and actual block given"
|
535
|
+
);
|
536
|
+
}
|
537
|
+
}
|
467
538
|
|
468
539
|
/******************************************************************************/
|
469
540
|
/* Node creation functions */
|
470
541
|
/******************************************************************************/
|
471
542
|
|
472
543
|
// Parse out the options for a regular expression.
|
473
|
-
static inline
|
544
|
+
static inline yp_node_flags_t
|
474
545
|
yp_regular_expression_flags_create(const yp_token_t *closing) {
|
475
|
-
|
546
|
+
yp_node_flags_t flags = 0;
|
476
547
|
|
477
548
|
if (closing->type == YP_TOKEN_REGEXP_END) {
|
478
549
|
for (const char *flag = closing->start + 1; flag < closing->end; flag++) {
|
@@ -587,6 +658,27 @@ yp_and_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *opera
|
|
587
658
|
return node;
|
588
659
|
}
|
589
660
|
|
661
|
+
// Allocate and initialize a new AndWriteNode.
|
662
|
+
static yp_and_write_node_t *
|
663
|
+
yp_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
664
|
+
yp_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_and_write_node_t);
|
665
|
+
|
666
|
+
*node = (yp_and_write_node_t) {
|
667
|
+
{
|
668
|
+
.type = YP_NODE_AND_WRITE_NODE,
|
669
|
+
.location = {
|
670
|
+
.start = target->location.start,
|
671
|
+
.end = value->location.end
|
672
|
+
},
|
673
|
+
},
|
674
|
+
.target = target,
|
675
|
+
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
676
|
+
.value = value
|
677
|
+
};
|
678
|
+
|
679
|
+
return node;
|
680
|
+
}
|
681
|
+
|
590
682
|
// Allocate an initialize a new arguments node.
|
591
683
|
static yp_arguments_node_t *
|
592
684
|
yp_arguments_node_create(yp_parser_t *parser) {
|
@@ -926,7 +1018,7 @@ yp_block_argument_node_create(yp_parser_t *parser, const yp_token_t *operator, y
|
|
926
1018
|
|
927
1019
|
// Allocate and initialize a new BlockNode node.
|
928
1020
|
static yp_block_node_t *
|
929
|
-
yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *opening, yp_block_parameters_node_t *parameters, yp_node_t *
|
1021
|
+
yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *opening, yp_block_parameters_node_t *parameters, yp_node_t *body, const yp_token_t *closing) {
|
930
1022
|
yp_block_node_t *node = YP_ALLOC_NODE(parser, yp_block_node_t);
|
931
1023
|
|
932
1024
|
*node = (yp_block_node_t) {
|
@@ -936,7 +1028,7 @@ yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y
|
|
936
1028
|
},
|
937
1029
|
.locals = *locals,
|
938
1030
|
.parameters = parameters,
|
939
|
-
.
|
1031
|
+
.body = body,
|
940
1032
|
.opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
|
941
1033
|
.closing_loc = YP_LOCATION_TOKEN_VALUE(closing)
|
942
1034
|
};
|
@@ -1063,8 +1155,7 @@ yp_call_node_create(yp_parser_t *parser) {
|
|
1063
1155
|
.opening_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
|
1064
1156
|
.arguments = NULL,
|
1065
1157
|
.closing_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
|
1066
|
-
.block = NULL
|
1067
|
-
.flags = 0
|
1158
|
+
.block = NULL
|
1068
1159
|
};
|
1069
1160
|
|
1070
1161
|
return node;
|
@@ -1140,7 +1231,7 @@ yp_call_node_call_create(yp_parser_t *parser, yp_node_t *receiver, yp_token_t *o
|
|
1140
1231
|
node->block = arguments->block;
|
1141
1232
|
|
1142
1233
|
if (operator->type == YP_TOKEN_AMPERSAND_DOT) {
|
1143
|
-
node->flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION;
|
1234
|
+
node->base.flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION;
|
1144
1235
|
}
|
1145
1236
|
|
1146
1237
|
yp_string_shared_init(&node->name, message->start, message->end);
|
@@ -1216,7 +1307,7 @@ yp_call_node_shorthand_create(yp_parser_t *parser, yp_node_t *receiver, yp_token
|
|
1216
1307
|
node->block = arguments->block;
|
1217
1308
|
|
1218
1309
|
if (operator->type == YP_TOKEN_AMPERSAND_DOT) {
|
1219
|
-
node->flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION;
|
1310
|
+
node->base.flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION;
|
1220
1311
|
}
|
1221
1312
|
|
1222
1313
|
yp_string_constant_init(&node->name, "call", 4);
|
@@ -1257,7 +1348,7 @@ yp_call_node_variable_call_create(yp_parser_t *parser, yp_token_t *message) {
|
|
1257
1348
|
// without a receiver that could also have been a local variable read).
|
1258
1349
|
static inline bool
|
1259
1350
|
yp_call_node_variable_call_p(yp_call_node_t *node) {
|
1260
|
-
return node->flags & YP_CALL_NODE_FLAGS_VARIABLE_CALL;
|
1351
|
+
return node->base.flags & YP_CALL_NODE_FLAGS_VARIABLE_CALL;
|
1261
1352
|
}
|
1262
1353
|
|
1263
1354
|
// Allocate and initialize a new CallOperatorAndWriteNode node.
|
@@ -1395,7 +1486,7 @@ yp_case_node_end_keyword_loc_set(yp_case_node_t *node, const yp_token_t *end_key
|
|
1395
1486
|
|
1396
1487
|
// Allocate a new ClassNode node.
|
1397
1488
|
static yp_class_node_t *
|
1398
|
-
yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *
|
1489
|
+
yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *body, const yp_token_t *end_keyword) {
|
1399
1490
|
yp_class_node_t *node = YP_ALLOC_NODE(parser, yp_class_node_t);
|
1400
1491
|
|
1401
1492
|
*node = (yp_class_node_t) {
|
@@ -1408,81 +1499,13 @@ yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y
|
|
1408
1499
|
.constant_path = constant_path,
|
1409
1500
|
.inheritance_operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(inheritance_operator),
|
1410
1501
|
.superclass = superclass,
|
1411
|
-
.
|
1502
|
+
.body = body,
|
1412
1503
|
.end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
|
1413
1504
|
};
|
1414
1505
|
|
1415
1506
|
return node;
|
1416
1507
|
}
|
1417
1508
|
|
1418
|
-
// Allocate and initialize a new ClassVariableOperatorAndWriteNode node.
|
1419
|
-
static yp_class_variable_operator_and_write_node_t *
|
1420
|
-
yp_class_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1421
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE));
|
1422
|
-
assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
|
1423
|
-
yp_class_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_and_write_node_t);
|
1424
|
-
|
1425
|
-
*node = (yp_class_variable_operator_and_write_node_t) {
|
1426
|
-
{
|
1427
|
-
.type = YP_NODE_CLASS_VARIABLE_OPERATOR_AND_WRITE_NODE,
|
1428
|
-
.location = {
|
1429
|
-
.start = target->location.start,
|
1430
|
-
.end = value->location.end
|
1431
|
-
}
|
1432
|
-
},
|
1433
|
-
.name_loc = target->location,
|
1434
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1435
|
-
.value = value
|
1436
|
-
};
|
1437
|
-
|
1438
|
-
return node;
|
1439
|
-
}
|
1440
|
-
|
1441
|
-
// Allocate and initialize a new ClassVariableOperatorWriteNode node.
|
1442
|
-
static yp_class_variable_operator_write_node_t *
|
1443
|
-
yp_class_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1444
|
-
yp_class_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_write_node_t);
|
1445
|
-
|
1446
|
-
*node = (yp_class_variable_operator_write_node_t) {
|
1447
|
-
{
|
1448
|
-
.type = YP_NODE_CLASS_VARIABLE_OPERATOR_WRITE_NODE,
|
1449
|
-
.location = {
|
1450
|
-
.start = target->location.start,
|
1451
|
-
.end = value->location.end
|
1452
|
-
}
|
1453
|
-
},
|
1454
|
-
.name_loc = target->location,
|
1455
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1456
|
-
.value = value,
|
1457
|
-
.operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
|
1458
|
-
};
|
1459
|
-
|
1460
|
-
return node;
|
1461
|
-
}
|
1462
|
-
|
1463
|
-
// Allocate and initialize a new ClassVariableOperatorOrWriteNode node.
|
1464
|
-
static yp_class_variable_operator_or_write_node_t *
|
1465
|
-
yp_class_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1466
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE));
|
1467
|
-
assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
|
1468
|
-
yp_class_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_or_write_node_t);
|
1469
|
-
|
1470
|
-
*node = (yp_class_variable_operator_or_write_node_t) {
|
1471
|
-
{
|
1472
|
-
.type = YP_NODE_CLASS_VARIABLE_OPERATOR_OR_WRITE_NODE,
|
1473
|
-
.location = {
|
1474
|
-
.start = target->location.start,
|
1475
|
-
.end = value->location.end
|
1476
|
-
}
|
1477
|
-
},
|
1478
|
-
.name_loc = target->location,
|
1479
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1480
|
-
.value = value
|
1481
|
-
};
|
1482
|
-
|
1483
|
-
return node;
|
1484
|
-
}
|
1485
|
-
|
1486
1509
|
// Allocate and initialize a new ClassVariableReadNode node.
|
1487
1510
|
static yp_class_variable_read_node_t *
|
1488
1511
|
yp_class_variable_read_node_create(yp_parser_t *parser, const yp_token_t *token) {
|
@@ -1513,72 +1536,6 @@ yp_class_variable_read_node_to_class_variable_write_node(yp_parser_t *parser, yp
|
|
1513
1536
|
return node;
|
1514
1537
|
}
|
1515
1538
|
|
1516
|
-
// Allocate and initialize a new ConstantPathOperatorAndWriteNode node.
|
1517
|
-
static yp_constant_path_operator_and_write_node_t *
|
1518
|
-
yp_constant_path_operator_and_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1519
|
-
assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
|
1520
|
-
yp_constant_path_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_and_write_node_t);
|
1521
|
-
|
1522
|
-
*node = (yp_constant_path_operator_and_write_node_t) {
|
1523
|
-
{
|
1524
|
-
.type = YP_NODE_CONSTANT_PATH_OPERATOR_AND_WRITE_NODE,
|
1525
|
-
.location = {
|
1526
|
-
.start = target->base.location.start,
|
1527
|
-
.end = value->location.end
|
1528
|
-
}
|
1529
|
-
},
|
1530
|
-
.target = target,
|
1531
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1532
|
-
.value = value
|
1533
|
-
};
|
1534
|
-
|
1535
|
-
return node;
|
1536
|
-
}
|
1537
|
-
|
1538
|
-
// Allocate and initialize a new ConstantPathOperatorWriteNode node.
|
1539
|
-
static yp_constant_path_operator_write_node_t *
|
1540
|
-
yp_constant_path_operator_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1541
|
-
yp_constant_path_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_write_node_t);
|
1542
|
-
|
1543
|
-
*node = (yp_constant_path_operator_write_node_t) {
|
1544
|
-
{
|
1545
|
-
.type = YP_NODE_CONSTANT_PATH_OPERATOR_WRITE_NODE,
|
1546
|
-
.location = {
|
1547
|
-
.start = target->base.location.start,
|
1548
|
-
.end = value->location.end
|
1549
|
-
}
|
1550
|
-
},
|
1551
|
-
.target = target,
|
1552
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1553
|
-
.value = value,
|
1554
|
-
.operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
|
1555
|
-
};
|
1556
|
-
|
1557
|
-
return node;
|
1558
|
-
}
|
1559
|
-
|
1560
|
-
// Allocate and initialize a new ConstantPathOperatorOrWriteNode node.
|
1561
|
-
static yp_constant_path_operator_or_write_node_t *
|
1562
|
-
yp_constant_path_operator_or_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1563
|
-
assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
|
1564
|
-
yp_constant_path_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_or_write_node_t);
|
1565
|
-
|
1566
|
-
*node = (yp_constant_path_operator_or_write_node_t) {
|
1567
|
-
{
|
1568
|
-
.type = YP_NODE_CONSTANT_PATH_OPERATOR_OR_WRITE_NODE,
|
1569
|
-
.location = {
|
1570
|
-
.start = target->base.location.start,
|
1571
|
-
.end = value->location.end
|
1572
|
-
}
|
1573
|
-
},
|
1574
|
-
.target = target,
|
1575
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1576
|
-
.value = value
|
1577
|
-
};
|
1578
|
-
|
1579
|
-
return node;
|
1580
|
-
}
|
1581
|
-
|
1582
1539
|
// Allocate and initialize a new ConstantPathNode node.
|
1583
1540
|
static yp_constant_path_node_t *
|
1584
1541
|
yp_constant_path_node_create(yp_parser_t *parser, yp_node_t *parent, const yp_token_t *delimiter, yp_node_t *child) {
|
@@ -1621,74 +1578,6 @@ yp_constant_path_write_node_create(yp_parser_t *parser, yp_constant_path_node_t
|
|
1621
1578
|
return node;
|
1622
1579
|
}
|
1623
1580
|
|
1624
|
-
// Allocate and initialize a new ConstantOperatorAndWriteNode node.
|
1625
|
-
static yp_constant_operator_and_write_node_t *
|
1626
|
-
yp_constant_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1627
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE));
|
1628
|
-
assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
|
1629
|
-
yp_constant_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_and_write_node_t);
|
1630
|
-
|
1631
|
-
*node = (yp_constant_operator_and_write_node_t) {
|
1632
|
-
{
|
1633
|
-
.type = YP_NODE_CONSTANT_OPERATOR_AND_WRITE_NODE,
|
1634
|
-
.location = {
|
1635
|
-
.start = target->location.start,
|
1636
|
-
.end = value->location.end
|
1637
|
-
}
|
1638
|
-
},
|
1639
|
-
.name_loc = target->location,
|
1640
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1641
|
-
.value = value
|
1642
|
-
};
|
1643
|
-
|
1644
|
-
return node;
|
1645
|
-
}
|
1646
|
-
|
1647
|
-
// Allocate and initialize a new ConstantOperatorWriteNode node.
|
1648
|
-
static yp_constant_operator_write_node_t *
|
1649
|
-
yp_constant_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1650
|
-
yp_constant_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_write_node_t);
|
1651
|
-
|
1652
|
-
*node = (yp_constant_operator_write_node_t) {
|
1653
|
-
{
|
1654
|
-
.type = YP_NODE_CONSTANT_OPERATOR_WRITE_NODE,
|
1655
|
-
.location = {
|
1656
|
-
.start = target->location.start,
|
1657
|
-
.end = value->location.end
|
1658
|
-
}
|
1659
|
-
},
|
1660
|
-
.name_loc = target->location,
|
1661
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1662
|
-
.value = value,
|
1663
|
-
.operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
|
1664
|
-
};
|
1665
|
-
|
1666
|
-
return node;
|
1667
|
-
}
|
1668
|
-
|
1669
|
-
// Allocate and initialize a new ConstantOperatorOrWriteNode node.
|
1670
|
-
static yp_constant_operator_or_write_node_t *
|
1671
|
-
yp_constant_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
1672
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE));
|
1673
|
-
assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
|
1674
|
-
yp_constant_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_or_write_node_t);
|
1675
|
-
|
1676
|
-
*node = (yp_constant_operator_or_write_node_t) {
|
1677
|
-
{
|
1678
|
-
.type = YP_NODE_CONSTANT_OPERATOR_OR_WRITE_NODE,
|
1679
|
-
.location = {
|
1680
|
-
.start = target->location.start,
|
1681
|
-
.end = value->location.end
|
1682
|
-
}
|
1683
|
-
},
|
1684
|
-
.name_loc = target->location,
|
1685
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
1686
|
-
.value = value
|
1687
|
-
};
|
1688
|
-
|
1689
|
-
return node;
|
1690
|
-
}
|
1691
|
-
|
1692
1581
|
// Allocate and initialize a new ConstantReadNode node.
|
1693
1582
|
static yp_constant_read_node_t *
|
1694
1583
|
yp_constant_read_node_create(yp_parser_t *parser, const yp_token_t *name) {
|
@@ -1727,7 +1616,7 @@ yp_def_node_create(
|
|
1727
1616
|
const yp_token_t *name,
|
1728
1617
|
yp_node_t *receiver,
|
1729
1618
|
yp_parameters_node_t *parameters,
|
1730
|
-
yp_node_t *
|
1619
|
+
yp_node_t *body,
|
1731
1620
|
yp_constant_id_list_t *locals,
|
1732
1621
|
const yp_token_t *def_keyword,
|
1733
1622
|
const yp_token_t *operator,
|
@@ -1740,7 +1629,7 @@ yp_def_node_create(
|
|
1740
1629
|
const char *end;
|
1741
1630
|
|
1742
1631
|
if (end_keyword->type == YP_TOKEN_NOT_PROVIDED) {
|
1743
|
-
end =
|
1632
|
+
end = body->location.end;
|
1744
1633
|
} else {
|
1745
1634
|
end = end_keyword->end;
|
1746
1635
|
}
|
@@ -1753,7 +1642,7 @@ yp_def_node_create(
|
|
1753
1642
|
.name_loc = YP_LOCATION_TOKEN_VALUE(name),
|
1754
1643
|
.receiver = receiver,
|
1755
1644
|
.parameters = parameters,
|
1756
|
-
.
|
1645
|
+
.body = body,
|
1757
1646
|
.locals = *locals,
|
1758
1647
|
.def_keyword_loc = YP_LOCATION_TOKEN_VALUE(def_keyword),
|
1759
1648
|
.operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
|
@@ -2123,74 +2012,6 @@ yp_hash_pattern_node_node_list_create(yp_parser_t *parser, yp_node_list_t *assoc
|
|
2123
2012
|
return node;
|
2124
2013
|
}
|
2125
2014
|
|
2126
|
-
// Allocate and initialize a new GlobalVariableOperatorAndWriteNode node.
|
2127
|
-
static yp_global_variable_operator_and_write_node_t *
|
2128
|
-
yp_global_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2129
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE));
|
2130
|
-
assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
|
2131
|
-
yp_global_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_and_write_node_t);
|
2132
|
-
|
2133
|
-
*node = (yp_global_variable_operator_and_write_node_t) {
|
2134
|
-
{
|
2135
|
-
.type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE,
|
2136
|
-
.location = {
|
2137
|
-
.start = target->location.start,
|
2138
|
-
.end = value->location.end
|
2139
|
-
}
|
2140
|
-
},
|
2141
|
-
.name_loc = target->location,
|
2142
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2143
|
-
.value = value
|
2144
|
-
};
|
2145
|
-
|
2146
|
-
return node;
|
2147
|
-
}
|
2148
|
-
|
2149
|
-
// Allocate and initialize a new GlobalVariableOperatorWriteNode node.
|
2150
|
-
static yp_global_variable_operator_write_node_t *
|
2151
|
-
yp_global_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2152
|
-
yp_global_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_write_node_t);
|
2153
|
-
|
2154
|
-
*node = (yp_global_variable_operator_write_node_t) {
|
2155
|
-
{
|
2156
|
-
.type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE,
|
2157
|
-
.location = {
|
2158
|
-
.start = target->location.start,
|
2159
|
-
.end = value->location.end
|
2160
|
-
}
|
2161
|
-
},
|
2162
|
-
.name_loc = target->location,
|
2163
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2164
|
-
.value = value,
|
2165
|
-
.operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
|
2166
|
-
};
|
2167
|
-
|
2168
|
-
return node;
|
2169
|
-
}
|
2170
|
-
|
2171
|
-
// Allocate and initialize a new GlobalVariableOperatorOrWriteNode node.
|
2172
|
-
static yp_global_variable_operator_or_write_node_t *
|
2173
|
-
yp_global_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2174
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE));
|
2175
|
-
assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
|
2176
|
-
yp_global_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_or_write_node_t);
|
2177
|
-
|
2178
|
-
*node = (yp_global_variable_operator_or_write_node_t) {
|
2179
|
-
{
|
2180
|
-
.type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE,
|
2181
|
-
.location = {
|
2182
|
-
.start = target->location.start,
|
2183
|
-
.end = value->location.end
|
2184
|
-
}
|
2185
|
-
},
|
2186
|
-
.name_loc = target->location,
|
2187
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2188
|
-
.value = value
|
2189
|
-
};
|
2190
|
-
|
2191
|
-
return node;
|
2192
|
-
}
|
2193
|
-
|
2194
2015
|
// Allocate a new GlobalVariableReadNode node.
|
2195
2016
|
static yp_global_variable_read_node_t *
|
2196
2017
|
yp_global_variable_read_node_create(yp_parser_t *parser, const yp_token_t *name) {
|
@@ -2269,6 +2090,7 @@ yp_if_node_create(yp_parser_t *parser,
|
|
2269
2090
|
yp_node_t *consequent,
|
2270
2091
|
const yp_token_t *end_keyword
|
2271
2092
|
) {
|
2093
|
+
yp_flip_flop(predicate);
|
2272
2094
|
yp_if_node_t *node = YP_ALLOC_NODE(parser, yp_if_node_t);
|
2273
2095
|
|
2274
2096
|
const char *end;
|
@@ -2304,6 +2126,7 @@ yp_if_node_create(yp_parser_t *parser,
|
|
2304
2126
|
// Allocate and initialize new IfNode node in the modifier form.
|
2305
2127
|
static yp_if_node_t *
|
2306
2128
|
yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_token_t *if_keyword, yp_node_t *predicate) {
|
2129
|
+
yp_flip_flop(predicate);
|
2307
2130
|
yp_if_node_t *node = YP_ALLOC_NODE(parser, yp_if_node_t);
|
2308
2131
|
|
2309
2132
|
yp_statements_node_t *statements = yp_statements_node_create(parser);
|
@@ -2331,6 +2154,8 @@ yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_t
|
|
2331
2154
|
// Allocate and initialize an if node from a ternary expression.
|
2332
2155
|
static yp_if_node_t *
|
2333
2156
|
yp_if_node_ternary_create(yp_parser_t *parser, yp_node_t *predicate, yp_node_t *true_expression, const yp_token_t *colon, yp_node_t *false_expression) {
|
2157
|
+
yp_flip_flop(predicate);
|
2158
|
+
|
2334
2159
|
yp_statements_node_t *if_statements = yp_statements_node_create(parser);
|
2335
2160
|
yp_statements_node_body_append(if_statements, true_expression);
|
2336
2161
|
|
@@ -2477,74 +2302,6 @@ yp_in_node_create(yp_parser_t *parser, yp_node_t *pattern, yp_statements_node_t
|
|
2477
2302
|
return node;
|
2478
2303
|
}
|
2479
2304
|
|
2480
|
-
// Allocate and initialize a new InstanceVariableOperatorAndWriteNode node.
|
2481
|
-
static yp_instance_variable_operator_and_write_node_t *
|
2482
|
-
yp_instance_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2483
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE));
|
2484
|
-
assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
|
2485
|
-
yp_instance_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_and_write_node_t);
|
2486
|
-
|
2487
|
-
*node = (yp_instance_variable_operator_and_write_node_t) {
|
2488
|
-
{
|
2489
|
-
.type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE,
|
2490
|
-
.location = {
|
2491
|
-
.start = target->location.start,
|
2492
|
-
.end = value->location.end
|
2493
|
-
}
|
2494
|
-
},
|
2495
|
-
.name_loc = target->location,
|
2496
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2497
|
-
.value = value
|
2498
|
-
};
|
2499
|
-
|
2500
|
-
return node;
|
2501
|
-
}
|
2502
|
-
|
2503
|
-
// Allocate and initialize a new InstanceVariableOperatorWriteNode node.
|
2504
|
-
static yp_instance_variable_operator_write_node_t *
|
2505
|
-
yp_instance_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2506
|
-
yp_instance_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_write_node_t);
|
2507
|
-
|
2508
|
-
*node = (yp_instance_variable_operator_write_node_t) {
|
2509
|
-
{
|
2510
|
-
.type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE,
|
2511
|
-
.location = {
|
2512
|
-
.start = target->location.start,
|
2513
|
-
.end = value->location.end
|
2514
|
-
}
|
2515
|
-
},
|
2516
|
-
.name_loc = target->location,
|
2517
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2518
|
-
.value = value,
|
2519
|
-
.operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
|
2520
|
-
};
|
2521
|
-
|
2522
|
-
return node;
|
2523
|
-
}
|
2524
|
-
|
2525
|
-
// Allocate and initialize a new InstanceVariableOperatorOrWriteNode node.
|
2526
|
-
static yp_instance_variable_operator_or_write_node_t *
|
2527
|
-
yp_instance_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2528
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE));
|
2529
|
-
assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
|
2530
|
-
yp_instance_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_or_write_node_t);
|
2531
|
-
|
2532
|
-
*node = (yp_instance_variable_operator_or_write_node_t) {
|
2533
|
-
{
|
2534
|
-
.type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE,
|
2535
|
-
.location = {
|
2536
|
-
.start = target->location.start,
|
2537
|
-
.end = value->location.end
|
2538
|
-
}
|
2539
|
-
},
|
2540
|
-
.name_loc = target->location,
|
2541
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2542
|
-
.value = value
|
2543
|
-
};
|
2544
|
-
|
2545
|
-
return node;
|
2546
|
-
}
|
2547
|
-
|
2548
2305
|
// Allocate and initialize a new InstanceVariableReadNode node.
|
2549
2306
|
static yp_instance_variable_read_node_t *
|
2550
2307
|
yp_instance_variable_read_node_create(yp_parser_t *parser, const yp_token_t *token) {
|
@@ -2593,7 +2350,6 @@ yp_interpolated_regular_expression_node_create(yp_parser_t *parser, const yp_tok
|
|
2593
2350
|
},
|
2594
2351
|
.opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
|
2595
2352
|
.closing_loc = YP_LOCATION_TOKEN_VALUE(opening),
|
2596
|
-
.flags = 0,
|
2597
2353
|
.parts = YP_EMPTY_NODE_LIST
|
2598
2354
|
};
|
2599
2355
|
|
@@ -2610,7 +2366,7 @@ static inline void
|
|
2610
2366
|
yp_interpolated_regular_expression_node_closing_set(yp_interpolated_regular_expression_node_t *node, const yp_token_t *closing) {
|
2611
2367
|
node->closing_loc = YP_LOCATION_TOKEN_VALUE(closing);
|
2612
2368
|
node->base.location.end = closing->end;
|
2613
|
-
node->flags
|
2369
|
+
node->base.flags |= yp_regular_expression_flags_create(closing);
|
2614
2370
|
}
|
2615
2371
|
|
2616
2372
|
// Allocate and initialize a new InterpolatedStringNode node.
|
@@ -2637,6 +2393,10 @@ yp_interpolated_string_node_create(yp_parser_t *parser, const yp_token_t *openin
|
|
2637
2393
|
// Append a part to an InterpolatedStringNode node.
|
2638
2394
|
static inline void
|
2639
2395
|
yp_interpolated_string_node_append(yp_interpolated_string_node_t *node, yp_node_t *part) {
|
2396
|
+
if (node->parts.size == 0 && node->opening_loc.start == NULL) {
|
2397
|
+
node->base.location.start = part->location.start;
|
2398
|
+
}
|
2399
|
+
|
2640
2400
|
yp_node_list_append(&node->parts, part);
|
2641
2401
|
node->base.location.end = part->location.end;
|
2642
2402
|
}
|
@@ -2793,7 +2553,7 @@ yp_lambda_node_create(
|
|
2793
2553
|
yp_constant_id_list_t *locals,
|
2794
2554
|
const yp_token_t *opening,
|
2795
2555
|
yp_block_parameters_node_t *parameters,
|
2796
|
-
yp_node_t *
|
2556
|
+
yp_node_t *body,
|
2797
2557
|
const yp_token_t *closing
|
2798
2558
|
) {
|
2799
2559
|
yp_lambda_node_t *node = YP_ALLOC_NODE(parser, yp_lambda_node_t);
|
@@ -2807,80 +2567,9 @@ yp_lambda_node_create(
|
|
2807
2567
|
},
|
2808
2568
|
},
|
2809
2569
|
.locals = *locals,
|
2810
|
-
.opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
|
2811
|
-
.parameters = parameters,
|
2812
|
-
.
|
2813
|
-
};
|
2814
|
-
|
2815
|
-
return node;
|
2816
|
-
}
|
2817
|
-
|
2818
|
-
// Allocate and initialize a new LocalVariableOperatorAndWriteNode node.
|
2819
|
-
static yp_local_variable_operator_and_write_node_t *
|
2820
|
-
yp_local_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
|
2821
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE));
|
2822
|
-
assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
|
2823
|
-
yp_local_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_and_write_node_t);
|
2824
|
-
|
2825
|
-
*node = (yp_local_variable_operator_and_write_node_t) {
|
2826
|
-
{
|
2827
|
-
.type = YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE,
|
2828
|
-
.location = {
|
2829
|
-
.start = target->location.start,
|
2830
|
-
.end = value->location.end
|
2831
|
-
}
|
2832
|
-
},
|
2833
|
-
.name_loc = target->location,
|
2834
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2835
|
-
.value = value,
|
2836
|
-
.constant_id = constant_id
|
2837
|
-
};
|
2838
|
-
|
2839
|
-
return node;
|
2840
|
-
}
|
2841
|
-
|
2842
|
-
// Allocate and initialize a new LocalVariableOperatorWriteNode node.
|
2843
|
-
static yp_local_variable_operator_write_node_t *
|
2844
|
-
yp_local_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
|
2845
|
-
yp_local_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_write_node_t);
|
2846
|
-
|
2847
|
-
*node = (yp_local_variable_operator_write_node_t) {
|
2848
|
-
{
|
2849
|
-
.type = YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE,
|
2850
|
-
.location = {
|
2851
|
-
.start = target->location.start,
|
2852
|
-
.end = value->location.end
|
2853
|
-
}
|
2854
|
-
},
|
2855
|
-
.name_loc = target->location,
|
2856
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2857
|
-
.value = value,
|
2858
|
-
.constant_id = constant_id,
|
2859
|
-
.operator_id = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
|
2860
|
-
};
|
2861
|
-
|
2862
|
-
return node;
|
2863
|
-
}
|
2864
|
-
|
2865
|
-
// Allocate and initialize a new LocalVariableOperatorOrWriteNode node.
|
2866
|
-
static yp_local_variable_operator_or_write_node_t *
|
2867
|
-
yp_local_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
|
2868
|
-
assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE));
|
2869
|
-
assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
|
2870
|
-
yp_local_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_or_write_node_t);
|
2871
|
-
|
2872
|
-
*node = (yp_local_variable_operator_or_write_node_t) {
|
2873
|
-
{
|
2874
|
-
.type = YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE,
|
2875
|
-
.location = {
|
2876
|
-
.start = target->location.start,
|
2877
|
-
.end = value->location.end
|
2878
|
-
}
|
2879
|
-
},
|
2880
|
-
.name_loc = target->location,
|
2881
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2882
|
-
.value = value,
|
2883
|
-
.constant_id = constant_id
|
2570
|
+
.opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
|
2571
|
+
.parameters = parameters,
|
2572
|
+
.body = body
|
2884
2573
|
};
|
2885
2574
|
|
2886
2575
|
return node;
|
@@ -2990,7 +2679,7 @@ yp_match_required_node_create(yp_parser_t *parser, yp_node_t *value, yp_node_t *
|
|
2990
2679
|
|
2991
2680
|
// Allocate a new ModuleNode node.
|
2992
2681
|
static yp_module_node_t *
|
2993
|
-
yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, yp_node_t *
|
2682
|
+
yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, yp_node_t *body, const yp_token_t *end_keyword) {
|
2994
2683
|
yp_module_node_t *node = YP_ALLOC_NODE(parser, yp_module_node_t);
|
2995
2684
|
|
2996
2685
|
*node = (yp_module_node_t) {
|
@@ -3004,7 +2693,7 @@ yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const
|
|
3004
2693
|
.locals = (locals == NULL ? ((yp_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals),
|
3005
2694
|
.module_keyword_loc = YP_LOCATION_TOKEN_VALUE(module_keyword),
|
3006
2695
|
.constant_path = constant_path,
|
3007
|
-
.
|
2696
|
+
.body = body,
|
3008
2697
|
.end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
|
3009
2698
|
};
|
3010
2699
|
|
@@ -3119,6 +2808,28 @@ yp_numbered_reference_read_node_create(yp_parser_t *parser, const yp_token_t *na
|
|
3119
2808
|
return node;
|
3120
2809
|
}
|
3121
2810
|
|
2811
|
+
// Allocate and initialize a new OperatorWriteNode.
|
2812
|
+
static yp_operator_write_node_t *
|
2813
|
+
yp_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2814
|
+
yp_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_operator_write_node_t);
|
2815
|
+
|
2816
|
+
*node = (yp_operator_write_node_t) {
|
2817
|
+
{
|
2818
|
+
.type = YP_NODE_OPERATOR_WRITE_NODE,
|
2819
|
+
.location = {
|
2820
|
+
.start = target->location.start,
|
2821
|
+
.end = value->location.end
|
2822
|
+
},
|
2823
|
+
},
|
2824
|
+
.target = target,
|
2825
|
+
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2826
|
+
.operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1),
|
2827
|
+
.value = value
|
2828
|
+
};
|
2829
|
+
|
2830
|
+
return node;
|
2831
|
+
}
|
2832
|
+
|
3122
2833
|
// Allocate a new OptionalParameterNode node.
|
3123
2834
|
static yp_optional_parameter_node_t *
|
3124
2835
|
yp_optional_parameter_node_create(yp_parser_t *parser, const yp_token_t *name, const yp_token_t *operator, yp_node_t *value) {
|
@@ -3162,6 +2873,27 @@ yp_or_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *operat
|
|
3162
2873
|
return node;
|
3163
2874
|
}
|
3164
2875
|
|
2876
|
+
// Allocate and initialize a new OrWriteNode.
|
2877
|
+
static yp_or_write_node_t *
|
2878
|
+
yp_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
|
2879
|
+
yp_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_or_write_node_t);
|
2880
|
+
|
2881
|
+
*node = (yp_or_write_node_t) {
|
2882
|
+
{
|
2883
|
+
.type = YP_NODE_OR_WRITE_NODE,
|
2884
|
+
.location = {
|
2885
|
+
.start = target->location.start,
|
2886
|
+
.end = value->location.end
|
2887
|
+
},
|
2888
|
+
},
|
2889
|
+
.target = target,
|
2890
|
+
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
2891
|
+
.value = value
|
2892
|
+
};
|
2893
|
+
|
2894
|
+
return node;
|
2895
|
+
}
|
2896
|
+
|
3165
2897
|
// Allocate and initialize a new ParametersNode node.
|
3166
2898
|
static yp_parameters_node_t *
|
3167
2899
|
yp_parameters_node_create(yp_parser_t *parser) {
|
@@ -3274,7 +3006,7 @@ yp_program_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, yp_st
|
|
3274
3006
|
|
3275
3007
|
// Allocate and initialize new ParenthesesNode node.
|
3276
3008
|
static yp_parentheses_node_t *
|
3277
|
-
yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_node_t *
|
3009
|
+
yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_node_t *body, const yp_token_t *closing) {
|
3278
3010
|
yp_parentheses_node_t *node = YP_ALLOC_NODE(parser, yp_parentheses_node_t);
|
3279
3011
|
|
3280
3012
|
*node = (yp_parentheses_node_t) {
|
@@ -3285,7 +3017,7 @@ yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_no
|
|
3285
3017
|
.end = closing->end
|
3286
3018
|
}
|
3287
3019
|
},
|
3288
|
-
.
|
3020
|
+
.body = body,
|
3289
3021
|
.opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
|
3290
3022
|
.closing_loc = YP_LOCATION_TOKEN_VALUE(closing)
|
3291
3023
|
};
|
@@ -3394,14 +3126,13 @@ yp_range_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *ope
|
|
3394
3126
|
},
|
3395
3127
|
.left = left,
|
3396
3128
|
.right = right,
|
3397
|
-
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator)
|
3398
|
-
.flags = 0,
|
3129
|
+
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator)
|
3399
3130
|
};
|
3400
3131
|
|
3401
3132
|
switch (operator->type) {
|
3402
3133
|
case YP_TOKEN_DOT_DOT_DOT:
|
3403
3134
|
case YP_TOKEN_UDOT_DOT_DOT:
|
3404
|
-
node->flags |=
|
3135
|
+
node->base.flags |= YP_RANGE_FLAGS_EXCLUDE_END;
|
3405
3136
|
break;
|
3406
3137
|
default:
|
3407
3138
|
break;
|
@@ -3428,6 +3159,7 @@ yp_regular_expression_node_create(yp_parser_t *parser, const yp_token_t *opening
|
|
3428
3159
|
*node = (yp_regular_expression_node_t) {
|
3429
3160
|
{
|
3430
3161
|
.type = YP_NODE_REGULAR_EXPRESSION_NODE,
|
3162
|
+
.flags = yp_regular_expression_flags_create(closing),
|
3431
3163
|
.location = {
|
3432
3164
|
.start = opening->start,
|
3433
3165
|
.end = closing->end
|
@@ -3436,7 +3168,7 @@ yp_regular_expression_node_create(yp_parser_t *parser, const yp_token_t *opening
|
|
3436
3168
|
.opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
|
3437
3169
|
.content_loc = YP_LOCATION_TOKEN_VALUE(content),
|
3438
3170
|
.closing_loc = YP_LOCATION_TOKEN_VALUE(closing),
|
3439
|
-
.
|
3171
|
+
.unescaped = YP_EMPTY_STRING
|
3440
3172
|
};
|
3441
3173
|
|
3442
3174
|
return node;
|
@@ -3631,7 +3363,7 @@ yp_self_node_create(yp_parser_t *parser, const yp_token_t *token) {
|
|
3631
3363
|
|
3632
3364
|
// Allocate a new SingletonClassNode node.
|
3633
3365
|
static yp_singleton_class_node_t *
|
3634
|
-
yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, const yp_token_t *operator, yp_node_t *expression, yp_node_t *
|
3366
|
+
yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, const yp_token_t *operator, yp_node_t *expression, yp_node_t *body, const yp_token_t *end_keyword) {
|
3635
3367
|
yp_singleton_class_node_t *node = YP_ALLOC_NODE(parser, yp_singleton_class_node_t);
|
3636
3368
|
|
3637
3369
|
*node = (yp_singleton_class_node_t) {
|
@@ -3646,7 +3378,7 @@ yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *local
|
|
3646
3378
|
.class_keyword_loc = YP_LOCATION_TOKEN_VALUE(class_keyword),
|
3647
3379
|
.operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
|
3648
3380
|
.expression = expression,
|
3649
|
-
.
|
3381
|
+
.body = body,
|
3650
3382
|
.end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
|
3651
3383
|
};
|
3652
3384
|
|
@@ -3749,7 +3481,7 @@ yp_statements_node_body_append(yp_statements_node_t *node, yp_node_t *statement)
|
|
3749
3481
|
node->base.location.end = statement->location.end;
|
3750
3482
|
|
3751
3483
|
// Every statement gets marked as a place where a newline can occur.
|
3752
|
-
statement->flags
|
3484
|
+
statement->flags |= YP_NODE_FLAG_NEWLINE;
|
3753
3485
|
}
|
3754
3486
|
|
3755
3487
|
// Allocate a new StringConcatNode node.
|
@@ -3865,10 +3597,10 @@ yp_symbol_node_label_create(yp_parser_t *parser, const yp_token_t *token) {
|
|
3865
3597
|
yp_token_t label = { .type = YP_TOKEN_LABEL, .start = token->start, .end = token->end - 1 };
|
3866
3598
|
node = yp_symbol_node_create(parser, &opening, &label, &closing);
|
3867
3599
|
|
3868
|
-
|
3869
|
-
|
3600
|
+
assert((label.end - label.start) >= 0);
|
3601
|
+
yp_string_shared_init(&node->unescaped, label.start, label.end);
|
3870
3602
|
|
3871
|
-
yp_unescape_manipulate_string(parser,
|
3603
|
+
yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
|
3872
3604
|
break;
|
3873
3605
|
}
|
3874
3606
|
case YP_TOKEN_MISSING: {
|
@@ -3996,6 +3728,7 @@ yp_undef_node_append(yp_undef_node_t *node, yp_node_t *name) {
|
|
3996
3728
|
// Allocate a new UnlessNode node.
|
3997
3729
|
static yp_unless_node_t *
|
3998
3730
|
yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements) {
|
3731
|
+
yp_flip_flop(predicate);
|
3999
3732
|
yp_unless_node_t *node = YP_ALLOC_NODE(parser, yp_unless_node_t);
|
4000
3733
|
|
4001
3734
|
const char *end;
|
@@ -4027,6 +3760,7 @@ yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t
|
|
4027
3760
|
// Allocate and initialize new UnlessNode node in the modifier form.
|
4028
3761
|
static yp_unless_node_t *
|
4029
3762
|
yp_unless_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_token_t *unless_keyword, yp_node_t *predicate) {
|
3763
|
+
yp_flip_flop(predicate);
|
4030
3764
|
yp_unless_node_t *node = YP_ALLOC_NODE(parser, yp_unless_node_t);
|
4031
3765
|
|
4032
3766
|
yp_statements_node_t *statements = yp_statements_node_create(parser);
|
@@ -4059,7 +3793,7 @@ yp_unless_node_end_keyword_loc_set(yp_unless_node_t *node, const yp_token_t *end
|
|
4059
3793
|
|
4060
3794
|
// Allocate a new UntilNode node.
|
4061
3795
|
static yp_until_node_t *
|
4062
|
-
yp_until_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements,
|
3796
|
+
yp_until_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements, yp_node_flags_t flags) {
|
4063
3797
|
yp_until_node_t *node = YP_ALLOC_NODE(parser, yp_until_node_t);
|
4064
3798
|
bool has_statements = (statements != NULL) && (statements->body.size != 0);
|
4065
3799
|
|
@@ -4080,6 +3814,7 @@ yp_until_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *
|
|
4080
3814
|
*node = (yp_until_node_t) {
|
4081
3815
|
{
|
4082
3816
|
.type = YP_NODE_UNTIL_NODE,
|
3817
|
+
.flags = flags,
|
4083
3818
|
.location = {
|
4084
3819
|
.start = start,
|
4085
3820
|
.end = end,
|
@@ -4087,8 +3822,7 @@ yp_until_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *
|
|
4087
3822
|
},
|
4088
3823
|
.keyword_loc = YP_LOCATION_TOKEN_VALUE(keyword),
|
4089
3824
|
.predicate = predicate,
|
4090
|
-
.statements = statements
|
4091
|
-
.flags = flags
|
3825
|
+
.statements = statements
|
4092
3826
|
};
|
4093
3827
|
|
4094
3828
|
return node;
|
@@ -4134,7 +3868,7 @@ yp_when_node_statements_set(yp_when_node_t *node, yp_statements_node_t *statemen
|
|
4134
3868
|
|
4135
3869
|
// Allocate a new WhileNode node.
|
4136
3870
|
static yp_while_node_t *
|
4137
|
-
yp_while_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements,
|
3871
|
+
yp_while_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements, yp_node_flags_t flags) {
|
4138
3872
|
yp_while_node_t *node = YP_ALLOC_NODE(parser, yp_while_node_t);
|
4139
3873
|
|
4140
3874
|
const char *start = NULL;
|
@@ -4155,6 +3889,7 @@ yp_while_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *
|
|
4155
3889
|
*node = (yp_while_node_t) {
|
4156
3890
|
{
|
4157
3891
|
.type = YP_NODE_WHILE_NODE,
|
3892
|
+
.flags = flags,
|
4158
3893
|
.location = {
|
4159
3894
|
.start = start,
|
4160
3895
|
.end = end,
|
@@ -4162,8 +3897,7 @@ yp_while_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *
|
|
4162
3897
|
},
|
4163
3898
|
.keyword_loc = YP_LOCATION_TOKEN_VALUE(keyword),
|
4164
3899
|
.predicate = predicate,
|
4165
|
-
.statements = statements
|
4166
|
-
.flags = flags
|
3900
|
+
.statements = statements
|
4167
3901
|
};
|
4168
3902
|
|
4169
3903
|
return node;
|
@@ -4599,6 +4333,7 @@ parser_lex_encoding_comment(yp_parser_t *parser) {
|
|
4599
4333
|
ENCODING("cp1252", yp_encoding_windows_1252);
|
4600
4334
|
ENCODING("cp932", yp_encoding_windows_31j);
|
4601
4335
|
ENCODING("sjis", yp_encoding_windows_31j);
|
4336
|
+
ENCODING("utf8-mac", yp_encoding_utf8_mac);
|
4602
4337
|
|
4603
4338
|
#undef ENCODING
|
4604
4339
|
|
@@ -5344,13 +5079,14 @@ lex_question_mark(yp_parser_t *parser) {
|
|
5344
5079
|
} else {
|
5345
5080
|
size_t encoding_width = parser->encoding.char_width(parser->current.end, parser->end - parser->current.end);
|
5346
5081
|
|
5347
|
-
//
|
5348
|
-
//
|
5082
|
+
// Ternary operators can have a ? immediately followed by an identifier which starts with
|
5083
|
+
// an underscore. We check for this case
|
5349
5084
|
if (
|
5350
|
-
!parser->encoding.alnum_char(parser->current.end, parser->end - parser->current.end) ||
|
5085
|
+
!(parser->encoding.alnum_char(parser->current.end, parser->end - parser->current.end) ||
|
5086
|
+
*parser->current.end == '_') ||
|
5351
5087
|
(
|
5352
5088
|
(parser->current.end + encoding_width >= parser->end) ||
|
5353
|
-
!
|
5089
|
+
!char_is_identifier(parser, parser->current.end + encoding_width)
|
5354
5090
|
)
|
5355
5091
|
) {
|
5356
5092
|
lex_state_set(parser, YP_LEX_STATE_END);
|
@@ -5572,13 +5308,23 @@ parser_lex(yp_parser_t *parser) {
|
|
5572
5308
|
break;
|
5573
5309
|
case '\\':
|
5574
5310
|
if (peek_at(parser, 1) == '\n') {
|
5575
|
-
|
5576
|
-
|
5577
|
-
|
5578
|
-
|
5579
|
-
|
5580
|
-
|
5581
|
-
|
5311
|
+
if (parser->heredoc_end) {
|
5312
|
+
parser->current.end = parser->heredoc_end;
|
5313
|
+
parser->heredoc_end = NULL;
|
5314
|
+
} else {
|
5315
|
+
yp_newline_list_append(&parser->newline_list, parser->current.end + 1);
|
5316
|
+
parser->current.end += 2;
|
5317
|
+
space_seen = true;
|
5318
|
+
}
|
5319
|
+
} else if (peek_at(parser, 1) == '\r' && peek_at(parser, 2) == '\n') {
|
5320
|
+
if (parser->heredoc_end) {
|
5321
|
+
parser->current.end = parser->heredoc_end;
|
5322
|
+
parser->heredoc_end = NULL;
|
5323
|
+
} else {
|
5324
|
+
yp_newline_list_append(&parser->newline_list, parser->current.end + 2);
|
5325
|
+
parser->current.end += 3;
|
5326
|
+
space_seen = true;
|
5327
|
+
}
|
5582
5328
|
} else if (yp_char_is_inline_whitespace(*parser->current.end)) {
|
5583
5329
|
parser->current.end += 2;
|
5584
5330
|
} else {
|
@@ -6413,13 +6159,11 @@ parser_lex(yp_parser_t *parser) {
|
|
6413
6159
|
|
6414
6160
|
// % %= %i %I %q %Q %w %W
|
6415
6161
|
case '%': {
|
6416
|
-
//
|
6417
|
-
//
|
6418
|
-
//
|
6419
|
-
|
6420
|
-
|
6421
|
-
if (lex_state_beg_p(parser) && (parser->current.end >= parser->end)) {
|
6422
|
-
yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "unexpected end of input");
|
6162
|
+
// If there is no subsequent character then we have an invalid token. We're
|
6163
|
+
// going to say it's the percent operator because we don't want to move into the
|
6164
|
+
// string lex mode unnecessarily.
|
6165
|
+
if ((lex_state_beg_p(parser) || lex_state_arg_p(parser)) && (parser->current.end >= parser->end)) {
|
6166
|
+
yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "Unexpected end of input");
|
6423
6167
|
LEX(YP_TOKEN_PERCENT);
|
6424
6168
|
}
|
6425
6169
|
|
@@ -6592,7 +6336,7 @@ parser_lex(yp_parser_t *parser) {
|
|
6592
6336
|
((parser->current.end - parser->current.start) == 7) &&
|
6593
6337
|
current_token_starts_line(parser) &&
|
6594
6338
|
(strncmp(parser->current.start, "__END__", 7) == 0) &&
|
6595
|
-
(*parser->current.end == '\n' || (*parser->current.end == '\r' && parser->current.end[1] == '\n'))
|
6339
|
+
(parser->current.end == parser->end || *parser->current.end == '\n' || (*parser->current.end == '\r' && parser->current.end[1] == '\n'))
|
6596
6340
|
) {
|
6597
6341
|
parser->current.end = parser->end;
|
6598
6342
|
parser->current.type = YP_TOKEN___END__;
|
@@ -7009,6 +6753,7 @@ parser_lex(yp_parser_t *parser) {
|
|
7009
6753
|
} else {
|
7010
6754
|
parser->current.start = parser->next_start;
|
7011
6755
|
parser->current.end = parser->next_start;
|
6756
|
+
parser->heredoc_end = NULL;
|
7012
6757
|
parser->next_start = NULL;
|
7013
6758
|
}
|
7014
6759
|
|
@@ -7084,14 +6829,14 @@ parser_lex(yp_parser_t *parser) {
|
|
7084
6829
|
breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1));
|
7085
6830
|
break;
|
7086
6831
|
case '\n': {
|
7087
|
-
yp_newline_list_append(&parser->newline_list, breakpoint);
|
7088
|
-
|
7089
6832
|
if (parser->heredoc_end != NULL && (parser->heredoc_end > breakpoint)) {
|
7090
6833
|
parser_flush_heredoc_end(parser);
|
7091
6834
|
parser->current.end = breakpoint + 1;
|
7092
6835
|
LEX(YP_TOKEN_STRING_CONTENT);
|
7093
6836
|
}
|
7094
6837
|
|
6838
|
+
yp_newline_list_append(&parser->newline_list, breakpoint);
|
6839
|
+
|
7095
6840
|
const char *start = breakpoint + 1;
|
7096
6841
|
if (parser->lex_modes.current->as.heredoc.indent != YP_HEREDOC_INDENT_NONE) {
|
7097
6842
|
start += yp_strspn_inline_whitespace(start, parser->end - start);
|
@@ -7130,11 +6875,16 @@ parser_lex(yp_parser_t *parser) {
|
|
7130
6875
|
break;
|
7131
6876
|
}
|
7132
6877
|
case '\\': {
|
7133
|
-
// If we hit
|
7134
|
-
//
|
7135
|
-
//
|
7136
|
-
|
6878
|
+
// If we hit an escape, then we need to skip past
|
6879
|
+
// however many characters the escape takes up. However
|
6880
|
+
// it's important that if \n or \r\n are escaped that we
|
6881
|
+
// stop looping before the newline and not after the
|
6882
|
+
// newline so that we can still potentially find the
|
6883
|
+
// terminator of the heredoc.
|
6884
|
+
if (breakpoint + 1 < parser->end && breakpoint[1] == '\n') {
|
7137
6885
|
breakpoint++;
|
6886
|
+
} else if (breakpoint + 2 < parser->end && breakpoint[1] == '\r' && breakpoint[2] == '\n') {
|
6887
|
+
breakpoint += 2;
|
7138
6888
|
} else {
|
7139
6889
|
yp_unescape_type_t unescape_type = (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL;
|
7140
6890
|
size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, unescape_type, false, &parser->error_list);
|
@@ -7145,6 +6895,7 @@ parser_lex(yp_parser_t *parser) {
|
|
7145
6895
|
|
7146
6896
|
breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference));
|
7147
6897
|
}
|
6898
|
+
|
7148
6899
|
break;
|
7149
6900
|
}
|
7150
6901
|
case '#': {
|
@@ -7191,10 +6942,10 @@ static yp_regular_expression_node_t *
|
|
7191
6942
|
yp_regular_expression_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
|
7192
6943
|
yp_regular_expression_node_t *node = yp_regular_expression_node_create(parser, opening, content, closing);
|
7193
6944
|
|
7194
|
-
|
7195
|
-
|
6945
|
+
assert((content->end - content->start) >= 0);
|
6946
|
+
yp_string_shared_init(&node->unescaped, content->start, content->end);
|
7196
6947
|
|
7197
|
-
yp_unescape_manipulate_string(parser,
|
6948
|
+
yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
|
7198
6949
|
return node;
|
7199
6950
|
}
|
7200
6951
|
|
@@ -7202,10 +6953,10 @@ static yp_symbol_node_t *
|
|
7202
6953
|
yp_symbol_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
|
7203
6954
|
yp_symbol_node_t *node = yp_symbol_node_create(parser, opening, content, closing);
|
7204
6955
|
|
7205
|
-
|
7206
|
-
|
6956
|
+
assert((content->end - content->start) >= 0);
|
6957
|
+
yp_string_shared_init(&node->unescaped, content->start, content->end);
|
7207
6958
|
|
7208
|
-
yp_unescape_manipulate_string(parser,
|
6959
|
+
yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
|
7209
6960
|
return node;
|
7210
6961
|
}
|
7211
6962
|
|
@@ -7213,10 +6964,10 @@ static yp_string_node_t *
|
|
7213
6964
|
yp_string_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
|
7214
6965
|
yp_string_node_t *node = yp_string_node_create(parser, opening, content, closing);
|
7215
6966
|
|
7216
|
-
|
7217
|
-
|
6967
|
+
assert((content->end - content->start) >= 0);
|
6968
|
+
yp_string_shared_init(&node->unescaped, content->start, content->end);
|
7218
6969
|
|
7219
|
-
yp_unescape_manipulate_string(parser,
|
6970
|
+
yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
|
7220
6971
|
return node;
|
7221
6972
|
}
|
7222
6973
|
|
@@ -7224,10 +6975,10 @@ static yp_x_string_node_t *
|
|
7224
6975
|
yp_xstring_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing) {
|
7225
6976
|
yp_x_string_node_t *node = yp_xstring_node_create(parser, opening, content, closing);
|
7226
6977
|
|
7227
|
-
|
7228
|
-
|
6978
|
+
assert((content->end - content->start) >= 0);
|
6979
|
+
yp_string_shared_init(&node->unescaped, content->start, content->end);
|
7229
6980
|
|
7230
|
-
yp_unescape_manipulate_string(parser,
|
6981
|
+
yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
|
7231
6982
|
return node;
|
7232
6983
|
}
|
7233
6984
|
|
@@ -7705,7 +7456,7 @@ parse_target(yp_parser_t *parser, yp_node_t *target, yp_token_t *operator, yp_no
|
|
7705
7456
|
char *name = calloc(length + 2, sizeof(char));
|
7706
7457
|
if (name == NULL) return NULL;
|
7707
7458
|
|
7708
|
-
|
7459
|
+
snprintf(name, length + 2, "%.*s=", (int) length, yp_string_source(&call->name));
|
7709
7460
|
|
7710
7461
|
// Now switch the name to the new string.
|
7711
7462
|
yp_string_free(&call->name);
|
@@ -8032,7 +7783,7 @@ parse_assocs(yp_parser_t *parser, yp_node_t *node) {
|
|
8032
7783
|
|
8033
7784
|
// Parse a list of arguments.
|
8034
7785
|
static void
|
8035
|
-
parse_arguments(yp_parser_t *parser,
|
7786
|
+
parse_arguments(yp_parser_t *parser, yp_arguments_t *arguments, bool accepts_forwarding, yp_token_type_t terminator) {
|
8036
7787
|
yp_binding_power_t binding_power = yp_binding_powers[parser->current.type].left;
|
8037
7788
|
|
8038
7789
|
// First we need to check if the next token is one that could be the start of
|
@@ -8085,6 +7836,7 @@ parse_arguments(yp_parser_t *parser, yp_arguments_node_t *arguments, bool accept
|
|
8085
7836
|
|
8086
7837
|
argument = (yp_node_t *)yp_block_argument_node_create(parser, &operator, expression);
|
8087
7838
|
parsed_block_argument = true;
|
7839
|
+
arguments->implicit_block = true;
|
8088
7840
|
break;
|
8089
7841
|
}
|
8090
7842
|
case YP_TOKEN_USTAR: {
|
@@ -8171,7 +7923,7 @@ parse_arguments(yp_parser_t *parser, yp_arguments_node_t *arguments, bool accept
|
|
8171
7923
|
}
|
8172
7924
|
}
|
8173
7925
|
|
8174
|
-
yp_arguments_node_arguments_append(arguments, argument);
|
7926
|
+
yp_arguments_node_arguments_append(arguments->arguments, argument);
|
8175
7927
|
|
8176
7928
|
// If parsing the argument failed, we need to stop parsing arguments.
|
8177
7929
|
if (YP_NODE_TYPE_P(argument, YP_NODE_MISSING_NODE) || parser->recovering) break;
|
@@ -8308,6 +8060,10 @@ update_parameter_state(yp_parser_t *parser, yp_token_t *token, yp_parameters_ord
|
|
8308
8060
|
return;
|
8309
8061
|
}
|
8310
8062
|
|
8063
|
+
if (token->type == YP_TOKEN_USTAR && *current == YP_PARAMETERS_ORDER_AFTER_OPTIONAL) {
|
8064
|
+
yp_diagnostic_list_append(&parser->error_list, token->start, token->end, "Unexpected parameter *");
|
8065
|
+
}
|
8066
|
+
|
8311
8067
|
if (*current == YP_PARAMETERS_ORDER_NOTHING_AFTER || state > *current) {
|
8312
8068
|
// We know what transition we failed on, so we can provide a better error here.
|
8313
8069
|
yp_diagnostic_list_append(&parser->error_list, token->start, token->end, "Unexpected parameter order");
|
@@ -8863,7 +8619,7 @@ parse_arguments_list(yp_parser_t *parser, yp_arguments_t *arguments, bool accept
|
|
8863
8619
|
arguments->arguments = yp_arguments_node_create(parser);
|
8864
8620
|
|
8865
8621
|
yp_accepts_block_stack_push(parser, true);
|
8866
|
-
parse_arguments(parser, arguments
|
8622
|
+
parse_arguments(parser, arguments, true, YP_TOKEN_PARENTHESIS_RIGHT);
|
8867
8623
|
expect(parser, YP_TOKEN_PARENTHESIS_RIGHT, "Expected a ')' to close the argument list.");
|
8868
8624
|
yp_accepts_block_stack_pop(parser);
|
8869
8625
|
|
@@ -8877,7 +8633,7 @@ parse_arguments_list(yp_parser_t *parser, yp_arguments_t *arguments, bool accept
|
|
8877
8633
|
// operator. In this case we assume the subsequent token is part of an
|
8878
8634
|
// argument to this method call.
|
8879
8635
|
arguments->arguments = yp_arguments_node_create(parser);
|
8880
|
-
parse_arguments(parser, arguments
|
8636
|
+
parse_arguments(parser, arguments, true, YP_TOKEN_EOF);
|
8881
8637
|
|
8882
8638
|
yp_accepts_block_stack_pop(parser);
|
8883
8639
|
}
|
@@ -8895,6 +8651,7 @@ parse_arguments_list(yp_parser_t *parser, yp_arguments_t *arguments, bool accept
|
|
8895
8651
|
}
|
8896
8652
|
}
|
8897
8653
|
|
8654
|
+
yp_arguments_validate(parser, arguments);
|
8898
8655
|
return found;
|
8899
8656
|
}
|
8900
8657
|
|
@@ -8920,7 +8677,7 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
|
|
8920
8677
|
}
|
8921
8678
|
|
8922
8679
|
yp_token_t end_keyword = not_provided(parser);
|
8923
|
-
yp_node_t *parent;
|
8680
|
+
yp_node_t *parent = NULL;
|
8924
8681
|
|
8925
8682
|
switch (context) {
|
8926
8683
|
case YP_CONTEXT_IF:
|
@@ -8930,7 +8687,6 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
|
|
8930
8687
|
parent = (yp_node_t *) yp_unless_node_create(parser, &keyword, predicate, statements);
|
8931
8688
|
break;
|
8932
8689
|
default:
|
8933
|
-
parent = NULL;
|
8934
8690
|
assert(false && "unreachable");
|
8935
8691
|
break;
|
8936
8692
|
}
|
@@ -8976,50 +8732,49 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
|
|
8976
8732
|
switch (context) {
|
8977
8733
|
case YP_CONTEXT_IF:
|
8978
8734
|
((yp_if_node_t *) current)->consequent = (yp_node_t *) else_node;
|
8979
|
-
// Recurse down if nodes setting the appropriate end location in
|
8980
|
-
// all cases.
|
8981
|
-
yp_node_t *recursing_node = parent;
|
8982
|
-
bool recursing = true;
|
8983
|
-
|
8984
|
-
while (recursing) {
|
8985
|
-
switch (YP_NODE_TYPE(recursing_node)) {
|
8986
|
-
case YP_NODE_IF_NODE:
|
8987
|
-
yp_if_node_end_keyword_loc_set((yp_if_node_t *) recursing_node, &parser->previous);
|
8988
|
-
recursing_node = ((yp_if_node_t *) recursing_node)->consequent;
|
8989
|
-
break;
|
8990
|
-
case YP_NODE_ELSE_NODE:
|
8991
|
-
yp_else_node_end_keyword_loc_set((yp_else_node_t *) recursing_node, &parser->previous);
|
8992
|
-
recursing = false;
|
8993
|
-
break;
|
8994
|
-
default: {
|
8995
|
-
recursing = false;
|
8996
|
-
break;
|
8997
|
-
}
|
8998
|
-
}
|
8999
|
-
}
|
9000
8735
|
break;
|
9001
8736
|
case YP_CONTEXT_UNLESS:
|
9002
8737
|
((yp_unless_node_t *) parent)->consequent = else_node;
|
9003
|
-
yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
|
9004
8738
|
break;
|
9005
8739
|
default:
|
9006
8740
|
assert(false && "unreachable");
|
9007
8741
|
break;
|
9008
8742
|
}
|
9009
8743
|
} else {
|
9010
|
-
expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close
|
8744
|
+
expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close conditional statement.");
|
8745
|
+
}
|
9011
8746
|
|
9012
|
-
|
9013
|
-
|
9014
|
-
|
9015
|
-
|
9016
|
-
|
9017
|
-
|
9018
|
-
|
9019
|
-
|
9020
|
-
|
9021
|
-
|
8747
|
+
// Set the appropriate end location for all of the nodes in the subtree.
|
8748
|
+
switch (context) {
|
8749
|
+
case YP_CONTEXT_IF: {
|
8750
|
+
yp_node_t *current = parent;
|
8751
|
+
bool recursing = true;
|
8752
|
+
|
8753
|
+
while (recursing) {
|
8754
|
+
switch (YP_NODE_TYPE(current)) {
|
8755
|
+
case YP_NODE_IF_NODE:
|
8756
|
+
yp_if_node_end_keyword_loc_set((yp_if_node_t *) current, &parser->previous);
|
8757
|
+
current = ((yp_if_node_t *) current)->consequent;
|
8758
|
+
recursing = current != NULL;
|
8759
|
+
break;
|
8760
|
+
case YP_NODE_ELSE_NODE:
|
8761
|
+
yp_else_node_end_keyword_loc_set((yp_else_node_t *) current, &parser->previous);
|
8762
|
+
recursing = false;
|
8763
|
+
break;
|
8764
|
+
default: {
|
8765
|
+
recursing = false;
|
8766
|
+
break;
|
8767
|
+
}
|
8768
|
+
}
|
8769
|
+
}
|
8770
|
+
break;
|
9022
8771
|
}
|
8772
|
+
case YP_CONTEXT_UNLESS:
|
8773
|
+
yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
|
8774
|
+
break;
|
8775
|
+
default:
|
8776
|
+
assert(false && "unreachable");
|
8777
|
+
break;
|
9023
8778
|
}
|
9024
8779
|
|
9025
8780
|
return parent;
|
@@ -9093,7 +8848,12 @@ parse_string_part(yp_parser_t *parser) {
|
|
9093
8848
|
yp_unescape_type_t unescape_type = YP_UNESCAPE_ALL;
|
9094
8849
|
|
9095
8850
|
if (parser->lex_modes.current->mode == YP_LEX_HEREDOC) {
|
9096
|
-
if (parser->lex_modes.current->as.heredoc.
|
8851
|
+
if (parser->lex_modes.current->as.heredoc.indent == YP_HEREDOC_INDENT_TILDE) {
|
8852
|
+
// If we're in a tilde heredoc, we want to unescape it later
|
8853
|
+
// because we don't want unescaped newlines to disappear
|
8854
|
+
// before we handle them in the dedent.
|
8855
|
+
unescape_type = YP_UNESCAPE_NONE;
|
8856
|
+
} else if (parser->lex_modes.current->as.heredoc.quote == YP_HEREDOC_QUOTE_SINGLE) {
|
9097
8857
|
unescape_type = YP_UNESCAPE_MINIMAL;
|
9098
8858
|
}
|
9099
8859
|
}
|
@@ -9359,7 +9119,7 @@ parse_alias_argument(yp_parser_t *parser, bool first) {
|
|
9359
9119
|
// Parse an identifier into either a local variable read or a call.
|
9360
9120
|
static yp_node_t *
|
9361
9121
|
parse_variable_call(yp_parser_t *parser) {
|
9362
|
-
|
9122
|
+
yp_node_flags_t flags = 0;
|
9363
9123
|
|
9364
9124
|
if (!match_type_p(parser, YP_TOKEN_PARENTHESIS_LEFT) && (parser->previous.end[-1] != '!') && (parser->previous.end[-1] != '?')) {
|
9365
9125
|
int depth;
|
@@ -9371,7 +9131,7 @@ parse_variable_call(yp_parser_t *parser) {
|
|
9371
9131
|
}
|
9372
9132
|
|
9373
9133
|
yp_call_node_t *node = yp_call_node_variable_call_create(parser, &parser->previous);
|
9374
|
-
node->flags
|
9134
|
+
node->base.flags |= flags;
|
9375
9135
|
|
9376
9136
|
return (yp_node_t *) node;
|
9377
9137
|
}
|
@@ -9466,14 +9226,30 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
|
|
9466
9226
|
int common_whitespace;
|
9467
9227
|
if ((common_whitespace = parse_heredoc_common_whitespace(parser, nodes)) <= 0) return;
|
9468
9228
|
|
9469
|
-
//
|
9470
|
-
|
9471
|
-
|
9472
|
-
|
9229
|
+
// The next node should be dedented if it's the first node in the list or if
|
9230
|
+
// if follows a string node.
|
9231
|
+
bool dedent_next = true;
|
9232
|
+
|
9233
|
+
// Iterate over all nodes, and trim whitespace accordingly. We're going to
|
9234
|
+
// keep around two indices: a read and a write. If we end up trimming all of
|
9235
|
+
// the whitespace from a node, then we'll drop it from the list entirely.
|
9236
|
+
size_t write_index = 0;
|
9237
|
+
|
9238
|
+
for (size_t read_index = 0; read_index < nodes->size; read_index++) {
|
9239
|
+
yp_node_t *node = nodes->nodes[read_index];
|
9240
|
+
|
9241
|
+
// We're not manipulating child nodes that aren't strings. In this case
|
9242
|
+
// we'll skip past it and indicate that the subsequent node should not
|
9243
|
+
// be dedented.
|
9244
|
+
if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) {
|
9245
|
+
nodes->nodes[write_index++] = node;
|
9246
|
+
dedent_next = false;
|
9247
|
+
continue;
|
9248
|
+
}
|
9473
9249
|
|
9474
9250
|
// Get a reference to the string struct that is being held by the string
|
9475
9251
|
// node. This is the value we're going to actual manipulate.
|
9476
|
-
yp_string_t *string = &((yp_string_node_t *) node)->unescaped;
|
9252
|
+
yp_string_t *string = &(((yp_string_node_t *) node)->unescaped);
|
9477
9253
|
yp_string_ensure_owned(string);
|
9478
9254
|
|
9479
9255
|
// Now get the bounds of the existing string. We'll use this as a
|
@@ -9489,7 +9265,6 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
|
|
9489
9265
|
// whitespace, so we'll maintain a pointer to the current position in the
|
9490
9266
|
// string that we're writing to.
|
9491
9267
|
char *dest_cursor = source_start;
|
9492
|
-
bool dedent_next = (index == 0) || YP_NODE_TYPE_P(nodes->nodes[index - 1], YP_NODE_STRING_NODE);
|
9493
9268
|
|
9494
9269
|
while (source_cursor < source_end) {
|
9495
9270
|
// If we need to dedent the next element within the heredoc or the next
|
@@ -9534,8 +9309,20 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
|
|
9534
9309
|
dedent_next = true;
|
9535
9310
|
}
|
9536
9311
|
|
9537
|
-
|
9312
|
+
// We only want to write this node into the list if it has any content.
|
9313
|
+
if (dest_length == 0) {
|
9314
|
+
yp_node_destroy(parser, node);
|
9315
|
+
} else {
|
9316
|
+
string->length = dest_length;
|
9317
|
+
yp_unescape_manipulate_string(parser, string, (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL, &parser->error_list);
|
9318
|
+
nodes->nodes[write_index++] = node;
|
9319
|
+
}
|
9320
|
+
|
9321
|
+
// We always dedent the next node if it follows a string node.
|
9322
|
+
dedent_next = true;
|
9538
9323
|
}
|
9324
|
+
|
9325
|
+
nodes->size = write_index;
|
9539
9326
|
}
|
9540
9327
|
|
9541
9328
|
static yp_node_t *
|
@@ -10172,6 +9959,30 @@ parse_pattern(yp_parser_t *parser, bool top_pattern, const char *message) {
|
|
10172
9959
|
return node;
|
10173
9960
|
}
|
10174
9961
|
|
9962
|
+
// Incorporate a negative sign into a numeric node by subtracting 1 character
|
9963
|
+
// from its start bounds. If it's a compound node, then we will recursively
|
9964
|
+
// apply this function to its value.
|
9965
|
+
static inline void
|
9966
|
+
parse_negative_numeric(yp_node_t *node) {
|
9967
|
+
switch (YP_NODE_TYPE(node)) {
|
9968
|
+
case YP_NODE_INTEGER_NODE:
|
9969
|
+
case YP_NODE_FLOAT_NODE:
|
9970
|
+
node->location.start--;
|
9971
|
+
break;
|
9972
|
+
case YP_NODE_RATIONAL_NODE:
|
9973
|
+
node->location.start--;
|
9974
|
+
parse_negative_numeric(((yp_rational_node_t *) node)->numeric);
|
9975
|
+
break;
|
9976
|
+
case YP_NODE_IMAGINARY_NODE:
|
9977
|
+
node->location.start--;
|
9978
|
+
parse_negative_numeric(((yp_imaginary_node_t *) node)->numeric);
|
9979
|
+
break;
|
9980
|
+
default:
|
9981
|
+
assert(false && "unreachable");
|
9982
|
+
break;
|
9983
|
+
}
|
9984
|
+
}
|
9985
|
+
|
10175
9986
|
// Parse an expression that begins with the previous node that we just lexed.
|
10176
9987
|
static inline yp_node_t *
|
10177
9988
|
parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
@@ -10260,6 +10071,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
10260
10071
|
}
|
10261
10072
|
case YP_TOKEN_PARENTHESIS_LEFT:
|
10262
10073
|
case YP_TOKEN_PARENTHESIS_LEFT_PARENTHESES: {
|
10074
|
+
yp_token_type_t current_token_type = parser->current.type;
|
10263
10075
|
parser_lex(parser);
|
10264
10076
|
|
10265
10077
|
yp_token_t opening = parser->previous;
|
@@ -10280,7 +10092,11 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
10280
10092
|
|
10281
10093
|
// If we hit a right parenthesis, then we're done parsing the parentheses
|
10282
10094
|
// node, and we can check which kind of node we should return.
|
10283
|
-
if (
|
10095
|
+
if (match_type_p(parser, YP_TOKEN_PARENTHESIS_RIGHT)) {
|
10096
|
+
if (current_token_type == YP_TOKEN_PARENTHESIS_LEFT_PARENTHESES) {
|
10097
|
+
lex_state_set(parser, YP_LEX_STATE_ENDARG);
|
10098
|
+
}
|
10099
|
+
parser_lex(parser);
|
10284
10100
|
yp_accepts_block_stack_pop(parser);
|
10285
10101
|
|
10286
10102
|
// If we have a single statement and are ending on a right parenthesis,
|
@@ -10496,7 +10312,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
10496
10312
|
if (parse_arguments_list(parser, &arguments, true)) {
|
10497
10313
|
// Since we found arguments, we need to turn off the
|
10498
10314
|
// variable call bit in the flags.
|
10499
|
-
call->flags &= (
|
10315
|
+
call->base.flags &= (yp_node_flags_t) ~YP_CALL_NODE_FLAGS_VARIABLE_CALL;
|
10500
10316
|
|
10501
10317
|
call->opening_loc = arguments.opening_loc;
|
10502
10318
|
call->arguments = arguments.arguments;
|
@@ -10565,12 +10381,15 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
10565
10381
|
|
10566
10382
|
lex_state_set(parser, YP_LEX_STATE_END);
|
10567
10383
|
expect(parser, YP_TOKEN_HEREDOC_END, "Expected a closing delimiter for heredoc.");
|
10384
|
+
|
10568
10385
|
if (quote == YP_HEREDOC_QUOTE_BACKTICK) {
|
10569
10386
|
assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_X_STRING_NODE));
|
10570
10387
|
yp_interpolated_xstring_node_closing_set(((yp_interpolated_x_string_node_t *) node), &parser->previous);
|
10388
|
+
node->location = ((yp_interpolated_x_string_node_t *) node)->opening_loc;
|
10571
10389
|
} else {
|
10572
10390
|
assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_STRING_NODE));
|
10573
10391
|
yp_interpolated_string_node_closing_set((yp_interpolated_string_node_t *) node, &parser->previous);
|
10392
|
+
node->location = ((yp_interpolated_string_node_t *) node)->opening_loc;
|
10574
10393
|
}
|
10575
10394
|
|
10576
10395
|
// If this is a heredoc that is indented with a ~, then we need to dedent
|
@@ -10850,7 +10669,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
10850
10669
|
parser_lex(parser);
|
10851
10670
|
|
10852
10671
|
yp_token_t keyword = parser->previous;
|
10853
|
-
|
10672
|
+
yp_arguments_t arguments = YP_EMPTY_ARGUMENTS;
|
10854
10673
|
|
10855
10674
|
if (
|
10856
10675
|
token_begins_expression_p(parser->current.type) ||
|
@@ -10859,16 +10678,16 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
10859
10678
|
yp_binding_power_t binding_power = yp_binding_powers[parser->current.type].left;
|
10860
10679
|
|
10861
10680
|
if (binding_power == YP_BINDING_POWER_UNSET || binding_power >= YP_BINDING_POWER_RANGE) {
|
10862
|
-
arguments = yp_arguments_node_create(parser);
|
10863
|
-
parse_arguments(parser, arguments, false, YP_TOKEN_EOF);
|
10681
|
+
arguments.arguments = yp_arguments_node_create(parser);
|
10682
|
+
parse_arguments(parser, &arguments, false, YP_TOKEN_EOF);
|
10864
10683
|
}
|
10865
10684
|
}
|
10866
10685
|
|
10867
10686
|
switch (keyword.type) {
|
10868
10687
|
case YP_TOKEN_KEYWORD_BREAK:
|
10869
|
-
return (yp_node_t *) yp_break_node_create(parser, &keyword, arguments);
|
10688
|
+
return (yp_node_t *) yp_break_node_create(parser, &keyword, arguments.arguments);
|
10870
10689
|
case YP_TOKEN_KEYWORD_NEXT:
|
10871
|
-
return (yp_node_t *) yp_next_node_create(parser, &keyword, arguments);
|
10690
|
+
return (yp_node_t *) yp_next_node_create(parser, &keyword, arguments.arguments);
|
10872
10691
|
case YP_TOKEN_KEYWORD_RETURN: {
|
10873
10692
|
if (
|
10874
10693
|
(parser->current_context->context == YP_CONTEXT_CLASS) ||
|
@@ -10876,7 +10695,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
10876
10695
|
) {
|
10877
10696
|
yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "Invalid return in class/module body");
|
10878
10697
|
}
|
10879
|
-
return (yp_node_t *) yp_return_node_create(parser, &keyword, arguments);
|
10698
|
+
return (yp_node_t *) yp_return_node_create(parser, &keyword, arguments.arguments);
|
10880
10699
|
}
|
10881
10700
|
default:
|
10882
10701
|
assert(false && "unreachable");
|
@@ -11342,6 +11161,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
11342
11161
|
arguments.closing_loc = ((yp_location_t) { .start = parser->previous.start, .end = parser->previous.end });
|
11343
11162
|
} else {
|
11344
11163
|
receiver = parse_expression(parser, YP_BINDING_POWER_COMPOSITION, "Expected expression after `not`.");
|
11164
|
+
yp_flip_flop(receiver);
|
11345
11165
|
|
11346
11166
|
if (!parser->recovering) {
|
11347
11167
|
accept(parser, YP_TOKEN_NEWLINE);
|
@@ -11351,6 +11171,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
11351
11171
|
}
|
11352
11172
|
} else {
|
11353
11173
|
receiver = parse_expression(parser, YP_BINDING_POWER_DEFINED, "Expected expression after `not`.");
|
11174
|
+
yp_flip_flop(receiver);
|
11354
11175
|
}
|
11355
11176
|
|
11356
11177
|
return (yp_node_t *) yp_call_node_not_create(parser, receiver, &message, &arguments);
|
@@ -11928,6 +11749,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
11928
11749
|
yp_node_t *receiver = parse_expression(parser, yp_binding_powers[parser->previous.type].right, "Expected a receiver after unary !.");
|
11929
11750
|
yp_call_node_t *node = yp_call_node_unary_create(parser, &operator, receiver, "!");
|
11930
11751
|
|
11752
|
+
yp_flip_flop(receiver);
|
11931
11753
|
return (yp_node_t *) node;
|
11932
11754
|
}
|
11933
11755
|
case YP_TOKEN_TILDE: {
|
@@ -11939,8 +11761,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
11939
11761
|
|
11940
11762
|
return (yp_node_t *) node;
|
11941
11763
|
}
|
11942
|
-
case YP_TOKEN_UMINUS:
|
11943
|
-
case YP_TOKEN_UMINUS_NUM: {
|
11764
|
+
case YP_TOKEN_UMINUS: {
|
11944
11765
|
parser_lex(parser);
|
11945
11766
|
|
11946
11767
|
yp_token_t operator = parser->previous;
|
@@ -11949,6 +11770,26 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
|
|
11949
11770
|
|
11950
11771
|
return (yp_node_t *) node;
|
11951
11772
|
}
|
11773
|
+
case YP_TOKEN_UMINUS_NUM: {
|
11774
|
+
parser_lex(parser);
|
11775
|
+
|
11776
|
+
yp_token_t operator = parser->previous;
|
11777
|
+
yp_node_t *node = parse_expression(parser, yp_binding_powers[parser->previous.type].right, "Expected a receiver after unary -.");
|
11778
|
+
|
11779
|
+
switch (YP_NODE_TYPE(node)) {
|
11780
|
+
case YP_NODE_INTEGER_NODE:
|
11781
|
+
case YP_NODE_FLOAT_NODE:
|
11782
|
+
case YP_NODE_RATIONAL_NODE:
|
11783
|
+
case YP_NODE_IMAGINARY_NODE:
|
11784
|
+
parse_negative_numeric(node);
|
11785
|
+
break;
|
11786
|
+
default:
|
11787
|
+
node = (yp_node_t *) yp_call_node_unary_create(parser, &operator, node, "-@");
|
11788
|
+
break;
|
11789
|
+
}
|
11790
|
+
|
11791
|
+
return node;
|
11792
|
+
}
|
11952
11793
|
case YP_TOKEN_MINUS_GREATER: {
|
11953
11794
|
int previous_lambda_enclosure_nesting = parser->lambda_enclosure_nesting;
|
11954
11795
|
parser->lambda_enclosure_nesting = parser->enclosure_nesting;
|
@@ -12195,18 +12036,18 @@ static inline yp_node_t *
|
|
12195
12036
|
parse_assignment_value(yp_parser_t *parser, yp_binding_power_t previous_binding_power, yp_binding_power_t binding_power, const char *message) {
|
12196
12037
|
yp_node_t *value = parse_starred_expression(parser, binding_power, message);
|
12197
12038
|
|
12198
|
-
if (previous_binding_power == YP_BINDING_POWER_STATEMENT &&
|
12039
|
+
if (previous_binding_power == YP_BINDING_POWER_STATEMENT && (YP_NODE_TYPE_P(value, YP_NODE_SPLAT_NODE) || match_type_p(parser, YP_TOKEN_COMMA))) {
|
12199
12040
|
yp_token_t opening = not_provided(parser);
|
12200
12041
|
yp_array_node_t *array = yp_array_node_create(parser, &opening);
|
12201
12042
|
|
12202
12043
|
yp_array_node_elements_append(array, value);
|
12203
12044
|
value = (yp_node_t *) array;
|
12204
12045
|
|
12205
|
-
|
12046
|
+
while (accept(parser, YP_TOKEN_COMMA)) {
|
12206
12047
|
yp_node_t *element = parse_starred_expression(parser, binding_power, "Expected an element for the array.");
|
12207
12048
|
yp_array_node_elements_append(array, element);
|
12208
12049
|
if (YP_NODE_TYPE_P(element, YP_NODE_MISSING_NODE)) break;
|
12209
|
-
}
|
12050
|
+
}
|
12210
12051
|
}
|
12211
12052
|
|
12212
12053
|
return value;
|
@@ -12264,14 +12105,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12264
12105
|
case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
|
12265
12106
|
yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
|
12266
12107
|
/* fallthrough */
|
12267
|
-
case
|
12108
|
+
case YP_NODE_CLASS_VARIABLE_READ_NODE:
|
12109
|
+
case YP_NODE_CONSTANT_PATH_NODE:
|
12110
|
+
case YP_NODE_CONSTANT_READ_NODE:
|
12111
|
+
case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
|
12112
|
+
case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
|
12113
|
+
case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
|
12268
12114
|
parser_lex(parser);
|
12269
12115
|
|
12270
|
-
|
12271
|
-
|
12116
|
+
yp_token_t operator = not_provided(parser);
|
12117
|
+
node = parse_target(parser, node, &operator, NULL);
|
12272
12118
|
|
12273
|
-
|
12274
|
-
return
|
12119
|
+
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12120
|
+
return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
|
12275
12121
|
}
|
12276
12122
|
case YP_NODE_CALL_NODE: {
|
12277
12123
|
yp_call_node_t *call_node = (yp_call_node_t *) node;
|
@@ -12289,12 +12135,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12289
12135
|
|
12290
12136
|
parser_lex(parser);
|
12291
12137
|
|
12292
|
-
|
12293
|
-
|
12294
|
-
yp_node_t *result = (yp_node_t *) yp_local_variable_operator_and_write_node_create(parser, node, &token, value, constant_id);
|
12138
|
+
yp_token_t operator = not_provided(parser);
|
12139
|
+
node = parse_target(parser, node, &operator, NULL);
|
12295
12140
|
|
12296
|
-
|
12297
|
-
return
|
12141
|
+
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12142
|
+
return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
|
12298
12143
|
}
|
12299
12144
|
|
12300
12145
|
parser_lex(parser);
|
@@ -12305,49 +12150,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12305
12150
|
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12306
12151
|
return (yp_node_t *) yp_call_operator_and_write_node_create(parser, (yp_call_node_t *) node, &token, value);
|
12307
12152
|
}
|
12308
|
-
case YP_NODE_CLASS_VARIABLE_READ_NODE: {
|
12309
|
-
parser_lex(parser);
|
12310
|
-
|
12311
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12312
|
-
yp_node_t *result = (yp_node_t *) yp_class_variable_operator_and_write_node_create(parser, node, &token, value);
|
12313
|
-
|
12314
|
-
yp_node_destroy(parser, node);
|
12315
|
-
return result;
|
12316
|
-
}
|
12317
|
-
case YP_NODE_CONSTANT_PATH_NODE: {
|
12318
|
-
parser_lex(parser);
|
12319
|
-
|
12320
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12321
|
-
return (yp_node_t *) yp_constant_path_operator_and_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
|
12322
|
-
}
|
12323
|
-
case YP_NODE_CONSTANT_READ_NODE: {
|
12324
|
-
parser_lex(parser);
|
12325
|
-
|
12326
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12327
|
-
yp_node_t *result = (yp_node_t *) yp_constant_operator_and_write_node_create(parser, node, &token, value);
|
12328
|
-
|
12329
|
-
yp_node_destroy(parser, node);
|
12330
|
-
return result;
|
12331
|
-
}
|
12332
|
-
case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
|
12333
|
-
parser_lex(parser);
|
12334
|
-
|
12335
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12336
|
-
yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_and_write_node_create(parser, node, &token, value);
|
12337
|
-
|
12338
|
-
yp_node_destroy(parser, node);
|
12339
|
-
return result;
|
12340
|
-
}
|
12341
|
-
case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
|
12342
|
-
parser_lex(parser);
|
12343
|
-
|
12344
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12345
|
-
yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
|
12346
|
-
yp_node_t *result = (yp_node_t *) yp_local_variable_operator_and_write_node_create(parser, node, &token, value, constant_id);
|
12347
|
-
|
12348
|
-
yp_node_destroy(parser, node);
|
12349
|
-
return result;
|
12350
|
-
}
|
12351
12153
|
case YP_NODE_MULTI_WRITE_NODE: {
|
12352
12154
|
parser_lex(parser);
|
12353
12155
|
yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Cannot use `&&=' on a multi-write.");
|
@@ -12369,14 +12171,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12369
12171
|
case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
|
12370
12172
|
yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
|
12371
12173
|
/* fallthrough */
|
12372
|
-
case
|
12174
|
+
case YP_NODE_CLASS_VARIABLE_READ_NODE:
|
12175
|
+
case YP_NODE_CONSTANT_PATH_NODE:
|
12176
|
+
case YP_NODE_CONSTANT_READ_NODE:
|
12177
|
+
case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
|
12178
|
+
case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
|
12179
|
+
case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
|
12373
12180
|
parser_lex(parser);
|
12374
12181
|
|
12375
|
-
|
12376
|
-
|
12182
|
+
yp_token_t operator = not_provided(parser);
|
12183
|
+
node = parse_target(parser, node, &operator, NULL);
|
12377
12184
|
|
12378
|
-
|
12379
|
-
return
|
12185
|
+
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12186
|
+
return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
|
12380
12187
|
}
|
12381
12188
|
case YP_NODE_CALL_NODE: {
|
12382
12189
|
yp_call_node_t *call_node = (yp_call_node_t *) node;
|
@@ -12394,12 +12201,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12394
12201
|
|
12395
12202
|
parser_lex(parser);
|
12396
12203
|
|
12397
|
-
|
12398
|
-
|
12399
|
-
yp_node_t *result = (yp_node_t *) yp_local_variable_operator_or_write_node_create(parser, node, &token, value, constant_id);
|
12204
|
+
yp_token_t operator = not_provided(parser);
|
12205
|
+
node = parse_target(parser, node, &operator, NULL);
|
12400
12206
|
|
12401
|
-
|
12402
|
-
return
|
12207
|
+
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12208
|
+
return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
|
12403
12209
|
}
|
12404
12210
|
|
12405
12211
|
parser_lex(parser);
|
@@ -12410,49 +12216,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12410
12216
|
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12411
12217
|
return (yp_node_t *) yp_call_operator_or_write_node_create(parser, (yp_call_node_t *) node, &token, value);
|
12412
12218
|
}
|
12413
|
-
case YP_NODE_CLASS_VARIABLE_READ_NODE: {
|
12414
|
-
parser_lex(parser);
|
12415
|
-
|
12416
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12417
|
-
yp_node_t *result = (yp_node_t *) yp_class_variable_operator_or_write_node_create(parser, node, &token, value);
|
12418
|
-
|
12419
|
-
yp_node_destroy(parser, node);
|
12420
|
-
return result;
|
12421
|
-
}
|
12422
|
-
case YP_NODE_CONSTANT_PATH_NODE: {
|
12423
|
-
parser_lex(parser);
|
12424
|
-
|
12425
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12426
|
-
return (yp_node_t *) yp_constant_path_operator_or_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
|
12427
|
-
}
|
12428
|
-
case YP_NODE_CONSTANT_READ_NODE: {
|
12429
|
-
parser_lex(parser);
|
12430
|
-
|
12431
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12432
|
-
yp_node_t *result = (yp_node_t *) yp_constant_operator_or_write_node_create(parser, node, &token, value);
|
12433
|
-
|
12434
|
-
yp_node_destroy(parser, node);
|
12435
|
-
return result;
|
12436
|
-
}
|
12437
|
-
case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
|
12438
|
-
parser_lex(parser);
|
12439
|
-
|
12440
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12441
|
-
yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_or_write_node_create(parser, node, &token, value);
|
12442
|
-
|
12443
|
-
yp_node_destroy(parser, node);
|
12444
|
-
return result;
|
12445
|
-
}
|
12446
|
-
case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
|
12447
|
-
parser_lex(parser);
|
12448
|
-
|
12449
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
|
12450
|
-
yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
|
12451
|
-
yp_node_t *result = (yp_node_t *) yp_local_variable_operator_or_write_node_create(parser, node, &token, value, constant_id);
|
12452
|
-
|
12453
|
-
yp_node_destroy(parser, node);
|
12454
|
-
return result;
|
12455
|
-
}
|
12456
12219
|
case YP_NODE_MULTI_WRITE_NODE: {
|
12457
12220
|
parser_lex(parser);
|
12458
12221
|
yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Cannot use `||=' on a multi-write.");
|
@@ -12484,14 +12247,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12484
12247
|
case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
|
12485
12248
|
yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
|
12486
12249
|
/* fallthrough */
|
12487
|
-
case
|
12250
|
+
case YP_NODE_CLASS_VARIABLE_READ_NODE:
|
12251
|
+
case YP_NODE_CONSTANT_PATH_NODE:
|
12252
|
+
case YP_NODE_CONSTANT_READ_NODE:
|
12253
|
+
case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
|
12254
|
+
case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
|
12255
|
+
case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
|
12488
12256
|
parser_lex(parser);
|
12489
12257
|
|
12490
|
-
|
12491
|
-
|
12258
|
+
yp_token_t operator = not_provided(parser);
|
12259
|
+
node = parse_target(parser, node, &operator, NULL);
|
12492
12260
|
|
12493
|
-
|
12494
|
-
return
|
12261
|
+
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator");
|
12262
|
+
return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
|
12495
12263
|
}
|
12496
12264
|
case YP_NODE_CALL_NODE: {
|
12497
12265
|
yp_call_node_t *call_node = (yp_call_node_t *) node;
|
@@ -12509,12 +12277,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12509
12277
|
|
12510
12278
|
parser_lex(parser);
|
12511
12279
|
|
12512
|
-
|
12513
|
-
|
12514
|
-
yp_node_t *result = (yp_node_t *) yp_local_variable_operator_write_node_create(parser, node, &token, value, constant_id);
|
12280
|
+
yp_token_t operator = not_provided(parser);
|
12281
|
+
node = parse_target(parser, node, &operator, NULL);
|
12515
12282
|
|
12516
|
-
|
12517
|
-
return
|
12283
|
+
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
|
12284
|
+
return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
|
12518
12285
|
}
|
12519
12286
|
|
12520
12287
|
yp_token_t operator = not_provided(parser);
|
@@ -12524,49 +12291,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12524
12291
|
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
|
12525
12292
|
return (yp_node_t *) yp_call_operator_write_node_create(parser, (yp_call_node_t *) node, &token, value);
|
12526
12293
|
}
|
12527
|
-
case YP_NODE_CLASS_VARIABLE_READ_NODE: {
|
12528
|
-
parser_lex(parser);
|
12529
|
-
|
12530
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
|
12531
|
-
yp_node_t *result = (yp_node_t *) yp_class_variable_operator_write_node_create(parser, node, &token, value);
|
12532
|
-
|
12533
|
-
yp_node_destroy(parser, node);
|
12534
|
-
return result;
|
12535
|
-
}
|
12536
|
-
case YP_NODE_CONSTANT_PATH_NODE: {
|
12537
|
-
parser_lex(parser);
|
12538
|
-
|
12539
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
|
12540
|
-
return (yp_node_t *) yp_constant_path_operator_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
|
12541
|
-
}
|
12542
|
-
case YP_NODE_CONSTANT_READ_NODE: {
|
12543
|
-
parser_lex(parser);
|
12544
|
-
|
12545
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
|
12546
|
-
yp_node_t *result = (yp_node_t *) yp_constant_operator_write_node_create(parser, node, &token, value);
|
12547
|
-
|
12548
|
-
yp_node_destroy(parser, node);
|
12549
|
-
return result;
|
12550
|
-
}
|
12551
|
-
case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
|
12552
|
-
parser_lex(parser);
|
12553
|
-
|
12554
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
|
12555
|
-
yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_write_node_create(parser, node, &token, value);
|
12556
|
-
|
12557
|
-
yp_node_destroy(parser, node);
|
12558
|
-
return result;
|
12559
|
-
}
|
12560
|
-
case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
|
12561
|
-
parser_lex(parser);
|
12562
|
-
|
12563
|
-
yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
|
12564
|
-
yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
|
12565
|
-
yp_node_t *result = (yp_node_t *) yp_local_variable_operator_write_node_create(parser, node, &token, value, constant_id);
|
12566
|
-
|
12567
|
-
yp_node_destroy(parser, node);
|
12568
|
-
return result;
|
12569
|
-
}
|
12570
12294
|
case YP_NODE_MULTI_WRITE_NODE: {
|
12571
12295
|
parser_lex(parser);
|
12572
12296
|
yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Unexpected operator.");
|
@@ -12808,12 +12532,13 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12808
12532
|
case YP_CASE_KEYWORD:
|
12809
12533
|
case YP_TOKEN_IDENTIFIER: {
|
12810
12534
|
parser_lex(parser);
|
12535
|
+
yp_token_t message = parser->previous;
|
12811
12536
|
|
12812
12537
|
// If we have an identifier following a '::' operator, then it is for
|
12813
12538
|
// sure a method call.
|
12814
12539
|
yp_arguments_t arguments = YP_EMPTY_ARGUMENTS;
|
12815
12540
|
parse_arguments_list(parser, &arguments, true);
|
12816
|
-
yp_call_node_t *call = yp_call_node_call_create(parser, node, &delimiter, &
|
12541
|
+
yp_call_node_t *call = yp_call_node_call_create(parser, node, &delimiter, &message, &arguments);
|
12817
12542
|
|
12818
12543
|
// If this is followed by a comma then it is a multiple assignment.
|
12819
12544
|
if (previous_binding_power == YP_BINDING_POWER_STATEMENT && match_type_p(parser, YP_TOKEN_COMMA)) {
|
@@ -12854,7 +12579,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12854
12579
|
yp_accepts_block_stack_push(parser, true);
|
12855
12580
|
arguments.arguments = yp_arguments_node_create(parser);
|
12856
12581
|
|
12857
|
-
parse_arguments(parser, arguments
|
12582
|
+
parse_arguments(parser, &arguments, false, YP_TOKEN_BRACKET_RIGHT);
|
12858
12583
|
yp_accepts_block_stack_pop(parser);
|
12859
12584
|
|
12860
12585
|
expect(parser, YP_TOKEN_BRACKET_RIGHT, "Expected ']' to close the bracket expression.");
|
@@ -12878,6 +12603,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
|
12878
12603
|
arguments.block = parse_block(parser);
|
12879
12604
|
}
|
12880
12605
|
|
12606
|
+
yp_arguments_validate(parser, &arguments);
|
12881
12607
|
return (yp_node_t *) yp_call_node_aref_create(parser, node, &arguments);
|
12882
12608
|
}
|
12883
12609
|
case YP_TOKEN_KEYWORD_IN: {
|
@@ -13058,6 +12784,8 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
|
|
13058
12784
|
.enclosure_nesting = 0,
|
13059
12785
|
.lambda_enclosure_nesting = -1,
|
13060
12786
|
.brace_nesting = 0,
|
12787
|
+
.do_loop_stack = YP_STATE_STACK_EMPTY,
|
12788
|
+
.accepts_block_stack = YP_STATE_STACK_EMPTY,
|
13061
12789
|
.lex_modes = {
|
13062
12790
|
.index = 0,
|
13063
12791
|
.stack = {{ .mode = YP_LEX_DEFAULT }},
|
@@ -13069,6 +12797,9 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
|
|
13069
12797
|
.current = { .type = YP_TOKEN_EOF, .start = source, .end = source },
|
13070
12798
|
.next_start = NULL,
|
13071
12799
|
.heredoc_end = NULL,
|
12800
|
+
.comment_list = YP_LIST_EMPTY,
|
12801
|
+
.warning_list = YP_LIST_EMPTY,
|
12802
|
+
.error_list = YP_LIST_EMPTY,
|
13072
12803
|
.current_scope = NULL,
|
13073
12804
|
.current_context = NULL,
|
13074
12805
|
.recovering = false,
|
@@ -13081,16 +12812,12 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
|
|
13081
12812
|
.pattern_matching_newlines = false,
|
13082
12813
|
.in_keyword_arg = false,
|
13083
12814
|
.filepath_string = filepath_string,
|
12815
|
+
.constant_pool = YP_CONSTANT_POOL_EMPTY,
|
12816
|
+
.newline_list = YP_NEWLINE_LIST_EMPTY
|
13084
12817
|
};
|
13085
12818
|
|
13086
|
-
yp_state_stack_init(&parser->do_loop_stack);
|
13087
|
-
yp_state_stack_init(&parser->accepts_block_stack);
|
13088
12819
|
yp_accepts_block_stack_push(parser, true);
|
13089
12820
|
|
13090
|
-
yp_list_init(&parser->warning_list);
|
13091
|
-
yp_list_init(&parser->error_list);
|
13092
|
-
yp_list_init(&parser->comment_list);
|
13093
|
-
|
13094
12821
|
// Initialize the constant pool. We're going to completely guess as to the
|
13095
12822
|
// number of constants that we'll need based on the size of the input. The
|
13096
12823
|
// ratio we chose here is actually less arbitrary than you might think.
|