diff --git a/test/yarp/errors_test.rb b/test/yarp/errors_test.rb index 57a2cab011..9664c47148 100644 --- a/test/yarp/errors_test.rb +++ b/test/yarp/errors_test.rb @@ -949,7 +949,21 @@ module YARP ) assert_errors expected, "case :a\nelse\nend", [ - ["Unexpected `else` in `case` statement; a `when` clause must precede `else`", 8..12] + ["Expected a `when` or `in` clause after `case`", 0..4] + ] + end + + def test_case_without_clauses + expected = CaseNode( + SymbolNode(Location(), Location(), nil, "a"), + [], + nil, + Location(), + Location() + ) + + assert_errors expected, "case :a\nend", [ + ["Expected a `when` or `in` clause after `case`", 0..4] ] end diff --git a/yarp/diagnostic.c b/yarp/diagnostic.c index 9bbc30edee..34da3f97a5 100644 --- a/yarp/diagnostic.c +++ b/yarp/diagnostic.c @@ -85,7 +85,7 @@ static const char* const diagnostic_messages[YP_DIAGNOSTIC_ID_LEN] = { [YP_ERR_CANNOT_PARSE_STRING_PART] = "Cannot parse the string part", [YP_ERR_CASE_EXPRESSION_AFTER_CASE] = "Expected an expression after `case`", [YP_ERR_CASE_EXPRESSION_AFTER_WHEN] = "Expected an expression after `when`", - [YP_ERR_CASE_LONELY_ELSE] = "Unexpected `else` in `case` statement; a `when` clause must precede `else`", + [YP_ERR_CASE_MISSING_CONDITIONS] = "Expected a `when` or `in` clause after `case`", [YP_ERR_CASE_TERM] = "Expected an `end` to close the `case` statement", [YP_ERR_CLASS_IN_METHOD] = "Unexpected class definition in a method body", [YP_ERR_CLASS_NAME] = "Expected a constant name after `class`", diff --git a/yarp/diagnostic.h b/yarp/diagnostic.h index a4b030adfd..b8d9fe0100 100644 --- a/yarp/diagnostic.h +++ b/yarp/diagnostic.h @@ -50,7 +50,7 @@ typedef enum { YP_ERR_CANNOT_PARSE_STRING_PART, YP_ERR_CASE_EXPRESSION_AFTER_CASE, YP_ERR_CASE_EXPRESSION_AFTER_WHEN, - YP_ERR_CASE_LONELY_ELSE, + YP_ERR_CASE_MISSING_CONDITIONS, YP_ERR_CASE_TERM, YP_ERR_CLASS_IN_METHOD, YP_ERR_CLASS_NAME, diff --git a/yarp/yarp.c b/yarp/yarp.c index aeb015611b..b250220e7e 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -11935,6 +11935,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } if (accept1(parser, YP_TOKEN_KEYWORD_END)) { + yp_diagnostic_list_append(&parser->error_list, case_keyword.start, case_keyword.end, YP_ERR_CASE_MISSING_CONDITIONS); return (yp_node_t *) yp_case_node_create(parser, &case_keyword, predicate, NULL, &parser->previous); } @@ -12041,12 +12042,14 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } } + // If we didn't parse any conditions (in or when) then we need to + // indicate that we have an error. + if (case_node->conditions.size == 0) { + yp_diagnostic_list_append(&parser->error_list, case_keyword.start, case_keyword.end, YP_ERR_CASE_MISSING_CONDITIONS); + } + accept2(parser, YP_TOKEN_NEWLINE, YP_TOKEN_SEMICOLON); if (accept1(parser, YP_TOKEN_KEYWORD_ELSE)) { - if (case_node->conditions.size < 1) { - yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, YP_ERR_CASE_LONELY_ELSE); - } - yp_token_t else_keyword = parser->previous; yp_else_node_t *else_node;