@@ -3206,6 +3206,7 @@ static pm_if_node_t *
32063206pm_if_node_create(pm_parser_t *parser,
32073207 const pm_token_t *if_keyword,
32083208 pm_node_t *predicate,
3209+ const pm_token_t *then_keyword,
32093210 pm_statements_node_t *statements,
32103211 pm_node_t *consequent,
32113212 const pm_token_t *end_keyword
@@ -3235,6 +3236,7 @@ pm_if_node_create(pm_parser_t *parser,
32353236 },
32363237 .if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
32373238 .predicate = predicate,
3239+ .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
32383240 .statements = statements,
32393241 .consequent = consequent,
32403242 .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
32653267 },
32663268 .if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
32673269 .predicate = predicate,
3270+ .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
32683271 .statements = statements,
32693272 .consequent = NULL,
32703273 .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
32773280 * Allocate and initialize an if node from a ternary expression.
32783281 */
32793282static 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) {
32813284 pm_assert_value_expression(parser, predicate);
32823285 pm_conditional_predicate(predicate);
32833286
@@ -3303,6 +3306,7 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, pm_node_t *
33033306 },
33043307 .if_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
33053308 .predicate = predicate,
3309+ .then_keyword_loc = PM_LOCATION_TOKEN_VALUE(qmark),
33063310 .statements = if_statements,
33073311 .consequent = (pm_node_t *)else_node,
33083312 .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) {
53485352 * Allocate a new UnlessNode node.
53495353 */
53505354static 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) {
53525356 pm_conditional_predicate(predicate);
53535357 pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t);
53545358
@@ -5370,6 +5374,7 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t
53705374 },
53715375 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
53725376 .predicate = predicate,
5377+ .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
53735378 .statements = statements,
53745379 .consequent = NULL,
53755380 .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
54005405 },
54015406 .keyword_loc = PM_LOCATION_TOKEN_VALUE(unless_keyword),
54025407 .predicate = predicate,
5408+ .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
54035409 .statements = statements,
54045410 .consequent = NULL,
54055411 .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
1183911845}
1184011846
1184111847static 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 ) {
1184311849 context_push(parser, PM_CONTEXT_PREDICATE);
1184411850 pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE;
1184511851 pm_node_t *predicate = parse_value_expression(parser, binding_power, error_id);
1184611852
1184711853 // Predicates are closed by a term, a "then", or a term and then a "then".
1184811854 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+
1185011861 if (!predicate_closed) {
1185111862 pm_parser_err_current(parser, PM_ERR_CONDITIONAL_PREDICATE_TERM);
1185211863 }
@@ -11858,7 +11869,9 @@ parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_contex
1185811869static inline pm_node_t *
1185911870parse_conditional(pm_parser_t *parser, pm_context_t context) {
1186011871 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);
1186211875 pm_statements_node_t *statements = NULL;
1186311876
1186411877 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) {
1187311886
1187411887 switch (context) {
1187511888 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);
1187711890 break;
1187811891 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);
1188011893 break;
1188111894 default:
1188211895 assert(false && "unreachable");
@@ -11890,14 +11903,14 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
1189011903 if (context == PM_CONTEXT_IF) {
1189111904 while (accept1(parser, PM_TOKEN_KEYWORD_ELSIF)) {
1189211905 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 );
1189411907 pm_accepts_block_stack_push(parser, true);
1189511908 pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_ELSIF);
1189611909 pm_accepts_block_stack_pop(parser);
1189711910
1189811911 accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
1189911912
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);
1190111914 ((pm_if_node_t *) current)->consequent = elsif;
1190211915 current = elsif;
1190311916 }
@@ -16179,6 +16192,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
1617916192 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);
1618016193 }
1618116194 case PM_TOKEN_QUESTION_MARK: {
16195+ pm_token_t qmark = parser->current;
1618216196 parser_lex(parser);
1618316197 pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_TRUE);
1618416198
@@ -16192,7 +16206,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
1619216206 pm_token_t colon = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
1619316207 pm_node_t *false_expression = (pm_node_t *) pm_missing_node_create(parser, colon.start, colon.end);
1619416208
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);
1619616210 }
1619716211
1619816212 accept1(parser, PM_TOKEN_NEWLINE);
@@ -16201,7 +16215,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
1620116215 pm_token_t colon = parser->previous;
1620216216 pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_FALSE);
1620316217
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);
1620516219 }
1620616220 case PM_TOKEN_COLON_COLON: {
1620716221 parser_lex(parser);
0 commit comments