Skip to content

Commit fa4535e

Browse files
committed
refactor(fe): create helper function for arrow parameter validation
Reduce clutter in parse_expression_remainder.
1 parent 9f7105f commit fa4535e

File tree

2 files changed

+75
-50
lines changed

2 files changed

+75
-50
lines changed

src/quick-lint-js/fe/parse-expression.cpp

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,57 +1988,18 @@ Expression* Parser::parse_expression_remainder(Parse_Visitor_Base& v,
19881988
Source_Code_Span arrow_span = this->peek().span();
19891989
this->skip();
19901990
Expression* lhs = binary_builder.last_expression();
1991-
Expression* lhs_without_paren = lhs->without_paren();
1992-
switch (lhs_without_paren->kind()) {
1993-
// f(x, y) => {} // Invalid.
1994-
// f(x, y) => {} // Invalid.
1995-
// f.x => z // Invalid.
1996-
// 42 => {} // Invalid.
1997-
case Expression_Kind::Call:
1998-
case Expression_Kind::Dot:
1999-
case Expression_Kind::Literal: {
2000-
if (lhs_without_paren->kind() == Expression_Kind::Call) {
2001-
if (this->peek().type == Token_Type::left_curly) {
2002-
// f(x, y) => {}
2003-
// This is handled by parse_arrow_function_expression_remainder.
2004-
break;
2005-
} else {
2006-
// f(x, y) => x+y
2007-
}
2008-
}
2009-
2010-
Source_Code_Span lhs_span = lhs->span();
2011-
switch (lhs_without_paren->kind()) {
2012-
case Expression_Kind::Call:
2013-
case Expression_Kind::Dot:
2014-
this->diag_reporter_->report(Diag_Unexpected_Arrow_After_Expression{
2015-
.arrow = arrow_span,
2016-
.expression = lhs_span,
2017-
});
2018-
break;
2019-
case Expression_Kind::Literal:
2020-
this->diag_reporter_->report(Diag_Unexpected_Arrow_After_Literal{
2021-
.arrow = arrow_span,
2022-
.literal_parameter = lhs_span,
2023-
});
2024-
break;
2025-
default:
2026-
QLJS_UNREACHABLE();
2027-
}
2028-
2029-
if (this->peek().type != Token_Type::left_curly) {
2030-
// Treat the '=>' as if it was a binary operator (like '>=').
2031-
binary_builder.add_child(
2032-
arrow_span,
2033-
this->parse_expression(
2034-
v, Precedence{.binary_operators = false, .commas = false}));
2035-
goto next;
2036-
}
2037-
break;
2038-
}
2039-
2040-
default:
1991+
switch (this->validate_arrow_function_parameter_list(lhs, arrow_span)) {
1992+
case Arrow_Function_Parameter_List_Validation::ok:
1993+
case Arrow_Function_Parameter_List_Validation::error:
20411994
break;
1995+
case Arrow_Function_Parameter_List_Validation::
1996+
equal_greater_looks_like_operator:
1997+
// Treat the '=>' as if it was a binary operator (like '>=').
1998+
binary_builder.add_child(
1999+
arrow_span,
2000+
this->parse_expression(
2001+
v, Precedence{.binary_operators = false, .commas = false}));
2002+
goto next;
20422003
}
20432004

20442005
if (binary_builder.has_multiple_children()) {
@@ -2321,6 +2282,61 @@ Expression* Parser::parse_expression_remainder(Parse_Visitor_Base& v,
23212282
return this->build_expression(binary_builder);
23222283
}
23232284

2285+
Parser::Arrow_Function_Parameter_List_Validation
2286+
Parser::validate_arrow_function_parameter_list(
2287+
Expression* parameters_expression, Source_Code_Span arrow_span) {
2288+
Expression* lhs = parameters_expression;
2289+
Expression* lhs_without_paren = lhs->without_paren();
2290+
switch (lhs_without_paren->kind()) {
2291+
// f(x, y) => {} // Invalid.
2292+
// f(x, y) => {} // Invalid.
2293+
// f.x => z // Invalid.
2294+
// 42 => {} // Invalid.
2295+
case Expression_Kind::Call:
2296+
case Expression_Kind::Dot:
2297+
case Expression_Kind::Literal: {
2298+
if (lhs_without_paren->kind() == Expression_Kind::Call) {
2299+
if (this->peek().type == Token_Type::left_curly) {
2300+
// f(x, y) => {}
2301+
// Diagnostic reporting is done by
2302+
// parse_arrow_function_expression_remainder.
2303+
return Arrow_Function_Parameter_List_Validation::error;
2304+
} else {
2305+
// f(x, y) => x+y
2306+
}
2307+
}
2308+
2309+
Source_Code_Span lhs_span = lhs->span();
2310+
switch (lhs_without_paren->kind()) {
2311+
case Expression_Kind::Call:
2312+
case Expression_Kind::Dot:
2313+
this->diag_reporter_->report(Diag_Unexpected_Arrow_After_Expression{
2314+
.arrow = arrow_span,
2315+
.expression = lhs_span,
2316+
});
2317+
break;
2318+
case Expression_Kind::Literal:
2319+
this->diag_reporter_->report(Diag_Unexpected_Arrow_After_Literal{
2320+
.arrow = arrow_span,
2321+
.literal_parameter = lhs_span,
2322+
});
2323+
break;
2324+
default:
2325+
QLJS_UNREACHABLE();
2326+
}
2327+
2328+
if (this->peek().type != Token_Type::left_curly) {
2329+
return Arrow_Function_Parameter_List_Validation::
2330+
equal_greater_looks_like_operator;
2331+
}
2332+
return Arrow_Function_Parameter_List_Validation::error;
2333+
}
2334+
2335+
default:
2336+
return Arrow_Function_Parameter_List_Validation::ok;
2337+
}
2338+
}
2339+
23242340
Expression* Parser::parse_arrow_function_expression_remainder(
23252341
Parse_Visitor_Base& v, Buffering_Visitor* generic_parameter_visits,
23262342
Expression* parameters_expression, Buffering_Visitor* return_type_visits,

src/quick-lint-js/fe/parse.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,15 @@ class Parser {
760760
const Token &await_token, Precedence prec);
761761
Expression *parse_expression_remainder(Parse_Visitor_Base &, Expression *,
762762
Precedence);
763+
enum class Arrow_Function_Parameter_List_Validation {
764+
ok,
765+
error,
766+
// '=>' should be parsed as an operator like '>='.
767+
equal_greater_looks_like_operator,
768+
};
769+
Arrow_Function_Parameter_List_Validation
770+
validate_arrow_function_parameter_list(Expression *parameters_expression,
771+
Source_Code_Span arrow_span);
763772
Expression *parse_arrow_function_expression_remainder(
764773
Parse_Visitor_Base &, Buffering_Visitor *generic_parameter_visits,
765774
Expression *parameters_expression, Buffering_Visitor *return_type_visits,

0 commit comments

Comments
 (0)