Skip to content

Commit 73f272a

Browse files
committed
Add basic plumbing for parser options
In the future, we will need the parser to support conflicting syntaxes (E.g. TypeScript vs Flow, or ES Modules vs scripts). The user will need to configure quick-lint-js to get the best diagnostics. Add a way to internally tweak the parser's treatment of 'await' at the module scope. In the future, this will be configured using quick-lint-js.config. For now, this is only used in tests.
1 parent 7b11341 commit 73f272a

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

src/parse.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,10 @@ expression* parser::parse_async_expression_only(token async_token,
684684

685685
expression* parser::parse_await_expression(token await_token, precedence prec) {
686686
bool is_identifier = [&]() -> bool {
687-
if (this->in_async_function_) {
687+
if (this->in_async_function_ ||
688+
(this->in_top_level_ &&
689+
this->options_.top_level_await_mode ==
690+
parser_top_level_await_mode::await_operator)) {
688691
return false;
689692
} else {
690693
// await is a unary operator (in modules) or an identifier (in scripts).

src/quick-lint-js/parse.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@
9292
} while (false)
9393

9494
namespace quick_lint_js {
95+
enum class parser_top_level_await_mode {
96+
auto_detect = 0,
97+
await_operator,
98+
};
99+
100+
// TODO(#465): Accept parser options from quick-lint-js.config or CLI options.
101+
struct parser_options {
102+
parser_top_level_await_mode top_level_await_mode =
103+
parser_top_level_await_mode::auto_detect;
104+
};
105+
95106
// A parser reads JavaScript source code and calls the member functions of a
96107
// parse_visitor (visit_variable_declaration, visit_enter_function_scope, etc.).
97108
class parser {
@@ -105,7 +116,13 @@ class parser {
105116

106117
public:
107118
explicit parser(padded_string_view input, error_reporter *error_reporter)
108-
: lexer_(input, error_reporter), error_reporter_(error_reporter) {}
119+
: parser(input, error_reporter, parser_options()) {}
120+
121+
explicit parser(padded_string_view input, error_reporter *error_reporter,
122+
parser_options options)
123+
: lexer_(input, error_reporter),
124+
error_reporter_(error_reporter),
125+
options_(options) {}
109126

110127
quick_lint_js::lexer &lexer() noexcept { return this->lexer_; }
111128

@@ -3732,6 +3749,7 @@ class parser {
37323749

37333750
quick_lint_js::lexer lexer_;
37343751
error_reporter *error_reporter_;
3752+
parser_options options_;
37353753
quick_lint_js::expression_arena expressions_;
37363754

37373755
// Memory used for temporary memory allocations (e.g. vectors on the stack).

test/test-parse-var.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,37 @@ TEST(test_parse, use_await_at_top_level_as_variable) {
15311531
}
15321532
}
15331533

1534+
TEST(test_parse, forced_top_level_await_operator) {
1535+
{
1536+
padded_string code(u8"await p;"_sv);
1537+
spy_visitor v;
1538+
parser p(
1539+
&code, &v,
1540+
parser_options{
1541+
.top_level_await_mode = parser_top_level_await_mode::await_operator,
1542+
});
1543+
p.parse_and_visit_module(v);
1544+
EXPECT_THAT(v.visits, ElementsAre("visit_variable_use", // p
1545+
"visit_end_of_module"));
1546+
EXPECT_THAT(v.errors, IsEmpty());
1547+
}
1548+
1549+
{
1550+
padded_string code(u8"await;"_sv);
1551+
spy_visitor v;
1552+
parser p(
1553+
&code, &v,
1554+
parser_options{
1555+
.top_level_await_mode = parser_top_level_await_mode::await_operator,
1556+
});
1557+
p.parse_and_visit_module(v);
1558+
EXPECT_THAT(v.visits, ElementsAre("visit_end_of_module"));
1559+
EXPECT_THAT(v.errors, ElementsAre(ERROR_TYPE_FIELD(
1560+
error_missing_operand_for_operator, where,
1561+
offsets_matcher(&code, 0, u8"await"))));
1562+
}
1563+
}
1564+
15341565
TEST(
15351566
test_parse,
15361567
declare_await_in_async_function_is_allowed_for_named_function_expressions) {

0 commit comments

Comments
 (0)