@@ -3206,6 +3206,7 @@ static pm_if_node_t *
3206
3206
pm_if_node_create(pm_parser_t *parser,
3207
3207
const pm_token_t *if_keyword,
3208
3208
pm_node_t *predicate,
3209
+ const pm_token_t *then_keyword,
3209
3210
pm_statements_node_t *statements,
3210
3211
pm_node_t *consequent,
3211
3212
const pm_token_t *end_keyword
@@ -3235,6 +3236,7 @@ pm_if_node_create(pm_parser_t *parser,
3235
3236
},
3236
3237
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
3237
3238
.predicate = predicate,
3239
+ .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
3238
3240
.statements = statements,
3239
3241
.consequent = consequent,
3240
3242
.end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
@@ -3265,6 +3267,7 @@ pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_t
3265
3267
},
3266
3268
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
3267
3269
.predicate = predicate,
3270
+ .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
3268
3271
.statements = statements,
3269
3272
.consequent = NULL,
3270
3273
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
@@ -3277,7 +3280,7 @@ pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_t
3277
3280
* Allocate and initialize an if node from a ternary expression.
3278
3281
*/
3279
3282
static pm_if_node_t *
3280
- pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, pm_node_t *true_expression, const pm_token_t *colon, pm_node_t *false_expression) {
3283
+ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_token_t *qmark, pm_node_t *true_expression, const pm_token_t *colon, pm_node_t *false_expression) {
3281
3284
pm_assert_value_expression(parser, predicate);
3282
3285
pm_conditional_predicate(predicate);
3283
3286
@@ -3303,6 +3306,7 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, pm_node_t *
3303
3306
},
3304
3307
.if_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
3305
3308
.predicate = predicate,
3309
+ .then_keyword_loc = PM_LOCATION_TOKEN_VALUE(qmark),
3306
3310
.statements = if_statements,
3307
3311
.consequent = (pm_node_t *)else_node,
3308
3312
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
@@ -5348,7 +5352,7 @@ pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) {
5348
5352
* Allocate a new UnlessNode node.
5349
5353
*/
5350
5354
static pm_unless_node_t *
5351
- pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements) {
5355
+ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements) {
5352
5356
pm_conditional_predicate(predicate);
5353
5357
pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t);
5354
5358
@@ -5370,6 +5374,7 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t
5370
5374
},
5371
5375
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5372
5376
.predicate = predicate,
5377
+ .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
5373
5378
.statements = statements,
5374
5379
.consequent = NULL,
5375
5380
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
@@ -5400,6 +5405,7 @@ pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const
5400
5405
},
5401
5406
.keyword_loc = PM_LOCATION_TOKEN_VALUE(unless_keyword),
5402
5407
.predicate = predicate,
5408
+ .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
5403
5409
.statements = statements,
5404
5410
.consequent = NULL,
5405
5411
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
@@ -11839,14 +11845,19 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
11839
11845
}
11840
11846
11841
11847
static inline pm_node_t *
11842
- parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context) {
11848
+ parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword ) {
11843
11849
context_push(parser, PM_CONTEXT_PREDICATE);
11844
11850
pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE;
11845
11851
pm_node_t *predicate = parse_value_expression(parser, binding_power, error_id);
11846
11852
11847
11853
// Predicates are closed by a term, a "then", or a term and then a "then".
11848
11854
bool predicate_closed = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
11849
- predicate_closed |= accept1(parser, PM_TOKEN_KEYWORD_THEN);
11855
+
11856
+ if (accept1(parser, PM_TOKEN_KEYWORD_THEN)) {
11857
+ predicate_closed = true;
11858
+ *then_keyword = parser->previous;
11859
+ }
11860
+
11850
11861
if (!predicate_closed) {
11851
11862
pm_parser_err_current(parser, PM_ERR_CONDITIONAL_PREDICATE_TERM);
11852
11863
}
@@ -11858,7 +11869,9 @@ parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_contex
11858
11869
static inline pm_node_t *
11859
11870
parse_conditional(pm_parser_t *parser, pm_context_t context) {
11860
11871
pm_token_t keyword = parser->previous;
11861
- pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context);
11872
+ pm_token_t then_keyword = not_provided(parser);
11873
+
11874
+ pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context, &then_keyword);
11862
11875
pm_statements_node_t *statements = NULL;
11863
11876
11864
11877
if (!match3(parser, PM_TOKEN_KEYWORD_ELSIF, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
@@ -11873,10 +11886,10 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
11873
11886
11874
11887
switch (context) {
11875
11888
case PM_CONTEXT_IF:
11876
- parent = (pm_node_t *) pm_if_node_create(parser, &keyword, predicate, statements, NULL, &end_keyword);
11889
+ parent = (pm_node_t *) pm_if_node_create(parser, &keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
11877
11890
break;
11878
11891
case PM_CONTEXT_UNLESS:
11879
- parent = (pm_node_t *) pm_unless_node_create(parser, &keyword, predicate, statements);
11892
+ parent = (pm_node_t *) pm_unless_node_create(parser, &keyword, predicate, &then_keyword, statements);
11880
11893
break;
11881
11894
default:
11882
11895
assert(false && "unreachable");
@@ -11890,14 +11903,14 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
11890
11903
if (context == PM_CONTEXT_IF) {
11891
11904
while (accept1(parser, PM_TOKEN_KEYWORD_ELSIF)) {
11892
11905
pm_token_t elsif_keyword = parser->previous;
11893
- pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF);
11906
+ pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF, &then_keyword );
11894
11907
pm_accepts_block_stack_push(parser, true);
11895
11908
pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_ELSIF);
11896
11909
pm_accepts_block_stack_pop(parser);
11897
11910
11898
11911
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
11899
11912
11900
- pm_node_t *elsif = (pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, statements, NULL, &end_keyword);
11913
+ pm_node_t *elsif = (pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
11901
11914
((pm_if_node_t *) current)->consequent = elsif;
11902
11915
current = elsif;
11903
11916
}
@@ -16179,6 +16192,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
16179
16192
return (pm_node_t *) pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
16180
16193
}
16181
16194
case PM_TOKEN_QUESTION_MARK: {
16195
+ pm_token_t qmark = parser->current;
16182
16196
parser_lex(parser);
16183
16197
pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_TRUE);
16184
16198
@@ -16192,7 +16206,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
16192
16206
pm_token_t colon = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
16193
16207
pm_node_t *false_expression = (pm_node_t *) pm_missing_node_create(parser, colon.start, colon.end);
16194
16208
16195
- return (pm_node_t *) pm_if_node_ternary_create(parser, node, true_expression, &colon, false_expression);
16209
+ return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
16196
16210
}
16197
16211
16198
16212
accept1(parser, PM_TOKEN_NEWLINE);
@@ -16201,7 +16215,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
16201
16215
pm_token_t colon = parser->previous;
16202
16216
pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_FALSE);
16203
16217
16204
- return (pm_node_t *) pm_if_node_ternary_create(parser, node, true_expression, &colon, false_expression);
16218
+ return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
16205
16219
}
16206
16220
case PM_TOKEN_COLON_COLON: {
16207
16221
parser_lex(parser);
0 commit comments